Game Development Community

Ray Casting

by Justin Mosiman · in Torque Game Engine · 07/14/2006 (12:10 pm) · 9 replies

Hi,

Based on the direction that I am looking, I want to cast a ray and find the point that the ray intersects with the terrain or another object. The variables that I have to work with are yaw angle, pitch angle, and position (x,y,z). Is this possible?

Thanks,
Justin

#1
07/14/2006 (1:10 pm)
Sure. A raycast just takes two points, so take your first position and then create a second position by scaling your initial position based off the angles and a distance for how far you want to check ahead. Though if this is a direction you are "looking", there is probably a function you can call that will give you a direct vector instead of having to use angle values. Depends where you're working in code (script, source, what objects, etc.).
#2
07/14/2006 (1:12 pm)
Here's some sample code. The function below will return the ID of whatever object the current control object (usually the player or the editor camera) is looking at.

function testRay()
{
   %client = localClientConnection;
   %player = %client.getControlObject();
	
   %start = %player.getEyePoint();
	
   %rayLength = 1000;
   %rayDirection = VectorScale(%player.getEyeVector(), %rayLength);
   %end = VectorAdd(%start, %rayDirection);
   
	%mask = $TypeMasks::InteriorObjectType | $TypeMasks::StaticObjectType | $TypeMasks::ShapeBaseObjectType;
	%rayInfo = ContainerRayCast(%start, %end, %mask, %player);
	
	if (getWordCount(%rayInfo))
	{
   	%object = getWord(%rayInfo, 0);
		%point  = getWords(%rayInfo, 1, 3);
		%normal = getWords(%rayInfo, 4, 6);
		
		return %object;
	} else {
		
		return 0;	
	}
}
#3
07/14/2006 (1:19 pm)
It's not too hard. Since ray casts require an end point, I would convert your yaw and pitch angle into a unit vector. Then multiply that unit vector by some large number (say 500) and add it to your position. Set the start position to your (x,y,z) and your end position to the (x',y',z') position.

If theta is your angle off of the x-axis heading towards your y-axis and rho is your angle off the z-axis heading towards the x-y-plane, then your unit vector will be:

x = sin( rho ) * cos( theta ),
y = sin( rho ) * sin( theta ),
z = cos( rho ).

Usually a pitch angle is defined as the angle up from the x-y-plane towards the z-axis. In that case, change the rho to (90 - pitch). (Of course, then the sin and cos can be re-simplified, but I leave that as an exercise for the reader.)
#4
07/14/2006 (2:11 pm)
Thanks for the help, what if I don't know the distance to the endpoint? I'm trying to find that endpoint. Maybe ray cast is the wrong word.

Here's what I'm working on:

I'm pretty close to finsihing a new camera, one that is similar to the RTS camera except it changes position when you pitch/yaw/zoom so it rotates around a center position. I have that part working, but right now the camera has a problem with terrain height changes (it just goes through the terrain). I can calculate if the camera position is greater/equal to the terrain, so I will be able to make sure it doesn't go through the terrain while moving.

I have a center variable (x,y) that updates when you pan, so the center always changes when you move. I cannot use the same method for updating the center z variable because the center is not always at the same height as the camera. For example, if you are moving up a hill, the center is not moving up at the same rate because it's not necessarly on the same hill (or even on a hill). So the problem that I'm having is finding the center, and I thought that it could be solved with a ray cast. Am I on the right track with this whole ray cast thing?

Thanks
#5
07/14/2006 (2:38 pm)
Well if it's terrain... then just doing a downward raycast would be fine (just subtract a bunch from the z value of your initial position for the second point of the raycast). The distance of the raycast isn't that important, just needs to be far enough so it can always find the ground. The raycast will return the point (and thus the height) you are looking to avoid going below.

I know the stock third person camera has "collision" on it for if you back up against a wall or something it won't go through the wall, so you could maybe look at how that works too.
#6
07/14/2006 (9:35 pm)
Quote:The raycast will return the point (and thus the height) you are looking to avoid going below.

I already can figure out the current height, and if it goes under the terrain or not, that's not the problem. Let me come up with a different example.

Lets say that you are looking almost parallel with the terrain (but not totally parallel, we want the center to exist). And then lets say that you move left up a small hill (along the x axis just to make it easy). The way that I am doing it right now, the center position's x axis would change at the same rate that the camera's x axis is changing. So if I move left 5 units, the center would move left 5 units also. That is all well and good, but then you have to factor in the hill. Because you increase in height with the hill, I can't just increase the centers height because then the centers height would be floating (or if I'm going down a hill for example, it could be below the terrain).

So that way won't work. What I want to do is find out if there is some way that I can cast a ray (or a vector, I don't know what I would have to use) that would create a line and get the coordinates with the terrain that it intersects with, because eventually this line will intersect with the terrain somewhere.

So that's the idea, I can come up with another example if needed.
Thanks
#7
11/30/2009 (3:27 am)
The question above is way above my head, but the testRay function above has helped me understand how to use the rayCast function. I am very new, so please bear with me.

I have modified the testRay function above to all me to use it on AIPlayers as well...

function testRay(%forAi,%id)
{
   if(%forAi == false){
   %client = localClientConnection;
   %player = %client.getControlObject();
   }else{
      %player = %id;
   }
	
   %start = %player.getEyePoint();
	
   %rayLength = 1000;
   %rayDirection = VectorScale(%player.getEyeVector(), %rayLength);
   %end = VectorAdd(%start, %rayDirection);
   
	%mask = $TypeMasks::PlayerObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticObjectType | $TypeMasks::ShapeBaseObjectType;
	%rayInfo = ContainerRayCast(%start, %end, %mask, %player);
	
	if (getWordCount(%rayInfo))
	{
   	%object = getWord(%rayInfo, 0);
		%point  = getWords(%rayInfo, 1, 3);
		%normal = getWords(%rayInfo, 4, 6);
		
		return %object;
	} else {
		
		return 0;	
	}
}

When I use it as it was originally designed, everything works, fine, I point my cursor at an Object (based on the masks) and I get the ID of the object returned, however when i use it for an AI client ie.
echo(testRay(true,2259));//where 2259 is the ID of one of the AIPlayers.


unless Im standing right in front of the AI player, it returns the id of the terrain. Is there a simple xyz intercept formula for me to verify that the AI is able to see me at the specified distance? I am using TGEA 1.8.1. Also, if I am not asking the right questions I apologize. The documentation for TGEA is hard to find sine it is community driven. If there is somewhere else I should be looking please let me know.
#8
11/30/2009 (3:41 am)
I used the setAimLocation() function to verify that my function was working properly.

2423.setAimLocation(2296.getTransform());//2423 is the ID of the AIPlayer
// and 2296 is the ID of the localclient player
echo(testRay(true,2423)); //returned 2296 at the correct distances

Hope this helps someone else out!
#9
11/30/2009 (11:58 pm)
i havent ran or tested the script but it looks like it calls to use the ray at

%start = %player.getEyePoint();

now if you set the id to the id of the ai player then that would mean its using the eye point of the ai player

is it possible that the eye point and the vector of the ai player is not facing in the right direction?

maybe its on an angle that shoots into the air or the ground being that it works when you are standing directly in front of it?