Search Unity

Unity.Physics Raycast on MeshCollider get Triangle Index

Discussion in 'Physics for ECS' started by alfiare, Mar 12, 2020.

  1. alfiare

    alfiare

    Joined:
    Feb 10, 2017
    Posts:
    30
    I have a MeshCollider on an Entity in UnityPhysics, I do a raycast and get a hit in the right place etc. What I can't seem to find is a way to get the index of the triangle in the mesh from which the mesh collider was built. I've looked through the info on using the ColliderKey but that seems to let me get to a PolygonCollider which gives me the positions of the vertices of the triangle that was hit, but no way (without searching the mesh manually, yuck) to get the index of the triangle in the mesh that was used to generate the MeshCollider.

    Has anyone found a way to do this?
     
  2. Adam-Mechtley

    Adam-Mechtley

    Administrator

    Joined:
    Feb 5, 2007
    Posts:
    290
    Hi! The MeshCollider will not necessarily correspond 1:1 with the render mesh(es) used to generate it, as it undergoes some simplification/cleanup processes. Could you provide more information about what precisely you're trying to accomplish?
     
  3. alfiare

    alfiare

    Joined:
    Feb 10, 2017
    Posts:
    30
    Hi there, sure, so I'm constructing a nav mesh which I was then thinking to use simple raycasts to locate a triangle for start and end then build a path between them. The triangles really represent a graph that I store in a better format for doing pathfinding. So that's why I'm trying to get from a raycast back to the index of the triangle because it would translate into my pathfinding graph.

    This is because I'm generating everything from a voxel engine under the hood so when I generate the visual mesh from the voxel I then just simplify the mesh further before using it as a nav mesh (I'm not concerned with gravity and such in this game, just being able to get from a-b on the surface of the voxels).
     
    Last edited: Mar 12, 2020
  4. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    Thanks for the details of your use-case. Unfortunately, at the minute, the mesh collider is not holding the original triangle indicies use in construction.
    The mesh is build up from sections with spatially coherent primitives (i.e. triangles or quads). Note that the resulting Mesh does not necessarily include all the original input triangles. Some will be removed based on size tolerance and welding, and some will be merged into quads.
    That said, in theory, each primitive can have a material associated with it and the Material struct does have a CustomTag which is just for user data and returned with the raycast results. That tag is currently a byte, though there is justification for it to be an int or that we add a CustomIndex field as well.
    At the minute, during MeshCollider construction, every section and primitive is associated to a single common material. In the current codebase, this could be changed to take an array of materials, setup to hold the index of the original triangle, but its not a trivial change.

    We should really bake the original triangle index in as part of the Mesh Builder. I don't have a timeline for this but I will add your use-case to the issue logged.
     
  5. one_one

    one_one

    Joined:
    May 20, 2013
    Posts:
    621
    Is there a way to disable that? And that should definitely be communicated somewhere in the documentation, especially because the simplification seems to be a bit heavy-handed...
     
  6. one_one

    one_one

    Joined:
    May 20, 2013
    Posts:
    621
    @steveeHavok @Adam-Mechtley I would really appreciate an answer - this simplification can unfortunately lead to some very undesirable behaviour...
    Could the simplification perhaps be commented out relatively easily in the source code? Is there maybe even a plan to specify whether a mesh collider should be simplified when it is being created?
     
  7. Adam-Mechtley

    Adam-Mechtley

    Administrator

    Joined:
    Feb 5, 2007
    Posts:
    290
    I haven't tested it, but it _may_ be possible to a) bypass the calls to MeshConnectivityBuilder.WeldVertices() and b) not bypass degenerate triangles. But I am interested in what you mean by "very undesirable behavior". If the input geometry is being simplified now, it is likely that _not_ simplifying it would lead to physics behavior or performance problems.

    The plan is instead to store some information about the originating triangle index, which could then by retrieved from a query, but this task has not yet been prioritized.
     
    LudiKha and one_one like this.
  8. one_one

    one_one

    Joined:
    May 20, 2013
    Posts:
    621
    To give some context: My use case is part of a baking solution and part of the workflow is finding the closest point from surface points of one mesh to the surface of another mesh. This means that performance is not as much of a concern, it's fine if the baking process takes multiple seconds because it does not happen at runtime. As for the undesirable behaviour:
    1. Parts of the mesh are not taken into consideration at all (e.g. when raycasting against the simplified mesh collider), this has been particularly noticeable with thin triangles. It does not seem like vertices are wielded, instead, it seems like the rays are simply passing through the mesh surface.
    2. Even more weirdly, it seems that entire regions seem to be ignored and/or collapsed if the mesh is more finely tesselated. This is noticeable e.g. in the area around the hands of a human-shaped mesh, which have a higher resolution than the majority of the mesh.

    Perhaps some visualization helps. For these pictures, I created a mesh collider from one of our character meshes. I then iterated through each vertex of the original mesh and tried to find the closest position on this mesh collider. I then visualized the differences in position with magenta arrows. Long arrow = large difference in vertex position and closest point of vertex mesh, lots of arrows = high density of vertices and large-ish differences.

    upload_2020-7-23_1-37-27.png

    upload_2020-7-23_1-37-56.png

    The issue appears particularly pronounced in regions with small and/or thin triangles. In coarser regions (torso, most of the arms, shoulders, legs...) position differences appear to be minimal. As you can see in the close-up of one hand, it seems that the calculated closest points of the mesh collider actually seem to be at the wrist.
     
    LudiKha likes this.
  9. Adam-Mechtley

    Adam-Mechtley

    Administrator

    Joined:
    Feb 5, 2007
    Posts:
    290
    Is there any chance you could send us this exact mesh (i.e. model + import settings)? Either via Unity's bug reporter tool, or directly to myself or @petarmHavok
     
    LudiKha and one_one like this.
  10. one_one

    one_one

    Joined:
    May 20, 2013
    Posts:
    621
    I've sent you the files through a private message.
     
    LudiKha likes this.
  11. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    Just off the top of my head, your behavior does sound like degenerate triangles, not welded vertices.

    There is a function called IsTriangleDegenerate() and it checks 2 things - area of the triangle and whether 3 points make a valid triangle. So you could try to tweak this and see if it gets any better.
     
  12. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    Just curious if this is still being worked on. I just recently came across a use-case of retrieving the vertex color after raycasting a mesh. This is trivial to do with the old RaycastHit.triangleIndex. But since Unity.Physics gives me about 2x raycast performance boost (vs RaycastCommand), I'd like to be able to get triangleIndex in Unity.Physics. :)
     
    Last edited: Feb 15, 2021
  13. MNNoxMortem

    MNNoxMortem

    Joined:
    Sep 11, 2016
    Posts:
    723
    @petarmHavok, @Adam-Mechtley has there been any update on this? Is it by now
    • a) possible to get the exact MeshCollider a mesh is actually representing without any optimization?
    • b) possible to get the triangle index, and maybe even some connectivity information (neighbouring triangles/edges/etc), barycentrics, ...?
    @Creepgin, @alfiare did you find a solution?
     
    Last edited: Mar 1, 2022
  14. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    Sadly no. I hit some other hurdles relating to Unity.Physics' handling of large meshes and had to give up.
     
    MNNoxMortem likes this.
  15. alfiare

    alfiare

    Joined:
    Feb 10, 2017
    Posts:
    30
    I ended up doing my own raycast against my own triangle data instead of using the one in Unity.Physics, working for me at the moment but that's because I'm doing this for path mesh.
     
    MNNoxMortem likes this.