Game Development Community

TGE - Trying to adapt FlyingVehicle to SpaceVehicle

by Iain Craig · in Torque Game Engine · 05/29/2006 (7:08 am) · 17 replies

Hi all,

I'm trying to get into space :)

I've used David Grace's suggestions from this thread with success but I've maxed out the possibilities with the existing FlyingVehicle. I can make it sort of spacecrafty but I really want to forget about "up" when flying.

So I need to get a SpaceVehicle class out of FlyingVehicle. I want to implement:

- Yaw/Pitch/Roll at any orientation
- Forwards/backwards thrust (facing direction)
- Sideways (Slide) thrust would be nice to have but isn't essential

I don't need auto stabilizers or anything too fancy.

I'm about to dive into the class hierachy and figure out what Vehicle implements and whether I'll be stepping on the toes of the physics model etc.

First I just wanted to check if maybe someone's already been through this hurdle, and has any code/tips/advice. And, I can't get my head round quaternions so I'm looking for a simpler way to control the thing :(

Any thoughts?

#1
05/29/2006 (7:12 am)
Quote:
Yaw/Pitch/Roll at any orientation

Take a look at setTransform / setRenderTransform, and packUpdate/unpackUpdate. Roll is set to 0 there on every tick, if I remember correctly.

Quote:
- Forwards/backwards thrust (facing direction)

This is already in, am I misunderstanding something?
#2
05/29/2006 (8:16 am)
Hi Stefan,

It is already there, but I'm not sure how to expand on what's there to get rid of the aircraft-like nature with respect to up and down, which I want to be arbitrary.
#3
05/29/2006 (10:19 am)
Perhaps I should rephrase my question :)

I'm using a PhysicalArea to set GravityMod to 0, and I've put a FlyingVehicle in it. I'm already forcing FlyingVehicle's mCeilingFactor to 1.0f in FlyingVehicle::updateMove().

If I just float there with no thrust, and using the mouse turn the craft 180 in the horizontal plane, all is good. However if I tilt the craft I'm unable to do the same rotation in the vertical plane as the craft rolls at the top and bottom of each rotation.

I *think* that's the only thing stopping it feel like a spaceship (an arcadey one of course, I'm not going for realism) and the rest is down to a nice low drag in the datablock, etc.

Any thoughts on how I can modify FlyingVehicle to allow this full rotation?
#4
05/29/2006 (10:27 am)
Doh. I must have glanced over your post.

Quote:
If I just float there with no thrust, and using the mouse turn the craft 180 in the horizontal plane, all is good. However if I tilt the craft I'm unable to do the same rotation in the vertical plane as the craft rolls at the top and bottom of each rotation.

Incase no one else answers this one before me, do you think you could go into a little bit more detail here? Do you want to clamp rotation about the Y axis? Ie. only allow Z and X.

When you rotate around Z & X you'll eventually start rolling, which you can prevent by clamping Y and setting it to 0 on each tick, I think. Check out the playerclass if you have the time, alot of interesting stuff in there which could apply.
#5
05/29/2006 (10:52 am)
Hi Stefan,

Many thanks for your help :) I'll attempt to distil it down further.

I want to have a spacecraft with the direction controlled by the mouse in such a way that up/down movement of the mouse causes a turn up/down (pitch) steering thrust on the craft with respect to the craft's current up vector (NOT the Y-axis), and left/right movement of the mouse causes a turn left/right steering thrust (yaw) - again with respect to the craft's current up vector.

Then I have say S and X on the keyboard for forward/backwards thrust in the craft's facing direction.
#6
05/29/2006 (12:02 pm)
If I understood you correctly, you want the vehicle to rotate like the player does, and travel in the direction it faces but being in the air and with the physics that the rigidClass provides. A more arcade-like flyer.

That should be achievable with the changes I mentioned earlier to setRenderTransform and whatnot. I had the same problem when modifying the player class and the changes were in those functions, pretty sure.

Hope it helps.
#7
05/29/2006 (12:54 pm)
Stefan - that's great, many thanks. That's exactly what I want. I'll go and look at those now :)
#8
05/29/2006 (1:34 pm)
Stefan, forgive my ignorance if I'm missing something - did you mean me to work in the below, or elsewhere in the object hierachy?


packUpdate/unpackUpdate:

U32 FlyingVehicle::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
{
   U32 retMask = Parent::packUpdate(con, mask, stream);

   // The rest of the data is part of the control object packet update.
   // If we're controlled by this client, we don't need to send it.
   if(getControllingClient() == con && !(mask & InitialUpdateMask))
      return retMask;

   stream->writeFlag(createHeightOn);

   stream->writeInt(mThrustDirection,NumThrustBits);

   return retMask;
}

void FlyingVehicle::unpackUpdate(NetConnection *con, BitStream *stream)
{
   Parent::unpackUpdate(con,stream);

   if(getControllingClient() == con)
      return;

   createHeightOn = stream->readFlag();

   mThrustDirection = ThrustDirection(stream->readInt(NumThrustBits));
}

