IMPORTANT NOTE: All declarations of TSShapeConstructor should use the singleton keyword instead of the datablock keyword which was used in the past.
TSShapeConstructor is a special object used to modify a DTS or COLLADA shape model after is has been loaded by Torque, but before it is used by any other object. It is often used to share animations from DSQ files between shapes with a common skeleton, or to gain access to the inner details of a shape.
This document describes extensions to TSShapeConstructor which allow dynamic modification of a loaded 3space shape such as adding and manipulating nodes, geometry and sequences. Torque 3D also includes an in-engine tool called Shape Editor which provides a visual means of creating and editing TSShapeConstructor objects. Additional functionality can be added by defining an 'onLoad' TorqueScript function which is called when the TSShapeConstructor object is loaded.
It may also be used to correct a model that is missing
the nodes and/or sequences required to function as a particular Torque
object. A model used for a Player character, for example, should have an
eye and a cam node, but these might not be present in a model not
specifically created for Torque. TSShapeConstructor allows the missing
nodes to be added and positioned so that the shape does not need to be
re-worked or re-exported by an artist.
To use TSShapeConstructor, simply create a TorqueScript
file in the same folder as your DTS or COLLADA model, with the same
filename but .cs extension. For example, if your model file was called
myShape.dts, you would create a file called myShape.cs. Edit this file
with a text editor to define the TSShapeConstructor object and specify
any operations to apply to the model after it has been loaded.
When Torque loads a DTS (.dts) or COLLADA (.dae) file, it
first looks in the same folder for a TorqueScript file with the same
filename (but .cs extension) in order to create the TSShapeConstructor
object. Such scripts are executed automatically by Torque 3D, so there
is no need to manually call exec("myShape.cs") from another script.
You should avoid adding other object and datablock declarations
to this script because it will be executed every time the model is
loaded, which may cause unexpected results.
After Torque has loaded the model from the DTS or COLLADA
file, it executes the TSShapeConstructor onLoad method to apply the defined changes to the shape. It should be noted that the
changes are applied to the loaded model in memory rather than to the DTS or COLLADA file itself. This means the model can
be re-exported to DTS or COLLADA without overwriting the
TSShapeConstructor changes. TSShapeConstructor should be thought of as
a post-export processing step, and is intended to be used alongside
existing object and datablock setups.
TSShapeConstructor also includes features to aid in loading
COLLADA models. Specifically, it allows the <up_axis> and
<unit> elements to be overridden, and can also apply a custom prefix to the names of COLLADA materials as shown below.
Prefixing material names is useful to avoid name clashes, particularly
for 3D apps like Google SketchUp that export models with generic
material names like "material0".
Code Sample 1
singleton TSShapeConstructor(MyShapeDae)
{
baseShape = "./myShape.dae";
upAxis = "DEFAULT"; // use <up_axis> defined in myShape.dae
unit = "1.0"; // override <unit> to be 1.0
matNamePrefix = ""; // no prefix applied to collada materials
};
singleton TSShapeConstructor(MyShape2Dae)
{
baseShape = "./myShape2.dae";
upAxis = "Y_AXIS"; // override <up_axis> to be Y_AXIS
unit = -1; // use <unit> defined in myShape2.dae
matNamePrefix = "myShape2_"; // prefix all collada material names with "myShape2_"
}
The name of the TSShapeConstructor object (MyShapeDae and
MyShape2Dae in the code sample above) is up to you, but you should
choose a name that does not conflict with other objects or datablocks.
A common convention for TSShapeConstructor objects is to use the name of the
shape file as the object name.
Note that DSQ sequences may still be specified within the TSShapeConstructor object as normal:
node: A node is a place-holder for transform (position
and rotation) information. Nodes are arranged in a parent/child
hierarchy allowing complex skeleton structures to be built up.
object: An object is a collection of meshes, each at a
different detail level. Each object is attached to a certain node, and
is rendered at that nodes current transform.
mesh: A mesh is a piece of geometry, and may be a
rigid body or a skin (vertex weighted mesh). Each mesh is associated
with an object and a certain detail level.
sequence: A sequence is a set of keyframed node transforms and object states (eg. visibility).
Example 1: Adding a Collision Mesh To an Existing Shape
Imagine you have a model that you want to add to the scene as a
StaticShape, but it is missing a collision mesh. TSShapeConstructor
makes it simple to modify an existing DTS shape to add a collision (or
line-of-sight collision) mesh.
First, define the StaticShapeData datablock as normal.
Create a script called myShape.cs in the art/datablocks folder, and
define the datablock:
This script will add a cube mesh with the same center and
dimensions as the original model using the "Col" detail level at size
-1. The negative detail size means that the cube mesh will not be
rendered in-game, and the use of the special "Col" name means that this
mesh will be detected as a collision mesh by the Torque engine. See the function
reference at the end of this document for more details on addMesh.
When a Torque mission is started, the following steps occur:
On the server, Torque executes art/datablocks/datablockExec.cs, which in turn executes art/datablocks/myShape.cs
Executing art/datablocks/myShape.cs causes the MyShapeData datablock to attempt to load the DTS file
Before loading the DTS file, Torque notices andexecutes art/shapes/myShape/myShape.cs, which creates the TSShapeConstructor object
After loading the DTS file, Torque executes MyShapeDts::onLoad, which adds the collision mesh to the shape
The StaticShape object can now be added to the scene (it will
appear in the world editor (in the "Misc" category under the
Library/Scripted tab)
Example 2: Adding a Mesh From an Existing DTS File
The image below shows a boulder.dts shape in the Torque Show Tool
Pro (TSTPro). The circled items indicate the geometry and material that
will be copied into a different shape using TSShapeConstructor.
The following shows how to include the boulder1 mesh in another shape:
The output of the dumpShape command is shown below.
The detail level referenced in the output refers to the size the object must be on the screen
before the specific mesh will be rendered. A mesh with a negative detail level
is not rendered.
Shape Hierarchy:
Details:
detail128, Subtree 0, objectDetail 0, size 128
detail2, Subtree 0, objectDetail 1, size 2
collision-1, Subtree 0, objectDetail 2, size -1
Subtrees:
Subtree 0
Rock2 --> Object Rock with following details: 2
--> Object test with following details: 128
col-1 --> Object col with following details: -1
Sequences:
Material list:
material #0: 'rock2'.
material #1: 'MossyRock02'.
Note that the new detail ("detail128"), object ("test") and material
("MossyRock02") have been added to the normal rock1.dts shape.
Example 3: Auto-loading animations
Instead of manually specifying all of the animations to load, its
easy to write some TorqueScript that will scan a folder for any
matching animations and add them to the shape automatically. This example uses the addSequence function, and demonstrates the flexibility and power of TSShapeConstructor.
Code Sample 6
singleton TSShapeConstructor(ForgeSoldierDts)
{
baseShape = "~/data/shapes/actors/ForgeSoldier/ForgeSolder.dts";
};
function ForgeSoldierDts::onLoad(%this)
{
AddAnimations(%this);
}
function AddAnimations(%shape)
{
// Scan for all player_*.dsq files and add the animations to the shape.
// Sequence names are taken from the base name of the dsq file. eg.
// player_run.dsq would add a sequence called 'run'.
%filePatterns = "art/shapes/actors/animations/player_*.dsq";
%fullPath = findFirstFileMultiExpr(%filePatterns);
while (%fullPath !$= "")
{
// add this animation to the shape
%fullPath = makeRelativePath(%fullPath, getMainDotCSDir());
%seq_name = strreplace(filebase(%fullPath), "player_", "");
%shape.addSequence(%fullpath, %seq_name);
%fullPath = findNextFileMultiExpr(%filePatterns);
}
}
Example 4: Splitting COLLADA animations
Many COLLADA exporters do not support the <animation_clip>
element, meaning that animated models imported into Torque appear to
have only a single sequence containing all of the animations.
If you know the keyframe ranges used in the individual animations, TSShapeConstructor can be used to split this combined animation into individual sequences. This is most easily done using the Shape Editor tool, but can be done manually by specifying the source sequence name, new sequence name, start and end keyframes as follows:
Code Sample 7
singleton TSShapeConstructor(PlayerModelDts)
{
baseShape = "~/data/shapes/collada/myPlayer.dae";
};
function PlayerModelDts::onLoad(%this)
{
// Split animations from combined "ambient" sequence
%this.addSequence("ambient", "root", 0, 15);
%this.addSequence("ambient", "run", 16, 40);
%this.addSequence("ambient", "back", 41, 55);
%this.addSequence("ambient", "side", 56, 70);
%this.addSequence("ambient", "death0", 80, 120);
// Remove combined "ambient" sequence => we don't need it anymore
%this.removeSequence("ambient");
}
Example 5: Rigid-body Player Character
Using the addNode and addMesh functions, it is possible to create a rigid-body (ie. non-skinned) player model compatible with the default animations, completely from TorqueScript. This is extremely powerful, and demonstrates the full range of functionality available.
The default player skeleton node transforms were obtained
by adding the following code to the TSShapeConstructor onLoad function
for a shape that already contained the default skeleton:
The contents of the console can then be copied and pasted into a new
script. The script below shows the player model creation process: first
pick a dummy dts file (rock1.dts in this case), and delete its existing
nodes and meshes. Then create the default player skeleton. Finally,
some cube meshes are added at certain nodes to build up a rigid-body
player character.
Code Sample 9
// Create the default Torque skeleton (compatible with the default player animations)
function CreateDefaultSkeleton(%shape)
{
%shape.addNode("Bip01 Pelvis", "",
"-8.10647e-005 8.34974e-006 1.28118 0.00147092 0.999914 0.000312013 1.50833");
%shape.addNode("Bip01 Spine", "Bip01 Pelvis",
"0.117738 -0.000117005 0.00695224 0.995531 0 0.054662 0.178899");
%shape.addNode("Bip01 Spine1", "Bip01 Spine",
"0.149188 -0.000154936 5.87594e-006 0.158383 0.207314 0.965104 0.285376");
%shape.addNode("Bip01 Spine2", "Bip01 Spine1",
"0.202462 -0.000162536 2.93078e-005 0.731516 -0.35723 -0.579706 0.251143");
%shape.addNode("Bip01 Neck", "Bip01 Spine2",
"0.209867 -4.86846e-005 -2.05922e-005 -0.926274 0.0899337 -0.365008 0.431595");
%shape.addNode("Bip01 Head", "Bip01 Neck",
"0.067264 -6.98505e-009 -6.66524e-009 -0.139433 0.872649 -0.450268 0.089769");
%shape.addNode("Eye", "Bip01 Head",
"0.180021 0.33282 -0.00125568 -0.0139777 -0.999387 0.030751 1.57784");
%shape.addNode("Bip01 L Clavicle", "Bip01 Neck",
"0.0059334 0.0332864 0.0795624 -0.632128 -0.230228 -0.739819 2.58923");
%shape.addNode("Bip01 L UpperArm", "Bip01 L Clavicle",
"0.358891 -1.27006e-008 1.34618e-007 0.300944 -0.93298 0.197112 1.51847");
%shape.addNode("Bip01 L Forearm", "Bip01 L UpperArm",
"0.395474 -1.37648e-008 1.96789e-008 0 0 0.999871 0.850149");
%shape.addNode("Bip01 L Hand", "Bip01 L Forearm",
"0.363508 3.95569e-008 3.80099e-008 -0.975012 -0.0676349 0.211535 3.8945");
%shape.addNode("Bip01 R Clavicle", "Bip01 Neck",
"-0.00593357 -0.0331793 -0.0795624 0.631473 -0.0957054 -0.769459 3.0916");
%shape.addNode("Bip01 R UpperArm", "Bip01 R Clavicle",
"0.358891 -1.02138e-008 1.01681e-007 0.594451 0.803854 -0.017401 1.47305");
%shape.addNode("Bip01 R Forearm", "Bip01 R UpperArm",
"0.395474 6.19864e-008 1.31302e-008 0 0 0.999951 1.88239");
%shape.addNode("Bip01 R Hand", "Bip01 R Forearm",
"0.363508 1.03579e-008 -1.18848e-008 -0.976003 -0.105148 0.190568 1.71108");
%shape.addNode("mount0", "Bip01 R Hand",
"0.192386 0.0479768 0.000897807 0.0616579 0.0736096 0.995312 1.76131");
%shape.addNode("mount2", "Bip01 Spine2",
"0.101603 -0.255502 0.00682753 0.0431623 -0.998124 -0.0431623 1.57267");
%shape.addNode("mount1", "Bip01 Spine2",
"0.101603 -0.255502 0.00682756 0.0431623 -0.998124 -0.0431623 1.57267");
%shape.addNode("Bip01 L Thigh", "Bip01 Spine",
"-0.117582 -0.0342993 0.1847 -0.227865 -0.966002 -0.121932 3.27836");
%shape.addNode("Bip01 L Calf", "Bip01 L Thigh",
"0.567764 2.88694e-008 -2.61884e-009 0 0 0.999795 0.784881");
%shape.addNode("Bip01 L Foot", "Bip01 L Calf",
"0.659264 6.37417e-009 5.70856e-009 -0.0798252 0.398941 -0.913186 0.331842");
%shape.addNode("Ski0", "Bip01 L Foot",
"0.587469 -0.0426512 -0.0990439 0.750521 0.554827 0.358877 1.9778");
%shape.addNode("Bip01 R Thigh", "Bip01 Spine",
"-0.117896 0.0347 -0.198562 -0.134559 -0.982239 0.130533 2.9039");
%shape.addNode("Bip01 R Calf", "Bip01 R Thigh",
"0.567764 8.48371e-010 1.88575e-009 0 0 0.999915 0.836729");
%shape.addNode("Bip01 R Foot", "Bip01 R Calf",
"0.659264 -3.34983e-008 -2.20877e-008 0.0784375 -0.241304 -0.967069 0.567876");
%shape.addNode("Ski1", "Bip01 R Foot",
"0.600815 -0.0369749 0.0998079 -0.352371 -0.698146 -0.62318 3.91937");
%shape.addNode("Unlink", "",
"-0.00586435 -0.000234549 0.056661 -0.579417 -0.577691 -0.574872 2.09521");
%shape.addNode("Cam", "Unlink",
"0.237214 2.06536 -0.00742381 0.999942 -0.00266823 -0.00189359 1.57655");
}
// Create a new cube mesh, then attach it to the specified node
function CreateCubeObject(%shape, %name, %node, %size)
{
%shape.addMesh("cube", %size, %name @ "2");
%shape.setObjectNode(%name, %node);
}
// Create a simple (rigid) player model using boxes for body parts
function CreateRigidPlayer(%shape)
{
CreateCubeObject(%shape, "head", "Eye", "0.2 0.2 0.3");
CreateCubeObject(%shape, "upper_torso", "Bip01 Spine2", "0.3 0.2 0.4");
CreateCubeObject(%shape, "lower_torso", "Bip01 Spine", "0.3 0.2 0.35");
CreateCubeObject(%shape, "left_thigh", "Bip01 L Thigh", "0.5 0.2 0.2 0.25 0 0");
CreateCubeObject(%shape, "left_leg", "Bip01 L Calf", "0.4 0.2 0.2 0.25 0 0");
CreateCubeObject(%shape, "left_foot", "Bip01 L Foot", "0.2 0.2 0.2");
CreateCubeObject(%shape, "right_thigh", "Bip01 R Thigh", "0.5 0.2 0.2 0.25 0 0");
CreateCubeObject(%shape, "right_leg", "Bip01 R Calf", "0.4 0.2 0.2 0.25 0 0");
CreateCubeObject(%shape, "right_foot", "Bip01 R Foot", "0.2 0.2 0.2");
CreateCubeObject(%shape, "left_upper_arm", "Bip01 L UpperArm", "0.3 0.15 0.15 0.15 0 0");
CreateCubeObject(%shape, "left_forearm", "Bip01 L Forearm", "0.2 0.15 0.15 0.1 0 0");
CreateCubeObject(%shape, "left_hand", "Bip01 L Hand", "0.15 0.15 0.15");
CreateCubeObject(%shape, "right_upper_arm", "Bip01 R UpperArm", "0.3 0.15 0.15 0.15 0 0");
CreateCubeObject(%shape, "right_forearm", "Bip01 R Forearm", "0.2 0.15 0.15 0.1 0 0");
CreateCubeObject(%shape, "right_hand", "Bip01 R Hand", "0.15 0.15 0.15");
// create collision mesh
%shape.addMesh("cube", "bounds", "Col-1");
}
singleton TSShapeConstructor(TestModelDts)
{
baseShape = "~/data/shapes/rocks/rock1.dts";
};
function TestModelDts::onLoad(%this)
{
// remove the existing nodes and geometry so we start with a blank shape
%count = %this.getObjectCount();
for (%i = %count-1; %i >= 0; %i--)
%this.removeObject(%this.getObjectName(%i));
%count = %this.getNodeCount();
for (%i = %count-1; %i >= 0; %i--)
%this.removeNode(%this.getNodeName(%i));
// create the player skeleton and rigid body parts
CreateDefaultSkeleton(%this);
CreateRigidPlayer(%this);
// now load the default sequences
%this.addSequence("~/data/shapes/players/animations/player_root.dsq", "root");
%this.addSequence("~/data/shapes/players/animations/player_forward.dsq", "run");
%this.dumpShape();
}
// The player model definition
singleton PlayerData(TestModelData : DefaultPlayerData)
{
renderFirstPerson = false;
emap = true;
//className = Armor;
shapeFile = "~/data/shapes/rocks/rock1.dts";
};
PlayerDatasGroup.add(TestModelData);
This produces the following shape:
Shape Hierarchy:
Details:
detail2, Subtree 0, objectDetail 0, size 2
collision-1, Subtree 0, objectDetail 1, size -1
Subtrees:
Subtree 0
Bip01 Pelvis --> Object col with following details: -1
Bip01 Spine --> Object lower_torso with following details: 2
Bip01 Spine1
Bip01 Spine2 --> Object upper_torso with following details: 2
Bip01 Neck
Bip01 Head
Eye --> Object head with following details: 2
Bip01 L Clavicle
Bip01 L UpperArm --> Object left_upper_arm with following details: 2
Bip01 L Forearm --> Object left_forearm with following details: 2
Bip01 L Hand --> Object left_Hand with following details: 2
Bip01 R Clavicle
Bip01 R UpperArm --> Object right_upper_arm with following details: 2
Bip01 R Forearm --> Object right_forearm with following details: 2
Bip01 R Hand --> Object right_hand with following details: 2
Mount0
Mount2
Mount1
Bip01 L Thigh --> Object left_thigh with following details: 2
Bip01 L Calf --> Object left_leg with following details: 2
Bip01 L Foot --> Object left_foot with following details: 2
Ski0
Bip01 R Thigh --> Object right_thigh with following details: 2
Bip01 R Calf --> Object right_leg with following details: 2
Bip01 R Foot --> Object right_foot with following details: 2
Ski1
Unlink
Cam
Sequences:
0: Root (cyclic)
1: run (cyclic)
TSShapeConstructor Commands
Miscellaneous
dumpShape([string])
This command dumps the shape hierarchy to the console or to a file.
It is useful for reviewing the result of a series of construction
commands.
Syntax
dumpShape([string filename])
filename: Optional. name of the file to dump the shape hierarchy to. If not specified, the shape hierarchy is dumped to the console.
Returns
No return value.
Examples
%this.dumpShape(); // dump to console
%this.dumpShape("./dump.txt"); // dump to file
saveShape(string)
This command saves the shape to a new DTS file. Handy after modifications via script.
Syntax
saveShape(string filename)
filename: name of the file to write the shape.
Returns
No return value.
Examples
%this.saveShape("./myShape.dts");
Nodes
getNodeCount()
This command returns the total number of nodes in the shape.
Syntax
getNodeCount()
Returns
S32
Examples
%count = %this.getNodeCount();
getNodeIndex(string)
This command retrieves the index of the named node. If a node with
the specified name cannot be found, the command will return -1.
Syntax
getNodeIndex(string node_name);
node_name: the name of the node to get the index for
Returns
S32
Examples
// get the index of Bip01 Pelvis node in the shape
%index = %this.getNodeIndex("Bip01 Pelvis");
getNodeName(S32)
This command retrieves the name of the indexed node.
Syntax
getNodeName(S32 index);
index: the index of the node to get (valid range is 0 – (num_nodes-1))
Returns
string
Examples
// print the names of all the nodes in the shape
%count = %this.getNodeCount();
for (%i = 0; %i < %count; %i++)
echo(%i SPC %this.getNodeName(%i));
getNodeParentName(S32)
This command retrieves the name of the nodes parent. If the node
has no parent (ie. it is at the root level), this command will return
an empty string.
This command retrieves the name of the nodes parent. If the node
has no parent (ie. it is at the root level), this command will return
an empty string.
Syntax
getNodeChildCount(string node_name);
node_name: the name of the parent node to query
Returns
S32
Examples
%count = %this.getNodeChildCount("Bip01 Pelvis");
getNodeChildName(string, S32)
This command retrieves the name of the indexed child node. Note that
the indices in this case range from 0 to one less than the value returned by
getNodeChildCount.
This command retrieves the number of objects attached to a node.
Syntax
getNodeObjectCount(string node_name)
node_name: the name of the node to query
Returns
S32
Examples
%count = %this.getNodeObjectCount("Bip01 Head");
getNodeObjectName(string, S32)
This command is used to get the name of an object attached to the
node. Note that the object indices range from 0 to the value returned
by getNodeObjectCount.
// print the names of all objects attached to the node
%count = %this.getNodeObjectCount("Bip01 Head");
for (%i = 0; %i < %count; %i++)
echo(%this.getNodeObjectName("Bip01 Head", %i));
getNodeTransform(string)
This command is used to retrieve the base (ie. not animated) transform of a node.
node_name: the name of the node for which to get the transform
isworld: Optional. Flag indicating whether to
retrieve the local-to-parent or the global transform. If not specified,
the local-to-parent transform is returned.
px py pz: 3 values indicating the new node position
rx ry rz ra: Optional. 4 values indicating the
new node orientation. The orientation is specified in axis-angle form.
ie. the axis of rotation and the angle (in radians) to rotate around
that axis. Default is "0 0 1 0".
isworld: Optional. Flag indicating whether to
set the local-to-parent or the global transform. If not specified, the
position and orientation are treated as relative to the node's parent.
name: the name of the new node – must not be the same as an existing node.
parent_name: the name of an existing node to be the
parent of the new node. If empty (""), the new node will be at the root
level of the node hierarchy.
px py pz: Optional. 3 values indicating the
position of the new node. Note that this is relative to the parent
nodes transform (or the origin if there is no parent). Default is "0 0
0".
rx ry rz ra: Optional. 4 values indicating the
new node orientation (note that this is relative to the parent nodes
transform. The orientation is specified in axis-angle form. ie. the
axis of rotation and the angle (in radians) to rotate around that axis.
Default is "0 0 1 0".
isworld: Optional. Flag indicating whether to
set the local-to-parent or the global transform. If not specified, the
position and orientation are treated as relative to the node's parent.
This command removes the named node from the shape, including from
any sequences that use the node. Child nodes and objects attached to
the node are re-assigned to the node's parent.
Syntax
removeNode(string node_name)
node_name: the name of the node to remove
Returns
boolean flag indicating success
Examples
%this.removeNode("Nose");
Objects
getObjectCount()
This command is used to get the total number of objects in the shape.
Syntax
getObjectCount()
Returns
S32
Examples
%count = %this.getObjectCount();
getObjectName(S32)
This command is used to get the name of the indexed object.
Syntax
getObjectName(S32 index)
index: the index of the object for which to get the name
Returns
string
Examples
// print the names of all objects in the shape
%count = %this.getObjectCount();
for (%i = 0; %i < %count; %i++)
echo(%i SPC %this.getObjectName(%i));
getObjectNode(string)
This command is used to get the name of the node that an object is
attached to. If the object is not attached to a node (ie. it is at the
root level), this command will return an empty string.
Syntax
getObjectNode(string object_name)
object_name: the name of the object to query
Returns
string
Examples
echo("Hand is attached to " @ %this.getObjectNode("Hand"));
setObjectNode(string, string)
This command is used to set the node that an object is attached to.
When the shape is rendered, the object geometry is rendered at the
nodes current transform. Useful in mounting weapons to
node_name: the name of the node to attach the object to
Returns
boolean flag indicating success
Examples
%this.setObjectNode("Hand", "Bip01 LeftHand");
renameObject(string, string)
This command is used to rename an object (all detail level meshes for the object will be renamed).
Syntax
renameObject(string old_name, string new_name)
old_name: old object name
new_name: new name of the object
Returns
boolean flag indicating success
Examples
%this.renameObject("MyBox", "Box");
removeObject(string)
This command is used to remove an object (including all meshes for that object) from the shape.
Syntax
removeObject(string object_name)
object_name: the name of the object to remove
Returns
boolean flag indicating success
Examples
// clear all objects in the shape
%count = %this.getObjectCount();
for (%i = %count-1; %i >= 0; %i--)
%this.removeObject(%this.getObjectName(%i));
Meshes
getMeshCount(string)
This command is used to get the number of meshes for a given object.
Syntax
getMeshCount(string object_name)
object_name: the name of the object to query
Returns
S32
Examples
%count = %this.getMeshCount("SimpleShape");
getMeshname(string, S32)
This command is used to get the name of the indexed mesh within a
given object. Mesh names are of the form:
<object_name><detail_size>. eg. SimpleShape128 is the mesh
with detail size 128 for the SimpleShape object.
Syntax
getMeshName(string object_name, S32 index)
object_name: the name of the object to query
index: the index of the mesh for which to get the name
Returns
string
Examples
// print the names of all meshes in the shape
%objCount = %this.getObjectCount();
for (%i = 0; %i < %objCount; %i++)
{
%objName = %this.getObjectName(%i);
%meshCount = %this.getMeshCount(%objName);
for (%j = 0; %j < %meshCount; %j++)
echo(%this.getMeshName(%objName, %j));
}
setMeshSize(string, S32)
This command is used to change the detail size of a mesh.
Syntax
setMeshSize(string mesh_name, S32 new_size)
mesh_name: the name of the mesh
new_size: new size for the mesh
Returns
boolean flag indicating success
Examples
%this.setMeshSize("SimpleShape128", 64);
getMeshType(string)
This command is used to retrieve the type of a particular mesh. The returned value is one of:
normal: a normal 3D mesh
billboard: a mesh that always faces the camera
billboardzaxis: a mesh that always faces the camera in the Z-axis
Syntax
getMeshType(string mesh_name)
mesh_name: the name of the mesh to query
Returns
string
Examples
echo("Mesh type is " @ %this.getMeshType("SimpleShape128"));
setMeshType(string, string)
This command is used to set the type of a particular mesh; the type affects how the mesh will be rendered in-game.
Syntax
setMeshType(string mesh_name, string mesh_type)
mesh_name: the name of the mesh to query
mesh_type: the new type for the mesh. Must be one of "normal", "billboard" or "billboardzaxis".
Returns
boolean flag indicating success
Examples
// set the mesh to be a billboard
%this.setMeshType("SimpleShape64", "billboard");
getMeshMaterial(string)
This command is used to retrieve the name of the material attached
to a mesh. Note that only the first material used by the mesh is
returned.
Syntax
getMeshMaterial(string mesh_name)
mesh_name: the name of the mesh to query
Returns
string
Examples
echo("Mesh material is " @ %this.sgetMeshMaterial("SimpleShape128"));
setMeshMaterial(string, string)
This command is used to set the name of the material attached to the mesh.
material_name: the new material name. This could be the
base name of the diffuse texture (eg. "test_mat" for "test_mat.jpg"),
or the name of a Material object already defined in script.
Returns
boolean flag indicating success
Examples
// set the mesh material
%this.setMeshMaterial("SimpleShape128", "test_mat");
addMesh(string, string, string)
This command is used to add new geometry to the shape. There are two
forms to this command as shown below. The first form copies geometry
from an existing DTS or DAE shape file. The second form generates the
mesh geometry programmatically using a set of predefined geometry
primitives (eg. cube, sphere, cylinder etc).
When a mesh is copied from an existing shape file, any
materials required by that mesh are also copied into the constructed
shape.
The Torque engine uses fixed names to extract collision and
line-of-sight (LOS) collision geometry from the shape. When adding this
type of geometry to a shape, it is essential that the mesh_name
parameter be set as shown in the table below:
Geometry type
mesh_name
Normal (visible)
any_nameN (where N is > 0)
Collision
ColN (where N is -1 to -8)
LOS Collision
LOSColN (where N is -9 to -16)
If no detail size is present at the end of the name, a value
of 2 is used. An underscore before the number at the end of the name
will be interpreted as a negative sign. eg. "MyMesh_4" will be
interpreted as "MyMesh-4".
prim_type: the type of geometric primitive to use. Currently only "cube" is supported.
prim_size: the size and center of the geometric
primitive - either "bounds" or "size.x size.y size.z center.x center.y
center.z" format. The center values are optional (ie. just the size can
be specified and center will default to "0 0 0").
mesh_name: name of the new mesh, using the form <object_name><detail_size>. eg. SimpleShape128
This command is used to add an auto-billboard detail level to the
shape. Auto-billboards are special detail levels that render a series
of 'snapshots of an object that always face the camera rather than
actual 3D geometry. They are frequently used for the lowest detail
level of an object.
equator_steps: defines the number of snapshots to take
around the equator. Imagine the object being rotated around the
vertical axis, then a snapshot taken at regularly spaced intervals.
polar_steps: defines the number of snapshots taken
between the poles, at each equator step. eg. At each equator snapshot,
snapshots are taken at regular intervals between the poles.
dl: the detail level to use when generating the
snapshots. Note that this is an array index rather than a detail size.
So if an object has detail sizes of: 200, 150, and 40, then setting dl
to 1 will generate the snapshot using detail size 150.
dim: defines the size of the billboard images in
pixels (must be a power of 2: eg. 2, 4, 8, 16….128). The larger the
number, the more detailed the billboard will be.
include_poles: flag indicating whether to include the "pole" snapshots. ie. the views from the top and bottom of the object.
polar_angle: if pole snapshots are active
(include_poles is true), this parameter defines the camera angle within
which to render the pole snapshot. eg. if polar_angle is set to 25
degrees, then the snapshot taken at the pole (looking directly down or
up at the object) will be rendered when the camera is within 25 degrees
of the pole.
This command is used to remove an auto-billboard detail level from the shape.
Syntax
removeAutoBillboard(S32 size)
size: the size of the auto-billboard detail level to remove
Returns
boolean flag indicating success
Examples
%this.removeAutoBillboard(2);
Sequences
getSequenceCount()
This command is used to get the total number of animation sequences present in the shape.
Syntax
getSequenceCount()
Returns
S32
Examples
%count = %this.getSequenceCount();
getSequenceIndex(S32)
This command is used to get the index of the named sequence. If the sequence does not exist, the command will return -1.
Syntax
getSequenceIndex(string sequence_name)
sequence_name: the name of the sequence to get the index of
Returns
S32
Examples
// Check if a given sequence exists in the shape
if (%this.getSequenceIndex("walk") == -1)
echo("Could not find 'walk' sequence");
getSequenceName(S32)
This command is used to get the name of the indexed sequence.
Syntax
getSequenceName(S32 index)
index: the index of the sequence for which to get the name
Returns
string
Examples
// print the name of all sequences in the shape
%count = %this.getSequenceCount();
for (%i = 0; %i < %count; %i++)
echo(%i SPC %this.getSequenceName(%i));
getSequenceSource(S32)
This command is used to get information about where the sequence
data came from, for example, whether it was loaded from an external DSQ
file.
Syntax
getSequenceSource(string sequence_name)
sequence_name: the name of the sequence to retrieve information for
source_data: the source of the animation data, such as
the path to a DSQ file, or the name of an existing sequence in the
shape. Sequences already embedded in DTS or DAE files will use the
sequence name itself in this field.
reserved: reserved value
start_frame: the first frame in the source sequence used to create this sequence
end_frame: the last frame in the source sequence used to create this sequence
total_frames: the total number of frames in the source sequence
Examples
// print the source for the walk animation
echo("walk source:" SPC getField(%this.getSequenceSource("walk"), 0));
getSequenceFrameCount(string)
This command is used to get the number of keyframes in a sequence.
Syntax
getSequenceFrameCount(string sequence_name)
sequence_name: name of the sequence to query
Returns
S32
Examples
echo("Run has " @ %this.getSequenceFrameCount("run") @ " keyframes");
getSequencePriority(string)
This command is used to get the priority of a sequence.
This command is used to set the priority of a sequence. Priority is used to establish order of importance when multiple sequences operate on the same skeletal node.
blend_flag: a boolean flag indicating whether this sequence is a blend
blend_seq_name: the name of the sequence that contains the reference frame (empty for blend sequences embedded in DTS files)
blend_seq_frame: the blend reference frame (empty for blend sequences embedded in DTS files)
Note that only sequences set to be blends using the setSequenceBlend command will contain the blend_seq_name and blend_seq_frame information.
Examples
%blendData = %this.getSequenceBlend("look");
if (getField(%blendData, 0))
echo("look is a blend, reference: " @ getField(%blendData, 1));
setSequenceBlend(string, bool, string, S32)
This command is used to make an animation sequence a blend
sequence, that is,
a sequence that will be added on top of any other playing sequences.
This is done by storing the animated node transforms relative to a
reference frame, rather than as absolute transforms. Commonly used for things like head turns/nods, or weapon aiming.
sequence_name: the name of an existing sequence on which to set the blend flag
blend_flag: state of the blend flag (true or false)
blend_seq_name: the name of the sequence that contains the blend reference frame.
blend_seq_name: the reference frame in the blend_seq_name sequence.
Returns
boolean flag indicating success
Examples
%this.setSequenceBlend("look", true, "root", 0);
getSequenceGroundSpeed(string)
This command returns the ground speed of an animation sequence in
the form "tx ty tz rx ry rz". Note that only the first 2 ground frames
of the sequence are examined; the speed is assumed to be constant
throughout the sequence. Ground speed information is used to switch between walk and run states.
Syntax
getSequenceGroundSpeed(string sequence_name)
sequence_name: name of the sequence to query
Returns
string
"tx ty tz rx ry rz"
Examples
%speed = VectorLen(getWords(%this.getSequenceGroundSpeed("run"), 0, 2));
echo("Run moves at " @ %speed @ " units per frame");
setSequenceGroundSpeed(string, string, [string])
This command is used to set the ground speed of an animation
sequence by generating ground transform keyframes. The ground
translational and rotational speed is assumed to be constant for the
duration of the sequence. Existing ground frames for the sequence (if
any) will be replaced.
Syntax
setSequenceGroundSpeed(string sequence_name, string tx ty tz, [string rx ry rz])
sequence_name: name of the sequence to modify
tx ty tz: ground translational speed in the X, Y and Z axes
rx ry rz: Optional. Ground rotational speed around the X, Y and Z axes.
This command is used to rename an animation sequence.
Syntax
renameSequence(string old_name, string new_name)
old_name: old sequence name
new_name: new name of the sequence
Returns
boolean flag indicating success
Examples
%this.renameSequence("walking", "walk");
addSequence(string, string, [S32], [S32]
This command is used to add a new sequence to the shape. The
sequence can be a subset of frames from an existing sequence in the
shape, or loaded from a different file altogether.
sequence_or_shape_file: the name of an existing
sequence, or the name of a DTS or DAE shape or DSQ sequence file. When
the shape file contains more than one sequence, the desired sequence
can be specified by appending the name to the end of the shape file.
eg. "myShape.dts run" would select the "run" sequence from the
"myShape.dts" file.
new_name: the name of the new sequence.
start_frame: Optional. The first sequence frame to copy. Defaults to 0: the first frame in the sequence.
end_frame: Optional. The last sequence frame to copy. Defaults to -1: the last frame in the sequence.
Returns
boolean flag indicating success
Examples
%this.addSequence("./testShape.dts ambient", "ambient");
%this.addSequence("./myPlayer.dae run", "run");
%this.addSequence("./player_look.dsq", "look", 0, -1); // start to end
%this.addSequence("walk", "walk_shortA", 0, 4); // start to frame 4
%this.addSequence("walk", "walk_shortB", 4, -1); // frame 4 to end
removeSequence(string)
This command is used to remove an animation sequence from the shape.
Syntax
removeSequence(string sequence_name)
sequence_name: the name of the sequence to remove
Returns
boolean flag indicating success
Examples
%this.removeSequence ("Run");
getTriggerCount(string)
This command returns the number of triggers in a sequence.
This command returns the frame and state of a trigger in the sequence.
Syntax
getTrigger(string sequence_name, S32 index)
sequence_name: the name of the sequence to query
index: index of the trigger to get
Returns
The string returned is of the form:
trigger_frame SPC trigger_state
Examples
// print all triggers in the sequence
%count = %this.getTriggerCount("back");
for (%i = 0; %i < %count; %i++)
echo(%i SPC %this.getTrigger("back", %i));
addTrigger(string, S32, S32)
This command is used to add a new trigger to a sequence in the shape. A trigger is used to fire off some kind of code event when the animation reaches the given keyframe. Very useful for footprints or attack animations.
sequence_name: the name of an existing sequence to add the trigger to
keyframe: the frame in the sequence at which to set the trigger (the frames for each sequence start at 0)
state: the trigger index (1-30) and on/off state (usually +ve for on and –ve for off)
Returns
boolean flag indicating success
Examples
%this.removeTrigger("walk", 3, 1);
Conclusion
From this document, you should have a better understanding of how to use the new TSShapeConstructor.
There are several ways you can take advantage of the module, so be sure
to bookmark this article so you can refer back to the examples and
command list.