Game Development Community

FAQs and helpful info about TorqueX 3D

by Russell Bishop · in Torque X 2D · 04/08/2008 (4:51 pm) · 20 replies

Here is a quick jot down of some of my notes while trying to get going on TorqueX. There is absolutely, positively zero documentation for the 3D stuff and the Torque Developers Network wiki page on TorqueX is as good as empty.

I sincerely hope this information will be useful to others. I may try to edit it into a wiki page at some point.



1. You'll get a failure if you bring in a model without any materials defined (such as for testing), because the T3DTSRenderComponent has no Materials defined and you'll get a NullReference exception when it tries to render. Add this code to the ShapeName property setter, just above the "Shape = shape;" line.

Note: You must have a DefaultMaterial texture in the folder with your shapes for this to work. I just created a blank white bitmap in visual studio.


if (shape.MaterialList == null || shape.MaterialList.Length == 0)
     {
          shape.MaterialList = new Material[] { new Material() };
          shape.MaterialList[0].Name = "DefaultMaterial";
     }



2. Rendering Collision Bounds doesn't work. CollisionShape3D sets _material = new LightingMaterial(); for rendering collision bounds, but that doesn't do squat. In LightingMaterial, _SetupObjectParameters, the arrays are null/empty so you get an IndexOutOfBounds exception.



3. The default starter game has no sun, so no light sources defined. You can add one easily to the XML.
Note: The sun will render as a white plane in the middle of the sky unless a FogMaterial is defined.

in scenedata:
    <FogMaterial nameRef="DistanceFogMaterial" />    
    <Sun type="GarageGames.Torque.T3D.Sun" name="Sun">
      <Material1 nameRef="SunMaterial1" />
      <Material2 nameRef="SunMaterial2" />
      <Size>35</Size>
      <RotationSpeed1>0</RotationSpeed1>
      <RotationSpeed2>0</RotationSpeed2>
      <Scale1>1</Scale1>
      <Scale2>0.8</Scale2>
      <Components inPlace="true">
        <SceneComponent type="GarageGames.Torque.T3D.T3DSceneComponent" />
        <LightComponent type="GarageGames.Torque.Lighting.T3DLightComponent">
          <LightList>
            <Light type="GarageGames.Torque.Lighting.DirectionalLight">
              <DiffuseColor>
                <X>0.9</X>
                <Y>0.9</Y>
                <Z>0.63</Z>
              </DiffuseColor>
              <AmbientColor>
                <X>0.4</X>
                <Y>0.5</Y>
                <Z>0.65</Z>
              </AmbientColor>
              <Direction>
                <X>0</X>
                <Y>-0.8191521</Y>
                <Z>-0.5735765</Z>
              </Direction>
              <ConstantAttenuation>1.0</ConstantAttenuation>
            </Light>
          </LightList>
        </LightComponent>
      </Components>
    </Sun>


in materials:
    <SunMaterial type="GarageGames.Torque.Materials.SimpleMaterial" name="SunMaterial1">
      <TextureFilename>data/skies/corona01</TextureFilename>
    </SunMaterial>
    <SunMaterial type="GarageGames.Torque.Materials.SimpleMaterial" name="SunMaterial2">
      <TextureFilename>data/skies/corona02</TextureFilename>
    </SunMaterial>
    <FogMaterial type="GarageGames.Torque.Materials.DistanceFog" name="DistanceFogMaterial">
      <FogColorAsVector3>
        <X>0.941</X>
        <Y>0.859</Y>
        <Z>0.612</Z>
      </FogColorAsVector3>
      <FogNearDistance>700</FogNearDistance>
      <FogFarDistance>1000</FogFarDistance>
    </FogMaterial>

#1
04/08/2008 (4:51 pm)
4. Default starter game 3D doesn't define collision bounds for terrain so objects will just fall through. Again, add this to the XML:
in scene data:
<RigidManager type="GarageGames.Torque.T3D.RigidCollision.RigidCollisionManager" name="RigidManager" />

on terrain object:
     <Components>
          <SceneComponent type="GarageGames.Torque.T3D.T3DSceneComponent" />
          <RigidComponent type="GarageGames.Torque.T3D.T3DRigidComponent">
               <RenderCollisionBounds>false</RenderCollisionBounds>
               <CollisionShapes>
                    <CollisionShape>
                         <Shape type="GarageGames.Torque.T3D.RigidCollision.CollisionXTerrainShape" />
                    </CollisionShape>
               </CollisionShapes>
               <GravityScale>0.0</GravityScale>
               <Immovable>true</Immovable>
               <RigidManager nameRef="RigidManager" />
               <RigidMaterial type="GarageGames.Torque.T3D.RigidCollision.RigidMaterial">
                    <Restitution>0.0</Restitution>
                    <KineticFriction>1.0</KineticFriction>
                    <StaticFriction>1.0</StaticFriction>
               </RigidMaterial>
          </RigidComponent>
     </Components>



