Search code examples
c#unity-game-engineraycastingunits-of-measurementmesh-collider

Calculate distance between Mesh Edges


I've the point of origin readily available where my mouse is on screen like so,

            ray = Camera.main.ScreenPointToRay(Input.mousePosition);

Now imagine a cube. Anywhere you click on this cube, a line is drawn from the edge clicked on, through the object, and stops at the other end. Orientation, vertical or horizontal, is determined by which side is clicked on, one of the 4 sides, or top or bottom.

How does one determine the distance (from one edge of a mesh to the other), and orientation (vertical or horizontal)?

Thoughts?

Only idea I have so far is to use collision detection and using CollisionEnter as the start point and somehow draw a line that reaches the opposite end of the mesh and using CollisionExit to determine the destination (or exit) point. Then doing some calculation to determine the distance between the Enter and Exit methods.


Solution

  • The only way I can think of approaching this would be to cast a ray back in the other direction....

    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    RaycastHit hit;
    if (Physics.Raycast(ray, out hit))
    {
        //offset the ray, keeping it along the XZ plane of the hit
        Vector3 offsetDirection = -hit.normal;
        offsetDirection.y = 0;
        //offset a long way, minimum thickness of the object
        ray.origin = hit.point  + offsetDirection * 100;
        //point the ray back at the first hit point
        ray.direction = (hit.point - ray.origin).normalized;
        //raycast all, because there might be other objects in the way
        RaycastHit[] hits = Physics.RaycastAll(ray);
        foreach (RaycastHit h in hits)
        {
            if (h.collider == hit.collider)
            {
                h.point; //this is the point you're interested in
            }
        }
    }
    

    This offsets the ray to a new location so that it retains the same XZ coordinates of the original hit, so the resulting endpoints form a line that is perpendicular with the world / scene Y axis. To do this we use the camera's Forward direction (as we want to get a point farther away from the view point). If we wanted to get a point for a line that is perpendicular to the hit surface (parallel to the surface normal) we could create an offset using the hit.normal instead.

    You will probably want to put a layermask or maxdist parameter into the two raycast methods (so it checks fewer things and is faster), but that's on you.

    Original code: which finds the two endpoints of a "single" ray cast through the object.

    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    RaycastHit hit;
    if (Physics.Raycast(ray, out hit))
    {
        //offset the ray along its own direction by A LOT
        //at a minimum, this would be the maximum thickness of any object we care about,
        //PLUS the distance away from the camera that it is
        ray.origin += ray.direction * 100;
        //reverse the direction of the ray so it points towards the camera
        ray.direction *= -1;
        //raycast all, because there might be other objects in the way
        RaycastHit[] hits = Physics.RaycastAll(ray);
        foreach(RaycastHit h in hits)
        {
            if(h.collider == hit.collider)
            {
                h.point; //this is the point you're interested in
            }
        }
    }