3

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.

jtth
  • 876
  • 1
  • 12
  • 40
  • 1
    can you graphically explain what you want to achieve? (draw some lines with paint or whatever over a screenshot) – cortvi Jun 21 '17 at 20:52
  • 1
    Yes marsh! I'll do you one better, [here](https://ibb.co/ddsGq5) is a gif depicting what I'm going for. Currently as you'll see in the gif I've a two step process where I've an object that follows and rotates to an object as I move the mouse around it. I can then click to place the first point, and then click again to place the second point. It then creates a line renderer in between the two points. I'm seeking to be able to do this in 1 click. Also, I adjust the cubes material to transparent during the gif. – jtth Jun 21 '17 at 21:09

1 Answers1

4

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
        }
    }
}
  • 1
    @JHiggins If you look closely, `h.hit` is the point on the backside of the object. I perform a second raycast from *behind* the object *towards* the camera. `hit.point` would be the point on the near-side (the point you already knew about). The reason this works is that the second raycast starts off in the distance and moves towawrds the mouse until it collides with the object of interest (hence the foreach loop: we had to find the correct raycasthit). – Draco18s no longer trusts SE Jun 21 '17 at 20:55
  • @JHiggins I suggest using the surface normal as the offset. That will always get you to the other side of the object for convex objects. For concave, it will get you *otherside-ish.* That's the only thing I can think of that would have consistent results. – Draco18s no longer trusts SE Jun 22 '17 at 16:29
  • 1
    @JHiggins No no, all you need to do is change one line, `Vector3 offsetDirection = -1 * hit.normal;` – Draco18s no longer trusts SE Jun 22 '17 at 20:47
  • 1
    YES! YES! That is EXACTLY what I was trying to accomplish. Draco, thank you SOO much for your continued support these past few days. Truly you were immeasurably helpful. – jtth Jun 22 '17 at 21:02
  • @JHiggins glad to help out. With the way you were describing things I was sure that you didn't want that vector. – Draco18s no longer trusts SE Jun 22 '17 at 21:04
  • I'm re-entering this part of my project and it appears I need an additional functionality added to this. Essentially if you remember the way it works right now, a user can click anywhere on a gameobject and it will cast a ray through that object to the other side and end there. What I want to add is the ability to calculate thickness of a given edge. So think of a plane, it is a one-sided object. Now think of a cube, each wall has two sides. I want to be able to calculate the thickness of a given wall. I remember at some point I did this w this code accidentally.. Any ideas? – jtth Aug 07 '17 at 16:20
  • @jtth Calculate the distance between the two raycast collision points. – Draco18s no longer trusts SE Aug 07 '17 at 18:50
  • Hmm I don't follow. The two points are created one on the surface where clicked and the other on the surface where the ray exits the collider. The functionality I'm looking for is a a calculation of a given 'wall'. I didn't flesh out that plane example but basically thats how it works now, as if all the walls of the object were planes - one sided. But what if they were all two sided? How to calculate the thickness of any of the walls? – jtth Aug 07 '17 at 21:05
  • @jtth TThat would be tough. I can't think of a robust way of doing it. For example, take a hollow cube with walls of some thickness. Now how do you know, having a point on the outside, that it *is hollow at all*? – Draco18s no longer trusts SE Aug 07 '17 at 23:28
  • Right. I'll have to give the documentation on Rays a glance again. In the meantime how do I phrase this for a new question? How to find wall thickness with Rays? – jtth Aug 08 '17 at 13:14
  • @jtth "How to determine the thickness of a collider" probably – Draco18s no longer trusts SE Aug 08 '17 at 15:20
  • So is [this](https://ibb.co/kphqxF) possible? I realized this was not actually the correct functionality as the distance between the two points changes on every click which it wouldn't if it were truly calculating the thickness of the object (or collider on the objects wall). Someone relayed to me that [this](https://ibb.co/d5me9v) might be what I am looking for? But I am thinking not as this is not the objects wall/collider thickness but rather the distance between two different colliders... – jtth Aug 09 '17 at 16:14
  • Lets say we can safely assume any of the objects I'd be performing this measurement on would not be hollow. I.e. they are guaranteed to have two-sided walls. Then it is just a matter of calculating a walls thickness at any given click, much like the way we have it now except wall thickness not the objects width. Posted q [here](https://stackoverflow.com/questions/45576911/how-to-determine-the-thickness-of-a-collider). – jtth Aug 09 '17 at 16:51