5. Multisampling/anti-aliasing doesn't work on windows so don't waste your time trying to figure it out. I tried adding the proper code to the PrepareDeviceParams event handler in the engine but it still wouldn't work. I don't know if I am missing something minor or there is something funky with the way the engine manages render targets, but either way save yourself the headache and forget about it right now.


FAQs:

What about Megaterrain or Atlas? Nope, limited to plain .ter files. Not sure what the texture size limit is, but you can't have the artist just create a huge 32k by 32k texture and swap bits of it in and out. Artist will need to create a handful of textures, probably 256x256, then go in and paint the heightmap.


Is there a Terrain editor? Nope, but I'm working on one. Currently, you can download the TGE demo and use that to create .ter files with the terrain. Your assigned textures go into a terrain folder next to the ter file (see XML), then a detail texture can be drawn over top of all that (see XML). I'm modifying the XNATerrainEditor but it needs a lot of TLC to make it more usable right now.


What about a mission/level editor? Not yet, but the 3D version of TorqueX Builder is under development and should be out Sometime Soon(TM). Go check out the video on the TorqueX page - it looks really cool.

What about using XNA models? Only for static geometry, so don't plan on bringing over your .FBX character models.

Can I use collision meshes for DTS models? Nope! The reader doesn't even import them so don't bother. Polysoup collision class only works for static geometry, so you're stuck with manually specifying spheres in the XML.

I intend to look into getting polysoup working with non-static, then an artist can export two DTS shapes, one low-poly for collision and the regular model. Dunno about importing the collision mesh from DTS, importer currently skips that entirely. It makes creating models for TorqueX a huge PITA right now since artists hate any interruption in their routine.


Whats the deal with SceneGroups? Everything is defined in a tree, then the objects are kept in sorted buckets according to where they are in space, so that objects that aren't visible can be skipped when it is time to render.

For something like a Player object, there will be a top-level SceneGroup that contains all the renderable elements of that player, where that player is in the world right now, rotation, scale, etc. Various components must get a reference to that scene group so they can access those properties like position, or if they also need to be rendered.

The SceneGroup for an object is created by the SceneComponent assigned to the object. The the XML this is set by the SceneGroup element on that component. Note that it is "SceneGroup" and *NOT* "SceneGroupName" like the rest of the components. To hook up something to get rendered, your RenderComponent will specify SceneGroupName. Many other components, like Input components, Mount components, and Physics components must also specify this same SceneGroupName.


Whats the deal with Rigid? The RigidManager deals with collision physics by defining various CollisionShapes, then a pair class that details how two CollisionShapes impact each other. For every shape there must be a pair class for the intersection of that shape and all other shapes. Anything that has a Rigid component on it will interact with the physics system.
#2
04/27/2008 (6:55 am)
Hi, i want to buy torque X Pro for make 3D games, but Torque x 3D will be a separated engine from Torque X 2D???, or will be se same engine ??? (2D and 3D)... i will need to wait for a couple of months?
#3
04/27/2008 (11:13 pm)
Thanks Russell, this is really usefull.
Just a question on SceneGroups, can you add multiple players to the same scengroup, or do they have to be in their own scenegroup?
#4
04/28/2008 (8:57 am)
@Javier - TX is both 2D and 3D. It's a single engine, not two engines.
#5
04/28/2008 (2:58 pm)
They should have separate Scene Components; all the child objects of a scene group share the parent's Transform information (such as translation/position and rotation).

Where you would have multiple objects in one scene group would be a player that has a mounted weapon and two collision objects - both models and both collision objects need to stay sync'd in relation to each other and are conceptually the same "player", so they belong to the same scene group. Their individual transforms are just offsets from the player's center, the scene group's transform then puts the entire "player" somewhere in the world.
#6
04/28/2008 (4:30 pm)
Thanks Russell, that make sense.
I am having trouble with a player I am trying to use. I have created two instances of it, one controlled by the keyboard, the other by the computer.
The problem is that whilst one player is moving correctly the other also plays the run animation sequence, although it stays still. I thought this might have something to do with scenegroups but I have changed them to use different ones and it still happens. Doesnt happen with the blue_player.dts model included in the fps demo though that works fine, regardless of whether they are in the same scengroup or not?.
I can only presume its something to do with the player dts model, although being a beginner at this I am at a loss to how that could be so.
Have you any thoughts on what could be going on?
#7
04/29/2008 (3:24 pm)
I would guess that they are somehow sharing the animation component or animation threads. Are you creating two new instances from a single template?
#8
04/29/2008 (3:35 pm)
Yes I have one player template, basically lifted from the fps demo.
Heres the code...

