Game Development Community

mountObject( obj, node, txfm ) Questions and Problems

by John "Mythic" Henry · in Torque 3D Professional · 06/20/2011 (9:00 am) · 4 replies

Final 1.1 version..

So Im working away on this and needed to use %obj.mountObject( %newObj, %node );
Expectation is that the Object will mount on the mount[x] as set.
It should then be positioned on that mountpoint and render there as well.

Yes and no. Good simple example is the Cheetah Brakelights in the default FPS example.
They mount just fine with no txfm set.

Now setup a simple vehicle and add some headlights, same setup, just a
different vehicle, change headlights to spotlights and add just like brakelights.

Now open up the Editor (F11) and look at the Objects added to the vehicles...
The Spotlight Object Icon will be way out in front of the vehicle and the brakelight
will be in the right spot.. For some reason they still work correctly tho ??

Then try mounting a player to a vehicle with Multiple Mounting points...
StrykerIAV is a good example...

The Player is now Rendering at the Same Position for all Mount points.

example:
function VehicleData::setMountVehicle(%this, %vehicle, %player)
{
   //echo("c4VehicleData::setMountVehicle("@ %this.getName() @", "@ %vehicle @", "@ %player.client.nameBase @")");
   if (isObject(%vehicle) && %vehicle.getDamageState() !$= "Destroyed")
   {
      %node = %this.findEmptySeat(%vehicle, %player);
      if (%node >= 0)
      {
         %pilotNode = %this.pilotNode;
         //echo("c4Mount Node: "@ %node @" -- PilotNode : "@%pilotNode);
         ServerConnection.setFirstPerson(1);
         %player.mVehicle = %vehicle;

         %vehicle.mountObject( %player, %node ); //, %this.mountPointTransform[%node]);
         %player.setTransform(%this.mountPointTransform[%node]);

I've only just started to dig into this, so hopefully I'll find the issue. This
used to work correctly as late as TGEA 1.7.1 where the strykeriav kit was last
updated for. The real issue here is having players mounted inside moving vehicles :)

Original Base Engine code excerpts involved here...

DefineEngineMethod( SceneObject, mountObject, bool,
   ( SceneObject* objB, S32 slot, TransformF txfm ), ( MatrixF::Identity ),
   "@brief Mount objB to this object at the desired slot with optional transform.nn"

and...
void SceneObject::mountObject( SceneObject *obj, S32 node, const MatrixF &xfm )
{
   if ( obj->mMount.object == this )
   {
      // Already mounted to this
      // So update our node and xfm which may have changed.
      obj->mMount.node = node;
      obj->mMount.xfm = xfm;
   }
   else
   {
      if ( obj->mMount.object )
         obj->unmount();

      obj->mMount.object = this;
      obj->mMount.node = node;
      obj->mMount.link = mMount.list;
      obj->mMount.xfm = xfm;
      mMount.list = obj;

and even more important...
void Player::setPosition(const Point3F& pos,const Point3F& rot)
{
   MatrixF mat;
   if (isMounted()) {
      // Use transform from mounted object
      MatrixF nmat,zrot;
      mMount.object->getMountTransform( mMount.node, mMount.xfm, &nmat );
      zrot.set(EulerF(0.0f, 0.0f, rot.z));
      mat.mul(nmat,zrot);
   }

almost forgot the final one:
void ShapeBase::getMountTransform( S32 index, const MatrixF &xfm, MatrixF *outMat )
{
   // Returns mount point to world space transform
   if ( index >= 0 && index < SceneObject::NumMountPoints) {
      S32 ni = mDataBlock->mountPointNode[index];
      if (ni != -1) {
         MatrixF mountTransform = mShapeInstance->mNodeTransforms[ni];
         mountTransform.mul( xfm );
         const Point3F& scale = getScale();

         // The position of the mount point needs to be scaled.
         Point3F position = mountTransform.getPosition();
         position.convolve( scale );
         mountTransform.setPosition( position );

         // Also we would like the object to be scaled to the model.
         outMat->mul(mObjToWorld, mountTransform);
         return;
      }
   }

   // Then let SceneObject handle it.
   Parent::getMountTransform( index, xfm, outMat );      
}

Interestingly an Image calls this last function to get the Transform
just like the player does...

It definetly doesnt seem to be working right as they all end up at
the same point on the vehicle without offsets -> {mMount.xfm}.

I've checked the Vehicle Dts objects in the Shape Editor and all seems correct.
I've also tried to mount Dts Objects (topImage and plow) and these didn't even show up.
The original system mounted them as Images instead of objects [ mountImage(obj,node) ].

I also did a simple test. The Cheetah has Mount0 right almost on the Ground.
So lets not hide the player body after mounting and see where it ends up afterwards,
with no transform done to the player as well.

Result:
mount0 way below the vehicle, PlayerBody just under the Turret Way above mount0.
Where is the offset coming from that moves the player mounted up above the mountpoint?

That position is almost body center. I suspect it is using the objects center transform
for the starting point, NOT the mount[x] transform.

#1
06/20/2011 (9:10 am)
I've run it in Debug mode, it is correctly calling thru to the
function to get the mountNode transform and returning that transform.

I just seem to be having a brain fart here today :(

Looks like this is reported as "Soldier not in buggy correctly"
But doesnt mention the how/why, so maybe I've spotted the same issue?
Just not sure of the cause yet.
#2
06/20/2011 (11:14 am)
I've been testing and working this out and just noticed something...

The current DefaultCar has no mount0 in the Dts object.
It still mounts a player.

I tracked back and nowhere is a check done for mountObject(...)
that the node is valid??

It does fill out the node list, but it doesn't check that a valid
mount[x] has been used. This could create other problems as it has
limitations by the:

// Resolve mount point node indexes
      for (i = 0; i < SceneObject::NumMountPoints; i++) {
         char fullName[256];
         dSprintf(fullName,sizeof(fullName),"mount%d",i);
         mountPointNode[i] = mShape->findNode(fullName);

Which if you only have 5 in the Shape [mount0...mount4],
but mount 6 or more [ obj.mountObject(newobj, 5) ].

It will let you mount these, but they won't be seen/accessed wherever
it uses the list mountPointNode[x] to work with mounted objects.

The only actual check is when it tries to get the nodeTransform
and then it would just simply return the objworld transform if the
node was not valid.

I have been able to adjust the position rendered now with xtfm offset.
So far, rotation is giving me a problem, but position is working.
#3
06/21/2011 (9:01 am)
very interesting, explains a lot of issues I've been seeing regarding mounting.
keep at it John.
#4
06/22/2011 (6:45 am)
One difference I noticed from 1.7.1 is that there was no option for
an Offset txfm...

This is the first difference I spotted right away:
void ShapeBase::getMountTransform( S32 index, const MatrixF &xfm, MatrixF *outMat )  
{  
   // Returns mount point to world space transform  
   if ( index >= 0 && index < SceneObject::NumMountPoints) {  
      S32 ni = mDataBlock->mountPointNode[index];  
      if (ni != -1) {  
         MatrixF mountTransform = mShapeInstance->mNodeTransforms[ni];  
      ***   mountTransform.mul( xfm );  **** (Difference)

void ShapeBase::getMountTransform( .... **** const MatrixF &xfm *** (Difference)
*** mountTransform.mul( xfm ); **** (Difference)