PathShape
by Stefan Beffy Moises · 12/08/2003 (8:52 am) · 61 comments
Download Code File
**********************************************************
* A modified PathCamera object that enables you to move
* static shapes (DTS files) along (camera) paths
* This will only work in Release 1.2 or HEAD since it is based on
* the new PathCamera stuff!!!
**********************************************************
Here is how to add a pathed shape to your game:
Add the .cc and .h file to engine/game, add them to your project and recompile the engine...
copy pathShape.cs to your "example/demo/server/scripts/" folder e.g.
and exec it in "game.cs" as usually...
then add the path to your shape in that file:
You can add a PathShape like this from script e.g.:
**********************************************************
* A modified PathCamera object that enables you to move
* static shapes (DTS files) along (camera) paths
* This will only work in Release 1.2 or HEAD since it is based on
* the new PathCamera stuff!!!
**********************************************************
Here is how to add a pathed shape to your game:
Add the .cc and .h file to engine/game, add them to your project and recompile the engine...
copy pathShape.cs to your "example/demo/server/scripts/" folder e.g.
and exec it in "game.cs" as usually...
then add the path to your shape in that file:
datablock PathShapeData(LoopingShape)
{
emap = true;
// put path to your shape here!!
shapefile = "~/data/shapes/foo/bar.dts";
mode = "";
};You can add a PathShape like this from script e.g.:
// --> beffy: create pathed shape start ! :)
%pathshape = new PathShape() {
dataBlock = LoopingShape;
// set position to whatever suits your needs...
position = "102.46 155.34 98.22";
};
// give it a path to follow:
%pathshape.followPath("MissionGroup/Scenes/TerrainEngineScene/Path");
// cleanup
MissionCleanup.add( %pathshape );
// <-- beffy: create pathed shape end ! :)
#3
OK, as I promised in the forums, I'm posting the results of my looping fiasco and the fix.
In the code you include with this resource, there is a small bug. As far as I can tell, cameraSpline, and the class pathCamera, which this resource is based on, are really only intended for once around loops. i.e. The code doesn't have a mechnism to automatically go from end-node to start-node, starting the loop over. Given this, your script onNode(), does a check to see if we've reached the last node and if we are looping. This is where the error is. Your code adds the path nodes to the end of the existing list and sets the end node to something like (current node + path.getcount()). This does allow the shape to loop, but it grows the total nodes by path.getcount(), which eventually overflows the bitstream.
So, I played around for a long time with cameraSpline and pathShape, before it hit me that there is an easier solution than trying to add and remove nodes. I just changed your script a little to do the following (pseudo-code):
If (path.isLooping == true), Then add nodes from path, plus add beginning node to end of list.
then,
If (current node == end node), set current node to starting node.
So, that's pretty much it. Thanks for the resource. I'm going to post my code changes after this post (in case there is too much text).
[HOW]-Ed
03/16/2004 (9:47 pm)
Beffy,OK, as I promised in the forums, I'm posting the results of my looping fiasco and the fix.
In the code you include with this resource, there is a small bug. As far as I can tell, cameraSpline, and the class pathCamera, which this resource is based on, are really only intended for once around loops. i.e. The code doesn't have a mechnism to automatically go from end-node to start-node, starting the loop over. Given this, your script onNode(), does a check to see if we've reached the last node and if we are looping. This is where the error is. Your code adds the path nodes to the end of the existing list and sets the end node to something like (current node + path.getcount()). This does allow the shape to loop, but it grows the total nodes by path.getcount(), which eventually overflows the bitstream.
So, I played around for a long time with cameraSpline and pathShape, before it hit me that there is an easier solution than trying to add and remove nodes. I just changed your script a little to do the following (pseudo-code):
If (path.isLooping == true), Then add nodes from path, plus add beginning node to end of list.
then,
If (current node == end node), set current node to starting node.
So, that's pretty much it. Thanks for the resource. I'm going to post my code changes after this post (in case there is too much text).
[HOW]-Ed
#4
Note: added a few echos for debugging purposes too.
03/16/2004 (9:49 pm)
Here are the CHANGED SCRIPTS ONLY:function LoopingShape::onNode(%this,%theshape,%node) {
echo("PathShape::onNode(" @ %this @ "," SPC %theshape @ "," SPC %node@")");
if(%theshape.path.isLooping && (%node == %theshape.loopNode)) {
echo("At end of path, setting position back to starting node.");
%theshape.setPosition(0);
}
}
function PathShape::followPath(%this,%path) {
echo("PathShape::followPath(" @ %this @ "," SPC %path @")");
%this.path = %path;
if (!(%this.speed = %path.speed))
%this.speed = 10;
if (%path.isLooping) {
%this.loopNode = %path.getCount();
} else {
%this.loopNode = -1;
}
echo("PathShape::followPath() loopNode == ", %this.loopNode);
%this.pushPath(%path);
%this.popFront(); // This pop removes initial DUMMY node.
}
function PathShape::pushPath(%this,%path) {
echo("PathShape::pushPath(" @ %this @ "," SPC %path @")");
for (%i = 0; %i < %path.getCount(); %i++) {
%this.pushNode(%path.getObject(%i));
}
// If looping, push the starting node on to end to make this a loop
if(%this.path.isLooping) {
%this.pushNode(%path.getObject(0));
}
}Note: added a few echos for debugging purposes too.
#5
To add the ability to support the character you'll need to change the following in
pathShape.h
AND
AND
Finally, in pathShape.cc, find the routine: bool PathShape::onAdd()
and comment out this line:
violla. Now the player can stand on the shape. The shape will NOT move your character yet, but I'll probably post a resource separate from this one when I get that working.
Cheers - [HOW]-Ed
03/16/2004 (11:27 pm)
OK. There is an additional modification to this resource. The end goal of my efforts it to use these moving shapes as lifts. As part of this, we're going to need the shape to support the character. Unfortunately, shapeBase which this class is derived from doesn't have everything we need to do this. However, staticShape does.To add the ability to support the character you'll need to change the following in
pathShape.h
#ifndef _SHAPEBASE_H_ #include "game/shapeBase.h" #endifbecomes
#ifndef _STATICSHAPE_H_ #include "game/staticShape.h" #endif
AND
struct PathShapeData: public ShapeBaseData {
typedef ShapeBaseData Parent;becomesstruct PathShapeData: public StaticShapeData {
typedef StaticShapeData Parent;AND
class PathShape: public ShapeBase ... typedef ShapeBase Parent;becomes
class PathShape: public StaticShape ... typedef StaticShape Parent;
Finally, in pathShape.cc, find the routine: bool PathShape::onAdd()
and comment out this line:
// addToScene();
violla. Now the player can stand on the shape. The shape will NOT move your character yet, but I'll probably post a resource separate from this one when I get that working.
Cheers - [HOW]-Ed
#6
When I shoot at the object it only detects the collision at the bottom of the shape, however the colision box is fine when placed as a static shape (or viewed in the show tool).
It seems as if the collision works for running into the object, however I'm not certain.
Any ideas?
03/25/2004 (2:34 pm)
I'm having some problems with the collision meshes on the pathed shapes after implementing Ed's changes to inherit staticShape.When I shoot at the object it only detects the collision at the bottom of the shape, however the colision box is fine when placed as a static shape (or viewed in the show tool).
It seems as if the collision works for running into the object, however I'm not certain.
Any ideas?
#7
03/26/2004 (4:35 am)
Hi, great resource! Got it working no probs. I'd now like to be able to attach a camera to the shape while still retaining movement control of the player but can't work out how. Can anyone point me in the right direction?
#8
Thought I'd let you know how we got on with this; we've now fixed our bounding box and collision mesh problems. Hopefully this will help everyone who wants to be able to shoot the pathShapes.
Ok, first you should implement the changes Edward Maurina makes above.
Next you should implement the following modifications:
The first problem is that the bounds of the shape are set to the scale of the object - presumably done because a pathCamera doesn't have a model to set the bounds by, and this does not cover the whole shape.
This can be fixed by commenting out the following lines in pathShape.cc in function bool PathShape::onAdd():
Next we will define an objectType for PathShape, for the collision masks and so on.
Goto objectTypes.h and find the enum SimObjectTypes declaration. Replace any of the UNUSED types with the following, we chose bit(25):
becomes
Next we will want to add this TypeMask as a Con Variable.
In main.cc, bool initGame(), put in the following line, with the other setIntVariable() commands:
Finally back in pathShape.cc in the constructor PathShape::PathShape(), replace:
with:
And hopefully, after a recompile, you can shoot the object and bullets won't pass through. Again, this will not move your character if you want to use it as a lift, I think we'll leave that one upto Ed.
And thanks again Beffy and Ed for your work on a great resource.
03/28/2004 (8:52 pm)
Hello Beffy and friends,Thought I'd let you know how we got on with this; we've now fixed our bounding box and collision mesh problems. Hopefully this will help everyone who wants to be able to shoot the pathShapes.
Ok, first you should implement the changes Edward Maurina makes above.
Next you should implement the following modifications:
The first problem is that the bounds of the shape are set to the scale of the object - presumably done because a pathCamera doesn't have a model to set the bounds by, and this does not cover the whole shape.
This can be fixed by commenting out the following lines in pathShape.cc in function bool PathShape::onAdd():
//mObjBox.max = mObjScale; //mObjBox.min = mObjScale; //mObjBox.min.neg(); //resetWorldBox();
Next we will define an objectType for PathShape, for the collision masks and so on.
Goto objectTypes.h and find the enum SimObjectTypes declaration. Replace any of the UNUSED types with the following, we chose bit(25):
UNUSED_AVAILABLE3 = bit(25),
becomes
PathShapeObjectType = bit(25),
Next we will want to add this TypeMask as a Con Variable.
In main.cc, bool initGame(), put in the following line, with the other setIntVariable() commands:
Con::setIntVariable("$TypeMasks::PathShapeObjectType", PathShapeObjectType);Finally back in pathShape.cc in the constructor PathShape::PathShape(), replace:
mTypeMask |= ShapeBaseObjectType | ShapeBaseObjectType;
with:
mTypeMask |= PathShapeObjectType | StaticShapeObjectType;
And hopefully, after a recompile, you can shoot the object and bullets won't pass through. Again, this will not move your character if you want to use it as a lift, I think we'll leave that one upto Ed.
And thanks again Beffy and Ed for your work on a great resource.
#9
// --> beffy: create pathed shape start ! :)
%pathshape = new PathShape() { dataBlock = LoopingShape;
// set position to whatever suits your needs...
position = "102.46 155.34 98.22";};
// give it a path to follow:
%pathshape.followPath "MissionGroup/Scenes/TerrainEngineScene/Path");// cleanupMissionCleanup.add( %pathshape );// <-- beffy: create pathed shape end ! :)
I tried the mission file but now the mission does not load, must be the wrong place...also what do i put in place of "MissionGroup/Scenes/TerrainEngineScene/Path"?
I can get the actual dts shape into the game, it doesnt move or anything like that
12/14/2004 (1:49 pm)
where would I place this:// --> beffy: create pathed shape start ! :)
%pathshape = new PathShape() { dataBlock = LoopingShape;
// set position to whatever suits your needs...
position = "102.46 155.34 98.22";};
// give it a path to follow:
%pathshape.followPath "MissionGroup/Scenes/TerrainEngineScene/Path");// cleanupMissionCleanup.add( %pathshape );// <-- beffy: create pathed shape end ! :)
I tried the mission file but now the mission does not load, must be the wrong place...also what do i put in place of "MissionGroup/Scenes/TerrainEngineScene/Path"?
I can get the actual dts shape into the game, it doesnt move or anything like that
#10
Have you created a datablock to go with your shape? First you'll need to create a datablock, then you'll need to add a shape based on it as shown in your question code.
If you're unclear on how to do all this, please see the online docs.
You can find more docs on my web-site, but both Torque Notes and the free version of EGTGE are quite dated now. I'm nearly done with EGTGE Volume 1, so watch for the official announcement on that (if you're interested).
[HOW]EdM|EGTGE
ps - I know this wasn't exactly the kind of help you wanted, but I think it will get you where you need to go.
-EFM
12/15/2004 (11:23 pm)
Louis,Have you created a datablock to go with your shape? First you'll need to create a datablock, then you'll need to add a shape based on it as shown in your question code.
If you're unclear on how to do all this, please see the online docs.
You can find more docs on my web-site, but both Torque Notes and the free version of EGTGE are quite dated now. I'm nearly done with EGTGE Volume 1, so watch for the official announcement on that (if you're interested).
[HOW]EdM|EGTGE
ps - I know this wasn't exactly the kind of help you wanted, but I think it will get you where you need to go.
-EFM
#11
It may not be real clear, but you need to do the following:
1. make a file that contains your datablock definition. (see ~/server/scripts/crossbow.cs for an example)
2. load this file by exec'ing it from the game.cs file (in~/server/scripts). See this line for an example:
3. Start the kit and open a mission.
4. Check the console log (~) to be sure there were no errors when your script loaded. If there were, try correcting them, and then start the kit and reload the mission. Alternately, you could type: onServerCreated() in the console, but this won't always do what you desire.
5. If there were no errors, start the World Editor -> Creator (F11 -> F4) and check for your object in the shapes tree. It should be there. If not, then datablock did not load properly. Check you script and be sure it got exec'd.
[HOW]EdM|EGTGE
12/15/2004 (11:35 pm)
Louis,It may not be real clear, but you need to do the following:
1. make a file that contains your datablock definition. (see ~/server/scripts/crossbow.cs for an example)
2. load this file by exec'ing it from the game.cs file (in~/server/scripts). See this line for an example:
function onServerCreated()
{
//...
exec("./audioProfiles.cs");
// ..3. Start the kit and open a mission.
4. Check the console log (~) to be sure there were no errors when your script loaded. If there were, try correcting them, and then start the kit and reload the mission. Alternately, you could type: onServerCreated() in the console, but this won't always do what you desire.
5. If there were no errors, start the World Editor -> Creator (F11 -> F4) and check for your object in the shapes tree. It should be there. If not, then datablock did not load properly. Check you script and be sure it got exec'd.
[HOW]EdM|EGTGE
#12
I know I've added this to my engine source and I've compiled, but I'm ending up with... well, the above error, which I believe is caused by missing or non-working code.
I'm currently using TGE1.3. Is there another issue that could be giving me this error, or does this code just not work with flat 1.3 without modifications?
Thanks in advance,
-Dave
01/13/2005 (11:22 pm)
Excellent resource, and really excited to use it! Problem is, whenever I run he demo code, I get the error 'Unable to instantiate non-conobject'.I know I've added this to my engine source and I've compiled, but I'm ending up with... well, the above error, which I believe is caused by missing or non-working code.
I'm currently using TGE1.3. Is there another issue that could be giving me this error, or does this code just not work with flat 1.3 without modifications?
Thanks in advance,
-Dave
#13
Now that I've got it working, EXCELLENT resource, and was exactly what I was looking for! Keep up the good work!!
-Dave C.
01/14/2005 (12:18 am)
Bah, my bad. Was using the new TBE to compile and didn't realize you had to edit the targets.torque.mk file to add a new .CC! Was just trying to add it through Eclipse, so, oops, my bad! Now that I've got it working, EXCELLENT resource, and was exactly what I was looking for! Keep up the good work!!
-Dave C.
#14
03/24/2005 (6:47 am)
Isn't this functionality already in the TGE 1.3 Head?
#15
10/07/2005 (4:13 pm)
hmmm works good.... but at the end of the path, when a loop occurs... there's an ever so slight pause while setting the new position on the path. anyone else notice this?
#16
11/09/2005 (4:36 pm)
Yeah I noticed that also. Not sure how to solve this. Does anyone know how to start the object on a random position along the path instead of always starting at the beginning?
#17
Anybody else ran into this problem and/or has a solution to this? Thanks.
Nevermind, it appears all the PathShape functions are accessible to the scripts, it's just that followPath() doesn't exist in code, but as apart of the script pathShape.cs. What I did was I created my own script and just took parts of it and forgetting the myobject::followPath() function. Now it's working pretty good. Great resource! :)
11/30/2005 (10:30 pm)
Well I just gave this resource a try today and I implemented all the changes as Edward F. Maurina III and Ash "Slayeh" Berlin have suggested, but I've ran into a problem which is PathShape's functions some how are not script accessible and I've looked over the ConsoleMethod()s in the pathshape.cc and checked the header file pathshape.h and everything looks fine, but nothing I can see that is causing this.Anybody else ran into this problem and/or has a solution to this? Thanks.
Nevermind, it appears all the PathShape functions are accessible to the scripts, it's just that followPath() doesn't exist in code, but as apart of the script pathShape.cs. What I did was I created my own script and just took parts of it and forgetting the myobject::followPath() function. Now it's working pretty good. Great resource! :)
#19
Any ideas why this is happening?
Also, is there any way to align my dropship model with the path? I'd quite like it to fly along the path and change direction as the path changes.
Any clues on how to do this?
12/20/2005 (11:59 am)
I've just implemented this and I've got a nice dropship flying along my path.. but he gets to the first node and Stops... I implemented Edwards Scripting fix for looping but still stopped... only at the beginning of the path instead of at the end of the path (before I added Edwards fix)Any ideas why this is happening?
Also, is there any way to align my dropship model with the path? I'd quite like it to fly along the path and change direction as the path changes.
Any clues on how to do this?
#20
Fixed it. No problem with the resource, just my own stupidity.
12/20/2005 (2:37 pm)
Never mind :-)Fixed it. No problem with the resource, just my own stupidity.

Associate Stefan Beffy Moises