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

How to create wireframe mesh effects? #27

Closed
EleotleCram opened this issue Jun 23, 2020 · 7 comments
Closed

How to create wireframe mesh effects? #27

EleotleCram opened this issue Jun 23, 2020 · 7 comments
Labels
discussion Discussion about design or Q/A rather than an actual issue

Comments

@EleotleCram
Copy link

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?

@eliemichel
Copy link
Owner

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.

@tkarabela
Copy link
Contributor

I was also experimenting with this and as far as I can tell:

  • Blender -> OFX
    • edges don't get translated at all
  • OFX -> Blender
    • when I output 2-vertex faces, it fails assert in source/blender/blenlib/intern/math_geom_inline.c:255
    • when I output 3-vertex faces (with only 2 unique vertices), it fails assert in source/blender/bmesh/intern/bmesh_core.c:735
    • Blender OFX host is translating these into Blender faces, not Blender edges, hence probably the asserts

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?

@eliemichel
Copy link
Owner

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.

@tkarabela
Copy link
Contributor

tkarabela commented Oct 13, 2020

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:

  1. polygonal mesh - proper faces, no loose edges, no isolated points
  2. edge wireframe - no faces, only loose (ie. faceless) edges, no isolated points
  3. point cloud - no faces, no loose edges, just isolated points

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)

  • Disallow faces with less than 3 vertices.
  • Introduce new mandatory property to 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).
  • Layout vertex attribute arrays as follows:
    • First 2 * kOfxMeshPropEdgeCount vertices belong to edges (ie. kOfxMeshAttribVertexPoint[0], kOfxMeshAttribVertexPoint[1] is first edge, kOfxMeshAttribVertexPoint[2], kOfxMeshAttribVertexPoint[3] is second edge, ...)
    • Vertices after 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

Screenshot from 2020-10-13 20-29-18

Implications for use cases

  1. polygonal mesh - I don't have to care about edges, use host point, vertex and face buffers directly
  2. edge wireframe - I don't have to care about faces, use host point, vertex and edge (?) buffers directly
  3. point cloud - I don't have to care about edges or faces - this can already be optimized without the change

Extensibility in the future

  • If needed, we can introduce kOfxMeshAttribEdge attachment, which could refer to "loose" edges in the same way we can refer to them now by kOfxMeshAttribFace (as 2-vertex faces).
  • This would get us what VTK has - attributes for "loose" edges but not "face" edges.
  • Or it could be extended in a similar way to 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)

  • polygonal mesh - I don't see a problem, this is just what we need (know ahead of time there are no loose edges, before allocating the mesh or processing it)
  • edge wireframe - this may not be a win in terms of buffer sharing (in Blender, the edge buffer is strided as int2, but vertices are int)
  • the vertex attribute layout is a bit complicated (though not overly so)

If we were to prioritize polygonal meshes, the proposal may well be simplified:

Proposed extension of OpenMeshEffect spec (version 2, simpler)

  • Introduce new mandatory property to 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)

  • edge wireframe representation is a bit silly (kOfxMeshAttribFaceCounts is an array of 2's, which will almost certainly have to be allocated just for this purpose)
  • it doesn't do away with the edge-face confusion (not a technical issue, more conceptual/documentation)

@eliemichel
Copy link
Owner

eliemichel commented Oct 14, 2020

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:

  • Add a kOfxMeshPropConstantFaceCounts property type to meshes to skip the use of the kOfxMeshAttribFaceCounts buffer when it is not -1.
  • Add a kOfxMeshPropNoEdge boolean property turned on by default, that one must turn off when building a mesh with loose edges.
  • Add a kOfxMeshPropDeformOnly boolean property turned off by default that one can turn on to speed up processing when the effect does not affect connectivity.
  • Introduce arbitrary edge attributes (kOfxMeshAttribEdge) with no such attribute by default

What do you think?

@tkarabela
Copy link
Contributor

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:

  • (A) How do I tell the host that it should copy connectivity from input mesh (kOfxMeshMainInput?) to output (kOfxMeshMainOutput).
  • (B) How do I tell the host that (B1) I do or (B2) I don't care about certain attributes on input.

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

@eliemichel eliemichel added the discussion Discussion about design or Q/A rather than an actual issue label Oct 15, 2020
@eliemichel
Copy link
Owner

(Following up this whole discussion in a dedicated issue in the OpenMeshEffect repo, @tkarabela concluded the wireframe part just above)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion Discussion about design or Q/A rather than an actual issue
Projects
None yet
Development

No branches or pull requests

3 participants