private void createPlater(int playerIndex, bool ai_player)
{
_ai_player = ai_player;

//grab our free camera
TestCamera freeCamera = TorqueObjectDatabase.Instance.FindObject("FreeCamera");
freeCamera.PlayerIndex = playerIndex;
_playerIndex = playerIndex;

// Load player Template
TorqueObject playerTemplate = TorqueObjectDatabase.Instance.FindObject("Player");
TorqueObject playerInstance = playerTemplate.CloneT();
playerInstance.Name = "Player" + playerIndex;

// get scene component, and update scenegroup fot this player instance
T3DSceneComponent scenecomponent = playerInstance.Components.FindComponent();
scenecomponent.SceneGroup = "PayerMesh" + playerInstance.Name;

// get animation component, and update scenegroup fot this player instance
_playerAnimationComponent = playerInstance.Components.FindComponent();
_playerAnimationComponent.SceneGroupName = "PayerMesh" + playerInstance.Name;

// get control component, and update scenegroup fot this player instance
_PlayerControlComponent = playerInstance.Components.FindComponent();
_PlayerControlComponent.SceneGroupName = "PayerMesh"+ playerInstance.Name;

// get controller component, and assign player index
_playerControllerComponent = playerInstance.Components.FindComponent();
_playerControllerComponent.PlayerIndex = playerIndex;

// get input component, and update scenegroup fot this player instance
_PlayerInputComponent = playerInstance.Components.FindComponent();
_PlayerInputComponent.SceneGroupName = "PayerMesh" + playerInstance.Name;
_PlayerInputComponent.PlayerIndex = playerIndex;

//assign freecam to player
_PlayerInputComponent.FreeCamera = freeCamera;

//then setup controller
_playerControllerComponent.BaseControlObject = _PlayerInputComponent;
_playerControllerComponent.UseBaseControlObject();


// get mount component, and update scenegroup fot this player instance
T3DMountComponent mountcomponet = playerInstance.Components.FindComponent();
mountcomponet.SceneGroupName = "PayerMesh" + playerInstance.Name;

// get render component, and update scenegroup fot this player instance
T3DTSRenderComponent renderComp = playerInstance.Components.FindComponent();
renderComp.SceneGroupName = "PayerMesh" + playerInstance.Name;

// get render component, and update scenegroup fot this player instance
T3DRigidComponent rigidComp = playerInstance.Components.FindComponent();
rigidComp.SceneGroupName = "PayerMesh" + playerInstance.Name;

// get camera component, and update scenegroup fot this player instance
_PlayerCameraComponent = playerInstance.Components.FindComponent();
_PlayerCameraComponent.SceneGroupName = "PayerMesh" + playerInstance.Name;

// now assign camera to start off with
Game.Instance._sceneview.Camera = _PlayerCameraComponent;

// Get spawn point
T3DSpawnPointComponent spawnpointcomponent = playerInstance.Components.FindComponent();
spawnpointcomponent.SceneGroupName = "PayerMesh" + playerInstance.Name;
T3DSpawnSet spawnset;
spawnset = TorqueObjectDatabase.Instance.FindObject("SpawnSetTeam1");
spawnpointcomponent.SpawnSet = spawnset;
T3DSpawnPointComponent spawnPoint = spawnset.GetRandomActiveSpawnPoint();

//now register
if (!TorqueObjectDatabase.Instance.Register(playerInstance))
{
System.Diagnostics.Debug.WriteLine("Failed to register!");
}

spawnpointcomponent.SceneGroup.Transform = spawnPoint.SceneGroup.Transform;
spawnpointcomponent.OnSpawn();

_scenegroup = spawnpointcomponent.SceneGroup;

_startposition = _scenegroup.Position;

// make sure the GUICanvas has been initialized
GUICanvas.Instance.OnPreRender();


//load rigid component
T3DRigidComponent rigidcomponent = playerInstance.Components.FindComponent();

//assign oncollision delegate
OnCollisionDelegate adelagate = new OnCollisionDelegate(OnCollision);
rigidcomponent.OnCollision = adelagate;

ProcessList.Instance.AddTickCallback(this);

// set ground tolerance
_PlayerControlComponent.GroundTolerance = 0.8f;
}
#9
05/03/2008 (6:01 pm)
@ Steve Rap could it be because you are giving player 2 a input component?
Maybe go into the getInputMap Method of the component and put something like..

if (playerIndex > 0)
return;

