Skip to content

Add C-binding functions to access the normalIdx parameter of GetMeshGL/GetMeshGL64#1494

Merged
elalish merged 6 commits into
elalish:masterfrom
WNP78:master
Jan 30, 2026
Merged

Add C-binding functions to access the normalIdx parameter of GetMeshGL/GetMeshGL64#1494
elalish merged 6 commits into
elalish:masterfrom
WNP78:master

Conversation

@WNP78

@WNP78 WNP78 commented Jan 19, 2026

Copy link
Copy Markdown
Contributor

This functionality was not previously accessible via the C API and can be exposed via two new functions. Only new functions are added and no existing functions were changed, to not break FFI compatibility. Names chosen were manifold_get_meshgl_w_normals and manifold_get_meshgl64_w_normals, to match the naming established by manifold_meshgl64_w_tangents. I am unaware of any documentation for the C api but if this exists I can update it too.

@codecov

codecov Bot commented Jan 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.05%. Comparing base (301c165) to head (7825767).
⚠️ Report is 7 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1494      +/-   ##
==========================================
+ Coverage   91.79%   92.05%   +0.25%     
==========================================
  Files          35       35              
  Lines        6023     6039      +16     
==========================================
+ Hits         5529     5559      +30     
+ Misses        494      480      -14     

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@WNP78

WNP78 commented Jan 19, 2026

Copy link
Copy Markdown
Contributor Author

I'm also looking at a way to write to MeshGLP.runIndex and MeshGLP.runOriginalID, as well as mergeFromVert and mergeToVert through the C API - they are read only currently. Not sure whether to add it as an option on construction, or make functions to mutate them on an existing instance. Other similar properties (e.g. halfedgeTangent) seem to be set in constructor variants, but with tangents plus both optional "run" collections plus the merge collections (which should be provided both or none), plus the MeshGL/MeshGL64 split, it would turn into a bit of a combinatorial mess with 16 or 32 constructor options to cover, depending on if you consider run index + original ID as a unit.

So I wonder if it would be best to just add e.g:

void manifold_meshgl_set_run_index(ManifoldMeshGL* m, uint32_t* runIndex, size_t length);
void manifold_meshgl_set_run_original_id(ManifoldMeshGL* m, uint32_t* runOriginalID, size_t length);
void manifold_meshgl_set_merge_verts(ManifoldMeshGL* m, uint32_t* mergeFromVert, uint32_t* mergeToVert, size_t length);

(plus accompanying meshgl64 versions, which would be identical)

I don't know how strict the semantics on the C api are so I'd like your thoughts on this one

@pca006132

Copy link
Copy Markdown
Collaborator

I don't have much opinion about this, it sounds ok to me. @geoffder what do you think?

@elalish

elalish commented Jan 19, 2026

Copy link
Copy Markdown
Owner

Could we make a manifold_meshgl constructor that takes a struct instead to effectively get default arguments?

@WNP78

WNP78 commented Jan 19, 2026

Copy link
Copy Markdown
Contributor Author

Could we make a manifold_meshgl constructor that takes a struct instead to effectively get default arguments?

In this case I assume non-set optional fields would just be left as null pointers, so it's not super different from just adding a big constructor function with all the options in it and allowing nullptr arguments, other than the conciseness of the API although I don't know how many people are actualy using the C API directly without some sort of binding.

I can implement that either way on this PR or open a separate one if you want

@WNP78

WNP78 commented Jan 21, 2026

Copy link
Copy Markdown
Contributor Author

@elalish I did an implementation with a struct here, let me know if you want me to merge it into this PR or make a separate one

@elalish

elalish commented Jan 21, 2026

Copy link
Copy Markdown
Owner

Yeah, I think your struct version looks good. I like this because it's both more convenient to use, and it's easy for us to extend without breaking the API. Let's merge it in here.

@WNP78

WNP78 commented Jan 21, 2026

Copy link
Copy Markdown
Contributor Author

Yeah, I think your struct version looks good. I like this because it's both more convenient to use, and it's easy for us to extend without breaking the API. Let's merge it in here.

I'll merge it in here, although I would note that if the struct was extended in the future this could be potentially breaking if a newer dll is used with a program that was compiled for the pre-extension struct, since the API consumer is going to be allocating the options struct at the old smaller size, and the C-bindings would then read past it into undefined memory.

@elalish

elalish commented Jan 21, 2026

Copy link
Copy Markdown
Owner

Ugh, I hate C. I really hope that's not a use case - trying to upgrade a dependency without recompiling? What if we changed the order of an enum or something? Feels very fragile...

@WNP78

WNP78 commented Jan 26, 2026

Copy link
Copy Markdown
Contributor Author

Ugh, I hate C. I really hope that's not a use case - trying to upgrade a dependency without recompiling? What if we changed the order of an enum or something? Feels very fragile...

To be honest, I don't think that ABI compatibility is essential if you ship the bindings with headers, unless it's something that you guarantee. If you want to be extra sure I could add a function to get the size of the options struct, so that programs can armour against it growing in the future.

@elalish elalish left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks! Just a couple small things.

uint32_t* merge_from_vert;
uint32_t* merge_to_vert;
size_t merge_verts_length;
float* halfedge_tangents;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Do these need default values so that one doesn't have to specify all of them?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

IIRC C doesn't have default values. One way is to provide a function that returns the default value of the struct.

size_t n_verts, size_t n_props,
uint32_t* tri_verts, size_t n_tris,
float* halfedge_tangent);
ManifoldMeshGL* manifold_meshgl_w_options(void* mem, float* vert_props,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

with this function there's no longer a need for manifold_meshgl_w_tangents. I'm tempted to just remove it, but I suppose deprecating would be better.

@elalish elalish merged commit 8b27763 into elalish:master Jan 30, 2026
36 checks passed
@pca006132 pca006132 mentioned this pull request Feb 26, 2026
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.

3 participants