rigid rotation
by Cedrik zamo · in Torque 3D Professional · 12/26/2011 (3:04 am) · 15 replies
hi,
I rotate an object like this, based on flying vehicle code :
But when I rotate the object (with mouse) it rotate back to the original position.
If I don't use the mRigid.torque -= mRigid.angMomentum * mDataBlock->rotationalDrag; it rotate perfectly but as soon as there is a collision it start to rotate alone and never stop.
I rotate an object like this, based on flying vehicle code :
// in updateForces
mRigid.torque -= mRigid.angMomentum * mDataBlock->rotationalDrag;
Point3F torque = Point3F(-mRotation.x, 0 , -mRotation.y);
torque *= 10.0;
mObjToWorld.mulV(torque); //+
mRigid.applyRotationImpulse(torque);
// in rigid class
void Rigid::applyRotationImpulse(const Point3F &rotation)
{
angMomentum += rotation;
invWorldInertia.mulV(angMomentum, &angVelocity);
}But when I rotate the object (with mouse) it rotate back to the original position.
If I don't use the mRigid.torque -= mRigid.angMomentum * mDataBlock->rotationalDrag; it rotate perfectly but as soon as there is a collision it start to rotate alone and never stop.
#2
I don't really understand all rigid logic at this time.
I'm trying to rotate a vehicle according to the mouse without rotation inertia, but also with collisions.
12/26/2011 (12:40 pm)
All the code is there. Look at the applyRotationImpulse func.I don't really understand all rigid logic at this time.
I'm trying to rotate a vehicle according to the mouse without rotation inertia, but also with collisions.
#3
I change to
mRigid.angVelocity *= mDataBlock->rotationalDrag;
But the object still rotate back to it's original rotation, like if angVelocity was the object rotation, not the object angular velocity.
Is it possible to find more usefull information than those incredible comments ?
12/27/2011 (3:11 am)
There is something unclear.I change to
mRigid.angVelocity *= mDataBlock->rotationalDrag;
But the object still rotate back to it's original rotation, like if angVelocity was the object rotation, not the object angular velocity.
Is it possible to find more usefull information than those incredible comments ?
MatrixF objectInertia; ///< Moment of inertia MatrixF invObjectInertia; ///< Inverse moment of inertia MatrixF invWorldInertia; ///< Inverse moment of inertia in world space Point3F force; Point3F torque; Point3F linVelocity; ///< Linear velocity Point3F linPosition; ///< Current position Point3F linMomentum; ///< Linear momentum Point3F angVelocity; ///< Angular velocity QuatF angPosition; ///< Current rotation Point3F angMomentum; ///< Angular momentum Point3F centerOfMass; ///< Center of mass in object space Point3F worldCenterOfMass; ///< CofM in world space F32 mass; ///< Rigid body mass F32 oneOverMass; ///< 1 / mass F32 restitution; ///< Collision restitution F32 friction; ///< Friction coefficient
#4
mPreviousRotation is reseted to 0 every frame for un unknow reason.
The result is that the object return to it's original rotation as soon as I stop to move the mouse. The original rotation depends on previous collisions.
12/29/2011 (5:32 am)
This all my code.mPreviousRotation is reseted to 0 every frame for un unknow reason.
The result is that the object return to it's original rotation as soon as I stop to move the mouse. The original rotation depends on previous collisions.
#5
12/29/2011 (5:34 am)
amhplayer.h#ifndef _AMH_PLAYER_
#define _AMH_PLAYER_
#ifndef _VEHICLE_H_
#include "T3D/vehicles/Vehicle.h"
#endif
#ifndef _CLIPPEDPOLYLIST_H_
#include "collision/clippedPolyList.h"
#endif
class ParticleEmitter;
class ParticleEmitterData;
struct AMHPlayerData: public VehicleData {
typedef VehicleData Parent;
enum Sounds {
JetSound,
EngineSound,
MaxSounds,
};
SFXProfile* sound[MaxSounds];
enum Jets {
// These enums index into a static name list.
ForwardJetEmitter, // Thrust forward
BackwardJetEmitter, // Thrust backward
DownwardJetEmitter, // Thrust down
TrailEmitter, // Contrail
MaxJetEmitters,
};
ParticleEmitterData* jetEmitter[MaxJetEmitters];
F32 minTrailSpeed;
//
F32 maneuveringForce;
F32 horizontalSurfaceForce;
F32 verticalSurfaceForce;
F32 autoInputDamping;
F32 steeringForce;
F32 steeringRollForce;
F32 rollForce;
F32 autoAngularForce;
F32 rotationalDrag;
F32 maxAutoSpeed;
F32 autoLinearForce;
F32 hoverHeight;
F32 createHoverHeight;
F32 vertThrustMultiple;
// Initialized in preload
ClippedPolyList rigidBody;
S32 surfaceCount;
F32 maxSpeed;
enum JetNodes {
// These enums index into a static name list.
ForwardJetNode,
ForwardJetNode1,
BackwardJetNode,
BackwardJetNode1,
DownwardJetNode,
DownwardJetNode1,
//
TrailNode,
TrailNode1,
TrailNode2,
TrailNode3,
//
MaxJetNodes,
MaxDirectionJets = 2,
ThrustJetStart = ForwardJetNode,
NumThrustJets = TrailNode,
MaxTrails = 4,
};
static const char *sJetNode[MaxJetNodes];
S32 jetNode[MaxJetNodes];
//
AMHPlayerData();
DECLARE_CONOBJECT(AMHPlayerData);
static void initPersistFields();
bool preload(bool server, String &errorStr);
void packData(BitStream* stream);
void unpackData(BitStream* stream);
};
#6
12/29/2011 (5:35 am)
class AMHPlayer:
public Vehicle
{
typedef Vehicle Parent;
protected:
Point3F
mPreviousRotation,
mDesiredRotation;
AMHPlayerData * mDataBlock;
SFXSource* mJetSound;
SFXSource* mEngineSound;
enum NetMaskBits {
InitMask = BIT(0),
HoverHeight = BIT(1)
};
bool createHeightOn;
F32 mCeilingFactor;
enum ThrustDirection {
// Enums index into sJetActivationTable
ThrustForward,
ThrustBackward,
ThrustUp,
ThrustDown,
ThrustLeft,
ThrustRight,
NumThrustDirections,
NumThrustBits = 6
};
Point3F mThrust;
ThrustDirection mThrustDirection;
// Jet Threads
enum Jets {
// These enums index into a static name list.
BackActivate,
BackMaintain,
BottomActivate,
BottomMaintain,
JetAnimCount
};
static const char* sJetSequence[AMHPlayer::JetAnimCount];
TSThread* mJetThread[JetAnimCount];
S32 mJetSeq[JetAnimCount];
bool mBackMaintainOn;
bool mBottomMaintainOn;
// Jet Particles
struct JetActivation {
// Convert thrust direction into nodes & emitters
S32 node;
S32 emitter;
};
static JetActivation sJetActivation[NumThrustDirections];
SimObjectPtr<ParticleEmitter> mJetEmitter[AMHPlayerData::MaxJetNodes];
//
bool onNewDataBlock(GameBaseData* dptr,bool reload);
void updateMove(const Move *move);
void updateForces(F32);
// bool collideBody(const MatrixF& mat,Collision* info);
F32 getHeight();
// Client sounds & particles
void updateJet(F32 dt);
void updateEngineSound(F32 level);
void updateEmitter(bool active,F32 dt,ParticleEmitterData *emitter,S32 idx,S32 count);
U32 getCollisionMask();
public:
DECLARE_CONOBJECT(AMHPlayer);
static void initPersistFields();
AMHPlayer();
~AMHPlayer();
bool onAdd();
void onRemove();
void advanceTime(F32 dt);
void writePacketData(GameConnection *conn, BitStream *stream);
void readPacketData(GameConnection *conn, BitStream *stream);
U32 packUpdate(NetConnection *conn, U32 mask, BitStream *stream);
void unpackUpdate(NetConnection *conn, BitStream *stream);
void useCreateHeight(bool val);
};
#endif
#7
amhplayer.cpp
12/29/2011 (5:37 am)
amhplayer.cpp
//-----------------------------------------------------------------------------
// Torque
// Copyright GarageGames, LLC 2011
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "AMHPlayer.h"
#include "app/game.h"
#include "math/mMath.h"
#include "console/simBase.h"
#include "console/console.h"
#include "console/consoleTypes.h"
#include "console/engineAPI.h"
#include "collision/clippedPolyList.h"
#include "collision/planeExtractor.h"
#include "core/stream/bitStream.h"
#include "core/dnet.h"
#include "T3D/gameBase/gameConnection.h"
#include "ts/tsShapeInstance.h"
#include "T3D/fx/particleEmitter.h"
#include "sfx/sfxSystem.h"
#include "sfx/sfxProfile.h"
#include "sfx/sfxSource.h"
#include "T3D/missionArea.h"
//----------------------------------------------------------------------------
const static U32 sCollisionMoveMask = ( TerrainObjectType | InteriorObjectType |
WaterObjectType | PlayerObjectType |
StaticShapeObjectType | VehicleObjectType |
VehicleBlockerObjectType );
static U32 sServerCollisionMask = sCollisionMoveMask; // ItemObjectType
static U32 sClientCollisionMask = sCollisionMoveMask;
//
const char* AMHPlayer::sJetSequence[AMHPlayer::JetAnimCount] =
{
"activateBack",
"maintainBack",
"activateBot",
"maintainBot",
};
const char* AMHPlayerData::sJetNode[AMHPlayerData::MaxJetNodes] =
{
"JetNozzle0", // Thrust Forward
"JetNozzle1",
"JetNozzleX", // Thrust Backward
"JetNozzleY",
"JetNozzle2", // Thrust Downward
"JetNozzle3",
"contrail0", // Trail
"contrail1",
"contrail2",
"contrail3",
};
// Convert thrust direction into nodes & emitters
AMHPlayer::JetActivation AMHPlayer::sJetActivation[NumThrustDirections] = {
{ AMHPlayerData::ForwardJetNode, AMHPlayerData::ForwardJetEmitter },
{ AMHPlayerData::BackwardJetNode, AMHPlayerData::BackwardJetEmitter },
{ AMHPlayerData::DownwardJetNode, AMHPlayerData::DownwardJetEmitter },
};
//----------------------------------------------------------------------------
IMPLEMENT_CO_DATABLOCK_V1(AMHPlayerData);
ConsoleDocClass( AMHPlayerData,
"@brief Defines the properties of a AMHPlayer.nn"
"@ingroup Vehiclesn"
);
AMHPlayerData::AMHPlayerData()
{
maneuveringForce = 0;
horizontalSurfaceForce = 0;
verticalSurfaceForce = 0;
autoInputDamping = 1;
steeringForce = 1;
steeringRollForce = 1;
rollForce = 1;
autoAngularForce = 0;
rotationalDrag = 0;
autoLinearForce = 0;
maxAutoSpeed = 0;
hoverHeight = 2;
createHoverHeight = 2;
maxSteeringAngle = M_PI_F;
minTrailSpeed = 1;
maxSpeed = 100;
for (S32 k = 0; k < MaxJetNodes; k++)
jetNode[k] = -1;
for (S32 j = 0; j < MaxJetEmitters; j++)
jetEmitter[j] = 0;
for (S32 i = 0; i < MaxSounds; i++)
sound[i] = 0;
vertThrustMultiple = 1.0;
}
bool AMHPlayerData::preload(bool server, String &errorStr)
{
if (!Parent::preload(server, errorStr))
return false;
TSShapeInstance* si = new TSShapeInstance(mShape, false);
// Resolve objects transmitted from server
if (!server) {
for (S32 i = 0; i < MaxSounds; i++)
if (sound[i])
Sim::findObject(SimObjectId(sound[i]),sound[i]);
for (S32 j = 0; j < MaxJetEmitters; j++)
if (jetEmitter[j])
Sim::findObject(SimObjectId(jetEmitter[j]),jetEmitter[j]);
}
// Extract collision planes from shape collision detail level
if (collisionDetails[0] != -1)
{
MatrixF imat(1);
PlaneExtractorPolyList polyList;
polyList.mPlaneList = &rigidBody.mPlaneList;
polyList.setTransform(&imat, Point3F(1,1,1));
si->animate(collisionDetails[0]);
si->buildPolyList(&polyList,collisionDetails[0]);
}
// Resolve jet nodes
for (S32 j = 0; j < MaxJetNodes; j++)
jetNode[j] = mShape->findNode(sJetNode[j]);
//
maxSpeed = maneuveringForce / minDrag;
delete si;
return true;
}
#8
12/29/2011 (5:39 am)
void AMHPlayerData::initPersistFields()
{
addField( "jetSound", TYPEID< SFXProfile >(), Offset(sound[JetSound], AMHPlayerData),
"Looping sound to play while the vehicle is jetting." );
addField( "engineSound", TYPEID< SFXProfile >(), Offset(sound[EngineSound], AMHPlayerData),
"Looping engine sound." );
addField( "maneuveringForce", TypeF32, Offset(maneuveringForce, AMHPlayerData),
"Maximum X and Y (horizontal plane) maneuvering force.nThe actual force "
"applied depends on the current thrust." );
addField( "horizontalSurfaceForce", TypeF32, Offset(horizontalSurfaceForce, AMHPlayerData),
"Damping force in the opposite direction to sideways velocity." );
addField( "verticalSurfaceForce", TypeF32, Offset(verticalSurfaceForce, AMHPlayerData),
"Damping force in the opposite direction to vertical velocity." );
addField( "autoInputDamping", TypeF32, Offset(autoInputDamping, AMHPlayerData),
"Scale factor applied to steering input if speed is less than maxAutoSpeed.n"
"Smaller values make steering less sensitive." );
addField( "steeringForce", TypeF32, Offset(steeringForce, AMHPlayerData),
"Maximum X and Z (sideways and vertical) steering force.nThe actual force "
"applied depends on the current steering input." );
addField( "steeringRollForce", TypeF32, Offset(steeringRollForce, AMHPlayerData),
"Roll force induced by sideways steering input value." );
addField( "rollForce", TypeF32, Offset(rollForce, AMHPlayerData),
"Damping torque against rolling maneuvers (rotation about the y-axis).n"
"Acts to adjust roll to a stable position over time." );
addField( "autoAngularForce", TypeF32, Offset(autoAngularForce, AMHPlayerData),
"Corrective torque applied to level out the vehicle when moving at less "
"than maxAutoSpeed.nThe force is inversely proportional to vehicle speed." );
addField( "rotationalDrag", TypeF32, Offset(rotationalDrag, AMHPlayerData),
"Rotational drag factor.nSlows vehicle rotation." );
addField( "autoLinearForce", TypeF32, Offset(autoLinearForce, AMHPlayerData),
"Corrective force applied to slow the vehicle when moving at less than "
"maxAutoSpeed.nThe force is inversely proportional to vehicle speed." );
addField( "maxAutoSpeed", TypeF32, Offset(maxAutoSpeed, AMHPlayerData),
"Maximum speed for automatic vehicle control assistance.nVehicles "
"travelling at speeds above this value do not get control assitance." );
addField( "hoverHeight", TypeF32, Offset(hoverHeight, AMHPlayerData),
"The vehicle's height off the ground when at rest." );
addField( "createHoverHeight", TypeF32, Offset(createHoverHeight, AMHPlayerData),
"The vehicle's height off the ground when useCreateHeight is active.nThis "
"can help avoid problems with spawning the vehicle." );
addField( "forwardJetEmitter",TYPEID< ParticleEmitterData >(), Offset(jetEmitter[ForwardJetEmitter], AMHPlayerData),
"Emitter to generate particles for forward jet thrust.nForward jet "
"thrust particles are emitted from model nodes JetNozzle0 and JetNozzle1." );
addField( "backwardJetEmitter",TYPEID< ParticleEmitterData >(), Offset(jetEmitter[BackwardJetEmitter], AMHPlayerData),
"Emitter to generate particles for backward jet thrust.nBackward jet "
"thrust particles are emitted from model nodes JetNozzleX and JetNozzleY." );
addField( "downJetEmitter",TYPEID< ParticleEmitterData >(), Offset(jetEmitter[DownwardJetEmitter], AMHPlayerData),
"Emitter to generate particles for downward jet thrust.nDownward jet "
"thrust particles are emitted from model nodes JetNozzle2 and JetNozzle3." );
addField( "trailEmitter",TYPEID< ParticleEmitterData >(), Offset(jetEmitter[TrailEmitter], AMHPlayerData),
"Emitter to generate contrail particles from model nodes contrail0 - contrail3." );
addField( "minTrailSpeed", TypeF32, Offset(minTrailSpeed, AMHPlayerData),
"Minimum speed to start generating contrail particles." );
addField( "vertThrustMultiple", TypeF32, Offset(vertThrustMultiple, AMHPlayerData),
"Multiplier applied to the jetForce (defined in VehicleData) when thrusting vertically." );
Parent::initPersistFields();
}
#9
12/29/2011 (5:40 am)
void AMHPlayerData::packData(BitStream* stream)
{
Parent::packData(stream);
for (S32 i = 0; i < MaxSounds; i++)
{
if (stream->writeFlag(sound[i]))
{
SimObjectId writtenId = packed ? SimObjectId(sound[i]) : sound[i]->getId();
stream->writeRangedU32(writtenId, DataBlockObjectIdFirst, DataBlockObjectIdLast);
}
}
for (S32 j = 0; j < MaxJetEmitters; j++)
{
if (stream->writeFlag(jetEmitter[j]))
{
SimObjectId writtenId = packed ? SimObjectId(jetEmitter[j]) : jetEmitter[j]->getId();
stream->writeRangedU32(writtenId, DataBlockObjectIdFirst,DataBlockObjectIdLast);
}
}
stream->write(maneuveringForce);
stream->write(horizontalSurfaceForce);
stream->write(verticalSurfaceForce);
stream->write(autoInputDamping);
stream->write(steeringForce);
stream->write(steeringRollForce);
stream->write(rollForce);
stream->write(autoAngularForce);
stream->write(rotationalDrag);
stream->write(autoLinearForce);
stream->write(maxAutoSpeed);
stream->write(hoverHeight);
stream->write(createHoverHeight);
stream->write(minTrailSpeed);
stream->write(vertThrustMultiple);
}
void AMHPlayerData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
for (S32 i = 0; i < MaxSounds; i++) {
sound[i] = NULL;
if (stream->readFlag())
sound[i] = (SFXProfile*)stream->readRangedU32(DataBlockObjectIdFirst,
DataBlockObjectIdLast);
}
for (S32 j = 0; j < MaxJetEmitters; j++) {
jetEmitter[j] = NULL;
if (stream->readFlag())
jetEmitter[j] = (ParticleEmitterData*)stream->readRangedU32(DataBlockObjectIdFirst,
DataBlockObjectIdLast);
}
stream->read(&maneuveringForce);
stream->read(&horizontalSurfaceForce);
stream->read(&verticalSurfaceForce);
stream->read(&autoInputDamping);
stream->read(&steeringForce);
stream->read(&steeringRollForce);
stream->read(&rollForce);
stream->read(&autoAngularForce);
stream->read(&rotationalDrag);
stream->read(&autoLinearForce);
stream->read(&maxAutoSpeed);
stream->read(&hoverHeight);
stream->read(&createHoverHeight);
stream->read(&minTrailSpeed);
stream->read(&vertThrustMultiple);
}
//----------------------------------------------------------------------------
IMPLEMENT_CO_NETOBJECT_V1(AMHPlayer);
ConsoleDocClass( AMHPlayer,
"@brief A flying vehicle.nn"
"The model used for the AMHPlayer has the following requirements:n"
"<dl>"
"<dt>Collision mesh</dt><dd>A convex collision mesh at detail size -1.</dd>"
"<dt>JetNozzle0-1 nodes</dt><dd>Particle emitter nodes used when thrusting "
"forward.</dd>"
"<dt>JetNozzle2-3 nodes</dt><dd>Particle emitter nodes used when thrusting "
"downward.</dd>"
"<dt>JetNozzleX, JetNozzleY nodes</dt><dd>Particle emitter nodes used when "
"thrusting backward.</dd>"
"<dt>contrail0-3 nodes</dt><dd>Particle emitter nodes used when generating "
"contrails.</dd>"
"<dt>activateBack animation</dt><dd>Non-cyclic animation sequence played when "
"the vehicle begins thrusting forwards.</dd>"
"<dt>maintainBack animation</dt><dd>Cyclic animation sequence played after "
"activateBack when the vehicle continues thrusting forwards.</dd>"
"<dt>activateBot animation</dt><dd>Non-cyclic animation sequence played "
"when the vehicle begins thrusting upwards.</dd>"
"<dt>maintainBot animation</dt><dd>Cyclic animation sequence played after "
"activateBot when the vehicle continues thrusting upwards.</dd>"
"</dl>"
"@ingroup Vehiclesn"
);
#10
12/29/2011 (5:41 am)
AMHPlayer::AMHPlayer()
{
mTypeMask |= PlayerObjectType | DynamicShapeObjectType | VehicleObjectType;
mPreviousRotation.set(0,0,0);
mDesiredRotation.set(0,0,0);
mSteering.set(0,0);
mThrottle = 0;
mJetting = false;
mJetSound = 0;
mEngineSound = 0;
mBackMaintainOn = false;
mBottomMaintainOn = false;
createHeightOn = false;
for (S32 i = 0; i < JetAnimCount; i++)
mJetThread[i] = 0;
}
AMHPlayer::~AMHPlayer()
{
}
//----------------------------------------------------------------------------
bool AMHPlayer::onAdd()
{
if(!Parent::onAdd())
return false;
addToScene();
if (isServerObject())
scriptOnAdd();
return true;
}
bool AMHPlayer::onNewDataBlock(GameBaseData* dptr, bool reload)
{
mDataBlock = dynamic_cast<AMHPlayerData*>(dptr);
if (!mDataBlock || !Parent::onNewDataBlock(dptr,reload))
return false;
// Sounds
if ( isGhost() )
{
// Create the sounds ahead of time. This reduces runtime
// costs and makes the system easier to understand.
SFX_DELETE( mJetSound );
SFX_DELETE( mEngineSound );
if ( mDataBlock->sound[AMHPlayerData::EngineSound] )
mEngineSound = SFX->createSource( mDataBlock->sound[AMHPlayerData::EngineSound], &getTransform() );
if ( mDataBlock->sound[AMHPlayerData::JetSound] )
mJetSound = SFX->createSource( mDataBlock->sound[AMHPlayerData::JetSound], &getTransform() );
}
// Jet Sequences
for (S32 i = 0; i < JetAnimCount; i++) {
TSShape const* shape = mShapeInstance->getShape();
mJetSeq[i] = shape->findSequence(sJetSequence[i]);
if (mJetSeq[i] != -1) {
if (i == BackActivate || i == BottomActivate) {
mJetThread[i] = mShapeInstance->addThread();
mShapeInstance->setSequence(mJetThread[i],mJetSeq[i],0);
mShapeInstance->setTimeScale(mJetThread[i],0);
}
}
else
mJetThread[i] = 0;
}
scriptOnNewDataBlock();
return true;
}
void AMHPlayer::onRemove()
{
SFX_DELETE( mJetSound );
SFX_DELETE( mEngineSound );
scriptOnRemove();
removeFromScene();
Parent::onRemove();
}
//----------------------------------------------------------------------------
void AMHPlayer::advanceTime(F32 dt)
{
Parent::advanceTime(dt);
updateEngineSound(1);
updateJet(dt);
}
//----------------------------------------------------------------------------
void AMHPlayer::updateMove(const Move* move)
{
PROFILE_SCOPE( AMHPlayer_UpdateMove );
Parent::updateMove(move);
if (move == &NullMove)
mSteering.set(0,0);
F32 speed = mRigid.linVelocity.len();
if (speed < mDataBlock->maxAutoSpeed)
mSteering *= mDataBlock->autoInputDamping;
// Check the mission area to get the factor for the flight ceiling
MissionArea * obj = MissionArea::getServerObject();
mCeilingFactor = 1.0f;
if (obj != NULL)
{
F32 flightCeiling = obj->getFlightCeiling();
F32 ceilingRange = obj->getFlightCeilingRange();
if (mRigid.linPosition.len() > flightCeiling)
{
// Thrust starts to fade at the ceiling, and is 0 at ceil + range
if (ceilingRange == 0)
{
mCeilingFactor = 0;
}
else
{
mCeilingFactor = 1.0f - ((mRigid.linPosition.len() - flightCeiling) / (flightCeiling + ceilingRange));
if (mCeilingFactor < 0.0f)
mCeilingFactor = 0.0f;
}
}
}
mThrust.x = move->x;
mThrust.y = move->y;
mThrust.z = move->z;
mDesiredRotation.x = move->yaw - mPreviousRotation.x;
mDesiredRotation.y = move->pitch - mPreviousRotation.y;
mSteering.x = mDesiredRotation.x;
mSteering.y = mDesiredRotation.y;
mPreviousRotation.x = move->yaw;
mPreviousRotation.y = move->pitch;
if (mThrust.y != 0.0f)
if (mThrust.y > 0)
mThrustDirection = ThrustForward;
else
mThrustDirection = ThrustBackward;
else
mThrustDirection = ThrustDown;
if (mCeilingFactor != 1.0f)
mJetting = false;
}
#11
12/29/2011 (5:42 am)
void AMHPlayer::updateForces(F32 /*dt*/)
{
PROFILE_SCOPE( AMHPlayer_UpdateForces );
MatrixF currPosMat;
mRigid.getTransform(&currPosMat);
mRigid.atRest = false;
Point3F massCenter;
currPosMat.mulP(mDataBlock->massCenter,&massCenter);
Point3F xv,yv,zv;
currPosMat.getColumn(0,&xv);
currPosMat.getColumn(1,&yv);
currPosMat.getColumn(2,&zv);
F32 speed = mRigid.linVelocity.len();
Point3F force = Point3F(0, 0, 0);
Point3F torque = Point3F(0, 0, 0);
// Drag at any speed
force -= mRigid.linVelocity * mDataBlock->minDrag;
torque -= mRigid.angMomentum * mDataBlock->rotationalDrag;
// Auto-stop at low speeds
if (speed < mDataBlock->maxAutoSpeed) {
F32 autoScale = 1 - speed / mDataBlock->maxAutoSpeed;
// Gyroscope
F32 gf = mDataBlock->autoAngularForce * autoScale;
torque -= xv * gf * mDot(yv,Point3F(0,0,1));
// Manuevering jets
F32 sf = mDataBlock->autoLinearForce * autoScale;
force -= yv * sf * mDot(yv, mRigid.linVelocity);
force -= xv * sf * mDot(xv, mRigid.linVelocity);
}
// Hovering Jet
F32 vf = 0;
F32 h = getHeight();
if (h <= 1) {
if (h > 0) {
vf -= vf * h * 0.1;
} else {
vf += mDataBlock->jetForce * -h;
}
}
force += zv * vf;
// Damping "surfaces"
force -= xv * mDot(xv,mRigid.linVelocity) * mDataBlock->horizontalSurfaceForce;
force -= zv * mDot(zv,mRigid.linVelocity) * mDataBlock->verticalSurfaceForce;
// Turbo Jet
if (mJetting) {
if (mThrustDirection == ThrustForward)
force += yv * mDataBlock->jetForce * mCeilingFactor;
else if (mThrustDirection == ThrustBackward)
force -= yv * mDataBlock->jetForce * mCeilingFactor;
else
force += zv * mDataBlock->jetForce * mDataBlock->vertThrustMultiple * mCeilingFactor;
}
// Maneuvering jets
force += yv * (mThrust.y * mDataBlock->maneuveringForce * mCeilingFactor);
force += xv * (mThrust.x * mDataBlock->maneuveringForce * mCeilingFactor);
force += zv * (mThrust.z * mDataBlock->maneuveringForce * mCeilingFactor);
// Steering
Point2F steering;
steering.x = mSteering.x / mDataBlock->maxSteeringAngle;
steering.x *= mFabs(steering.x);
steering.y = mSteering.y / mDataBlock->maxSteeringAngle;
steering.y *= mFabs(steering.y);
torque -= xv * steering.y * mDataBlock->steeringForce;
torque -= zv * steering.x * mDataBlock->steeringForce;
// 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;
*/
// Add in force from physical zones...
force += mAppliedForce;
// Container buoyancy & drag
force -= mRigid.linVelocity * mDrag;
//
mRigid.force = force;
mRigid.torque = torque;
}
//----------------------------------------------------------------------------
F32 AMHPlayer::getHeight()
{
Point3F sp,ep;
RayInfo collision;
F32 height = (createHeightOn) ? mDataBlock->createHoverHeight : mDataBlock->hoverHeight;
F32 r = 10 + height;
getTransform().getColumn(3, &sp);
ep.x = sp.x;
ep.y = sp.y;
ep.z = sp.z - r;
disableCollision();
if( !mContainer->castRay(sp, ep, sClientCollisionMask, &collision) == true )
collision.t = 1;
enableCollision();
return (r * collision.t - height) / 10;
}
//----------------------------------------------------------------------------
U32 AMHPlayer::getCollisionMask()
{
if (isServerObject())
return sServerCollisionMask;
else
return sClientCollisionMask;
}
//----------------------------------------------------------------------------
void AMHPlayer::updateEngineSound(F32 level)
{
if ( !mEngineSound )
return;
if ( !mEngineSound->isPlaying() )
mEngineSound->play();
mEngineSound->setTransform( getTransform() );
mEngineSound->setVelocity( getVelocity() );
mEngineSound->setPitch( level );
}
#12
12/29/2011 (5:44 am)
void AMHPlayer::updateJet(F32 dt)
{
// Thrust Animation threads
// Back
if (mJetSeq[BackActivate] >=0 ) {
if(!mBackMaintainOn || mThrustDirection != ThrustForward) {
if(mBackMaintainOn) {
mShapeInstance->setPos(mJetThread[BackActivate], 1);
mShapeInstance->destroyThread(mJetThread[BackMaintain]);
mBackMaintainOn = false;
}
mShapeInstance->setTimeScale(mJetThread[BackActivate],
(mThrustDirection == ThrustForward)? 1.0f : -1.0f);
mShapeInstance->advanceTime(dt,mJetThread[BackActivate]);
}
if(mJetSeq[BackMaintain] >= 0 && !mBackMaintainOn &&
mShapeInstance->getPos(mJetThread[BackActivate]) >= 1.0) {
mShapeInstance->setPos(mJetThread[BackActivate], 0);
mShapeInstance->setTimeScale(mJetThread[BackActivate], 0);
mJetThread[BackMaintain] = mShapeInstance->addThread();
mShapeInstance->setSequence(mJetThread[BackMaintain],mJetSeq[BackMaintain],0);
mShapeInstance->setTimeScale(mJetThread[BackMaintain],1);
mBackMaintainOn = true;
}
if(mBackMaintainOn)
mShapeInstance->advanceTime(dt,mJetThread[BackMaintain]);
}
// Thrust Animation threads
// Bottom
if (mJetSeq[BottomActivate] >=0 ) {
if(!mBottomMaintainOn || mThrustDirection != ThrustDown || !mJetting) {
if(mBottomMaintainOn) {
mShapeInstance->setPos(mJetThread[BottomActivate], 1);
mShapeInstance->destroyThread(mJetThread[BottomMaintain]);
mBottomMaintainOn = false;
}
mShapeInstance->setTimeScale(mJetThread[BottomActivate],
(mThrustDirection == ThrustDown && mJetting)? 1.0f : -1.0f);
mShapeInstance->advanceTime(dt,mJetThread[BottomActivate]);
}
if(mJetSeq[BottomMaintain] >= 0 && !mBottomMaintainOn &&
mShapeInstance->getPos(mJetThread[BottomActivate]) >= 1.0) {
mShapeInstance->setPos(mJetThread[BottomActivate], 0);
mShapeInstance->setTimeScale(mJetThread[BottomActivate], 0);
mJetThread[BottomMaintain] = mShapeInstance->addThread();
mShapeInstance->setSequence(mJetThread[BottomMaintain],mJetSeq[BottomMaintain],0);
mShapeInstance->setTimeScale(mJetThread[BottomMaintain],1);
mBottomMaintainOn = true;
}
if(mBottomMaintainOn)
mShapeInstance->advanceTime(dt,mJetThread[BottomMaintain]);
}
// Jet particles
for (S32 j = 0; j < NumThrustDirections; j++) {
JetActivation& jet = sJetActivation[j];
updateEmitter(mJetting && j == mThrustDirection,dt,mDataBlock->jetEmitter[jet.emitter],
jet.node,AMHPlayerData::MaxDirectionJets);
}
// Trail jets
Point3F yv;
mObjToWorld.getColumn(1,&yv);
F32 speed = mFabs(mDot(yv,mRigid.linVelocity));
F32 trail = 0;
if (speed > mDataBlock->minTrailSpeed) {
trail = dt;
if (speed < mDataBlock->maxSpeed)
trail *= (speed - mDataBlock->minTrailSpeed) / mDataBlock->maxSpeed;
}
updateEmitter(trail,trail,mDataBlock->jetEmitter[AMHPlayerData::TrailEmitter],
AMHPlayerData::TrailNode,AMHPlayerData::MaxTrails);
// Allocate/Deallocate voice on demand.
if ( !mJetSound )
return;
if ( !mJetting )
mJetSound->stop();
else
{
if ( !mJetSound->isPlaying() )
mJetSound->play();
mJetSound->setTransform( getTransform() );
mJetSound->setVelocity( getVelocity() );
}
}
//----------------------------------------------------------------------------
void AMHPlayer::updateEmitter(bool active,F32 dt,ParticleEmitterData *emitter,S32 idx,S32 count)
{
if (!emitter)
return;
for (S32 j = idx; j < idx + count; j++)
if (active) {
if (mDataBlock->jetNode[j] != -1) {
if (!bool(mJetEmitter[j])) {
mJetEmitter[j] = new ParticleEmitter;
mJetEmitter[j]->onNewDataBlock(emitter,false);
mJetEmitter[j]->registerObject();
}
MatrixF mat;
Point3F pos,axis;
mat.mul(getRenderTransform(),
mShapeInstance->mNodeTransforms[mDataBlock->jetNode[j]]);
mat.getColumn(1,&axis);
mat.getColumn(3,&pos);
mJetEmitter[j]->emitParticles(pos,true,axis,getVelocity(),(U32)(dt * 1000));
}
}
else {
for (S32 j = idx; j < idx + count; j++)
if (bool(mJetEmitter[j])) {
mJetEmitter[j]->deleteWhenEmpty();
mJetEmitter[j] = 0;
}
}
}
#13
12/29/2011 (5:45 am)
void AMHPlayer::writePacketData(GameConnection *connection, BitStream *stream)
{
Parent::writePacketData(connection, stream);
}
void AMHPlayer::readPacketData(GameConnection *connection, BitStream *stream)
{
Parent::readPacketData(connection, stream);
setPosition(mRigid.linPosition,mRigid.angPosition);
mDelta.pos = mRigid.linPosition;
mDelta.rot[1] = mRigid.angPosition;
}
U32 AMHPlayer::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(stream->writeFlag(getControllingClient() == con && !(mask & InitialUpdateMask)))
return retMask;
stream->writeFlag(createHeightOn);
stream->writeInt(mThrustDirection,NumThrustBits);
return retMask;
}
void AMHPlayer::unpackUpdate(NetConnection *con, BitStream *stream)
{
Parent::unpackUpdate(con,stream);
if(stream->readFlag())
return;
createHeightOn = stream->readFlag();
mThrustDirection = ThrustDirection(stream->readInt(NumThrustBits));
}
void AMHPlayer::initPersistFields()
{
Parent::initPersistFields();
}
DefineEngineMethod( AMHPlayer, useCreateHeight, void, ( bool enabled ),,
"Set whether the vehicle should temporarily use the createHoverHeight "
"specified in the datablock.nThis can help avoid problems with spawning.n"
"@param enabled true to use the datablock createHoverHeight, false otherwisen" )
{
object->useCreateHeight( enabled );
}
void AMHPlayer::useCreateHeight(bool val)
{
createHeightOn = val;
setMaskBits(HoverHeight);
}
#14
I got the following log.
First mouse is at 0 0, then I move it up (block #2) but the mPreviousRotation is again 0 in the next block.
Nevermind, was a problem with float to int.
12/29/2011 (6:23 am)
Does updateMove called twice per frame with move reset to 0 ?I got the following log.
First mouse is at 0 0, then I move it up (block #2) but the mPreviousRotation is again 0 in the next block.
Nevermind, was a problem with float to int.
#15
12/29/2011 (6:50 am)
I give up. Going to continue with Unity.
Torque Owner Demolishun
DemolishunConsulting Rocks!
Does the mouse provide a rotational impulse? If not then it is not working inside of the physics code to apply a rotation with a mouse. You might need to apply rotation as an impulse.
What exactly are you trying to do?