Game Development Community

dev|Pro Game Development Curriculum

guiObjectView - Mountable Animated DTS Viewer

by Loonatik · 12/22/2002 (4:35 pm) · 56 comments

Download Code File

Install Steps:

1) Extract guiObjectView.zip into torque/

2) Do a clean build of torque

3) Extract objectViewExample.zip if needed



Usage:

"objectName" was used to identify an object, to allow you to reference it later on for things like setSequence.

// objectName, shape, skin, detail
view.setObject("objectName", "fps/data/shapes/object/object.dts", "", 0);
Sets the main object for the scene. Calling this again after the scene has a main object will cause everything to get unloaded and the new object to be loaded.

// objectName, shape, skin, parentNode, detail
view.mountObject("objectName", "fps/data/shapes/object/object.dts", "", "nodeName", 0);
Allows you to mount an object containing a node called mountPoint, to any node on the Main Object. Mounting an object to the same nodeName will cause the previous object to be unmounted.

// objectName, nodeName
view.unMountObject("objectName", "");
view.unMountObject("", "nodeName");
This allows you to unMount an object from the main object by either specifying the object name or the nodeName of the object.

// objectName, dsq
view.loadDSQ("objectName", "fps/data/shapes/object/object_animation.dsq");
This allows you to load dsq files for the specified object. Note: not all objects require you to load a DSQ to use thier sequence. An example would be the chaingun from tribes2.

// objectName, sequence, time
view.setSequence("objectName", "sequenceName", 1);
This allows you to run a sequence for the specified object. You can also control how fast or slow the sequence will play by using time.

//
view.setEmpty();
This clears the current scene of all objects.



Example:

Here is an example of how to load up a player object, mount a weapon and a pack. (saying you had these objects)

You can also animate mounted objects if they have sequences by using the same code that you did with player.

// Load the player up
view.setObject("player", "fps/data/shapes/player/player.dts", "", 0); // Example player, with default skin and detail level of 0
view.loadDSQ("player", "fps/data/shapes/player/player_root.dsq"); // Load up the root sequence
view.setSequence("player", "Root", 1); // Set the sequence to Root

// Mount the objects
view.mountObject("weapon", "fps/data/shapes/rifle/weapon.dts", "", "mount0", 0); // Example weapon with default skin and detail level of 0
view.mountObject("pack", "fps/data/shapes/pack1/pack.dts", "", "mount1", 0); // Example pack with default skin and detail level of 0

// Get rid of the pack
view.unMountObject("pack", ""); or view.unMountObject("", "mount1");

Todo:

* Better camera options are next, should be able to bust this out within a few days. I plan to add the ability to have it spin, and work on making it fit better.

* We really plan to expose all the animation options, including blending, multiple threads, and sound.

* Our other goal from this will be to create a Player Selection example. Which will allow people to pick a player model and customize its apperance and skin. Then allow you to load that customized object within the game.

About the author

Recent Blogs

#21
06/09/2005 (1:10 pm)
Okay. if you're back here because your objects will not mount reliably you need to look at the following thread.

www.garagegames.com/mg/forums/result.thread.php?qt=17161

Basically it says putting in a "mountPoint" in to your mounted model will fix the problem.
It didn't work for me at first but this was because I read the post like a node named
"mountPoint" needed to be created and unlinked like the bounds node. This is not so.
The "mountPoint" node needs to be linked under the start01 node so it will get exported
properly.

I am currently a 3ds max user which means I needed to do the following.

1)Create a dummy named "mountPoint" and link it under "start01".

2)include "mountPoint" in your .cfg file as such:

AlwaysExport:
mountPoint

3)Load the .cfg through the "configuration control" tab of the DTS Exporter Utility.

4)Export your model.

5)Take a look at your dump.dmp file. Scroll to the bottom and make sure node
"mountPoint" was exported.

That should do it.
#22
07/02/2005 (3:19 pm)
Here is some sample output from my object component list generating function:
//GuiObjectView Object and Component List ---------------------------------

