Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add MeshGL64 #927

Merged
merged 7 commits into from
Sep 16, 2024
Merged

add MeshGL64 #927

merged 7 commits into from
Sep 16, 2024

Conversation

pca006132
Copy link
Collaborator

Added MeshGL64 and removed usages of Mesh inside our library. Mesh is not yet removed because we use it extensively in tests, we should soon remove it soon though.

@elalish we have two failures related to refine and smooth though, they are Smooth.ToLength and Samples.Scallop. The stats are different significantly, so perhaps I did something wrong in my refactoring.

Note that we haven't yet exposed MeshGL64 to C and python bindings, I think that can be done later. I did remove Mesh from the C binding.

@pca006132 pca006132 linked an issue Sep 13, 2024 that may be closed by this pull request
@pca006132 pca006132 added this to the v3.0 milestone Sep 13, 2024
@pca006132 pca006132 requested a review from elalish September 13, 2024 13:38
@pca006132
Copy link
Collaborator Author

And it seems that we miss a vertex normal calculation function that write normals to property channels? If I understand it correctly, CalculateNormals calculate face normals.

@pca006132
Copy link
Collaborator Author

and I am thinking maybe we should add some simple iterators to MeshGL so we can easily iterate over vertex positions and tri verts as triples, without changing the memory representation.

@elalish
Copy link
Owner

elalish commented Sep 13, 2024

and I am thinking maybe we should add some simple iterators to MeshGL so we can easily iterate over vertex positions and tri verts as triples, without changing the memory representation.

Yeah, good idea. That fits with the helper functions we put in the WASM bindings too.

Copy link
Owner

@elalish elalish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great!

scallop.triVerts.push_back({0, 2 + i, 2 + j});
scallop.triVerts.insert(
scallop.triVerts.end(),
{0, static_cast<uint32_t>(2 + i), static_cast<uint32_t>(2 + j)});
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we skip the casting if we just define i and j as uint32_t?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It depends if we need signed results for other things that depend on i and j, iirc there are results that can be negative before this line?


