gradientspace / geometry3Sharp

C# library for 2D/3D geometric computation, mesh algorithms, and so on. Boost license.
http://www.gradientspace.com
Boost Software License 1.0
1.71k stars 387 forks source link

Get closest vertex on mesh surface #201

Closed faid123 closed 6 months ago

faid123 commented 6 months ago

I am trying to retrieve a vertex from a selected ray hit point. However, it seems that the output points are not on the mesh surface; some of the points are floating instead. I did try to draw the AABB Tree with gizmos in Unity editor, but the tree is not where it is supposed to be. Could someone guide me what am I missing or where did I go wrong?

andybak commented 6 months ago

@faid123 Would you mind explaining what resolved this? I think other people will see this issue and there's nothing worse than "closed but no explanation".

faid123 commented 6 months ago

@faid123 Would you mind explaining what resolved this? I think other people will see this issue and there's nothing worse than "closed but no explanation".

Apologies I'd give an explanation. The initial method i did was to load the mesh via

StandardMeshReader.ReadMesh(filePath)

However, loading via ReadMesh() to get the mesh data and then instantiating the prefab of the same mesh (.obj) file might have resulted in different data between the two such as discrepancies in some components such as transform. Hence, limiting the interaction to get the correct points on the surface of the mesh when doing a ray cast. Probably why the FindNearestVertex() function and int near_tid = spatial.FindNearestTriangle(point); if (near_tid != DMesh3.InvalidID) { DistPoint3Triangle3 dist = MeshQueries.TriangleDistance(mesh, near_tid, point); Vector3d nearest_pt = dist.TriangleClosest; Vector3 vertex_pt = new Vector3((float)nearest_pt.x, (float)nearest_pt.y, (float)nearest_pt.z); Instantiate(markerPrefab, vertex_pt, Quaternion.identity); Debug.Log(vertex_pt); }

returns the same incorrect vertices.

The way I did to resolve this might not be the best but it gets the interaction between the game object in unity and ray casting the selected points and generating nearest vertex perfectly fine.

  1. Object is firstly instantiated into the unity scene with default parameters.

  2. DMesh3 mesh data is built manually from the mesh filter data obtained from the instantiated game object consisting of vertices, triangles and normals.

  3. Writing to a file is optional to verify the mesh data. I use MeshLab to visualize. StandardMeshWriter.WriteFile("OutputMesh.obj", new List<WriteMesh>() { new WriteMesh(dMesh) }, WriteOptions.Defaults);

  4. Proceed to building the AABB Tree with the newly created DMesh3.

  5. Now you can raycast anywhere on the game object mesh in unity scene and use the DMeshAABBTree3 to retrieve the nearest vertex hsing FindNearestVertex().

`if (hit.collider.gameObject == go) { // Get the selected point on the mesh Vector3 pt = hit.point; Vector3d selectedPoint = new Vector3d(pt.x, pt.y, pt.z);

                // Find the closest vertex to the selected point
                int closestVertexIndex = spatial.FindNearestVertex(selectedPoint);

                if (closestVertexIndex != DMesh3.InvalidID)
                {
                    Vector3d closestVertex = dMesh.GetVertex(closestVertexIndex);
                    Debug.Log("Closest vertex: " + closestVertex);
                    Vector3 cv = new Vector3((float)closestVertex.x, (float)closestVertex.y, (float)closestVertex.z);`

Hope this will help somebody and let me know if anyone requires more details.