And setRenderPosition/setTransform (from Vehicle - FlyingVehicle doesn't override):

void Vehicle::setRenderPosition(const Point3F& pos, const QuatF& rot)
{
   MatrixF mat;
   rot.setMatrix(&mat);
   mat.setColumn(3,pos);
   Parent::setRenderTransform(mat);
}

void Vehicle::setTransform(const MatrixF& newMat)
{
   mRigid.setTransform(newMat);
   Parent::setTransform(newMat);
   mRigid.atRest = false;
   mContacts.count = 0;
}
#9
05/30/2006 (2:40 am)
Hmmm... been playing with this but aren't really getting anywhere :(
#10
05/30/2006 (5:26 am)
Sorry, just noticed your reply.

I was mistaken last night, the correct function should be setPosition/setRenderPosition.
You might have to tweak setTransform too, but I didn't do that yet with my own stuff so I don't know how to proceed there. It shouldn't be needed.

With that out of the way:

If you want this behaviour exclusively for your flyer then you'll have to override Vehicle.

Try changing this, in setPosition/setRenderPosition:
MatrixF mat;
   rot.setMatrix(&mat);
   mat.setColumn(3,pos);

to something like this:
MatrixF xRot, zRot;
   xRot.set(EulerF(rot.x, 0, 0));
   zRot.set(EulerF(0, 0, rot.z));
   MatrixF mat;
   mat.mul(zRot, xRot);
   mat.setColumn(3, pos);

And let me know if your vehicle is closer to what you want or if it fails. ( :/ )
#11
05/30/2006 (6:02 am)
Hi Stefan,

Erm - that does something very strange.. I can't control pitch and the roll and thrust directions are reversed... I think... actually it seems more complex than that... whatever it is it's not quite what I was going for :D
#12
05/30/2006 (7:19 am)
Hey,

Thought so. :) Well, the key is to set rot.y to 0, like I did above.. and make the appropriate changes to packUpdate/unpackUpdate. But there's a ton of other changes required that I simply don't have knowledge about.

That's why I ended up modifying the playerClass for our project. However, the physics get very unrealistic - but it wasn't a problem for us.

I hope someone else can step in and help you out. Good luck.
#13
05/30/2006 (1:26 pm)
FlyingVehicle should be a good base for a SpaceVehicle, and all you'll really need to do is remove the "auto-leveling" forces. It's not difficult. Forget rot.y and pack/unpackUpdate, what you want to modify is updateForces.

In FlyingVehicle::updateForces (or if you've made a new SpaceVehicle::updateForces), there are two places where auto-leveling forces are applied. First:
// Gyroscope
      F32 gf = mDataBlock->autoAngularForce * autoScale;
      torque -= xv * gf * mDot(yv,Point3F(0,0,1));
This appears to be auto-pitch-leveling, which you probably don't want in a space vehicle. So, remove those lines. Then a little further down:
// Roll
   torque += yv * steering.x * mDataBlock->steeringRollForce;
   F32 ar = mDataBlock->autoAngularForce * mDot(xv,Point3F(0,0,1));
   ar -= mDataBlock->rollForce * mDot(xv, mRigid.linVelocity);
   torque += yv * ar;
The first line applies roll force as a result of steering.x (yaw) input. You probably don't want that either. Then the next three lines apply an auto-leveling roll force. Remove those as well.

Now you should have full freedom for pitch and yaw. The vehicle should no longer auto-level. This still doesn't give you control over the vehicle roll though. For that you'll need to do a little more work. Probably, you'd want to set mSteering.z from move->roll in updateMove, then apply it in updateForces as "torque += yv * steering.z * mDataBlock->rollForce" or similar.


It's been a long time since I've worked with the stock Torque vehicle classes, so there might be something I missed, but that should get you started at least.
#14
05/30/2006 (3:40 pm)
Hi Scott,

You're an absolute star - works perfectly for pitch and yaw at any orientation. Setting cameraRoll = true in the datablock keeps the 3rd person camera behaving too. I have yaw and pitch, I can live without roll!!

I haven't been able to find any gimble-lock situations; this surprises me - I didn't think any Euler-based solution would be this convincing. I was expecting to have to use quaternions (*shudders*) and forcefeed my own updated position and rotation into the engine.

Thanks again :D
#15
05/30/2006 (4:05 pm)
Ah, but the vehicles do use quaternions! mRigid.angPosition is a QuatF (quaternion) type. Rotational force (torque) values are collected in updateForces as Euler angles (which is good because it makes the code much easier to understand), but these are applied to the QuatF angPosition, which performs the actual rotation. The final MatrixF mObjToWorld transform is then generated from angPosition.

edit: And, you're welcome. I'm happy to help. :)
#16
05/30/2006 (4:07 pm)
Nice one Scott.

What I attemped to above, was to remove rotation around the Y axis - to make the craft behave more like a flying player, which is what I thought Iain wanted. Your code doesn't accomplish that, though - and apparantly Iain didn't even need it. :)

Just wanted to say these two code examples are touching two totally different things and are not to replace eachother.
#17
06/01/2006 (2:05 am)
@Scott - Ahhhh I see!! Thanks for clarifying. Nice way of doing it.

@Stefan - No worries, thanks for trying to help :)

There are a couple of other small changes I've made to the class; possibly worth a SpaceVehicle resource in case anyone else needs this - I'll get on that.