Closed EleotleCram closed 4 years ago
Hi @EleotleCram indeed there is no explicit notion of edge, I still wonder if it is needed. To define edge only meshes, you can create polygons made of two vertices only. At least it is the intention, I haven't checked lately if it still works, let me know!
One reason to add support to explicit edges would be to be able to attach attributes to edges, but so far I haven't added this because it raises some technical issues and actually you can always attach data to vertices = face corners = loops in blender API. Houdini does not have explicit edge attributes iirc. But Blender has.
I was also experimenting with this and as far as I can tell:
source/blender/blenlib/intern/math_geom_inline.c:255
source/blender/bmesh/intern/bmesh_core.c:735
The "Feature edges" effect in https://github.com/tkarabela/MfxVTK can be used to create OFX mesh with just edges and no faces.
I've tried patching the host code to generate proper edges on Blender side ( https://github.com/tkarabela/OpenMeshEffectForBlender/commit/6005e1dcad4c20928dfcb7fb3b359bc660f6434e ) - it works, though some more work is needed to support attributes as well. In the future, it should also work the other way, ie. Blender should translate edges to 2-vertex faces for OFX. It looks like this will introduce a slow path in before_mesh_get()
, since we won't be able to reuse Blender's vertex/face buffers (we can still keep current fast path for polygonal inputs).
If it's OK, I can implement this and send a pull request?
Yes I consent to this PR, thank you for putting thinking in this! I am still balancing about whether to add proper edges to the Open Mesh Effect API or not, at least to distinguish edge attributes from other ones. Still being able to reuse Blender's buffer is a relevant point too, even though it is more implementation related and should hence be less influencial in design desisions.
I'll try to build your MfxVTK and point to it from Open Mesh Effect web page if you agree.
Thanks for linking to MfxVTK!
I've tried to summarize my thoughts on edges below. Sorry for the brain dump, like they say, "If I had more time I would have written a shorter letter" ^^; In summary, the main pain point I see is that in current spec, face count is really (face + loose edge) count, and we should declare/require both, to enable optimizations for common cases, regardless of how we want to handle edge attributes.
To implement current spec, both Blender host and MfxVTK have to do extra processing to handle 2-vertex faces correctly, even if the mesh doesn't have any - there is no way of knowing this in advance. I'm not familiar with Houdini API, but it wouldn't surprise me if there were some opportunities as well.
My understanding is that most of the time, OpenEffectMesh input/output will be "homogenous" in the sense that it will be either:
I wouldn't disallow other combinations, but these should be hitting fast paths in the implementation if possible. Here's what I came up with:
Proposed extension of OpenMeshEffect spec (version 1)
OfxMeshHandle
: kOfxMeshPropEdgeCount
, which will be the number of "loose" edges (define "loose" edge as a line between two vertices that does not belong to any face).2 * kOfxMeshPropEdgeCount
vertices belong to edges (ie. kOfxMeshAttribVertexPoint[0], kOfxMeshAttribVertexPoint[1]
is first edge, kOfxMeshAttribVertexPoint[2], kOfxMeshAttribVertexPoint[3]
is second edge, ...)2 * kOfxMeshPropEdgeCount
belong to faces (ie. like it is now: next kOfxMeshAttribFaceCounts[0]
number of vertices belong to first face, then kOfxMeshAttribFaceCounts[1]
belong to the second face, ...)Example
Implications for use cases
Extensibility in the future
kOfxMeshAttribEdge
attachment, which could refer to "loose" edges in the same way we can refer to them now by kOfxMeshAttribFace
(as 2-vertex faces).kOfxMeshAttribVertexPoint
in the above proposal, to get what Blender has (AFAIK) - attributes for both "loose" and "face" edges (in this case, kOfxMeshAttribEdge
array would look like: [first loose edge, second loose edge, ..., first edge of first face, second edge of first face, ...])Issues (proposal 1)
int2
, but vertices are int
)If we were to prioritize polygonal meshes, the proposal may well be simplified:
Proposed extension of OpenMeshEffect spec (version 2, simpler)
OfxMeshHandle
: kOfxMeshPropEdgeCount
, which will be the number of "loose" edges (2-vertex faces).This would require whoever creates the OFX mesh to declare how many "loose" edges there will be, without changing the current layout. Optimizations are still possible based on kOfxMeshPropEdgeCount == 0
or kOfxMeshPropEdgeCount == kOfxMeshPropFaceCount
(in common cases, there should be no need to separate faces from loose edges, as it will be homogenous).
Issues (proposal 2)
kOfxMeshAttribFaceCounts
is an array of 2's, which will almost certainly have to be allocated just for this purpose)Thanks for this pretty clear and structured brain dump. :)
In a similar spirit to version 2, I was thinking about (2b) a "tag" (I mean, a boolean prop) to tell that a mesh is edge only or face only. I don't see a use cas for knowing the exact edge count in mixed cases. If needed one can just iterate through face counts, they would at some point anyways. So I find it less missleading to just give the tags. BTW such a bool prop should eventually arise for tagging effects that only deform meshes without altering the connectivity.
Reading your point about kOfxMeshAttribFaceCounts
being a useless array of 2s, I was thinking the same occurs for fully triangular meshes. Maybe (2c) we could have a kOfxMeshPropConstantFaceCounts
set to 2 or 3 when there are only edges or triangles, and -1 to mean "use kOfxMeshAttribFaceCounts
".
NB: In Houdini, there is just no explicit notion of loose edge: https://www.sidefx.com/docs/houdini/model/attributes They are treated as open 2-polygons (dunno whether the closeness of polygons is actually stored but it is specified in addprim).
So, version 1 makes a lot of sense, but I am still wondering whether the cost in terms of minimalism and elegance of the API are worth the benefits once we have something like version 2/2b/2c. I am especially not totally happy with the idea of mixing different data in the same buffers (edge extremities and face corners).
I think we could introduce arbitrary edge attributes (kOfxMeshAttribEdge
) without requiring to separate lose edges from faces. Just define that seeing a primitive of 2 would imply to offset by only 1 in the edge attribute buffer, even though for all larger amounts it'd mean offseting by the number of vertices in the polygon.
Overall I'd lean toward the following changes:
kOfxMeshPropConstantFaceCounts
property type to meshes to skip the use of the kOfxMeshAttribFaceCounts
buffer when it is not -1.kOfxMeshPropNoEdge
boolean property turned on by default, that one must turn off when building a mesh with loose edges.kOfxMeshPropDeformOnly
boolean property turned off by default that one can turn on to speed up processing when the effect does not affect connectivity.kOfxMeshAttribEdge
) with no such attribute by defaultWhat do you think?
I like this, it fits nicely with the design so far while keeping the benefits of (1), (2) and bringing in more.
(2C) Add a kOfxMeshPropConstantFaceCounts property type to meshes to skip the use of the kOfxMeshAttribFaceCounts buffer when it is not -1.
Completely agree, this optimizes at least three things at once :) (better use of memory, signalling pure wireframe or triangular mesh). Perhaps I would name it in singular: kOfxMeshPropConstantFaceCount
, not that it matters much.
(2B) Add a kOfxMeshPropNoEdge boolean property turned on by default, that one must turn off when building a mesh with loose edges.
Agree.
(2D) Add a kOfxMeshPropNoEdge (incorrect name?) boolean property turned off by default that one can turn on to speed up processing when the effect does not affect connectivity.
Yes, we need something like this as well, as you mentioned before. I see this as two related concepts:
kOfxMeshMainInput
?) to output (kOfxMeshMainOutput
).With (A), we can bypass copying output to host as well as handle host-specific things like Blender treating deform modifiers specially. In terms of API, it looks kinda like kOfxMeshEffectActionIsIdentity
to me (kOfxMeshEffectActionIsDeformation
?), even specifying which input should be routed to output.
Thinking about the host not looking at connectivity output from effect, I realized that some effects may not need to look at their input connectivity either (like lattice deformation, which will just move points and keep connectivity; or like convex hull, which creates new connectivity from points; or extra inputs that are used just for their transform #35), hence the opportunity for (B2), which may be niche but it could be solved together with (B1), ie. how should an effect declare additional inputs it needs (like vertex weights).
A simple solution to (B1), (B2) that comes to mind - since the effect already has to have boilerplate to explicitly define kOfxMeshMainInput
, kOfxMeshMainOutput
in Describe, we could require it to also define kOfxMeshAttribPointPosition
, kOfxMeshAttribVertexPoint
, kOfxMeshAttribFaceCounts
on the meshes. It's a bit verbose, but pretty simple - you will get at cooking time, what you asked for at describe time (if data is available). If you need something more or less, that is the place to do it. (If you don't ask for points/vertices/faces on output mesh, I would be inclined to assume will be none, and leave the special handling to kOfxMeshEffectActionIsDeformation
.)
(2E) Introduce arbitrary edge attributes (kOfxMeshAttribEdge) with no such attribute by default
Agree, it would be good to put them into the spec now, so that the "where goes what data" story is complete, even if we don't have use for them now.
It looks like the issue "How to create wireframe mesh effects?" is a lot clearer now :) Wireframe is just 2-vertex faces, but you have to set kOfxMeshPropNoEdge = false
to be able to include them in the output. If you want to have edge attributes, create an attribute with kOfxMeshAttribEdge
attachment; faces have the same number of vertices and edges, except for 2-vertex faces that have just one edge. Finally, if all your faces have the same number of vertices, skip kOfxMeshAttribFaceCounts
and just use kOfxMeshPropConstantFaceCounts
. That is to say, (2B), (2C), (2E).
(2D) feels as a separate topic, maybe we can continue discussing it in a new ticket?
Having written this, I remembered what the use case for "knowing the exact edge count in mixed cases" is. It's so that the host knows how big a buffer to allocate for edge attributes, otherwise it has to overallocate up to number of vertices (~2x in the worst case). So I'm leaning slightly more towards (2), (2C), (2E) than (2B), (2C), (2E).
(Following up this whole discussion in a dedicated issue in the OpenMeshEffect repo, @tkarabela concluded the wireframe part just above)
I have one mesh effect that I want to create that adds a wireframe for sharp edges. For this I need to be able to define edges, no faces. But I could not find an edge array in the API.
Am I overlooking something, or is this not yet part of the API?