algorithmic modeling for Rhino
hi guys,
in Plankton.PlanktonVertexList.GetNormal(int index), you are calculating vertex normals by averaging the crossproducts of pairwise vectors from the respective vertex to its surrounding vertices.
since you're not normalizing the resulting crossproduct vectors (which are the normals for surrounding faces) before averaging, your vertex normals look fine for regular polyhedral shapes, but become distorted if the size of surrounding faces varies.
i'm asking because i'm not sure if that's on purpose. ;)
best regards from austria,
heinz.
Tags:
Hi Heinz,
Thanks for the feedback.
There are various possible weighting schemes for calculating the vertex normals of a triangular mesh, all of which have their pros and cons, rather than any definitive 'correct' normal.
Non-normalized cross products is effectively weighting face normals by area, and is fast and simple, so we put that one as the default.
In some cases normalizing the cross-products improves the result, but not always.
Another option is to weight by angles, though this is computationally slightly more expensive, so might not be ideal for real-time updates on large meshes.
As an example, here is a mesh with a 90° corner, and uneven meshing on the 2 sides.
The arrows show:
0- Area weighted (non-normalized cross products)
1- Angle weighted
2- Normalized cross-products
Here the angle-weighted normal is the one at 45°, which is intuitively the 'best' one in this case.
These 3 seem to be the most commonly used, but there are many other possible definitions of normals - such as inverse-area weighted, mean curvature, etc...
I think really what would be best would be to put a few of these into Plankton, and include an optional argument in GetNormal for selecting which one you need for a particular application.
Pull requests welcome if you feel inspired to add this!
http://meshlabstuff.blogspot.co.uk/2009/04/on-computation-of-vertex...
dear daniel, thanks for your very detailed answer!
true, for discrete representations of surfaces, a lot of things become undefined, especially in boundary regions or corners.
since i need a rather large amount of additional information in my half-edge structure, i initially intended to derive from plankton, which would have allowed to add my own routines, but since classes heavily depend upon each other, i'm now just using plankton for the initialization of a halfedge structure from an appropriate brep, after which i initialize my own datastructure from the connections plankton made. not really optimal but i didn't find another painless way to achieve what i want.
this question is a little off-topic, but - are there any plans to increase customization? i'm asking although i'm not entirely sure how to achieve that for such kind of intertwined structure. ;)
best regards,
heinz.
Heinz – what kind of customisation are you after? Daniel and I have talked for some time about adding some sort of key/value store to allow the setting of custom "properties" for mesh elements. Would this be of use? The tricky part is of course keeping the properties updated if you're making changes to the topology, hence we feel this needs some serious thought!
Daniel – what about creating a "setting" for the mesh which specifies the vertex normal type? Then any call to GetNormal should respect this. For me it feels like more of a global setting...
It would indeed be a very useful thing to be able to attach additional custom properties to the elements of the mesh. I still don't have a clear picture of how this is best structured though.
One option that could be relatively simple to implement is to maintain separate lists of these custom properties with indices matching those of the faces/edges/vertices, and make some helper methods for keeping these updated alongside them when the topology changes.
An alternative I guess is some way of extending the face/vertex/halfedge classes themselves as needed, but that seems more tricky to organize.
Or maybe the vertex, face and halfedge class could each have an additional CustomData property which is just an object that can hold whatever people need to put in it.
Heinz - would any of these work for your application?
For the different normal types - I think if they are just being calculated whenever GetNormal is called it makes sense to have it as an argument to that function. If we also had a SetNormals method that stored the normals, this could also have the option to choose which type of normals to store.
Welcome to
Grasshopper
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
Added by Parametric House 0 Comments 0 Likes
© 2024 Created by Scott Davidson. Powered by