Airplane Simple Flight [BuggySwires + Ogre 1.7]

CodeZealot

04-01-2012 17:23:19

Hi guys,

I was hoping someone would be able to point me in the right direction as to how to control a flying object using NxOgre. I am not looking for complex
flight dynamics such as lift and drag; the Airplane simply needs to move in the direction it's facing (similar to a spaceship, except that I will later add
forces for deceleration and gravity), with its orientation being controlled by a joystick. Previously, I was just using Ogre3D's translations and rotations,
so I need to convert the movement of the Airplane to use NxOgre. Here are my problems explained in detail:

My joystick with multiple axes has its input passed to the Airplane class in the following method:

void Airplane::injectJoystick(float rotX, float rotY, float rotZ, float transZ)

rotX, rotY, and rotZ are the angles to pitch, yaw and roll by respectively, with transZ being the amount to speed up or slow down by in the direction faced.
I previously used Ogre3D's SceneNode::pitch, yaw, roll functions to orient the Airplane, but have now been using Critter::Body::addTorque() like so:

// I have alternated between using this:
m_body->addTorque(NxOgre::Vec3(rotX, -rotY, rotZ));
// or this:
m_body->addLocalTorque(NxOgre::Vec3(rotX, -rotY, rotZ));

to achieve the same effect. Unfortunately, it tends to be quite clunky to control and some of the rotations get skewed - for example, the rotY axis actually
pitches the plane sometimes. I have also tried using Critter::Body::setGlobalOrientation and Critter::Body::setGlobalOrientationQuat (I'm not quite sure how
to use Matrix33/44 and quaternions for orientations anyway) but these methods make the Airplane rotate in a very jittery way.

Also, I previously accelerated the Plane in the direction it was facing by using translations:

// In Airplane::injectJoystick(float rotX, float rotY, float rotZ, float transZ)
// ...
m_speed = transZ;

// In Airplane::update(Ogre::Real timeSinceLastFrame)
// ...
m_sceneNode->translate(0, 0, timeSinceLastFrame * m_speed, Ogre::Node::TS_LOCAL);


But now have tried to use Critter::Body::addLocalForce():

// In Airplane::injectJoystick(float rotX, float rotY, float rotZ, float transZ)
// ...
m_body->addLocalForce(NxOgre::Vec3(0.0f, 0.0f, -transZ));


or Critter::Body::setLinearVelocity():

// In Airplane::injectJoystick(float rotX, float rotY, float rotZ, float transZ)
// ...
m_speed += transZ;

// In Airplane::update(Ogre::Real timeSinceLastFrame)
// ...
m_body->setLinearVelocity(0.0f, 0.0f, m_speed);

However, neither of these actually make the Airplane move in the direction its facing. The Airplane will move forwards, but once it turns, it
still moves in the direction it was pointing initially. I tried getting the orientation in Vec3 form, so that I could setLinearVelocity to (orientation * speed),
but I couldn't figure out how to get what I needed from getGlobalOrientation() and getGlobalOrientationQuat().

So, to my questions -
Question 1:
What would be the best way to get as close to the functionality of pitch, yaw and roll for orienting my Airplane, given axis data in the form of floats?

Question 2:
How can I make the Airplane constantly move in the direction it's facing, controlling the speed with another axis' data (float between 0.0 and 1.0)?

I have done extensive forum searches to see could I find the answers I'm looking for, but I can't find many posts relating directly to these issues.
Any help would be greatly appreciated.
Thanks.

saejox

05-01-2012 00:57:54

use a kinematic actor.
otherwise things get complicated. apply your own gravity and force yourself.

(or disable rotations by passing flags to body)

for quaternions, check this class: http://www.ogre3d.org/tikiwiki/Euler+Angle+Class
i'll allow you to use euler angles (yaw,pitch,roll) instead of quaternions.

CodeZealot

05-01-2012 01:38:14

Hi saejox, thank you for your quick reply.
I originally shied away from using the KinematicActor for my Plane, as the only functions that seem available for manipulating its movement are

moveGlobalOrientation
moveGlobalOrientationQuat
moveGlobalPose
moveGlobalPosition


