Auto-generate optimal direction for Raycast with specifications
Hello,
How can I have a Physics.Raycast
auto-generate a direction for itself to try to hit a given target through a restricted window of space?
[Update]
After much work, my problem has slightly morphed into one about mesh colliders: given a (convex) mesh collider, how can I detect all of the points intersecting with the collider? Or, if this can be done easily, can I get one vector3 per object that is within the mesh collider?
[/Update]
This is kind of a long question, so I'll try to explain it the best I can:
I have 3 GameObjects: a source, a target, and a "window". This window sits between the source and target.
I want the source to make a raycast that points in the direction of the target (not necessarily it's
transform.position
, just a direction that will make it hit the target) and this raycast must pass through (collide and continue through) the windows GameObjectI would like to automatically generate this direction for the raycast to follow such that #2 happens
I would like this algorithm to also recognize if the above is not possible
As an added item, I would like this raycast to pass through (collide and continue through) any objects that may be in it's way between it and the window
Here's an image describing my problem:
How can I accomplish this?
Thank you for your help in advanced!
Answer by streeetwalker · Apr 07, 2020 at 09:39 AM
HI @kyangeastsideprep, interesting problem! Are you working in 2D or 3D? What rotation can you expect the window to have? These issues will affect the complexity of algorithm you create.
Work it in 2D first, and I think you will see how to extend it to 3D. Also let's say the window will not be below the ground, nor rotated - take the window rotation case that you present in your image
Start by casting a ray to some object. You can easily determine if the hit object is in front of a window or behind a window by comparing it with the distance to the window. So in the hit object array, you ignore any that are closer than the window is.
(Or maybe you want to stop there because you know the object blocks the view? Or maybe you want to save those to determine in the next step if they block the view through the window? there are ways you can jigger the method - maybe check for the farthest hit object first... I didn't quite get exactly what you want to do in your description, but I think you can understand the general idea I am following. ).
Next, you want to know if any objects hit behind the window are within the window view. Conceptually, do this you need to get the angles between caster and the points at bottom and top of the window, and compare that with the hit object ray angle. If the ray is between those two angles, then you know you can "see" the object through the window.
I say 'conceptually', because there may be ways other than actually calculating angles that are more elegant, perhaps some vector or quaternion operations - you'd have to try to work through the necessary calculations to discover the best method of determining whether or not the ray cast went through the window opening.
Thanks for your reply! To answer some of the clarifying questions you posed: I’m working in 3D (but the problem probably works in both), the rotation of objects will be completely random, and I’m building a physics simulation for light and this is a situation where the reflection of an object in a mirror is being projected somewhere outside the mirror. $$anonymous$$y biggest problem is picking what point on the target object to raycast to. I could get caught in a situation where the target is like a massive plane above the window (like a ceiling) that extends really far, but it has its origins transform.position
behind the window. If I raycasted to the target’s position, it would look like a fail, but there are points on the target well in front of the window, I just don’t know how to get them. How can I picked those points? Also, how can I detect the angle the borders of the window create with my origin object, the potential solution you’ve pointed out seems viable, I’m just not sure how to calculate along the border of the window. Thanks again!
@kyangeastsideprep, OK, that helps a lot. This is a thorny problem. Yes, I understand what you mean about ray casting to the object's transform position.
Just to clarify, you really want to simulate a mirror? If that is the end result of you want to do, I don't think you want to do it with ray casts at all, but rather use camera and render the camera view on to the mirror plane. Let me know about that because there is some stuff out there that may help you with that.
Otherwise, to answer some of your queries:
Look at the various ray cast objects in the documentation. When you cast a ray it keeps going and returns an array of all hit objects. Each element of the array contains information about the hit object, include the distance to the hit point. You can easily deter$$anonymous$$e if the window is in the hit array, and compare the distance to that with the other hit object's distances to decide if an object is behind or in front of the window. If the window is not in the hit array you know the object at the hit point is not visible through the window, so it can be ignored. As you have identified, the problem is to know where on the objects to cast rays to, or from.
The window has a volume defined by it's transform scale values. If the window's origin is in the center, then you can calculate the corners of the volume by taking half the scale in each dimension and add it to the origin in each respective dimension. Conceptually, you can then use the distances from the viewer to those corners to get the pyramid that defines the viewing volume from viewer to the window. So, if you end up needing to cast rays you do not need to cast any rays outside of that volume.
You may not need to cast rays at all - I don't know. Again, conceptually, likewise you can calculate the volume for each object, and the pyramid formed by the extents of that volume to the viewer. Now I believe there is some mathematical way you could tell if those two volumes intersect.
With ray casts, to decide where to ray cast to or from, you could deter$$anonymous$$e if the top most point on an object volume is above the bottom most point of the window, and likewise for each side and top of the window. You could use those points to ray cast to, or ray cast from back to the viewer.
OK, conceptually that will work if you objects are all cubes or rectangular volumes, and there is no rotation relative to the viewer. What if things are odd shaped, like a sphere and not orthogonal to the viewer?
continued... I'm out of characters here.
continued...
This is where the problem becomes very difficult. So, I am thinking there is a better way to do all this: Reduce everything to 2D projections. This is where cameras become a better strategy, or to employ the same methods cameras use. Camera's have a projection matrix that flattens Unity's 3D world in to a 2D image. Conceptually by flattening into a 2D projection, you could mask out everything that does not intersect with the 2D projection of the window to deter$$anonymous$$e if it can be seen through a window.
However, this is getting beyond what I would be able to help you without quite a bit of work.