And let me know how it turns out.
#10
05/03/2008 (6:07 pm)
@ Russell

What do you mean my objects are falling through? When I add an object to the scene, it just floats wherever I position it. Is there a way we can add objects so they'll land somewhere on the terrain and bounce around with physics and gravity, like in the physics demo?
#11
05/05/2008 (10:09 am)
Make sure you have a RigidComponent defined on the object (check the Player object in the FPS demo for an example), and make sure that the gravity ratio is > 0.0; then the object will fall and participate in rigid body physics. (The rigid body shape is also defined by the shapes on the rigid component).

If you have TorqueX Pro, you can change the source code to get it to render the rigid body when RenderCollisionBounds is set to true (otherwise it will throw an exception and fail), by changing the static material to SimpleMaterial in the collision body class.

Personally, I also added a ColorMaterial and created a shader for it so I can do things like create a T3DBoxMesh, say boxMesh.Color = new Vector4(1,0,0,1), and have it render with that color. During debugging of my vehicle it was extremely useful to draw raycast points, hit points, etc with different colored squares.
#12
05/05/2008 (10:58 am)
Ok well heres my code.. I'm not sure why its not rendering any collision bounds...
public void CreateObject()
        {
           
            //create the simple torque object
            TorqueObject objObject = new TorqueObject();

            //create the render component
            T3DTSRenderComponent componentRender = new T3DTSRenderComponent();
            componentRender.ShapeName = @"data\shapes\player\mushroom.dts";

            //create the scene component
            T3DSceneComponent componentScene = new T3DSceneComponent();
            componentScene.Position = new Vector3(1024, 1024, 255);

            T3DRigidComponent componentRigid = new T3DRigidComponent();
            componentRigid.GravityScale = 1.5f;
            componentRigid.Mass = 2.5f;
            componentRigid.ResolveCollisions = true;
            componentRigid.RenderCollisionBounds = true;

            //add both of the components
            objObject.Components.AddComponent(componentRender);
            objObject.Components.AddComponent(componentScene);
            objObject.Components.AddComponent(componentRigid);
            //register the object
            TorqueObjectDatabase.Instance.Register(objObject);
        }

I also tried

componentScene.Position = new Vector3(1024, 1024, 290);

And it floated in the air.. so it must be something I'm not doing.
#13
05/05/2008 (1:00 pm)
Your rigid component needs a collision shape.
#14
05/05/2008 (1:41 pm)
Ok, but how do I assign that? I tried creating one on the fly, with no luck... can you give an example?
#15
05/05/2008 (9:36 pm)
Thanks, I figured it out...
#16
05/06/2008 (9:57 am)
For everyone else, it would look something like this...

T3DSphere sphereComponent = new T3DSphere();
    sphereComponent.SceneGroupName = "EnemyTemplate";
    sphereComponent.Material = material;
    sphereComponent.Radius = 0.5f;
    objEnemyTemplate.Components.AddComponent(sphereComponent);

    //define a proper collision shape
    CollisionSphereShape collisionShape = new CollisionSphereShape();
    collisionShape.Radius = 0.5f;

    //give the enemy some physics attributes, like gravity and collision
    T3DRigidComponent componentPhysics = new T3DRigidComponent();
    componentPhysics.SceneGroupName = "EnemyTemplate";
    componentPhysics.GravityScale = 5f;
    componentPhysics.Mass = 30.0f;
    componentPhysics.RigidManager = rigidManager;
    componentPhysics.CollisionBody.AddCollisionShape(collisionShape);
    objEnemyTemplate.Components.AddComponent(componentPhysics);

John K.
#17
06/06/2008 (7:09 am)
I'm trying to implement the script above using the basic StarterGame 3D, but I can't seem to access/find the componenet T3DSphere, is there a special library I should be accessing?

I found a reference in the .txschema file, but it's vaguely useless there.

I also got an error stating:

"Error 1 'GarageGames.Torque.T3D.T3DBox' is inaccessible due to its protection level C:\Documents and Settings\user\My Documents\Visual Studio 2005\Projects\3D Object Test\3D Object Test\Game\CreateBox.cs 29 13 Game"

Any ideas?
#18
06/06/2008 (11:35 pm)
For a box you want to access.. GarageGames.Torque.T3D.RigidCollision.CollisionBoxShape

try
CollisionBoxShape collisionShape = new CollisionBoxShape();


Thats what i used.. Also give it a Vector3 Size, a Position, and add it to the collisionBody, like john did...

componentPhysics.CollisionBody.AddCollisionShape(collisionShape);
#19
08/07/2008 (1:22 am)
Edit: moving this to another thread.
#20
04/10/2009 (5:43 am)
Where did you move this thread?