ContainerRayCast woes
by Stefan Lundmark · in Torque Game Engine · 01/28/2006 (3:57 pm) · 7 replies
I'm trying to do a RayCast from the players eye, determine where it hits, and then cast another RayCast from another players eye to the same position to see if they both can hit the spot (ie, see it).
The results are not satisfying and I suspect there's something wrong in my code here.
Basically, the two players never hit the same position. The further away the players are from eachother, the more error. The code is pretty simple and looks like this:
The echo's in the end return very different positions, they are far from the same.
What am I doing wrong here?
The results are not satisfying and I suspect there's something wrong in my code here.
Basically, the two players never hit the same position. The further away the players are from eachother, the more error. The code is pretty simple and looks like this:
function blaha(%player1, %player2)
{
// How long we want the ray to extend into the world.
%range = 500;
// We don't want to hit anything else than interiors or terrain here.
%mask = $TypeMasks::InteriorObjectType | $TypeMasks::TerrainObjectType;
// Get the eye's transform and vector from Player1.
%startPoint = %player1.getEyeTransform();
%eye = %player1.getEyeVector();
%eyeVec = VectorScale(%eye, %range);
%endPoint = VectorAdd(%startPoint, %eyeVec);
// Cast a ray from %startPoint to %endPoint.
%player1Target = ContainerRayCast (%startPoint, %endPoint, %mask);
if (%player1Target)
{
// Get the eye's transform from Player2.
%startPoint = %player2.getEyeTransform();
// Let's use the endpoint from our Player1 cast for the next one.
// This is where I'm starting to get confused. :p I also tried
// using the %player1Target variable, but I got the same result.
%player2Target = ContainerRayCast (%startPoint, %endPoint, %mask);
echo(%player1Target);
echo(%player2Target);
}
}The echo's in the end return very different positions, they are far from the same.
What am I doing wrong here?
About the author
#2

