Game Development Community

ContainerRayCast problem

by James Hill · in Torque Game Engine · 10/21/2004 (5:08 pm) · 16 replies

Hi everyone. I've got a teleport spell in working, but I'm having some issues. The idea is that the player can look at terrain in his line of sight and teleport to that spot. I've tried many different ways and suggestions posted on the forums, but I keep getting bad results. This is my code, can anyone see the problem with it?

%currPlayerPos = %this.getPosition();
	%eyeVec = %this.getEyeTransform();
	%vec = VectorScale(%eyeVec, 1000);
	%x = getWord(%currPlayerPos, 0);
	%y = getWord(%currPlayerPos, 1);
	%z = getWord(%currPlayerPos, 2);

	%mask = $TypeMasks::TerrainObjectType; 
	%target = ContainerRayCast(%currPlayerPos, %vec, %mask);
	echo("******************************");
	echo("Target position " @ %target);
	echo("******************************");
	%xx = getWord(%target, 0);
	%yy = getWord(%target, 1);
	%zz = getWord(%target, 2);
	%finalPos = %xx SPC %yy SPC %zz;
	%this.setTransform(%finalPos);

I get 0 for the %target echo

#1
10/22/2004 (3:26 am)
#1 Why are you extracting %x, %y, and %z?

Use:

%currentPlayerPos = %this.getPosition();
%eyeVec = $this.getEyeVector();
%mask = $typeMasks::TerrainObjectType;
%target = ContainerRayCast(%currPlayerPos, %eyeVec, %mask);
%xx = getWord(%target, 0);   
%yy = getWord(%target, 1);  
%zz = getWord(%target, 2);   
%finalPos = %xx SPC %yy SPC %zz;   
%this.setTransform(%finalPos);
EyeVector will give you an actual vector from the eye.

Marrion
#2
10/22/2004 (8:57 am)
Ah whoops meant to take that out. That code went through many revisions and the %x %y and %z just never got taken out; Thanks for the help. The problem that i'm having is that I go through the terrain when I teleport. Unless all the levels are flat I'm in trouble. Any ideas on how I should fix this? Thx
#3
10/22/2004 (10:13 am)
If I were you, I would adapt this function from Emo to get the terrain height...

www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=2347


And change the last function to use it. You don't need the radius portion of the function I don't believe, so you would just change the last line to be....

%this.setTransform(getTerrainLevel(%finalPos));
#4
10/22/2004 (11:04 am)
I was working on similar code for the BraveTree Car Pack and couldn't resist posting the correct code.

ContainerRayCast() takes a start point and and end point (not a direction vector) and returns 3 fields if it hits an object: the object id, the x pos, and the y pos. You would then have to use getTerrainHeight() whic luckily takes an x and y vector ;) to get the terrain's height at that point and pad it out a little to drop you a distance above the terrain so you don't get stuck (can play with this value).

Keep in mind that this would have to be executed in server scripts b/c of the %this.setTransform().

%eyeVec = %this.getEyeVector();

%startPos = %this.getEyePoint();
%endPos = VectorAdd(%startPos, VectorScale(%eyeVec, 1000));

%mask = $TypeMasks::TerrainObjectType;
%target = ContainerRayCast(%startPos, %endPos, %mask);

if (%target)
{
   %xx = getWord(%target, 1);
   %yy = getWord(%target, 2);

   %zz = getTerrainHeight(%xx SPC %yy);

   %drop = 3;

   %finalPos = %xx SPC %yy SPC %zz + %drop;

   %this.setTransform(%finalPos);
}
else
{
   echo("No terrain in your line of sight");
}
#5
10/22/2004 (8:45 pm)
I'll give that a shot first thing in the morning. Thanks for the help guys :)
#6
10/23/2004 (7:46 am)
Um, Matthew ContainerRayCast returns a z coordanate too! Here is the help string from the ConsoleFuntion in the engine source:

Cast a ray from start to end, checking for collision against items matching mask.

