owensgroup / RXMesh

GPU-accelerated triangle mesh processing
BSD 2-Clause "Simplified" License
216 stars 29 forks source link

How to access multiple relations within one kernel? #18

Closed g1n0st closed 2 years ago

g1n0st commented 2 years ago

Hi,

I am trying to implement an XPBD cloth simulation with the bilateral bending constraint model using RXMesh. To compute the bending constraint for an edge, I need to first access its two adjacent faces, and then assign the "bending force" to the vertices of those two faces. This procedure needs both E-F and F-V relations within a kernel. I think I need to use the query_block_dispatcher API to launch an Op::EF relation right? However, I wonder how can I get the VertexIterator associated with the faces accessed by the E-F relation.

Here's the pseudo-code to explain the computation logic better:

// bending constraint kernel
auto bending_lambda = [&](uint32_t edge_id, RXMeshIterator& ef) {
  if (ef.size() == 2) {
    uint32_t v1 = ev(edge_id, 0); // question: how to get E-V ?
    uint32_t v2 = ev(edge_id, 1);
    uint32_t v3 = 0;
    uint32_t v4 = 0;

    for (int i = 0; i < 3; ++i) {
      if (fv(ef[0], i) != v1 && fv(ef[0], i) != v2) { // question: how to get F-V ?
        v3 = fv(ef[0], i);
      }
    }
    for (int i = 0; i < 3; ++i) {
      if (fv(ef[1], i) != v1 && fv(ef[1], i) != v2) {
        v4 = fv(ef[1], i);
      }
    }
  }
  // do other computations ...
}

// dispatch E-F as the document described
query_block_dispatcher<Op::EF, blockThreads>(context, bending_lambda);

Thank you very much for releasing your great work. Any support would be much appreciated.

Ahdhn commented 2 years ago

I have not implemented such "compound" queries where multiple queries (e.g., EF, EV, FV in your case) are needed to be computed and be resident in shared memory. But it is on my roadmap!

However, from the code snippet above, I would recommend restructuring your computation such that it would be vertex-centric instead of edge-centric. Doing so, the code would just loop over the vertex (i.e., v1's) one ring. At each step, you would have access to v2. If the query is marked as "oriented" here, you could additionally have access to the vertex before and after v2 i.e., v3 and v4. You would also need to mark the query as "oriented" in prepare_launch_box.

An example of the above suggestion can be found in the mcf_rxmesh_kernel.cuh where p_id is the center vertex we iterate over q_id is the previous vertex in p_id's one-ring, r_id is the current one-ring vertex, and s_id is the next vertex after r_id.

Hope this is helpful! Please let me know if you have more questions.

g1n0st commented 2 years ago

Hi,

Thank you for your suggestion about reformulating the computation to being vertex-centric and using the V-V relation instead of E-F-V. I think it's feasible as long as using oriented=True to ensure the order of the neighborhood vertices.

However, I find that the oriented V-V query required the input mesh without boundary: https://github.com/owensgroup/RXMesh/blob/54f29b3e2b8f020a9d5e89f94002fdcc5273d124/tests/RXMesh_test/test_queries.h#L30-L31 But it's not the case in my application. I am currently doing cloth simulation where meshes have boundaries. Do you have any idea for this? Any support would be much appreciated.

Ahdhn commented 2 years ago

I have just pushed e95b38eebcee8ba5299dc81099d29dcf8bb99af8 a fix to allow oriented V-V (and V-E) on input mesh with boundaries (with a unit test). Please let me know if you need anything else to get your cloth simulation working :)

g1n0st commented 2 years ago

Sorry for the late reply. I updated to e95b38e and found the oriented V-V works well with my application. Thank you for your excellent work and help!