Game Development Community

TSShapeConstructor versus StaticShapeData

by Steve · in Technical Issues · 06/12/2009 (4:42 pm) · 7 replies


I think I am confused about when to use these two. I created a datablock using StaticShapeData and imported an animated object fine (a spinning crate). However, it apparently had no collision mesh. The discussion on TSShapeConstructor in T3D says:

"TSShapeConstructor makes it simple to to modify an existing DTS shape to add a collision mesh"

I figured my crate was a DTS, so, I switched my datablock type from StaticShapeData to TSShapeConstructor, and after much trouble I finally got the crate to import into T3D again, but I have now lost my animation. To make it worse, I still can not collide with the object.

Are there some types of DTS's that can not use the TSShapeConstructor data block? Am I misunderstanding how to use it?

#1
06/13/2009 (3:08 am)
The two datablocks are used for quite different things, and are not mutually exclusive (ie. you don't have to choose one or the other, but can - and should - use both together).

TSShapeConstructor is used to apply a set of changes to a DTS shape after it is loaded, but _before_ it is used by any other object. It is commonly used to share sequences (in DSQ files) between multiple DTS shapes, but has recently been extended to allow adding nodes and meshes as well. The TSShapeConstructor docs detail how to use this datablock to add a collision mesh to a DTS shape, but basically you just do this:

function MyShape::onPreload(%this)
{
   %this.addMesh("cube", "bounds", "Col-1");
}

datablock TSShapeConstructor(MyShape)
{
   baseShape = "myShape.dts";
};

Your DTS shape now has a collision mesh (in this case, a cube with the same extents as the entire shape).

Note that TSShapeConstructor does not add anything to the 3D scene => for that we need to use (for example) a StaticShapeData datablock. It sounds like you already had this part working (ie. use the onAdd method to create an animation thread and play the animation).

Then you just use the World Editor to place the StaticShape object (it will appear under the 'Scripted' tab, not the 'Library' tab which contains only TSStatic objects).
#2
06/13/2009 (5:11 am)
Chris -- thank you so much for your comments. Use Both! I followed your advice, but I am still getting strange results. The cube now imports and the collison mesh works, but I can not get the animation to run! Is there a definite sequence that the code blocks need to be in? Furthermore, I don't see how, bu the texture is wrong now. The cube lost detail and the way it reflects sunlight appear to have changed! Here is the code if you could be so kind as to look at it:

datablock StaticShapeData(Cube)
{
category = "collada";
shapeFile = "art/shapes/collada/queb/Cube.cached.dts";

};

function Cube2::onPreload(%this)
{
%this.addMesh("cube","bounds", "Col-1");

}

function Cube::OnAdd(%this,%obj)
{
%obj.playThread(0,"ambient");

}

datablock TSShapeConstructor(Cube2)
{
baseShape = "art/shapes/collada/queb/Cube.cached.dts";

};

#3
06/13/2009 (5:37 am)
Your code looks fine, though you should point at the .dae file instead of the cached.dts file (this file is produced automatically by T3D the first time it loads the .dae file).

Once you've done that, could you delete the cached.dts and retry? There have been some reports of collada files showing correct materials the first time, then incorrect materials on subsequent loads.

If that is the case, check the materials.cs file that is generated and make sure it looks ok.
#4
06/13/2009 (6:18 am)
This code neither loads the animation, nor puts a collision mesh:

datablock StaticShapeData(Cube)
{
category = "collada";
shapeFile = "art/shapes/collada/queb/Cube.dae";
};

function Cube2::onPreload(%this)
{
%this.addMesh("cube","bounds", "Col-1");

}

function Cube::OnAdd(%this,%obj)
{
%obj.playThread(0,"ambient");

}

datablock TSShapeConstructor(Cube2)
{
baseShape = "art/shapes/collada/queb/Cube.dae";

};

the object does load, does not animate, and the Material is still wrong. I looked at materials.cs, and it looks ok, I compared it to the file when it works (without adding the TSShapeConstructor part) and it is identical.

I did delete the cached.dts as you suggested.

Meanwhile, I don't understand why the animation is still not working, either.

Your help is appreciated.

Oh, this code, the materials are correct, the cube spins, everything works but no collision.

datablock StaticShapeData(Cube)
{
category = "collada";
shapeFile = "art/shapes/collada/queb/Cube.dae";
};

function Cube::OnAdd(%this,%obj)
{
%obj.playThread(0,"ambient");

#5
06/13/2009 (6:26 am)
FYI, If I leave out the TSShapeConstructor and preload part, I can load the spinning cube as many times as I want and the material is always correct.
#6
06/14/2009 (5:04 pm)
Very strange results. As an experiment, could you try re-ordering the code such that the TSShapeConstructor stuff appears first? ie.

function Cube2::onPreload(%this)
{
   %this.addMesh("cube", "bounds", "Col-1");
}

datablock TSShapeConstructor(Cube2)
{
   baseShape = "art/shapes/collada/queb/Cube.dae";
};


datablock StaticShapeData(Cube)
{
   category = "collada";
   shapeFile = "art/shapes/collada/queb/Cube.dae";
};

function Cube::onAdd(%this, %obj)
{
   %obj.playThread(0, "ambient");
}

It just occurred to me that the order of the datablocks might be significant, since TSShapeConstructor needs to add the collision mesh before StaticShapeData is instantiated (at which point it looks for the collision mesh).
#7
06/15/2009 (6:40 am)
Wow. I don't know what to do anymore. I reloaded a clean copy of the cube.dae file and the jpg, and here are the results:

1. copying code the way you have it above: cube appears in game w/ wrong texture, no collision mesh, and no animation.

2. Getting rid of the onPreload function and TSShapeConstuctor: Cube appears in game, with proper texture and proper animation. (no collision mesh, of course)

Therefore, I determine there is something possibly maybe could be wrong with the extended capabilities of TSShapeConstructor????

Just for grins I then tried this code (in the order as written below):

datablock TSShapeConstructor(Cube2)
{
baseShape = "art/shapes/collada/queb/cube.dae";

};

function Cube2::onPreload(%this)
{
%this.addMesh("cube","bounds", "Col-1");
}

Results: Proper collision mesh, improper texture. Object shows up as TSStatic when placed, but shows up under meshes/art/collada not the scripted tab.

However!! That code is NOT supposed to work in that order! From the official documentation:

"Because the onPreload function is called as soon as the script containing the TSShapeConstructor datablock is executed by the engine, the function must appear before the datablock (otherwise the engine will not be able to find the function as it has not been parsed yet!)".

Lastly, I tried this:

datablock TSShapeConstructor(Cube2)
{
baseShape = "art/shapes/collada/queb/cube.dae";

};

function Cube2::onPreload(%this)
{
%this.addMesh("cube","bounds", "Col-1");

}

datablock StaticShapeData(Cube)
{
category = "collada";
shapeFile = "art/shapes/collada/queb/cube.dae";
};

function Cube::OnAdd(%this,%obj)
{
%obj.playThread(0,"ambient");
}

Again, wrong texture, no animation, no collision mesh.

Well, I suppose there could be something wrong with my collada file, but why then does it seem to work perfectly with just the StaticShapeData and the onAdd function? Furthermore, why does the Preload function work (or partially work, since the mesh works, but the texture is wrong) even when placed *after* the TSShapeConstructor Datablock?

It appears to me there is something getting corrupted in the interaction of TSShapeConstuctor and StaticShapeData

I would appreciate it greatly if you would advise me what steps you think I could take next. And, as I said, my artist is very much a 3dsMax beginner, and I myself know nothing of Max, so if there is any possibility it could be my file, I will check that if you could tell me what to look for.