and the get/setGlobal-(etc.) equivalents of the above functions. With Critter::Body, at least I could directly addTorque which was simpler to me at
the time. I'm unsure how to use the above functions with my Joystick inputs to achieve the desired effect. How would someone go about using
these functions directly (if they weren't using your Euler class link) given inputs like this:


void Airplane::injectJoystick(float rotX, float rotY, float rotZ, float transZ)


Also, is the correct way to create a KinematicActor through the Critter::createKinematicBody function like so?

NxOgre::KinematicActor * kinematicActor = critterRenderSystem->createKinematicBody(NxOgre::BoxDescription(5.0f, 5.0f, 5.0f), NxOgre::Matrix44::IDENTITY, "Plane.mesh");

I can't spot a createKinematicActor function anywhere.

Thank you for the Euler link however, I'll have a read through it and hopefully that will solve my conversion problems between those kinds of
inputs and Quats. I have yet to find a good article explaining how to use Quaternions (and I forget my college teachings on it), otherwise I'm
sure I'd find this problem a lot easier!
EDIT: Just found an excellent quaternion primer here: http://www.ogre3d.org/tikiwiki/Quaterni ... ion+Primer
Cheers.

saejox

05-01-2012 16:46:31

that's right. use critter render system to create kinematic actors.

i know it would look easy to just call addforce/torque, but my understanding is that every time mWorld->advance(evt.timeSinceLastFrame); called physx changes orientation disregarding players input.

you can however get away without using kinematic actors. like this;


b->raiseDynamicFlag(NxOgre::DynamicRigidbodyFlags::DisableGravity);
b->raiseDynamicFlag(NxOgre::DynamicRigidbodyFlags::FreezePositionZ);
b->raiseDynamicFlag(NxOgre::DynamicRigidbodyFlags::FreezeRotationY);


pass flags like this and disable rotation and gravity. you still can apply torque and force or your own rotation.

i'm no pro at this, maybe i'm missing something.
i recently made a projectile system, that's what i used for my arrows. simulating my own gravity with addforce and setoritentation to face target.

CodeZealot

06-01-2012 13:34:19

Unfortunately I can't use the FreezeRotation flags with addTorque because that completely stops any rotations with the body, defeating the purpose of adding torque in the first place.

Also, I'm not sure whether I should use a KinematicActor for my Plane now as I found this quote from betajaen in this post viewtopic.php?f=6&t=10842 :

This is how I think kinematic actors work;
- Linear and angular moments are reset to zero every frame; stopping any further action from previous events.

Which wouldn't seem to suit the behaviour of a gliding Plane.

I've changed my Plane's Critter::Body to Critter::KinematicBody, to experiment with the moveGlobal_______ functions. I'm now using this code:


void Plane::injectJoystick(float rotX, float rotY, float rotZ, float transZ)
{
NxOgre::Quat x(NxOgre::Radian(rotX), NxOgre::Vec3::UNIT_X);
NxOgre::Quat y(NxOgre::Radian(rotY), NxOgre::Vec3::UNIT_Y);
NxOgre::Quat z(NxOgre::Radian(rotZ), NxOgre::Vec3::UNIT_Z);
m_body->moveGlobalOrientationQuat(x * y * z);

But the Plane doesn't seem to move with the Joystick at all, it just sits motionless. I also tried to take the original orientation into account, in case the
moveGlobal____ functions aren't accumulative (more like a setOrientation than an addToOrientation function), like so:


void Plane::injectJoystick(float rotX, float rotY, float rotZ, float transZ)
{
NxOgre::Quat o = m_body->getGlobalOrientationQuat();
NxOgre::Quat x(NxOgre::Radian(rotX), NxOgre::Vec3::UNIT_X);
NxOgre::Quat y(NxOgre::Radian(rotY), NxOgre::Vec3::UNIT_Y);
NxOgre::Quat z(NxOgre::Radian(rotZ), NxOgre::Vec3::UNIT_Z);
m_body->moveGlobalOrientationQuat(o * x * y * z);

But this doesn't work either, it just flips the Plane upside-down extremely quickly, alternating a few times per second.

Thank you again for all of your suggestions, I'm hoping I can figure this out or perhaps someone on the forums will have
encountered this before - I'm really stuck as to what to do next.