Mesh in slot 0 : player
Components in this object: 41
component 0 : Detail145
component 1 : Detail80
component 2 : Detail60
component 3 : Detail30
component 4 : Detail18
component 5 : Detail12
component 6 : Detail6
component 7 : Detail3
component 8 : Bip01 Pelvis
component 9 : Bip01 Spine
component 10 : Bip01 Spine1
component 11 : Bip01 Spine2
component 12 : Bip01 Neck
component 13 : Bip01 Head
component 14 : Eye
component 15 : Bip01 L Clavicle
component 16 : Bip01 L UpperArm
component 17 : Bip01 L Forearm
component 18 : Bip01 L Hand
component 19 : Bip01 R Clavicle
component 20 : Bip01 R UpperArm
component 21 : Bip01 R Forearm
component 22 : Bip01 R Hand
component 23 : Mount0
component 24 : Mount2
component 25 : Mount1
component 26 : Bip01 L Thigh
component 27 : Bip01 L Calf
component 28 : Bip01 L Foot
component 29 : Ski0
component 30 : Bip01 R Thigh
component 31 : Bip01 R Calf
component 32 : Bip01 R Foot
component 33 : Ski1
component 34 : Unlink
component 35 : Cam
component 36 : bodymesh
component 37 : Root
component 38 : Forward
component 39 : Back
component 40 : Jump

Mesh in slot 2 : balloon_01
Components in this object: 3
component 0 : detail2
component 1 : Balloon2
component 2 : Balloon

Notice it skipped slot 1. This is because GuiObjectView attaches mounted objects into the first empty mesh slot it finds.
There was something in slot 1 but it's been unMounted so not it's empty so it's being skipped.

So, Here is the code I added to GuiObjectView.cc to spit out the object component list:

// Added by Phong-----------------------------------------------------
// Script function handling for "getComponentNames"
ConsoleMethod( GuiObjectView, getComponentNames, void, 2, 2, "ObjectView.getComponentNames()" ) {
	argc;
	GuiObjectView* view = static_cast<GuiObjectView*>( object );
	view->getComponentNames();
}

void GuiObjectView::getComponentNames()
{
	Con::printf("");
	Con::printf("//GuiObjectView Object and Component List ---------------------------------");
	Con::printf("");

	for (S32 i = 0; i<33; i++)
	{
		if(dStrcmp(mMeshObjects.mMesh[i].name,"") == 1)
		{
			Con::printf("Mesh in slot %d : %s", i, mMeshObjects.mMesh[i].name);
			mMeshObjects.mMesh[i].printComponentNames();
		};
	}
}

void GuiObjectView::meshObjects::meshs::printComponentNames()
{
	S32 numComponents = mesh->getShape()->names.size();
	Con::printf("Components in this object: %d", numComponents);

	for (S32 i = 0; i<numComponents; i++) Con::printf("component %d : %s", i, mesh->getShape()->getName(i));
	Con::printf("");
}

You'll need to add these calls to the .h file like so:

struct meshs {
					private:
						
					public:
						meshs();
						~meshs();

						TSShapeInstance* mesh;
						char name[32];
						U32 mode; // 0 = normal, 1 = animated
						S32 node;
						S32 parentNode;
						U32 detail;
						TSThread *thread;
						S32 lastRenderTime;

						void loadDSQ(const char* dsq);
						void setSequence(const char* seq, F32 time);

						[b]void printComponentNames();[/b]

				} mMesh[33];

void loadObject(const char* name, const char* shape, const char* skin, const char* nodeName, S32 detail);
		void unLoadObject(const char* name, const char* node);
		void loadDSQ(const char* name, const char* dsq);
		void setSequence(const char* name, const char* seq, F32 time);
		void Clear();

		[b]void getComponentNames();[/b]

And you'll need to call it by assigning the command to a button in your .gui file with something like this:

new GuiButtonCtrl() {
         profile = "GuiButtonProfile";
         horizSizing = "right";
         vertSizing = "bottom";
         position = "25 150";
         extent = "140 30";
         minExtent = "8 2";
         visible = "1";
         [b]command = "view.getComponentNames();";[/b]
         helpTag = "0";
         text = "Animate";
         text = "componentNames";
         groupNum = "-1";
         buttonType = "PushButton";
      };

Hope it's useful.

Okay. Now it's on to the randomly broken mount problem...
#23
07/27/2005 (4:29 am)
Nice resource. I only have one complaint, and that is when you use wish to view multiple objects, each in a seperate window, only the first window will show its object.

I got around it by dropping this in the cs file *outside* of any functions (I dropped it right before the onWake function actually).


...

