Game Development Community

Point an object at another object

by James Greenhalgh · in Torque Game Engine · 01/19/2009 (1:13 am) · 9 replies

I'm trying to expand the functionality of the fsShapeReplicator to point at another object, but I'm not getting the exact results I'd like, am I missing a necessary rotation or is createOrientFromDir not proper?

Relevant Code:
SceneObject* SceneObj = dynamic_cast<SceneObject*>(Sim::findObject(mFieldData.mAimAtObject));
         if (SceneObj)
         {
            Point3F aimObjPos;
            aimObjPos = SceneObj->getPosition();

            VectorF los = aimObjPos - ShapePosition;
            los.normalize();

            XForm = MathUtils::createOrientFromDir(los);
         }
      }
      // Set Position.
      XForm.setColumn(3, ShapePosition);

      // Set Shape Position / Rotation.
      fxStatic->setTransform(XForm);


Figure 1:
orth.ca/los-orienting.png
Say I have a circular pit, I want all the trees along the cliff in a circle to point towards an invisible object I've placed in the center of the pit a little higher. (Image A)
Instead of getting the results I want (Image C), the object's rotation is oriented to the same vector that is calculated. (Image B) I can kind of cheat this and get the result I want by placing the object lower, but this will never allow for all the functionality I desire. (Image D) Anyone point me to what steps I need to do or if this is even possible?

#1
01/19/2009 (3:37 am)
I don't have the source here, but you might want to check t2dGunTurret since it should have what you need. The turret class has one bug though. There's something like
( -angle )
and you'd have to remove that minus sign to have it rotate properly.
#2
01/19/2009 (4:11 am)
Change line 271 from

t2dMatrix xForm( -angle );
to

t2dMatrix xForm( angle );
in T2D/activeTiles/t2dGunTurret.cc.
#3
01/19/2009 (5:26 am)
Hi Stefan,

Thanks for the tips, however I guess I wasn't clear, and owe you an apology for your time. This is for TGE 1.5.2 (probably work fine on TGEA as well), I just drew my diagram in 2d. I don't have a license to T2D though now I'm doubting your pointers will help any way. I did go take a look at the Turret resource and I'm hoping that'll point me in the right direction.

Thanks,
James
#4
01/19/2009 (7:05 am)
My fault, sorry. I thought you were posting in the TGB private forums :)
#5
01/19/2009 (7:40 am)
No worries Stefan,

I seemed to get the exact result I want simply by rotating on the X axis. I'm not sure if it can be done better or if it will cause problems in other areas, but all tests are appearing correct.

Here is the final code:
bool aimObjFound = false;
      if (mFieldData.mAimAtObject != ST_NULLSTRING)
      {
         SceneObject* SceneObj = dynamic_cast<SceneObject*>(Sim::findObject(mFieldData.mAimAtObject));
         if (SceneObj)
         {
            Point3F aimObjPos;
            aimObjPos = SceneObj->getPosition();

            VectorF los = aimObjPos - ShapePosition;
            los.normalize();

            // Orient our shape's transform to the same vector as the direction
            // between the RayCast ground transform and the object's position
            XForm = MathUtils::createOrientFromDir(los);
            aimObjFound = true;
         }
      }
      if (!aimObjFound)
      {
         // Set Quaternion Rotation.
         QRotation.set(ShapeRotation);

         // Set Transform Rotation.
         QRotation.setMatrix(&XForm);
      }
      
      // Set Position.
      XForm.setColumn(3, ShapePosition);

      // Set Shape Position / Rotation.
      fxStatic->setTransform(XForm);

      // If we're aiming at an object we need to rotate 90 degrees along the X
      if (aimObjFound)
      {
         EulerF rot(mDegToRad(90.f),0.f,0.f);
         fxStatic->RotateObj(rot);
      }
#6
01/20/2009 (5:19 pm)
james,
sounds like you've already got a solution,
but i wrote a method a while you might still find useful, or at least informative:

sceneObject::setForwardVector()



#7
01/21/2009 (12:24 pm)
Rotating around the X axis sounds like it will work. The problem you were encountering originally was that MathUtils::createOrientFromDir appears to be designed to orient things like particles and billboards to always face a particular direction (indeed, the only references to it that I found in code deal with particles).

In other words, this method call will always orient the object's local +Y (i.e. it's forward vector) along the specified direction vector. Indeed, looking at figure B in the original diagrams of the problem, this does appear to be exactly what it was doing: the trees were orienting their forward faces to point at the target object, as if it were a camera and they were billboard objects.

Based on this, your solution of rotating 90 degrees in the X is perfectly legit. Since you know the first move leaves +Y facing the target, following up with a 90 degree X rotation finishes the job. Just for the heck of it, though, here's an alternate approach that seemed to work in the rudimentary testing I was able to do without knowing your full code plans. The following listing represents a new function is intended to be a variation on createOrientFromDir, which does the same thing except that it points the object's local +Z along the direction vector (which, if I understand correctly, is what you're trying to do...)

MatrixF orientTopAtDirection( Point3F &direction )
{
	Point3F j = direction;
	Point3F k(0.0f, 0.0f, 1.0f);
	Point3F i;
	
	mCross( j, k, &i );

	if( i.magnitudeSafe() == 0.0f )
	{
		i.set( 0.0f, -1.0f, 0.0f );
	}

	i.normalizeSafe();
	mCross( j, i, &k );

   MatrixF mat( true );
   mat.setColumn( 0, i );
   mat.setColumn( 1, k );
   mat.setColumn( 2, j );

	return mat;
}

Note that this is basically the same as createOrientFromDir, except for a reversal of the order of the 2nd cross product's operands and a reversal of some matrix column assignments at the end, so its pretty much exactly the same efficiency, but with a modified result to match what you're trying to do.
#8
01/21/2009 (12:46 pm)
Thanks for that Charles, it does make things a little cleaner and lets me just set the transform the right way to begin with. I also understand what's going on much clearer now.

As for my full code plans, it was just a slight variation I added to fxShapeReplicator to make formations out of replicated shapes. Think like a log teepee or a cave entrance surrounded in stalagmites that look like teeth. Here's a gigantic pit we have in game that I've aligned with trees to show the result, (using your code btw), everything looks to be right.

orth.ca/aimatobject.png
#9
01/21/2009 (3:18 pm)
Excellent! Glad to hear it worked in the bigger picture. Demo screenshot looks cool, too.

OK, now that you describe it some more I can see what you were working toward. Sounds like it would be handy in a flight game for making rings of jagged spikes for players to crash into as they pass through narrow tunnels, or making basically conical (yet naturally randomized) constructs without a lot of tedious manual placements. Nice.