implemented isSolid() test; simplified cork.h; trimmed number of headers
This commit closes issue #2 and issue #8
This commit is contained in:
@@ -12,12 +12,12 @@ SUBDIRECTORIES := util file_formats math isct mesh rawmesh accel
|
||||
# make sure the subdirectories are mirrored in
|
||||
# the obj/ debug/ and depend/ directories
|
||||
# (HACK: use this dummy variable to get access to shell commands)
|
||||
SHELL_HACK := $(shell mkdir -p bin lib)
|
||||
SHELL_HACK := $(shell mkdir -p bin lib include)
|
||||
SHELL_HACK := $(shell mkdir -p $(addprefix obj/,$(SUBDIRECTORIES)))
|
||||
SHELL_HACK := $(shell mkdir -p $(addprefix debug/,$(SUBDIRECTORIES)))
|
||||
SHELL_HACK := $(shell mkdir -p $(addprefix depend/,$(SUBDIRECTORIES)))
|
||||
# also make a directory to expose headers in
|
||||
SHELL_HACK := $(shell mkdir -p $(addprefix include/,$(SUBDIRECTORIES)))
|
||||
#SHELL_HACK := $(shell mkdir -p $(addprefix include/,$(SUBDIRECTORIES)))
|
||||
|
||||
# +----------+
|
||||
# | Platform |
|
||||
@@ -121,14 +121,14 @@ MESH_HEADERS := mesh.h mesh.decl.h \
|
||||
ACCEL_HEADERS := aabvh.h
|
||||
FILE_HEADERS := files.h
|
||||
HEADERS := \
|
||||
cork.h \
|
||||
$(addprefix math/,$(MATH_HEADERS))\
|
||||
$(addprefix util/,$(UTIL_HEADERS))\
|
||||
$(addprefix isct/,$(ISCT_HEADERS))\
|
||||
$(addprefix mesh/,$(MESH_HEADERS))\
|
||||
$(addprefix rawmesh/,$(RAWMESH_HEADERS))\
|
||||
$(addprefix accel/,$(ACCEL_HEADERS))\
|
||||
$(addprefix file_formats/,$(FILE_HEADERS))
|
||||
cork.h
|
||||
# $(addprefix math/,$(MATH_HEADERS))\
|
||||
# $(addprefix util/,$(UTIL_HEADERS))\
|
||||
# $(addprefix isct/,$(ISCT_HEADERS))\
|
||||
# $(addprefix mesh/,$(MESH_HEADERS))\
|
||||
# $(addprefix rawmesh/,$(RAWMESH_HEADERS))\
|
||||
# $(addprefix accel/,$(ACCEL_HEADERS))\
|
||||
# $(addprefix file_formats/,$(FILE_HEADERS))
|
||||
HEADER_COPIES := $(addprefix include/,$(HEADERS))
|
||||
|
||||
# +-----------------------------+
|
||||
|
||||
+94
-155
@@ -27,6 +27,16 @@
|
||||
|
||||
#include "mesh.h"
|
||||
|
||||
|
||||
void freeCorkTriMesh(CorkTriMesh *mesh)
|
||||
{
|
||||
delete[] mesh->triangles;
|
||||
delete[] mesh->vertices;
|
||||
mesh->n_triangles = 0;
|
||||
mesh->n_vertices = 0;
|
||||
}
|
||||
|
||||
|
||||
struct CorkTriangle;
|
||||
|
||||
struct CorkVertex :
|
||||
@@ -97,223 +107,152 @@ struct CorkTriangle :
|
||||
using RawCorkMesh = RawMesh<CorkVertex, CorkTriangle>;
|
||||
using CorkMesh = Mesh<CorkVertex, CorkTriangle>;
|
||||
|
||||
void cMesh2CorkMesh(
|
||||
uint n_triangles_in, uint *triangles_in,
|
||||
uint n_vertices_in, float *vertices_in,
|
||||
void corkTriMesh2CorkMesh(
|
||||
CorkTriMesh in,
|
||||
CorkMesh *mesh_out
|
||||
) {
|
||||
RawCorkMesh raw;
|
||||
raw.vertices.resize(n_vertices_in);
|
||||
raw.triangles.resize(n_triangles_in);
|
||||
if(n_vertices_in == 0 || n_triangles_in == 0) {
|
||||
raw.vertices.resize(in.n_vertices);
|
||||
raw.triangles.resize(in.n_triangles);
|
||||
if(in.n_vertices == 0 || in.n_triangles == 0) {
|
||||
ERROR("empty mesh input to Cork routine.");
|
||||
*mesh_out = CorkMesh(raw);
|
||||
return;
|
||||
}
|
||||
|
||||
uint max_ref_idx = 0;
|
||||
for(uint i=0; i<n_triangles_in; i++) {
|
||||
raw.triangles[i].a = triangles_in[3*i+0];
|
||||
raw.triangles[i].b = triangles_in[3*i+1];
|
||||
raw.triangles[i].c = triangles_in[3*i+2];
|
||||
for(uint i=0; i<in.n_triangles; i++) {
|
||||
raw.triangles[i].a = in.triangles[3*i+0];
|
||||
raw.triangles[i].b = in.triangles[3*i+1];
|
||||
raw.triangles[i].c = in.triangles[3*i+2];
|
||||
max_ref_idx = std::max(
|
||||
std::max(max_ref_idx,
|
||||
triangles_in[3*i+0]),
|
||||
std::max(triangles_in[3*i+1],
|
||||
triangles_in[3*i+2])
|
||||
in.triangles[3*i+0]),
|
||||
std::max(in.triangles[3*i+1],
|
||||
in.triangles[3*i+2])
|
||||
);
|
||||
}
|
||||
if(max_ref_idx > n_vertices_in) {
|
||||
ERROR("mesh input to Cork routine has an out of range vertex index.");
|
||||
if(max_ref_idx > in.n_vertices) {
|
||||
ERROR("mesh input to Cork routine has an out of range reference "
|
||||
"to a vertex.");
|
||||
raw.vertices.clear();
|
||||
raw.triangles.clear();
|
||||
*mesh_out = CorkMesh(raw);
|
||||
return;
|
||||
}
|
||||
|
||||
for(uint i=0; i<n_vertices_in; i++) {
|
||||
raw.vertices[i].pos.x = vertices_in[3*i+0];
|
||||
raw.vertices[i].pos.y = vertices_in[3*i+1];
|
||||
raw.vertices[i].pos.z = vertices_in[3*i+2];
|
||||
for(uint i=0; i<in.n_vertices; i++) {
|
||||
raw.vertices[i].pos.x = in.vertices[3*i+0];
|
||||
raw.vertices[i].pos.y = in.vertices[3*i+1];
|
||||
raw.vertices[i].pos.z = in.vertices[3*i+2];
|
||||
}
|
||||
|
||||
*mesh_out = CorkMesh(raw);
|
||||
}
|
||||
void corkMesh2CMesh(
|
||||
void corkMesh2CorkTriMesh(
|
||||
CorkMesh *mesh_in,
|
||||
uint *n_triangles_out, uint **triangles_out,
|
||||
uint *n_vertices_out, float **vertices_out
|
||||
CorkTriMesh *out
|
||||
) {
|
||||
RawCorkMesh raw = mesh_in->raw();
|
||||
|
||||
*n_triangles_out = raw.triangles.size();
|
||||
*n_vertices_out = raw.vertices.size();
|
||||
out->n_triangles = raw.triangles.size();
|
||||
out->n_vertices = raw.vertices.size();
|
||||
|
||||
*triangles_out = new uint[(*n_triangles_out) * 3];
|
||||
*vertices_out = new float[(*n_vertices_out) * 3];
|
||||
out->triangles = new uint[(out->n_triangles) * 3];
|
||||
out->vertices = new float[(out->n_vertices) * 3];
|
||||
|
||||
for(uint i=0; i<*n_triangles_out; i++) {
|
||||
(*triangles_out)[3*i+0] = raw.triangles[i].a;
|
||||
(*triangles_out)[3*i+1] = raw.triangles[i].b;
|
||||
(*triangles_out)[3*i+2] = raw.triangles[i].c;
|
||||
for(uint i=0; i<out->n_triangles; i++) {
|
||||
(out->triangles)[3*i+0] = raw.triangles[i].a;
|
||||
(out->triangles)[3*i+1] = raw.triangles[i].b;
|
||||
(out->triangles)[3*i+2] = raw.triangles[i].c;
|
||||
}
|
||||
|
||||
for(uint i=0; i<*n_vertices_out; i++) {
|
||||
(*vertices_out)[3*i+0] = raw.vertices[i].pos.x;
|
||||
(*vertices_out)[3*i+1] = raw.vertices[i].pos.y;
|
||||
(*vertices_out)[3*i+2] = raw.vertices[i].pos.z;
|
||||
for(uint i=0; i<out->n_vertices; i++) {
|
||||
(out->vertices)[3*i+0] = raw.vertices[i].pos.x;
|
||||
(out->vertices)[3*i+1] = raw.vertices[i].pos.y;
|
||||
(out->vertices)[3*i+2] = raw.vertices[i].pos.z;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool isSolid(CorkTriMesh cmesh)
|
||||
{
|
||||
CorkMesh mesh;
|
||||
corkTriMesh2CorkMesh(cmesh, &mesh);
|
||||
|
||||
bool solid = true;
|
||||
|
||||
if(mesh.isSelfIntersecting()) {
|
||||
ERROR("isSolid() was given a self-intersecting mesh");
|
||||
solid = false;
|
||||
}
|
||||
|
||||
if(!mesh.isClosed()) {
|
||||
ERROR("isSolid() was given a non-closed mesh");
|
||||
solid = false;
|
||||
}
|
||||
|
||||
return solid;
|
||||
}
|
||||
|
||||
void computeUnion(
|
||||
// input mesh 0
|
||||
uint n_triangles_in0, uint *triangles_in0,
|
||||
uint n_vertices_in0, float *vertices_in0,
|
||||
// input mesh 1
|
||||
uint n_triangles_in1, uint *triangles_in1,
|
||||
uint n_vertices_in1, float *vertices_in1,
|
||||
// output mesh
|
||||
uint *n_triangles_out, uint **triangles_out,
|
||||
uint *n_vertices_out, float **vertices_out
|
||||
CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out
|
||||
) {
|
||||
// convert input
|
||||
CorkMesh in0, in1;
|
||||
cMesh2CorkMesh(
|
||||
n_triangles_in0, triangles_in0,
|
||||
n_vertices_in0, vertices_in0,
|
||||
&in0);
|
||||
cMesh2CorkMesh(
|
||||
n_triangles_in1, triangles_in1,
|
||||
n_vertices_in1, vertices_in1,
|
||||
&in1);
|
||||
CorkMesh cmIn0, cmIn1;
|
||||
corkTriMesh2CorkMesh(in0, &cmIn0);
|
||||
corkTriMesh2CorkMesh(in1, &cmIn1);
|
||||
|
||||
in0.boolUnion(in1);
|
||||
cmIn0.boolUnion(cmIn1);
|
||||
|
||||
// convert output
|
||||
corkMesh2CMesh(&in0,
|
||||
n_triangles_out, triangles_out,
|
||||
n_vertices_out, vertices_out);
|
||||
corkMesh2CorkTriMesh(&cmIn0, out);
|
||||
}
|
||||
|
||||
void computeDifference(
|
||||
// input mesh 0
|
||||
uint n_triangles_in0, uint *triangles_in0,
|
||||
uint n_vertices_in0, float *vertices_in0,
|
||||
// input mesh 1
|
||||
uint n_triangles_in1, uint *triangles_in1,
|
||||
uint n_vertices_in1, float *vertices_in1,
|
||||
// output mesh
|
||||
uint *n_triangles_out, uint **triangles_out,
|
||||
uint *n_vertices_out, float **vertices_out
|
||||
CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out
|
||||
) {
|
||||
// convert input
|
||||
CorkMesh in0, in1;
|
||||
cMesh2CorkMesh(
|
||||
n_triangles_in0, triangles_in0,
|
||||
n_vertices_in0, vertices_in0,
|
||||
&in0);
|
||||
cMesh2CorkMesh(
|
||||
n_triangles_in1, triangles_in1,
|
||||
n_vertices_in1, vertices_in1,
|
||||
&in1);
|
||||
CorkMesh cmIn0, cmIn1;
|
||||
corkTriMesh2CorkMesh(in0, &cmIn0);
|
||||
corkTriMesh2CorkMesh(in1, &cmIn1);
|
||||
|
||||
in0.boolDiff(in1);
|
||||
cmIn0.boolDiff(cmIn1);
|
||||
|
||||
// convert output
|
||||
corkMesh2CMesh(&in0,
|
||||
n_triangles_out, triangles_out,
|
||||
n_vertices_out, vertices_out);
|
||||
corkMesh2CorkTriMesh(&cmIn0, out);
|
||||
}
|
||||
|
||||
void computeIntersection(
|
||||
// input mesh 0
|
||||
uint n_triangles_in0, uint *triangles_in0,
|
||||
uint n_vertices_in0, float *vertices_in0,
|
||||
// input mesh 1
|
||||
uint n_triangles_in1, uint *triangles_in1,
|
||||
uint n_vertices_in1, float *vertices_in1,
|
||||
// output mesh
|
||||
uint *n_triangles_out, uint **triangles_out,
|
||||
uint *n_vertices_out, float **vertices_out
|
||||
CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out
|
||||
) {
|
||||
// convert input
|
||||
CorkMesh in0, in1;
|
||||
cMesh2CorkMesh(
|
||||
n_triangles_in0, triangles_in0,
|
||||
n_vertices_in0, vertices_in0,
|
||||
&in0);
|
||||
cMesh2CorkMesh(
|
||||
n_triangles_in1, triangles_in1,
|
||||
n_vertices_in1, vertices_in1,
|
||||
&in1);
|
||||
CorkMesh cmIn0, cmIn1;
|
||||
corkTriMesh2CorkMesh(in0, &cmIn0);
|
||||
corkTriMesh2CorkMesh(in1, &cmIn1);
|
||||
|
||||
in0.boolIsct(in1);
|
||||
cmIn0.boolIsct(cmIn1);
|
||||
|
||||
// convert output
|
||||
corkMesh2CMesh(&in0,
|
||||
n_triangles_out, triangles_out,
|
||||
n_vertices_out, vertices_out);
|
||||
corkMesh2CorkTriMesh(&cmIn0, out);
|
||||
}
|
||||
|
||||
void computeSymmetricDifference(
|
||||
// input mesh 0
|
||||
uint n_triangles_in0, uint *triangles_in0,
|
||||
uint n_vertices_in0, float *vertices_in0,
|
||||
// input mesh 1
|
||||
uint n_triangles_in1, uint *triangles_in1,
|
||||
uint n_vertices_in1, float *vertices_in1,
|
||||
// output mesh
|
||||
uint *n_triangles_out, uint **triangles_out,
|
||||
uint *n_vertices_out, float **vertices_out
|
||||
CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out
|
||||
) {
|
||||
// convert input
|
||||
CorkMesh in0, in1;
|
||||
cMesh2CorkMesh(
|
||||
n_triangles_in0, triangles_in0,
|
||||
n_vertices_in0, vertices_in0,
|
||||
&in0);
|
||||
cMesh2CorkMesh(
|
||||
n_triangles_in1, triangles_in1,
|
||||
n_vertices_in1, vertices_in1,
|
||||
&in1);
|
||||
CorkMesh cmIn0, cmIn1;
|
||||
corkTriMesh2CorkMesh(in0, &cmIn0);
|
||||
corkTriMesh2CorkMesh(in1, &cmIn1);
|
||||
|
||||
in0.boolXor(in1);
|
||||
cmIn0.boolXor(cmIn1);
|
||||
|
||||
// convert output
|
||||
corkMesh2CMesh(&in0,
|
||||
n_triangles_out, triangles_out,
|
||||
n_vertices_out, vertices_out);
|
||||
corkMesh2CorkTriMesh(&cmIn0, out);
|
||||
}
|
||||
|
||||
void resolveIntersections(
|
||||
// input mesh 0
|
||||
uint n_triangles_in0, uint *triangles_in0,
|
||||
uint n_vertices_in0, float *vertices_in0,
|
||||
// input mesh 1
|
||||
uint n_triangles_in1, uint *triangles_in1,
|
||||
uint n_vertices_in1, float *vertices_in1,
|
||||
// output mesh
|
||||
uint *n_triangles_out, uint **triangles_out,
|
||||
uint *n_vertices_out, float **vertices_out
|
||||
CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out
|
||||
) {
|
||||
// convert input
|
||||
CorkMesh in0, in1;
|
||||
cMesh2CorkMesh(
|
||||
n_triangles_in0, triangles_in0,
|
||||
n_vertices_in0, vertices_in0,
|
||||
&in0);
|
||||
cMesh2CorkMesh(
|
||||
n_triangles_in1, triangles_in1,
|
||||
n_vertices_in1, vertices_in1,
|
||||
&in1);
|
||||
CorkMesh cmIn0, cmIn1;
|
||||
corkTriMesh2CorkMesh(in0, &cmIn0);
|
||||
corkTriMesh2CorkMesh(in1, &cmIn1);
|
||||
|
||||
in0.disjointUnion(in1);
|
||||
in0.resolveIntersections();
|
||||
cmIn0.disjointUnion(cmIn1);
|
||||
cmIn0.resolveIntersections();
|
||||
|
||||
// convert output
|
||||
corkMesh2CMesh(&in0,
|
||||
n_triangles_out, triangles_out,
|
||||
n_vertices_out, vertices_out);
|
||||
corkMesh2CorkTriMesh(&cmIn0, out);
|
||||
}
|
||||
|
||||
|
||||
+26
-65
@@ -29,85 +29,46 @@
|
||||
typedef unsigned int uint;
|
||||
#endif
|
||||
|
||||
// TODO: describe input format here.
|
||||
// if a mesh is taken as input, the client must manage the memory
|
||||
// if a mesh is given as output, please use the provided
|
||||
// function to free the allocated memory.
|
||||
struct CorkTriMesh
|
||||
{
|
||||
uint n_triangles;
|
||||
uint n_vertices;
|
||||
uint *triangles;
|
||||
float *vertices;
|
||||
};
|
||||
|
||||
// the inputs to a Boolean operation must be "solid":
|
||||
// - closed (aka. watertight;
|
||||
// every edge has an even number of incident triangles)
|
||||
void freeCorkTriMesh(CorkTriMesh *mesh);
|
||||
|
||||
// the inputs to Boolean operations must be "solid":
|
||||
// - closed (aka. watertight; see comment at bottom)
|
||||
// - non-self-intersecting
|
||||
// - have consistent CCW triangle orientation
|
||||
// This function will test whether or not a given mesh is solid
|
||||
bool isSolid(
|
||||
uint n_triangles, uint *triangles,
|
||||
uint n_vertices, float *vertices
|
||||
);
|
||||
// additionally, inputs should use a counter-clockwise convention
|
||||
// for triangle facing. If the triangles are presented in clockwise
|
||||
// orientation, the object is interpreted as its unbounded complement
|
||||
|
||||
// This function will test whether or not a mesh is solid
|
||||
bool isSolid(CorkTriMesh mesh);
|
||||
|
||||
// Boolean operations follow
|
||||
// result = A U B
|
||||
void computeUnion(
|
||||
// input mesh 0
|
||||
uint n_triangles_in0, uint *triangles_in0,
|
||||
uint n_vertices_in0, float *vertices_in0,
|
||||
// input mesh 1
|
||||
uint n_triangles_in1, uint *triangles_in1,
|
||||
uint n_vertices_in1, float *vertices_in1,
|
||||
// output mesh
|
||||
uint *n_triangles_out, uint **triangles_out,
|
||||
uint *n_vertices_out, float **vertices_out
|
||||
);
|
||||
void computeUnion(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out);
|
||||
|
||||
// result = A - B
|
||||
void computeDifference(
|
||||
// input mesh 0
|
||||
uint n_triangles_in0, uint *triangles_in0,
|
||||
uint n_vertices_in0, float *vertices_in0,
|
||||
// input mesh 1
|
||||
uint n_triangles_in1, uint *triangles_in1,
|
||||
uint n_vertices_in1, float *vertices_in1,
|
||||
// output mesh
|
||||
uint *n_triangles_out, uint **triangles_out,
|
||||
uint *n_vertices_out, float **vertices_out
|
||||
);
|
||||
void computeDifference(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out);
|
||||
|
||||
// result = A ^ B
|
||||
void computeIntersection(
|
||||
// input mesh 0
|
||||
uint n_triangles_in0, uint *triangles_in0,
|
||||
uint n_vertices_in0, float *vertices_in0,
|
||||
// input mesh 1
|
||||
uint n_triangles_in1, uint *triangles_in1,
|
||||
uint n_vertices_in1, float *vertices_in1,
|
||||
// output mesh
|
||||
uint *n_triangles_out, uint **triangles_out,
|
||||
uint *n_vertices_out, float **vertices_out
|
||||
);
|
||||
void computeIntersection(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out);
|
||||
|
||||
// result = A XOR B
|
||||
void computeSymmetricDifference(
|
||||
// input mesh 0
|
||||
uint n_triangles_in0, uint *triangles_in0,
|
||||
uint n_vertices_in0, float *vertices_in0,
|
||||
// input mesh 1
|
||||
uint n_triangles_in1, uint *triangles_in1,
|
||||
uint n_vertices_in1, float *vertices_in1,
|
||||
// output mesh
|
||||
uint *n_triangles_out, uint **triangles_out,
|
||||
uint *n_vertices_out, float **vertices_out
|
||||
);
|
||||
CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out);
|
||||
|
||||
// An operation which is not a Boolean operation, but is related:
|
||||
// Not a Boolean operation, but related:
|
||||
// No portion of either surface is deleted. However, the
|
||||
// curve of intersection between the two surfaces is made explicit,
|
||||
// such that the two surfaces are now connected.
|
||||
void resolveIntersections(
|
||||
// input mesh 0
|
||||
uint n_triangles_in0, uint *triangles_in0,
|
||||
uint n_vertices_in0, float *vertices_in0,
|
||||
// input mesh 1
|
||||
uint n_triangles_in1, uint *triangles_in1,
|
||||
uint n_vertices_in1, float *vertices_in1,
|
||||
// output mesh
|
||||
uint *n_triangles_out, uint **triangles_out,
|
||||
uint *n_vertices_out, float **vertices_out
|
||||
);
|
||||
void resolveIntersections(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out);
|
||||
|
||||
|
||||
+67
-77
@@ -43,55 +43,49 @@ using std::ostream;
|
||||
#include "cork.h"
|
||||
|
||||
|
||||
void file2cmesh(
|
||||
const Files::FileMesh &in,
|
||||
uint *n_triangles_out, uint **triangles_out,
|
||||
uint *n_vertices_out, float **vertices_out
|
||||
void file2corktrimesh(
|
||||
const Files::FileMesh &in, CorkTriMesh *out
|
||||
) {
|
||||
*n_vertices_out = in.vertices.size();
|
||||
*n_triangles_out = in.triangles.size();
|
||||
out->n_vertices = in.vertices.size();
|
||||
out->n_triangles = in.triangles.size();
|
||||
|
||||
*triangles_out = new uint[(*n_triangles_out) * 3];
|
||||
*vertices_out = new float[(*n_vertices_out) * 3];
|
||||
out->triangles = new uint[(out->n_triangles) * 3];
|
||||
out->vertices = new float[(out->n_vertices) * 3];
|
||||
|
||||
for(uint i=0; i<*n_triangles_out; i++) {
|
||||
(*triangles_out)[3*i+0] = in.triangles[i].a;
|
||||
(*triangles_out)[3*i+1] = in.triangles[i].b;
|
||||
(*triangles_out)[3*i+2] = in.triangles[i].c;
|
||||
for(uint i=0; i<out->n_triangles; i++) {
|
||||
(out->triangles)[3*i+0] = in.triangles[i].a;
|
||||
(out->triangles)[3*i+1] = in.triangles[i].b;
|
||||
(out->triangles)[3*i+2] = in.triangles[i].c;
|
||||
}
|
||||
|
||||
for(uint i=0; i<*n_vertices_out; i++) {
|
||||
(*vertices_out)[3*i+0] = in.vertices[i].pos.x;
|
||||
(*vertices_out)[3*i+1] = in.vertices[i].pos.y;
|
||||
(*vertices_out)[3*i+2] = in.vertices[i].pos.z;
|
||||
for(uint i=0; i<out->n_vertices; i++) {
|
||||
(out->vertices)[3*i+0] = in.vertices[i].pos.x;
|
||||
(out->vertices)[3*i+1] = in.vertices[i].pos.y;
|
||||
(out->vertices)[3*i+2] = in.vertices[i].pos.z;
|
||||
}
|
||||
}
|
||||
|
||||
void cmesh2file(
|
||||
uint n_triangles_in, uint *triangles_in,
|
||||
uint n_vertices_in, float *vertices_in,
|
||||
Files::FileMesh &out
|
||||
void corktrimesh2file(
|
||||
CorkTriMesh in, Files::FileMesh &out
|
||||
) {
|
||||
out.vertices.resize(n_vertices_in);
|
||||
out.triangles.resize(n_triangles_in);
|
||||
out.vertices.resize(in.n_vertices);
|
||||
out.triangles.resize(in.n_triangles);
|
||||
|
||||
for(uint i=0; i<n_triangles_in; i++) {
|
||||
out.triangles[i].a = triangles_in[3*i+0];
|
||||
out.triangles[i].b = triangles_in[3*i+1];
|
||||
out.triangles[i].c = triangles_in[3*i+2];
|
||||
for(uint i=0; i<in.n_triangles; i++) {
|
||||
out.triangles[i].a = in.triangles[3*i+0];
|
||||
out.triangles[i].b = in.triangles[3*i+1];
|
||||
out.triangles[i].c = in.triangles[3*i+2];
|
||||
}
|
||||
|
||||
for(uint i=0; i<n_vertices_in; i++) {
|
||||
out.vertices[i].pos.x = vertices_in[3*i+0];
|
||||
out.vertices[i].pos.y = vertices_in[3*i+1];
|
||||
out.vertices[i].pos.z = vertices_in[3*i+2];
|
||||
for(uint i=0; i<in.n_vertices; i++) {
|
||||
out.vertices[i].pos.x = in.vertices[3*i+0];
|
||||
out.vertices[i].pos.y = in.vertices[3*i+1];
|
||||
out.vertices[i].pos.z = in.vertices[3*i+2];
|
||||
}
|
||||
}
|
||||
|
||||
void loadMesh(string filename,
|
||||
uint *n_triangles_out, uint **triangles_out,
|
||||
uint *n_vertices_out, float **vertices_out
|
||||
) {
|
||||
void loadMesh(string filename, CorkTriMesh *out)
|
||||
{
|
||||
Files::FileMesh filemesh;
|
||||
|
||||
if(Files::readTriMesh(filename, &filemesh) > 0) {
|
||||
@@ -99,22 +93,13 @@ void loadMesh(string filename,
|
||||
exit(1);
|
||||
}
|
||||
|
||||
file2cmesh(filemesh,
|
||||
n_triangles_out, triangles_out,
|
||||
n_vertices_out, vertices_out
|
||||
);
|
||||
file2corktrimesh(filemesh, out);
|
||||
}
|
||||
void saveMesh(string filename,
|
||||
uint n_triangles_in, uint *triangles_in,
|
||||
uint n_vertices_in, float *vertices_in
|
||||
) {
|
||||
void saveMesh(string filename, CorkTriMesh in)
|
||||
{
|
||||
Files::FileMesh filemesh;
|
||||
|
||||
cmesh2file(
|
||||
n_triangles_in, triangles_in,
|
||||
n_vertices_in, vertices_in,
|
||||
filemesh
|
||||
);
|
||||
corktrimesh2file(in, filemesh);
|
||||
|
||||
if(Files::writeTriMesh(filename, &filemesh) > 0) {
|
||||
cerr << "Unable to write to " << filename << endl;
|
||||
@@ -222,51 +207,37 @@ std::function< void(
|
||||
const std::vector<string>::iterator &
|
||||
) >
|
||||
genericBinaryOp(
|
||||
std::function< void(
|
||||
// input mesh 0
|
||||
uint n_triangles_in0, uint *triangles_in0,
|
||||
uint n_vertices_in0, float *vertices_in0,
|
||||
// input mesh 1
|
||||
uint n_triangles_in1, uint *triangles_in1,
|
||||
uint n_vertices_in1, float *vertices_in1,
|
||||
// output mesh
|
||||
uint *n_triangles_out, uint **triangles_out,
|
||||
uint *n_vertices_out, float **vertices_out
|
||||
) > binop
|
||||
std::function< void(CorkTriMesh in0, CorkTriMesh in1, CorkTriMesh *out) >
|
||||
binop
|
||||
) {
|
||||
return [binop]
|
||||
(std::vector<string>::iterator &args,
|
||||
const std::vector<string>::iterator &end) {
|
||||
// data...
|
||||
uint nTri0, nTri1, nTriOut;
|
||||
uint nVert0, nVert1, nVertOut;
|
||||
uint *tri0, *tri1, *triOut;
|
||||
float *vert0, *vert1, *vertOut;
|
||||
CorkTriMesh in0;
|
||||
CorkTriMesh in1;
|
||||
CorkTriMesh out;
|
||||
|
||||
if(args == end) { cerr << "too few args" << endl; exit(1); }
|
||||
loadMesh(*args, &nTri0, &tri0, &nVert0, &vert0);
|
||||
loadMesh(*args, &in0);
|
||||
args++;
|
||||
|
||||
if(args == end) { cerr << "too few args" << endl; exit(1); }
|
||||
loadMesh(*args, &nTri1, &tri1, &nVert1, &vert1);
|
||||
loadMesh(*args, &in1);
|
||||
args++;
|
||||
|
||||
binop(
|
||||
nTri0, tri0, nVert0, vert0,
|
||||
nTri1, tri1, nVert1, vert1,
|
||||
&nTriOut, &triOut, &nVertOut, &vertOut
|
||||
);
|
||||
binop(in0, in1, &out);
|
||||
|
||||
if(args == end) { cerr << "too few args" << endl; exit(1); }
|
||||
saveMesh(*args, nTriOut, triOut, nVertOut, vertOut);
|
||||
saveMesh(*args, out);
|
||||
args++;
|
||||
|
||||
delete [] tri0;
|
||||
delete [] tri1;
|
||||
delete [] triOut;
|
||||
delete [] vert0;
|
||||
delete [] vert1;
|
||||
delete [] vertOut;
|
||||
freeCorkTriMesh(&out);
|
||||
|
||||
delete[] in0.vertices;
|
||||
delete[] in0.triangles;
|
||||
delete[] in1.vertices;
|
||||
delete[] in1.triangles;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -293,6 +264,25 @@ int main(int argc, char *argv[])
|
||||
CmdList cmds;
|
||||
|
||||
// add cmds
|
||||
cmds.regCmd("solid",
|
||||
"-solid in Determine whether the input mesh represents\n"
|
||||
" a solid object. (aka. watertight) (technically\n"
|
||||
" solid == closed and non-self-intersecting)",
|
||||
[](std::vector<string>::iterator &args,
|
||||
const std::vector<string>::iterator &end) {
|
||||
CorkTriMesh in;
|
||||
if(args == end) { cerr << "too few args" << endl; exit(1); }
|
||||
string filename = *args;
|
||||
loadMesh(*args, &in);
|
||||
args++;
|
||||
|
||||
bool solid = isSolid(in);
|
||||
cout << "The mesh " << filename << " is: " << endl;
|
||||
cout << " " << ((solid)? "SOLID" : "NOT SOLID") << endl;
|
||||
|
||||
delete[] in.vertices;
|
||||
delete[] in.triangles;
|
||||
});
|
||||
cmds.regCmd("union",
|
||||
"-union in0 in1 out Compute the Boolean union of in0 and in1,\n"
|
||||
" and output the result",
|
||||
@@ -308,7 +298,7 @@ int main(int argc, char *argv[])
|
||||
cmds.regCmd("xor",
|
||||
"-xor in0 in1 out Compute the Boolean XOR of in0 and in1,\n"
|
||||
" and output the result\n"
|
||||
" (aka. the symmetric difference)\n",
|
||||
" (aka. the symmetric difference)",
|
||||
genericBinaryOp(computeSymmetricDifference));
|
||||
cmds.regCmd("resolve",
|
||||
"-resolve in0 in1 out Intersect the two meshes in0 and in1,\n"
|
||||
|
||||
@@ -184,6 +184,8 @@ public:
|
||||
std::function<void(TriData &,
|
||||
VertData &, VertData &, VertData &)> func);
|
||||
|
||||
// checks if the mesh is closed
|
||||
bool isClosed();
|
||||
|
||||
public: // REMESHING module
|
||||
// REQUIRES:
|
||||
@@ -194,6 +196,7 @@ public: // REMESHING module
|
||||
|
||||
public: // ISCT (intersections) module
|
||||
void resolveIntersections(); // makes all intersections explicit
|
||||
bool isSelfIntersecting(); // is the mesh self-intersecting?
|
||||
// TESTING
|
||||
void testingComputeStaticIsctPoints(std::vector<Vec3d> *points);
|
||||
void testingComputeStaticIsct(std::vector<Vec3d> *points,
|
||||
|
||||
@@ -789,6 +789,8 @@ public:
|
||||
// create edges as necessary...
|
||||
}*/
|
||||
|
||||
bool hasIntersections(); // test for iscts, exit if one is found
|
||||
|
||||
void findIntersections();
|
||||
void resolveAllIntersections();
|
||||
private:
|
||||
@@ -1056,6 +1058,29 @@ void Mesh<VertData,TriData>::IsctProblem::findIntersections()
|
||||
});
|
||||
}
|
||||
|
||||
template<class VertData, class TriData>
|
||||
bool Mesh<VertData,TriData>::IsctProblem::hasIntersections()
|
||||
{
|
||||
bool foundIsct = false;
|
||||
Empty3d::degeneracy_count = 0;
|
||||
// Find some edge-triangle intersection point...
|
||||
bvh_edge_tri([&](Eptr eisct, Tptr tisct)->bool{
|
||||
if(checkIsct(eisct,tisct)) {
|
||||
foundIsct = true;
|
||||
return false; // break;
|
||||
}
|
||||
if(Empty3d::degeneracy_count > 0) {
|
||||
return false; // break;
|
||||
}
|
||||
return true; // continue
|
||||
});
|
||||
|
||||
if(Empty3d::degeneracy_count > 0 || foundIsct) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class VertData, class TriData> inline
|
||||
@@ -1471,5 +1496,13 @@ void Mesh<VertData,TriData>::resolveIntersections()
|
||||
//iproblem.print();
|
||||
}
|
||||
|
||||
template<class VertData, class TriData>
|
||||
bool Mesh<VertData,TriData>::isSelfIntersecting()
|
||||
{
|
||||
IsctProblem iproblem(this);
|
||||
|
||||
return iproblem.hasIntersections();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -186,6 +186,34 @@ typename Mesh<VertData,TriData>::Isct
|
||||
|
||||
|
||||
|
||||
template<class VertData, class TriData>
|
||||
bool Mesh<VertData,TriData>::isClosed()
|
||||
{
|
||||
EGraphCache<int> chains = createEGraphCache<int>();
|
||||
// count up how many times each edge is encountered in one
|
||||
// orientation vs. the other
|
||||
for(Tri &tri : tris) {
|
||||
chains(tri.a, tri.b).data ++;
|
||||
chains(tri.b, tri.a).data --;
|
||||
|
||||
chains(tri.b, tri.c).data ++;
|
||||
chains(tri.c, tri.b).data --;
|
||||
|
||||
chains(tri.c, tri.a).data ++;
|
||||
chains(tri.a, tri.c).data --;
|
||||
}
|
||||
// now go through and see if any of these are non-zero
|
||||
bool closed = true;
|
||||
chains.for_each([&](uint i, uint j, EGraphEntry<int> &entry) {
|
||||
if(entry.data != 0)
|
||||
closed = false;
|
||||
});
|
||||
return closed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static inline
|
||||
bool contains(const ShortVec<uint, 8> &list, uint item)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user