GuiEditorInspectFields.apply(foo.setObject( "foo", "path_to_file/foo.dts","", 0));
GuiEditorInspectFields.apply(bar.setObject( "bar", "path_to_file/bar.dts","", 0));

...

It's a hack and the only problem with this is that you cant use a foo.setempty to unload it in onSleep so it will eat memory when its not being used.
#24
07/30/2005 (2:39 pm)
Hello all,

I'm using the Eclipse IDE but don't know how to add the files to the project. I placed them in the gui directory and refreshed the project so they show up in the IDE. Do I have to #include the guiobjectview.h to any other file?
#25
08/01/2005 (6:46 pm)
This is a really cool component. I can't believe it's not a standard part of Torque.

Anyhoo... I'm really interested in making a couple of things happen...

1, Setting the screen distance and rotation in code
2, Disabling the mouse control (for a logo)
3, Enabling Environment Mapping

Anyone already solved these problems?
#26
08/02/2005 (9:50 am)
Big Papa,

I'm not sure about Eclipse IDE, but all visual studio owners have to do is copy the files into the locations, add them to the workspace and recompile. This is probably similar to adding them to a make file. I don't know if Eclipse uses a make file system or a similar mechanism to Visual Studio, but if it does, I'd bet you just need to copy the lines for other GUI components and change them to suit.

I know that when it comes to me compiling my game for Linux, I've got a whole lot of make file editing to do...
#27
08/02/2005 (6:22 pm)
Well, how much of a chump do I feel?...

Just answered 2 of my own questions. by reading this thread properly and looking at the code.

1, Setting screen distance and rotation in code is perfectly demonstrated above by Max Robinson
2, The console method setMouse(Zoom, Spin) is used to turn the mouse features on and off..

Just need no 3 and I'm sorted.. :-)

could do with a no 4 though... adding a light. Currently everything is uniformly lit. It would be nice to have a light or two to make the models look nice... but that would be quite a complicated change I think. So far it's working 90% and that's good enough for me for now.
#28
08/02/2005 (8:30 pm)
@Jason - Thanks for the help. Eclipse uses make files so I did what step two of the instructions tell me todo; do a CLEAN build, meaning "make clean". RTFM!

It's working now. THX!
#29
08/31/2005 (6:42 am)
if you want your guiobjects in a popup window to show correctly, use the GuiObjectView::onWake and GuiObjectView::onSleep functions.

What I did is stored the command during onSleep and eval it in onWake, something like this:

function GuiObjectView::onSleep(%this)
{
%this.object = %this".setObject(\"name\", \"file\", \"\", 0);";
}

function GuiObjectView::onWake(%this)
{
eval(%this.object);
}
#30
10/12/2005 (4:36 pm)
OK, this is a really useful control and I've had some success with it, my GUI is covered with them ;-)

Trouble is, I've got this model I want to show made from interconnecting parts and even though they show up in the control, their positions are all wrong.. (the rotations are OK, just their general positioning is less than accurate.. by quite a margin)

In one example, A person... I've got a base model which is the shoulders, a head model, a helmet model and a spectacles model.
Shoulders has a mount1 and head has a mountpoint in the place I want them to connect.
Head has a mount1 and and helmet has a mount point in the place I want them to connect.
Head also has mount2 above the eyes and spectacles have a mountpoint where I want them to connect... you get the picture.

Trouble is, either the scale is all wrong or there's something funny going on with the transormation of mounted objects.

Anyone else had this? Know of a solution?

I'd like to get this working because the segmented soldier portrait idea looks really cool.

I'd also like a way to position the base object on its XYZ axis as an offset off the camera target so I can move my portrait up and down, 'cos centered is good for some things but not a bust portrait.
#31
10/17/2005 (5:49 am)
A Ha... It appears that someone else has fixed this problem in a different resource.

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

I'll give this a try tonight. <>
#32
11/02/2005 (3:06 pm)
OK, I wanted a transformed camera, so with many thanks to Markus Nuebel, here's the solution I implemented.

in guiObjectView.h

find:
EulerF   mCameraRot;
Add:
EulerF   mCameraOffset;

find:
void setCamera(F32 rX, F32 rY, F32 rZ, F32 dist);
Add:
void setCameraOffset(F32 oX, F32 oY, F32 oZ);

in GuiObjectView::GuiObjectView() : GuiTSCtrl()

Find:
mLastMousePoint.set( 0, 0 );