If exempt is specified, then it is temporarily excluded from collision checks (For 
instance, you might want to exclude the player if said player was firing a weapon.)
@Returns A string containing either null, if nothing was struck, or these fields:
            - The ID of the object that was struck.
            - The x, y, z position that it was struck.
            - The x, y, z of the normal of the face that was struck.

A bit of advice, check the normal returned from ContainerRayCast. if the terrian is too steep(IE a cliff) the player could end up stuck in the terrian.
#7
10/23/2004 (8:05 am)
An even better idea is to offset the position by the scaled normal.

%eyeVec = %this.getEyeVector();
%startPos = %this.getEyePoint();
%endPos = VectorAdd(%startPos, VectorScale(%eyeVec, 1000));
%mask = $TypeMasks::TerrainObjectType;
%target = ContainerRayCast(%startPos, %endPos, %mask);
if (%target)
{
   %xx = getWord(%target, 1);
   %yy = getWord(%target, 2);
   %zz = getWord(%target, 3);
   %nx = getWord(%target, 4);
   %ny = getWord(%target, 5);
   %nz = getWord(%target, 6);
   %drop = 3;
   %normal = %nx SPC %ny SPC %nz;
   %finalPos = %xx SPC %yy SPC %zz;
   %finalPos = VectorAdd(%finalPos,VectorScale(VectorNormalize(%normal),%drop));
   %this.setTransform(%finalPos);
}
else
{
   echo("No terrain in your line of sight");
}
#8
10/23/2004 (2:27 pm)
Good catch Michael! I don't know what I was smoking when I looked at that very same docos...I plead business =)

You solution is pretty good except that you shouldn't need to VectorNormalize() a normal. The other drawback is that if the terrain is steep then you could potentially drop relatively far from your intended spot on the terrain.
#9
10/23/2004 (6:42 pm)
WOW! Thanks a lot guys, worked like a charm :)
#10
10/24/2004 (6:46 am)
@Mat: the reason is to avoid the player intersecting the terrian. if it is steep moving the player up a bit might not help.
#11
10/24/2004 (3:32 pm)
Michael,
Yep...I knew that and your approach is a good one =) I was just pointing out that if the expected behavior of the spell is to teleport you directly to an exact spot on the terrain then moving them alogn the normal could have "unpredicatable" results. The best approach I can see is to calculate how far the bottom corners of the player's bounding box would impenetrate the terrain and moving the player up the furthest distance + a slight padding. This would drop them straight down on the spot and guarantee that they never get stuck inside the terrain. I haven't tried to write the script code for that yet but it is on my todo list =)
#12
12/17/2004 (9:45 pm)
@Michael-Paul Jakovlevski :
I you still listen, could you please tell me where do you get this "ConsoleFunction" help string on a script command ?
I'm so desperately in search of script documentation with description !
The example you quote for "ContainerRayCast" is a so perfect help string !
#13
12/17/2004 (11:34 pm)
I'm pretty sure that you get the Z as well from ContainerRayCast. If you don't, it's a bug...
#14
12/18/2004 (12:07 am)
Sorry ? my question was : how do I get detailed help on a script command like the one Michael-Paul was talking about ?
#15
12/19/2004 (12:15 am)
Please Ben, it seems you're the last one to listen to this post :
I've spent days and days to find a script reference with descriptions. Ok, there is none, this problem is discussed in others threads. This fabulous example of help on a script method :
Cast a ray from start to end, checking for collision against items matching mask.If exempt is specified, then it is temporarily excluded from collision checks (For instance, you might want to exclude the player if said player was firing a weapon.)
@Returns A string containing either null, if nothing was struck, or these fields:            
- The ID of the object that was struck.           
- The x, y, z position that it was struck.            
- The x, y, z of the normal of the face that was struck.
is the only thing I want. How do I get such help for a script method ? Pleeeeease !
#16
12/19/2004 (6:55 am)
Found it in TorqueScript_1_3_0.chm.
Unfortunately, each method has not such description, many has just their signature.
Since these descriptions seem to be defined in the C++ source, I guess improving these descriptions are part of the current GG documentation effort ?