If you cast from player1 to a point (A) x units along the players eye vector, and then cast a ray from player2 to the same point (A), the two rays will hit the wall at different points (B and C).
If you want to test whether player2 can see the same point that player1 is looking at, you'll need to ray cast from player2 to a point (D) beyond where the first cast hit. Then compare the results.
Maybe something like this:
01/28/2006 (6:11 pm)
Come to think of it, I'm not sure whether you'll get a result from that second ray cast or not, since %player1Target is on the wall, I don't know if a ray cast will consider that a hit or not? Maybe it would be best to extend the ray beyond %player1Target to ensure a hit. Anyway.. bad diagram time...
If you cast from player1 to a point (A) x units along the players eye vector, and then cast a ray from player2 to the same point (A), the two rays will hit the wall at different points (B and C).
If you want to test whether player2 can see the same point that player1 is looking at, you'll need to ray cast from player2 to a point (D) beyond where the first cast hit. Then compare the results.
Maybe something like this:
%startPoint = %player2.getEyeTransform(); %vec2 = VectorSub(%player1Target, %startPoint); %vec2 = VectorScale(%vec2, 2); %endPoint = VectorAdd(%startPoint, %vec2); %player2Target = ContainerRayCast(%startPoint, %endPoint, %mask);
#3
I've already tried your first suggestion though, using the return from ContainerRayCast, but that didn't work.
Might be because, as you said, it doesn't consider it a hit? I never thought of that.
The code you suggested didn't work.
So I'm basically (since I feel so lost with all these position returns) going to be placing flares where the rays hit and see if I can get a good idea of how this stuff works.
After testing:
You were right in both cases. Player2's raycast was hitting the wall but at an offset when using %endPoint.
When using the return from the first RayCast, player2's ray didn't hit, most of the time but not always.
That's what's confusing me right now, how it hits rarely(mostly at close range).
01/28/2006 (8:10 pm)
First I'd like to thank you so much for taking the time to look at this, Scott. Your diagram is great and this is one of the best explainations I've seen to date on these forums.I've already tried your first suggestion though, using the return from ContainerRayCast, but that didn't work.
Might be because, as you said, it doesn't consider it a hit? I never thought of that.
The code you suggested didn't work.
So I'm basically (since I feel so lost with all these position returns) going to be placing flares where the rays hit and see if I can get a good idea of how this stuff works.
After testing:
You were right in both cases. Player2's raycast was hitting the wall but at an offset when using %endPoint.
When using the return from the first RayCast, player2's ray didn't hit, most of the time but not always.
That's what's confusing me right now, how it hits rarely(mostly at close range).
#4
Note also that you'll probably need to test the results with a tolerance. That is to say, instead of testing for an exact equality between %player1Target and %player2Target, you'll probably want to test to see if they're "close enough". I say this because I would expect that even when they "should" be the same, floating point inaccuracies will probably crop up and throw them off by a small margin. So, after you've cast your two rays, I'd suggest comparing them like so:
01/29/2006 (9:42 am)
Did you try the second code block I posted? The second code block should replace the first one I posted, and should extend the second ray through the point where the first hit, to ensure a collision on the second ray. I'd be surprised if that doesn't work, unless there is an obstruction and player2 really can't see the same point. Note also that you'll probably need to test the results with a tolerance. That is to say, instead of testing for an exact equality between %player1Target and %player2Target, you'll probably want to test to see if they're "close enough". I say this because I would expect that even when they "should" be the same, floating point inaccuracies will probably crop up and throw them off by a small margin. So, after you've cast your two rays, I'd suggest comparing them like so:
%tolerance = 0.01; // or some relatively small value, adjust as appropriate
%difference = VectorSub(%player1Target, %player2Target);
%distance = VectorLen(%difference);
if (%distance < %tolerance) {
// consider them the same
} else {
// etc...
#5
in general two floats will never be exactly equal, and you should always use a threshhold.
strange that the ray isn't hitting the wall.
i think putting flares at the various points (start, end, result) is a great idea.
01/29/2006 (10:30 am)
What scott just said about comparing the results cannot be over-emphasized.in general two floats will never be exactly equal, and you should always use a threshhold.
strange that the ray isn't hitting the wall.
i think putting flares at the various points (start, end, result) is a great idea.
#6
I tried your code block last night Scott, but it didn't work and I went to bed.
And that's also what the problem was, I was too tired - because I did have a typo in
the second RayCast from Player2. It was still grabbing Player1Target instead of the new endPoint variable.
For future reference and to anyone reading this thread later:
So finally, it's working! Thanks Orion and a huge thanks to you Scott, your diagram is great and your help invaluable (:
Cheers mates
01/29/2006 (4:24 pm)
I had the tolerance stuff in already, but wanted to save space in the original post.I tried your code block last night Scott, but it didn't work and I went to bed.
And that's also what the problem was, I was too tired - because I did have a typo in
the second RayCast from Player2. It was still grabbing Player1Target instead of the new endPoint variable.
For future reference and to anyone reading this thread later:
function blaha(%player1, %player2)
{
%range = 500;
%mask = $TypeMasks::InteriorObjectType | $TypeMasks::TerrainObjectType;
// Check from player1's eye
%startPoint = %player1.getEyeTransform();
%startPoint = getWords(%startPoint, 0, 2);
%eye = %player1.getEyeVector();
%eyeVec = VectorScale(%eye, %range);
%endPoint = VectorAdd(%startPoint, %eyeVec);
%player1Target = ContainerRayCast (%startPoint, %endPoint, %mask);
if (%player1Target)
{
%player1Target = getWords(%player1Target, 1, 3);
// Check from player2's eye
%startPoint = %player2.getEyeTransform();
%startPoint = getWords(%startPoint, 0, 2);
%vec = VectorSub(%player2Target, %startPoint);
%vec = VectorScale(%vec, %range);
%endPoint = VectorAdd(%startPoint, %vec);
%player2Target = ContainerRayCast (%startPoint, %endPoint, %mask);
if (%player2Target)
{
%player2Target = getWords(%player2Target, 1, 3);
}
else
{
echo("player2Target (2) did not return a result.");
}
}
else
{
echo("player1Target (1) did not return a result.");
}
}So finally, it's working! Thanks Orion and a huge thanks to you Scott, your diagram is great and your help invaluable (:
Cheers mates
Torque 3D Owner Scott Richards