Jump to content

Moving spheres from origin point to closest mesh/face/vertex


Bladetrick
 Share

Recommended Posts

Hello!

My scenario: 
- An OBJ file containing several meshes (cube, cones, monkey head, etc) all touching each other
- A sphere (or more than one) created off to the side of the imported mesh.

My objectives are:
- Determine the closest point on the imported mesh from the sphere.
- Create another Sphere at that point.

The end result is a sphere on the surface of the imported mesh.

Before I started playing with Babylon JS, I had tried Three JS.  I found a small routine that would do this.  Now I'd like to do the same thing in Babylon.  Here's the Three JS.

        // This function is called first.  it accepts datapoint as a parameter.  datapoint is the sphere that is off to the side of the imported model.
        function updateClosestPointPosition(datapoint) {
            var p = datapoint.position;   
            var geom = partmodel.geometry; // cone.geometry
            
            var closestDistance = 1e9;     // Don't understand 1e9 to be honest
            var closestFace = geom.faces.forEach(function (face) {
                var normal = face.normal;
                var va = geom.vertices[face.a];
                var vb = geom.vertices[face.b];
                var vc = geom.vertices[face.c];
                var pd = normal.dot(p.clone().sub(va));
                // move p -(pd - td) units in the direction of the normal
                var proj = p.clone().sub(normal.clone().multiplyScalar(pd));
                // closest point of proj and the triangle
                var cp = closestPointToTriangle(proj, va, vb, vc);
                if (cp.distanceTo(p) < closestDistance) {
                    closestDistance = cp.distanceTo(p);
                    closestPoint.position.copy(cp);
                    closestPoint.position.y.toString() + ',' + closestPoint.position.z.toString() + ',';
                }                 
        })

        function sameSide(p1, p2, a, b) {
            var ab = b.clone().sub(a)
            var ap1 = p1.clone().sub(a)
            var ap2 = p2.clone().sub(a)
            var cp1 = new THREE.Vector3().crossVectors(ab, ap1)
            var cp2 = new THREE.Vector3().crossVectors(ab, ap2)
            return cp1.dot(cp2) >= 0
        }

        function pointInTriangle(p, a, b, c) {
            return sameSide(p, a, b, c) && sameSide(p, b, a, c) && sameSide(p, c, a, b)
        }

        function closestToSegment(p, a, b) {
            var ab = b.clone().sub(a)
            var nab = ab.clone().normalize()
            var n = nab.dot(p.clone().sub(a))
            if (n < 0) return a
            if (n > ab.length()) return b
            return a.clone().add(nab.multiplyScalar(n))
        }

        function closestToSides(p, sides) {
            var minDist = 1e9
            var ret
            sides.forEach(function (side) {
                var ct = closestToSegment(p, side[0], side[1])
                var dist = ct.distanceTo(p)
                if (dist < minDist) {
                    minDist = dist
                    ret = ct
                }
            })

            return ret
        }

        function closestPointToTriangle(p, a, b, c) {
            // if the point is inside the triangle then it's the closest point
            if (pointInTriangle(p, a, b, c)) return p
            // otherwise it's the closest point to one of the sides
            return closestToSides(p, [[a, b], [b, c], [a, c]])
        }
        

Is there an easy way to do this in babylon js or do i need to work on some conversion?

Here's the playground I started:  https://www.babylonjs-playground.com/indexStable.html#NSSAV4
The playground uses two spheres.

Unfortunately I am not sure how to do this offhand.

Thank you for the assistance!

Link to comment
Share on other sites

I ran through the documentation on facet data and used it to construct a function that seems to work for me.

function GetNearestPoint(currentSphere) {
    var nearestMesh, nearestFacet, facetPos;
    var projected;
    var distance = 0;
    var shortestDistance = 9999999;
    meshes.forEach(function (mesh) {     // meshes is an array containing the mesh and its "sub meshes"
    var facets = mesh.getFacetLocalPositions()

        if (facets.length > 0) {
            facets.forEach(function (facet) {
                distance = BABYLON.Vector3.Distance(currentSphere.position, facet);
                if (distance < shortestDistance) {
                    nearestFacet = facet;
                    shortestDistance = distance;
                    nearestMesh = mesh;
                }
            });
        }
    });

    projected = BABYLON.Vector3.Zero();
    var index = nearestMesh.getClosestFacetAtCoordinates(nearestFacet.x, nearestFacet.y, nearestFacet.z, projected);

    return projected;  // use this set of coordinates to construct the newer/closer sphere
}

Thanks for the help, everyone!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...