mCameraRot.set(0,0,10);

Add:
mCameraOffset.set(0,0,0);


find:
// Script function handling for "setCamera"
ConsoleMethod( GuiObjectView, setCamera, void, 6, 6, "ObjectView.setCamera(x, y, z, dist)" )
{
   argc;
   GuiObjectView* view = static_cast<GuiObjectView*>( object );
   view->setCamera(dAtof(argv[2]), dAtof(argv[3]), dAtof(argv[4]), dAtof(argv[5]));
}

add:
ConsoleMethod( GuiObjectView, setCameraOffset, void, 5, 5, "ObjectView.setCameraOffset(x, y, z)" )
{
   argc;
   GuiObjectView* view = static_cast<GuiObjectView*>( object );
   view->setCameraOffset(dAtof(argv[2]), dAtof(argv[3]), dAtof(argv[4]));
}

find:
void GuiObjectView::setCamera(F32 rX, F32 rY, F32 rZ, F32 dist)
{
   // Make sure there is a main object in the scene
   if (mMeshObjects.mMainObject)
   {
      F32 degToRad = (M_PI / 180);
      mCameraRot.x = rX * degToRad;
      mCameraRot.y = rY * degToRad;
      mCameraRot.z = rZ * degToRad;
      // Initialize camera values:
      mOrbitPos = mMeshObjects.mMainObject->getShape()->center;
      mMinOrbitDist = mMeshObjects.mMainObject->getShape()->radius;
      mOrbitDist = dist > mMinOrbitDist ? dist : mMinOrbitDist;
   }
}

add:
void GuiObjectView::setCameraOffset(F32 oX, F32 oY, F32 oZ)
{
   // Make sure there is a main object in the scene
   if (mMeshObjects.mMainObject)
   {
      mCameraOffset.x = oX ;
      mCameraOffset.y = oY ;
      mCameraOffset.z = oZ ;

   }
}

inside the method: bool GuiObjectView::processCameraQuery( CameraQuery* query )


find:
mCameraMatrix.getColumn( 1, &vec );
   vec *= mOrbitDist;
   mCameraPos = mOrbitPos - vec;
add:
mCameraPos += VectorF(mCameraOffset.x, mCameraOffset.y, mCameraOffset.z);

Unless I've missed something, this should give you a transformable camera.
#33
11/03/2005 (12:13 pm)
Nicely done. Don't suppose you would give a script example?
#34
11/04/2005 (3:32 am)
Script example?...

I'll post what I've got when I get home, but in the meantime, You could experiment using the control and playing with the different axis offsets using the control.setCameraOffset( Xoffset, Yoffset, Zoffset ); function. I put all of my code in the Screens onWake block.

Let me know if you get any problems.
#35
11/22/2005 (8:54 am)
Any simple way to see if an object is mounted? trying to unmount something that is not mounted causes a script "can not find object" bugger.
#36
12/03/2005 (4:08 pm)
Anyone compile this in to 1.4 yet?
#37
12/03/2005 (7:46 pm)
Sure, works no problem.
#38
12/07/2005 (4:07 am)
nice resource! works nice on TGE 1.4..
but.. did anyone managed to import this into TSE?
I've tried to update this but no luck so far.. It compiles without errors, but sure, I'm missing something, as there is no render at all... trying to change all gl* to GFX-> makes my head flying around so far...

Anyone?
UPD: http://www.garagegames.com/mg/forums/result.thread.php?qt=33605
#39
01/03/2006 (4:07 pm)
hey were there any modifications that had to be made to get this running on 1.4 or perhaps i have something set up wrong but i keep getting this error::

guiObjectView.obj : error LNK2001: unresolved external symbol "public: class ResourceObject * __thiscall ResManager::createResource(char const *)" (?createResource@ResManager@@QAEPAVResourceObject@@PBD@Z)
guiTerView.obj : error LNK2001: unresolved external symbol "public: bool __thiscall TerrainBlock::addToClientGraph(void)" (?addToClientGraph@TerrainBlock@@QAE_NXZ)
../example/torqueDemo.exe : fatal error LNK1120: 2 unresolved externals
#40
01/12/2006 (11:35 am)
great resource.

interesting - with some modification you can point it at an object already in the simulation, playing with its current animations, visible meshes, etc etc.

it might be useful for a character selection dialogue.