Skip to content

Commit

Permalink
Property output (#290)
Browse files Browse the repository at this point in the history
* first pass, boolean math needs refactor to work

* refactored property interpolation

* finished edge_op update

* updated sort

* updated MeshGL

* meshGL -> manifold

* existing tests pass

* prod CI

* fixed floating point error

* construct MeshGL from Mesh

* size fix

* added basic testing

* added property refinement test

* added property boolean test

* bug fix?

* fixed tolerance chacking

* fixed segfault

* fixed more bugs

* fixed mod bug

* basic properties tests passing

* added test

* fixed shared properties

* fixed duplicate merge entries

* compacting property verts

* tightened tests, fixed bug

* added MeshGL export

* fixed more bugs

* fixed coplanar tests

* removed old mesh relation from tests

* fixed property output, but still have extra propVerts

* removed barycentric from MeshRelation

* rename BaryRef to TriRef

* refactored boolean property creation

* moved GetBarycentric back out of the public API

* CreateProperties handles continuous and discontinuous properties

* avoid nan

* widened testing precision

* Update manifoldc to MeshGL breaking changes (#306)

* Update manifoldc to MeshGL breaking changes

* Update to latest MeshRelation/TriRef changes

* updated WASM bindings

* attempt at updating three.js example

* updated JS

* fixed examples

Co-authored-by: Geoff deRosenroll <geoffderosenroll@gmail.com>
  • Loading branch information
elalish and geoffder authored Jan 22, 2023
1 parent a701d2b commit 422c7f2
Show file tree
Hide file tree
Showing 31 changed files with 1,711 additions and 1,230 deletions.
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
"editor.formatOnSave": true,
"cmake.configureArgs": [
"-DBUILD_SHARED_LIBS=ON",
"-DMANIFOLD_EXPORT=OFF",
"-DMANIFOLD_EXPORT=ON",
"-DMANIFOLD_DEBUG=ON",
"-DMANIFOLD_USE_CUDA=OFF",
"-DMANIFOLD_PAR=NONE",
Expand All @@ -120,8 +120,12 @@
"editor.detectIndentation": false,
"cSpell.words": [
"Bary",
"csaszar",
"Gyroid",
"halfedge",
"halfedges",
"Tris",
"Verts"
],
"javascript.format.semicolons": "insert",
}
1 change: 1 addition & 0 deletions bindings/c/include/conv.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <public.h>
#include <sdf.h>
#include <types.h>

ManifoldManifold *to_c(manifold::Manifold *m);
ManifoldSimplePolygon *to_c(manifold::SimplePolygon *p);
ManifoldPolygons *to_c(manifold::Polygons *ps);
Expand Down
20 changes: 11 additions & 9 deletions bindings/c/include/manifoldc.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,9 @@ int manifold_original_id(ManifoldManifold *m);
// Mesh Relation
ManifoldMeshRelation *manifold_get_mesh_relation(void *mem,
ManifoldManifold *m);
size_t manifold_mesh_relation_barycentric_length(ManifoldMeshRelation *m);
ManifoldVec3 *manifold_mesh_relation_barycentric(void *mem,
ManifoldMeshRelation *m);
size_t manifold_mesh_relation_tri_bary_length(ManifoldMeshRelation *m);
ManifoldBaryRef *manifold_mesh_relation_tri_bary(void *mem,
ManifoldMeshRelation *m);
size_t manifold_mesh_relation_tri_ref_length(ManifoldMeshRelation *m);
ManifoldTriRef *manifold_mesh_relation_tri_ref(void *mem,
ManifoldMeshRelation *m);

// Bounding Box
ManifoldBox *manifold_box(void *mem, float x1, float y1, float z1, float x2,
Expand Down Expand Up @@ -180,13 +177,18 @@ ManifoldVec4 *manifold_mesh_halfedge_tangent(void *mem, ManifoldMesh *m);

ManifoldMeshGL *manifold_get_meshgl(void *mem, ManifoldManifold *m);
ManifoldMeshGL *manifold_meshgl_copy(void *mem, ManifoldMeshGL *m);
size_t manifold_meshgl_vert_length(ManifoldMeshGL *m);
int manifold_meshgl_num_prop(ManifoldMeshGL *m);
int manifold_meshgl_num_vert(ManifoldMeshGL *m);
int manifold_meshgl_num_tri(ManifoldMeshGL *m);
size_t manifold_meshgl_vert_properties_length(ManifoldMeshGL *m);
size_t manifold_meshgl_tri_length(ManifoldMeshGL *m);
size_t manifold_meshgl_normal_length(ManifoldMeshGL *m);
size_t manifold_meshgl_merge_length(ManifoldMeshGL *m);
size_t manifold_meshgl_tangent_length(ManifoldMeshGL *m);
float *manifold_meshgl_vert_pos(void *mem, ManifoldMeshGL *m);
float *manifold_meshgl_vert_properties(void *mem, ManifoldMeshGL *m);
uint32_t *manifold_meshgl_tri_verts(void *mem, ManifoldMeshGL *m);
float *manifold_meshgl_vert_normal(void *mem, ManifoldMeshGL *m);
uint32_t *manifold_meshgl_merge_from_vert(void *mem, ManifoldMeshGL *m);
uint32_t *manifold_meshgl_merge_to_vert(void *mem, ManifoldMeshGL *m);
float *manifold_meshgl_halfedge_tangent(void *mem, ManifoldMeshGL *m);

// MeshIO / Export
Expand Down
5 changes: 2 additions & 3 deletions bindings/c/include/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,11 @@ typedef struct ManifoldPolyVert {

} ManifoldPolyVert;

typedef struct ManifoldBaryRef {
typedef struct ManifoldTriRef {
int mesh_id;
int original_id;
int tri;
ManifoldIVec3 vert_bary;
} ManifoldBaryRef;
} ManifoldTriRef;

typedef struct ManifoldCurvatureBounds {
float max_mean_curvature;
Expand Down
75 changes: 35 additions & 40 deletions bindings/c/manifoldc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,27 +384,31 @@ ManifoldMeshGL *manifold_meshgl_copy(void *mem, ManifoldMeshGL *m) {
return to_c(new (mem) MeshGL(*from_c(m)));
}

size_t manifold_meshgl_vert_length(ManifoldMeshGL *m) {
return from_c(m)->vertPos.size();
int manifold_meshgl_num_prop(ManifoldMeshGL *m) { return from_c(m)->numProp; }
int manifold_meshgl_num_vert(ManifoldMeshGL *m) { return from_c(m)->NumVert(); }
int manifold_meshgl_num_tri(ManifoldMeshGL *m) { return from_c(m)->NumTri(); }

size_t manifold_meshgl_vert_properties_length(ManifoldMeshGL *m) {
return from_c(m)->vertProperties.size();
}

size_t manifold_meshgl_tri_length(ManifoldMeshGL *m) {
return from_c(m)->triVerts.size();
}

size_t manifold_meshgl_normal_length(ManifoldMeshGL *m) {
return from_c(m)->vertNormal.size();
size_t manifold_meshgl_merge_length(ManifoldMeshGL *m) {
return from_c(m)->mergeFromVert.size();
}

size_t manifold_meshgl_tangent_length(ManifoldMeshGL *m) {
return from_c(m)->halfedgeTangent.size();
}

float *manifold_meshgl_vert_pos(void *mem, ManifoldMeshGL *m) {
auto vert_pos = from_c(m)->vertPos;
auto len = vert_pos.size();
float *manifold_meshgl_vert_properties(void *mem, ManifoldMeshGL *m) {
auto vert_props = from_c(m)->vertProperties;
auto len = vert_props.size();
float *vs = reinterpret_cast<float *>(mem);
memcpy(vs, vert_pos.data(), sizeof(float) * len);
memcpy(vs, vert_props.data(), sizeof(float) * len);
return vs;
}

Expand All @@ -416,12 +420,20 @@ uint32_t *manifold_meshgl_tri_verts(void *mem, ManifoldMeshGL *m) {
return tris;
}

float *manifold_meshgl_vert_normal(void *mem, ManifoldMeshGL *m) {
auto vert_normal = from_c(m)->vertNormal;
auto len = vert_normal.size();
float *ns = reinterpret_cast<float *>(mem);
memcpy(ns, vert_normal.data(), sizeof(float) * len);
return ns;
uint32_t *manifold_meshgl_merge_from_vert(void *mem, ManifoldMeshGL *m) {
auto merge = from_c(m)->mergeFromVert;
auto len = merge.size();
uint32_t *ms = reinterpret_cast<uint32_t *>(mem);
memcpy(ms, merge.data(), sizeof(uint32_t) * len);
return ms;
}

uint32_t *manifold_meshgl_merge_to_vert(void *mem, ManifoldMeshGL *m) {
auto merge = from_c(m)->mergeToVert;
auto len = merge.size();
uint32_t *ms = reinterpret_cast<uint32_t *>(mem);
memcpy(ms, merge.data(), sizeof(uint32_t) * len);
return ms;
}

float *manifold_meshgl_halfedge_tangent(void *mem, ManifoldMeshGL *m) {
Expand All @@ -447,36 +459,19 @@ ManifoldMeshRelation *manifold_get_mesh_relation(void *mem,
return to_c(new (mem) MeshRelation(relation));
}

size_t manifold_mesh_relation_barycentric_length(ManifoldMeshRelation *m) {
return from_c(m)->barycentric.size();
}

ManifoldVec3 *manifold_mesh_relation_barycentric(void *mem,
ManifoldMeshRelation *m) {
auto barycentric = from_c(m)->barycentric;
auto len = barycentric.size();
ManifoldVec3 *vs = reinterpret_cast<ManifoldVec3 *>(mem);
for (int i = 0; i < len; ++i) {
vs[i] = {barycentric[i].x, barycentric[i].y, barycentric[i].z};
}
return vs;
}

size_t manifold_mesh_relation_tri_bary_length(ManifoldMeshRelation *m) {
return from_c(m)->triBary.size();
size_t manifold_mesh_relation_tri_ref_length(ManifoldMeshRelation *m) {
return from_c(m)->triRef.size();
}

ManifoldBaryRef *manifold_mesh_relation_tri_bary(void *mem,
ManifoldMeshRelation *m) {
auto tri_bary = from_c(m)->triBary;
auto len = tri_bary.size();
ManifoldBaryRef *brs = reinterpret_cast<ManifoldBaryRef *>(mem);
ManifoldTriRef *manifold_mesh_relation_tri_ref(void *mem,
ManifoldMeshRelation *m) {
auto tri_ref = from_c(m)->triRef;
auto len = tri_ref.size();
ManifoldTriRef *ts = reinterpret_cast<ManifoldTriRef *>(mem);
for (int i = 0; i < len; ++i) {
auto tb = tri_bary[i];
auto vb = tb.vertBary;
brs[i] = {tb.meshID, tb.originalID, tb.tri, {vb.x, vb.y, vb.z}};
ts[i] = {tri_ref[i].meshID, tri_ref[i].originalID, tri_ref[i].tri};
}
return brs;
return ts;
}

int manifold_is_empty(ManifoldManifold *m) { return from_c(m)->IsEmpty(); }
Expand Down
94 changes: 47 additions & 47 deletions bindings/python/pymanifold.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,53 +204,53 @@ PYBIND11_MODULE(pymanifold, m) {
":param n: The number of pieces to split every edge into. Must be > "
"1.")
.def("to_mesh", &Manifold::GetMesh)
.def_static("smooth", Manifold::Smooth,

"Constructs a smooth version of the input mesh by creating "
"tangents; this\n"
"method will throw if you have supplied tangents with your "
"mesh already. The\n"
"actual triangle resolution is unchanged; use the Refine() "
"method to\n"
"interpolate to a higher-resolution curve.\n"
"\n"
"By default, every edge is calculated for maximum smoothness "
"(very much\n"
"approximately), attempting to minimize the maximum mean "
"Curvature magnitude.\n"
"No higher-order derivatives are considered, as the "
"interpolation is\n"
"independent per triangle, only sharing constraints on their "
"boundaries.\n"
"\n"
":param mesh: input Mesh.\n"
":param sharpenedEdges: If desired, you can supply a vector "
"of sharpened\n"
"halfedges, which should in general be a small subset of all "
"halfedges. Order\n"
"of entries doesn't matter, as each one specifies the "
"desired smoothness\n"
"(between zero and one, with one the default for all "
"unspecified halfedges)\n"
"and the halfedge index (3 * triangle index + [0,1,2] where "
"0 is the edge\n"
"between triVert 0 and 1, etc).\n"
"\n"
"At a smoothness value of zero, a sharp crease is made. The "
"smoothness is\n"
"interpolated along each edge, so the specified value should "
"be thought of as\n"
"an average. Where exactly two sharpened edges meet at a "
"vertex, their\n"
"tangents are rotated to be colinear so that the sharpened "
"edge can be\n"
"continuous. Vertices with only one sharpened edge are "
"completely smooth,\n"
"allowing sharpened edges to smoothly vanish at termination. "
"A single vertex\n"
"can be sharpened by sharping all edges that are incident on "
"it, allowing\n"
"cones to be formed.")
.def_static(
"smooth", [](const Mesh &mesh) { return Manifold::Smooth(mesh); },
"Constructs a smooth version of the input mesh by creating "
"tangents; this\n"
"method will throw if you have supplied tangents with your "
"mesh already. The\n"
"actual triangle resolution is unchanged; use the Refine() "
"method to\n"
"interpolate to a higher-resolution curve.\n"
"\n"
"By default, every edge is calculated for maximum smoothness "
"(very much\n"
"approximately), attempting to minimize the maximum mean "
"Curvature magnitude.\n"
"No higher-order derivatives are considered, as the "
"interpolation is\n"
"independent per triangle, only sharing constraints on their "
"boundaries.\n"
"\n"
":param mesh: input Mesh.\n"
":param sharpenedEdges: If desired, you can supply a vector "
"of sharpened\n"
"halfedges, which should in general be a small subset of all "
"halfedges. Order\n"
"of entries doesn't matter, as each one specifies the "
"desired smoothness\n"
"(between zero and one, with one the default for all "
"unspecified halfedges)\n"
"and the halfedge index (3 * triangle index + [0,1,2] where "
"0 is the edge\n"
"between triVert 0 and 1, etc).\n"
"\n"
"At a smoothness value of zero, a sharp crease is made. The "
"smoothness is\n"
"interpolated along each edge, so the specified value should "
"be thought of as\n"
"an average. Where exactly two sharpened edges meet at a "
"vertex, their\n"
"tangents are rotated to be colinear so that the sharpened "
"edge can be\n"
"continuous. Vertices with only one sharpened edge are "
"completely smooth,\n"
"allowing sharpened edges to smoothly vanish at termination. "
"A single vertex\n"
"can be sharpened by sharping all edges that are incident on "
"it, allowing\n"
"cones to be formed.")
.def_static(
"from_mesh", [](const Mesh &mesh) { return Manifold(mesh); },
py::arg("mesh"))
Expand Down
42 changes: 26 additions & 16 deletions bindings/wasm/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,20 @@ val GetMeshJS(const Manifold& manifold) {
MeshGL mesh = manifold.GetMeshGL();
val meshJS = val::object();

meshJS.set("numProp", mesh.numProp);
meshJS.set("triVerts",
val(typed_memory_view(mesh.triVerts.size(), mesh.triVerts.data()))
.call<val>("slice"));
meshJS.set("vertPos",
val(typed_memory_view(mesh.vertPos.size(), mesh.vertPos.data()))
meshJS.set("vertProperties",
val(typed_memory_view(mesh.vertProperties.size(),
mesh.vertProperties.data()))
.call<val>("slice"));
meshJS.set("vertNormal", val(typed_memory_view(mesh.vertNormal.size(),
mesh.vertNormal.data()))
.call<val>("slice"));
meshJS.set("mergeFromVert", val(typed_memory_view(mesh.mergeFromVert.size(),
mesh.mergeFromVert.data()))
.call<val>("slice"));
meshJS.set("mergeToVert", val(typed_memory_view(mesh.mergeToVert.size(),
mesh.mergeToVert.data()))
.call<val>("slice"));
meshJS.set("halfedgeTangent",
val(typed_memory_view(mesh.halfedgeTangent.size(),
mesh.halfedgeTangent.data()))
Expand All @@ -81,10 +86,17 @@ val GetMeshJS(const Manifold& manifold) {

MeshGL MeshJS2GL(const val& mesh) {
MeshGL out;
out.numProp = mesh["numProp"].as<int>();
out.triVerts = convertJSArrayToNumberVector<uint32_t>(mesh["triVerts"]);
out.vertPos = convertJSArrayToNumberVector<float>(mesh["vertPos"]);
if (mesh["vertNormal"] != val::undefined()) {
out.vertNormal = convertJSArrayToNumberVector<float>(mesh["vertNormal"]);
out.vertProperties =
convertJSArrayToNumberVector<float>(mesh["vertProperties"]);
if (mesh["mergeFromVert"] != val::undefined()) {
out.mergeFromVert =
convertJSArrayToNumberVector<uint32_t>(mesh["mergeFromVert"]);
}
if (mesh["mergeToVert"] != val::undefined()) {
out.mergeToVert =
convertJSArrayToNumberVector<uint32_t>(mesh["mergeToVert"]);
}
if (mesh["halfedgeTangent"] != val::undefined()) {
out.halfedgeTangent =
Expand Down Expand Up @@ -175,15 +187,13 @@ EMSCRIPTEN_BINDINGS(whatever) {
.field("surfaceArea", &Properties::surfaceArea)
.field("volume", &Properties::volume);

value_object<BaryRef>("baryRef")
.field("meshID", &BaryRef::meshID)
.field("originalID", &BaryRef::originalID)
.field("tri", &BaryRef::tri)
.field("vertBary", &BaryRef::vertBary);
value_object<TriRef>("baryRef")
.field("meshID", &TriRef::meshID)
.field("originalID", &TriRef::originalID)
.field("tri", &TriRef::tri);

value_object<MeshRelation>("meshRelation")
.field("barycentric", &MeshRelation::barycentric)
.field("triBary", &MeshRelation::triBary);
.field("triRef", &MeshRelation::triRef);

value_object<Curvature>("curvature")
.field("maxMeanCurvature", &Curvature::maxMeanCurvature)
Expand All @@ -200,7 +210,7 @@ EMSCRIPTEN_BINDINGS(whatever) {
register_vector<float>("Vector_f32");
register_vector<Manifold>("Vector_manifold");
register_vector<Smoothness>("Vector_smoothness");
register_vector<BaryRef>("Vector_baryRef");
register_vector<TriRef>("Vector_baryRef");
register_vector<glm::vec4>("Vector_vec4");

class_<Manifold>("Manifold")
Expand Down
Loading

0 comments on commit 422c7f2

Please sign in to comment.