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

adding python set_properties #504

Merged
merged 3 commits into from
Jul 30, 2023
Merged

adding python set_properties #504

merged 3 commits into from
Jul 30, 2023

Conversation

elalish
Copy link
Owner

@elalish elalish commented Jul 26, 2023

Adding our colored Menger Sponge example to verify that mesh properties are working properly. I'll also update our trimesh usage to write a colored GLB.

@elalish elalish self-assigned this Jul 26, 2023
glm::vec3 v,
const float *oldProps) {
f(py::array(newNumProp, newProps), std::make_tuple(v.x, v.y, v.z),
py::array(oldNumProp, oldProps));
Copy link
Owner Author

Choose a reason for hiding this comment

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

I'm getting a compile error here that I don't understand. Am I missing something?

@elalish elalish requested a review from pca006132 July 26, 2023 16:18
@pca006132
Copy link
Collaborator

pca006132 commented Jul 26, 2023

I guess I understand the problem here, but this is not a simple issue to solve. I think the best way would be to change the python API for set_properties (and warp as well) due to fundamental issue with lifetime management and efficiency concerns.

The problem here is that py::array will and must perform copying when we give it a pointer, so the performance is slow due to many allocations and we need to copy the changes back.
Buffer protocol can allow us to give the raw buffer to python directly, but lifetime management would be a pain: we need to avoid deallocating the original vector until the buffer is released, and this requires reference counting. Also, the performance of calling a python function thousands of times is probably not great, comparing with using numpy to manipulate a large buffer directly.

I think the simplest way would be to pass a large buffer to python (requires large copying), get the return value and copy it back to c++. This requires 2 copy operations, but avoids calling the slow python function many times, and avoids the lifetime issue.

(sorry for accidentally closing the issue, I am on my phone now)

Also, I just noticed that I should not be using vsplit in the python code, it should be [:, :3].

@pca006132 pca006132 closed this Jul 26, 2023
@pca006132 pca006132 reopened this Jul 26, 2023
@elalish
Copy link
Owner Author

elalish commented Jul 26, 2023

Ugh, that's too bad - I had thought the point of giving py::array a pointer was to avoid copying. I'm surprised that functional binding is so much worse in Python than WASM. I don't really want to expose more internals in our public API just to get around Python's weirdness. What you're saying sounds a lot like GetMeshGL, rebuild vertProperties, then make a new Manifold. Maybe we should just tell people to do that and skip set_properties entirely?

@pca006132
Copy link
Collaborator

No it is not much worse comparing with WASM, we are also doing copying in our js binding or we will have similar issues regarding lifetime. We can do something similar, but I think the performance will likely be bad with Python.

Yeah, I think skipping set_properties is reasonable.

@elalish
Copy link
Owner Author

elalish commented Jul 27, 2023

Hmm, I haven't noticed anything too awful about the performance of Warp or SetProperties on WASM. Of course that's partly because they're pretty simple, O(n) operations. Maybe we should just give this a try and see how big a problem it is? Even if it's 2x slower, it's not a particularly long operation. I'm also curious to what extent the compiler is able to optimize away the copies.

If we did want to make this function work in Python so we could at least test its performance, do you know how?

@pca006132
Copy link
Collaborator

It should be pretty simple, just don't think about avoid copying and you are done, basically just the logic in our js code, but need to convert into python code.

Module.Manifold.prototype.setProperties = function(numProp, func) {
const oldNumProp = this.numProp();
const wasmFuncPtr = addFunction(function(newPtr, vec3Ptr, oldPtr) {
const newProp = [];
for (let i = 0; i < numProp; ++i) {
newProp[i] = getValue(newPtr + 4 * i, 'float');
}
const pos = [];
for (let i = 0; i < 3; ++i) {
pos[i] = getValue(vec3Ptr + 4 * i, 'float');
}
const oldProp = [];
for (let i = 0; i < oldNumProp; ++i) {
oldProp[i] = getValue(oldPtr + 4 * i, 'float');
}
func(newProp, pos, oldProp);
for (let i = 0; i < numProp; ++i) {
setValue(newPtr + 4 * i, newProp[i], 'float');
}
}, 'viii');
const out = this._SetProperties(numProp, wasmFuncPtr);
removeFunction(wasmFuncPtr);
return out;
};

I can only do it this weekend, as I am in the middle of doing something else.

@elalish
Copy link
Owner Author

elalish commented Jul 27, 2023

Okay, sounds good - I'm working on the 3MF export stuff so if you get to it first, you're welcome to it.

@pca006132
Copy link
Collaborator

Finished, and I also updated our trimesh export example to export vertex colors.

@codecov
Copy link

codecov bot commented Jul 29, 2023

Codecov Report

Patch coverage has no change and project coverage change: +0.01% 🎉

Comparison is base (18edefc) 90.34% compared to head (3894761) 90.36%.
Report is 3 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #504      +/-   ##
==========================================
+ Coverage   90.34%   90.36%   +0.01%     
==========================================
  Files          35       35              
  Lines        4422     4431       +9     
==========================================
+ Hits         3995     4004       +9     
  Misses        427      427              

see 1 file with indirect coverage changes

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

Copy link
Owner Author

@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.

Thanks for fixing this for me!



def posColors(pos, _):
return [1 - p / 2 for p in pos] + [1.0]
Copy link
Owner Author

Choose a reason for hiding this comment

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

Love the simplicity!

result -= hole.rotate([90, 0, 0])
result -= hole.rotate([0, 90, 0])

return result.trim_by_plane([1, 1, 1], 0).set_properties(4, posColors).scale(100)
Copy link
Owner Author

Choose a reason for hiding this comment

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

How is the new number of properties 4? It seems like it would be 3, and anything else would trigger your invalid shape error below? Did you check that the resulting GLB looks like our logo?

Copy link
Collaborator

Choose a reason for hiding this comment

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

trimesh expects rgba for vert_color (and max is 255, but I did the conversion in the export part)

Copy link
Owner Author

Choose a reason for hiding this comment

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

Oh, my python is just weak - I totally missed that + [1.0] was pushing an additional item into the array. Thanks!

@elalish elalish merged commit ffdd97d into master Jul 30, 2023
22 checks passed
@elalish elalish deleted the pythonSponge branch July 30, 2023 05:10
cartesian-theatrics pushed a commit to SovereignShop/manifold that referenced this pull request Mar 11, 2024
* adding test of properties

* python set_properties

* fixed sponge example

---------

Co-authored-by: pca006132 <[email protected]>
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.

2 participants