tornavis/intern/dualcon/intern/dualcon_c_api.cpp

169 lines
3.5 KiB
C++

/* SPDX-FileCopyrightText: 2011-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "ModelReader.h"
#include "dualcon.h"
#include "octree.h"
#include <cassert>
#include <cstdio>
#include <float.h>
#if defined(_WIN32)
# define isnan(n) _isnan(n)
#endif
static void veccopy(float dst[3], const float src[3])
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
}
#define GET_TRI(_mesh, _n) \
(*(DualConTri)(((char *)(_mesh)->looptris) + ((_n) * (_mesh)->tri_stride)))
#define GET_CO(_mesh, _n) (*(DualConCo)(((char *)(_mesh)->co) + ((_n) * (_mesh)->co_stride)))
#define GET_LOOP(_mesh, _n) \
(*(DualConLoop)(((char *)(_mesh)->mloop) + ((_n) * (_mesh)->loop_stride)))
class DualConInputReader : public ModelReader {
private:
const DualConInput *input_mesh;
int tottri, curtri;
float min[3], max[3], maxsize;
float scale;
public:
DualConInputReader(const DualConInput *mesh, float _scale) : input_mesh(mesh), scale(_scale)
{
reset();
}
void reset()
{
curtri = 0;
maxsize = 0;
tottri = input_mesh->tottri;
veccopy(min, input_mesh->min);
veccopy(max, input_mesh->max);
/* initialize maxsize */
for (int i = 0; i < 3; i++) {
float d = max[i] - min[i];
if (d > maxsize) {
maxsize = d;
}
}
/* redo the bounds */
for (int i = 0; i < 3; i++) {
min[i] = (max[i] + min[i]) / 2 - maxsize / 2;
max[i] = (max[i] + min[i]) / 2 + maxsize / 2;
}
for (int i = 0; i < 3; i++) {
min[i] -= maxsize * (1 / scale - 1) / 2;
}
maxsize *= 1 / scale;
}
Triangle *getNextTriangle()
{
if (curtri == input_mesh->tottri) {
return NULL;
}
Triangle *t = new Triangle();
unsigned int *tr = GET_TRI(input_mesh, curtri);
veccopy(t->vt[0], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[0])));
veccopy(t->vt[1], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[1])));
veccopy(t->vt[2], GET_CO(input_mesh, GET_LOOP(input_mesh, tr[2])));
curtri++;
/* remove triangle if it contains invalid coords */
for (int i = 0; i < 3; i++) {
const float *co = t->vt[i];
if (isnan(co[0]) || isnan(co[1]) || isnan(co[2])) {
delete t;
return getNextTriangle();
}
}
return t;
}
int getNextTriangle(int t[3])
{
if (curtri == input_mesh->tottri) {
return 0;
}
unsigned int *tr = GET_TRI(input_mesh, curtri);
t[0] = tr[0];
t[1] = tr[1];
t[2] = tr[2];
curtri++;
return 1;
}
int getNumTriangles()
{
return tottri;
}
int getNumVertices()
{
return input_mesh->totco;
}
float getBoundingBox(float origin[3])
{
veccopy(origin, min);
return maxsize;
}
/* output */
void getNextVertex(float /*v*/[3])
{
/* not used */
}
/* stubs */
void printInfo() {}
int getMemory()
{
return sizeof(DualConInputReader);
}
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:DualConInputReader")
#endif
};
void *dualcon(const DualConInput *input_mesh,
/* callbacks for output */
DualConAllocOutput alloc_output,
DualConAddVert add_vert,
DualConAddQuad add_quad,
DualConFlags flags,
DualConMode mode,
float threshold,
float hermite_num,
float scale,
int depth)
{
DualConInputReader r(input_mesh, scale);
Octree o(&r, alloc_output, add_vert, add_quad, flags, mode, depth, threshold, hermite_num);
o.scanConvert();
return o.getOutputMesh();
}