if (meshGL.runOriginalID.empty()) {
// FIXME: should we do this?
meshRelation_.originalID = Impl::ReserveIDs(1);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, it does seem to conflict with the statement at the end of the function. Does anything break if you remove it? I should probably think through the cases here...

}
tri[j] = prop2vert[vert];
// FIXME: do we need this check?
if (tri[j] < 0 || tri[j] >= static_cast<int>(numVert)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, looks like that's already checked above.

ivec3 tri;
for (const size_t j : {0, 1, 2}) {
const int vert = meshGL.triVerts[3 * i + j];
if (vert < 0 || vert >= static_cast<int>(numVert)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid the cast by declaring vert as size_t?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably yes

@pca006132
Copy link
Collaborator Author

Btw, MeshGLP is just a random naming, feel free to suggest another if you think of something better.

@pca006132
Copy link
Collaborator Author

And it seems that we miss a vertex normal calculation function that write normals to property channels? If I understand it correctly, CalculateNormals calculate face normals.

@elalish btw what about this? Am I overlooking some API or we should add this?

@pca006132
Copy link
Collaborator Author

For Smooth.ToLength, if we switch to using Smooth with a Mesh, it works:

diff --git a/test/smooth_test.cpp b/test/smooth_test.cpp
index 8d11dd89..88efcba1 100644
--- a/test/smooth_test.cpp
+++ b/test/smooth_test.cpp
@@ -109,7 +109,7 @@ TEST(Smooth, ToLength) {
       CrossSection::Circle(10, 10).Translate({10, 0}).ToPolygons(), 2, 0, 0,
       {0, 0});
   cone += cone.Scale({1, 1, -5});
-  Manifold smooth = Manifold::Smooth(cone.GetMeshGL64());
+  Manifold smooth = Manifold::Smooth(cone.GetMesh());
   smooth = smooth.RefineToLength(0.1);
   ExpectMeshes(smooth, {{85250, 170496}});
   auto prop = smooth.GetProperties();

So maybe the mesh is not being simplified due to not being original, and it is somehow giving a different volume?
The weird thing though is that the volume difference is pretty large:

The difference between prop.volume and 4604 is 77.845313791107401, which exceeds 1, where
prop.volume evaluates to 4526.1546862088926,
4604 evaluates to 4604, and
1 evaluates to 1.

@pca006132
Copy link
Collaborator Author

OK looking at the outputs it seems that they are indeed very different:

The expected one:
image

The current one with MeshGL:
image

It is like getting punched in the face XD

Copy link
Owner

@elalish elalish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for CalculateNormals, I realize now it's a bit confusing since we have both a Manifold and an Impl method with that name that don't do the same thing. We should rename the Impl one - it calculates both face and vertex normals, but just the simple internal versions. The public method does much more complicated vertex normal calculations that are put into the public property channels.

So, I don't think we're missing anything. Certainly some tests should fail if we are.

@elalish
Copy link
Owner

elalish commented Sep 14, 2024

I'm pretty certain the issue with Smooth.ToLength is that certain triangle pairs used to be found to be coplanar and treated as quads for smoothing, but now they are not. Would be good to know if it's some kind of precision error or something else. AsOriginal may fix it, but I'd like to understand why it's behaving differently in the first place. Take a look at the faceIDs right after CreateFaces runs to see the difference.

Should we mark the test as broken for now? I think this issue is not related to MeshGL/MeshGL64 in general?

@pca006132
Copy link
Collaborator Author

So, I don't think we're missing anything. Certainly some tests should fail if we are.

Oh, I don't mean we miss some calculation, I just mean there is no simple way to get vertex normal with MeshGL and it makes it hard to get rid of Mesh in our tests.

Copy link

codecov bot commented Sep 15, 2024

Codecov Report

Attention: Patch coverage is 92.04152% with 23 lines in your changes missing coverage. Please review.

Project coverage is 88.33%. Comparing base (d437097) to head (6cdbd95).
Report is 93 commits behind head on master.

Files with missing lines Patch % Lines
src/manifold/src/impl.h 91.48% 8 Missing ⚠️
src/manifold/src/manifold.cpp 86.88% 8 Missing ⚠️
src/manifold/src/sort.cpp 91.66% 5 Missing ⚠️
src/manifold/include/manifold/manifold.h 80.00% 1 Missing ⚠️
test/test_main.cpp 95.65% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #927      +/-   ##
==========================================
- Coverage   91.84%   88.33%   -3.51%     
==========================================
  Files          37       62      +25     
  Lines        4976     8670    +3694     
  Branches        0     1049    +1049     
==========================================
+ Hits         4570     7659    +3089     
- Misses        406     1011     +605     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Owner

@elalish elalish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just mean there is no simple way to get vertex normal with MeshGL and it makes it hard to get rid of Mesh in our tests.

Interesting - which tests is this making difficult? I can take a look at refactoring them.


#define IGNORE_DEPRECATED_BEGIN \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is cool, but should we just go ahead and remove Mesh for v3.0? It would be a lot less maintenance burden.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true

@pca006132
Copy link
Collaborator Author

Interesting - which tests is this making difficult? I can take a look at refactoring them.

In general, WithNormals, ExpectMeshes, CheckNormals in test_main.cpp, as well as Manifold.Normals.

And I also reverted the deprecated commit, that is a bit hard to get right on all platforms (e.g. clang 18 has a bug that breaks pragma diagnostic push.

@pca006132 pca006132 force-pushed the meshgl64 branch 2 times, most recently from edaaece to fb7a6ae Compare September 15, 2024 10:02
@pca006132
Copy link
Collaborator Author

@elalish so should I just disable the failed test xase and merge this?

@@ -111,8 +109,7 @@ TEST(Smooth, ToLength) {
CrossSection::Circle(10, 10).Translate({10, 0}).ToPolygons(), 2, 0, 0,
{0, 0});
cone += cone.Scale({1, 1, -5});
Manifold smooth = Manifold::Smooth(cone.GetMesh());
smooth = smooth.RefineToLength(0.1);
Manifold smooth = cone.AsOriginal().SmoothOut(180).RefineToLength(0.1);
Copy link
Owner

@elalish elalish Sep 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I fixed it with AsOriginal and I think I understand why - our old Mesh didn't keep track of IDs, which allowed those faces to become quads, but MeshGL keeps more info. I think this is fine.

Copy link
Owner

@elalish elalish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks!

@pca006132 pca006132 merged commit 22c6605 into elalish:master Sep 16, 2024
22 checks passed
@pca006132 pca006132 deleted the meshgl64 branch September 16, 2024 04:36
@elalish
Copy link
Owner

elalish commented Sep 16, 2024

Hmm, I should have asked - did you add any tests of MeshGL64? Not that it's likely to behave much differently, but at least one that tests, say, the difference of round-trip precision between MeshGL and MeshGL64? Fodder for a follow-on.

@pca006132
Copy link
Collaborator Author

Yeah, we should definitely add some tests for MeshGL64. I think I used it sparingly for some tests, but it is kind of random (depends on my mood) and only a few of them uses MeshGL64.

@elalish elalish mentioned this pull request Nov 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add MeshGL64
2 participants