Vehicle Based Animation
by Tim Hutcheson · in Torque Game Engine · 12/13/2005 (9:12 am) · 17 replies
I'm experimenting with adding the animation functionality found in the player class to the vehicle class and wonder if anyone else has any experience trying to do this. I have a wheeled vehicle that needs to articulate using a dsq sequence and am trying to merge the animation code from player into the vehicle class. Got it compiled and running but getting bogged down now trying to debug out of bounds errors from bitstream, etc.
So I thought it's time to take a breather and post this to see what others think of the problem. Any comments, negative or otherwise, are apprciated.
So I thought it's time to take a breather and post this to see what others think of the problem. Any comments, negative or otherwise, are apprciated.
About the author
#2
Thanks for opening up this solution path for me.
12/13/2005 (9:47 am)
Very interesting. But could you elaborate a little. I'm not accustomed to doing animations and had only thought of them interms of .dsq based effects. What then is the equivalent of the animated sequence being assigned, ie A,B,C,D? And where do I dig into the code for assigning them to frames, etc?Thanks for opening up this solution path for me.
#3
One of the available exporters is set to accept animations as materials with 'sequence' flags set.
At the time of export, you establish the name of a given sequence and what frames it refers to... if memory serves.
12/13/2005 (9:58 am)
Tim, you can export straightforward timline aimations through Milkshape.One of the available exporters is set to accept animations as materials with 'sequence' flags set.
At the time of export, you establish the name of a given sequence and what frames it refers to... if memory serves.
#4
I use 3DS Max but from what I understand the process is similiar among the different software packages. Once you have the animation executed you then place a Sequence helper in the scene with your vehicle. Name this something that describes what the animation is then open the Track View or equivalent so you can see the keyframe properties. In the treeview of the model scroll to the bottom and open the Sequence helper entry. With that open you have to add a starting key and an end key precisely where this particular animation starts and stops.
Now export.
That's not the whole of it though. The entire process is a bit complicated. Do a word search for vehicle animation and suspension and you should come up with several links. Hope this helps.
12/13/2005 (10:15 am)
Well, if you're working a wheeled vehicle you can animate each one of the axles to move in synch with the tires (which are already animated by Torque. That would be four animation sets right there. You can also animate other moving parts on the chassis of your vehicle, say a radar. That's another. You can also animate blinking running light, etc. Each one of these would be a separate animation that would be assigned a specific set of frames on your timeline.I use 3DS Max but from what I understand the process is similiar among the different software packages. Once you have the animation executed you then place a Sequence helper in the scene with your vehicle. Name this something that describes what the animation is then open the Track View or equivalent so you can see the keyframe properties. In the treeview of the model scroll to the bottom and open the Sequence helper entry. With that open you have to add a starting key and an end key precisely where this particular animation starts and stops.
Now export.
That's not the whole of it though. The entire process is a bit complicated. Do a word search for vehicle animation and suspension and you should come up with several links. Hope this helps.
#5
12/13/2005 (11:33 am)
@Tim, just look in the wheeledvehicle class at how the animations are triggered. None of them use dsq's so it's basically a matter of creating the animation in your vehicle object and then adding 2 or 3 lines of code to trigger the animation as required.
#6
I'll post later as/if I get this going.
12/13/2005 (11:46 am)
Thanks all. I've got the sequences in the .dts files and verified them with ShowTool. Digging into vehicle.cc and wheeledVehicle.cc once again...I'll post later as/if I get this going.
#7
I've progressed along in fits and starts and have the following to report.
I experimented in wheeledVehicle with code in onNewDataBlock like:
where the leanbackSequence03, for example, has the corrected reference to the motion needed for moving the bot into the "leanback' position. And added all/(?) the initialization and the bits of code that it seemed to need to initiate the sequence etc. But was never able to get the sequence to appear.
Anyway, in the process I returned to my original idea of extracting/merging the animationfunctionality of the player class, as that seems to be the most complete and generalized approach available.
So I wound up with an "AnimatedVehicle" class that has "Vehicle" class as its base class and has all of the missing animation routines from the "Player" class. My WheeledVehicle class is now derived from AnimatedVehicle.
So now, for example, my WheeledVehicle has available to it a routine, just like in the PLayer class,
and so on. The goal of all this is to be able to generalized behaviors simlar to the ORK's wave and salute animations. Any comments on this approach would be appreciated. I can post the AnimatedVehicle.cc class code if anyone is interested in having that.
Here is (next post) the AnimatedVehicle.h class description, with a few unrelated footpuffs stuff, etc., still existing: (still pretty raw).
12/15/2005 (8:05 am)
All,I've progressed along in fits and starts and have the following to report.
I experimented in wheeledVehicle with code in onNewDataBlock like:
if (mDataBlock->leanbackSequence03 != -1) {
mSequence03Thread = mShapeInstance->addThread();
mShapeInstance->setSequence(mSequence03Thread,mDataBlock->leanbackSequence03,0);
}
else
mSequence03Thread = 0;where the leanbackSequence03, for example, has the corrected reference to the motion needed for moving the bot into the "leanback' position. And added all/(?) the initialization and the bits of code that it seemed to need to initiate the sequence etc. But was never able to get the sequence to appear.
Anyway, in the process I returned to my original idea of extracting/merging the animationfunctionality of the player class, as that seems to be the most complete and generalized approach available.
So I wound up with an "AnimatedVehicle" class that has "Vehicle" class as its base class and has all of the missing animation routines from the "Player" class. My WheeledVehicle class is now derived from AnimatedVehicle.
So now, for example, my WheeledVehicle has available to it a routine, just like in the PLayer class,
ConsoleMethod( AnimatedVehicle, setActionThread, bool, 3, 5, "(string sequenceName, bool hold, bool fsp)")
{
Con::printf("Console - AnimatedVehicle::setActionThread");
bool hold = (argc > 3)? dAtob(argv[3]): false;
bool fsp = (argc > 4)? dAtob(argv[4]): true;
return object->setActionThread(argv[2],hold,true,fsp);
}and so on. The goal of all this is to be able to generalized behaviors simlar to the ORK's wave and salute animations. Any comments on this approach would be appreciated. I can post the AnimatedVehicle.cc class code if anyone is interested in having that.
Here is (next post) the AnimatedVehicle.h class description, with a few unrelated footpuffs stuff, etc., still existing: (still pretty raw).
#8
more...
12/15/2005 (8:09 am)
#ifndef _ANIMATED_VEHICLE_H_
#define _ANIMATED_VEHICLE_H_
#include "game/vehicles/vehicle.h"
class ParticleEmitter;
class ParticleEmitterData;
class ClippedPolyList;
class DecalData;
class SplashData;
struct AnimatedVehicleData: public VehicleData
{
typedef VehicleData Parent;
enum AnimatedVehicleConsts
{
NumSpineNodes = 6,
ImpactBits = 3,
};
bool renderFirstPerson;
F32 maxTimeScale;
F32 decalOffset;
struct ActionAnimationDef {
const char* name;
struct Vector {
F32 x,y,z;
} dir;
};
struct ActionAnimation {
const char* name;
S32 sequence;
VectorF dir;
F32 speed;
bool velocityScale;
bool death;
};
enum {
RootAnim,
RunForwardAnim,
BackBackwardAnim,
SideLeftAnim,
KipupAnim,
LeanbackAnim,
LeanforwardAnim,
KipdownAnim,
NumMoveActionAnims = SideLeftAnim + 1,
NumTableActionAnims = KipdownAnim + 1,
NumExtraActionAnims = 60,
NumActionAnims = NumTableActionAnims + NumExtraActionAnims,
ActionAnimBits = 8,
NullAnimation = (1 << ActionAnimBits) - 1
};
static ActionAnimationDef ActionAnimationList[NumTableActionAnims];
ActionAnimation actionList[NumActionAnims];
U32 actionCount;
U32 lookAction;
S32 spineNode[NumSpineNodes];
ParticleEmitterData * footPuffEmitter;
S32 footPuffID;
S32 footPuffNumParts;
F32 footPuffRadius;
DecalData* decalData;
S32 decalID;
AnimatedVehicleData();
bool preload(bool server, char errorBuffer[256]);
void getGroundInfo(TSShapeInstance* si, TSThread* thread,ActionAnimation *dp);
bool isTableSequence(S32 seq);
bool isJumpAction(U32 action);
DECLARE_CONOBJECT(AnimatedVehicleData);
};
class AnimatedVehicle: public Vehicle
{
typedef Vehicle Parent;
protected:
AnimatedVehicleData* mDataBlock;
enum MaskBits {
ActionMask = Parent::NextFreeMask << 0,
MoveMask = Parent::NextFreeMask << 1,
ImpactMask = Parent::NextFreeMask << 2,
PositionMask = Parent::NextFreeMask << 3,
EnergyMask = Parent::NextFreeMask << 4,
NextFreeMask = Parent::NextFreeMask << 5
};
struct Range {
Range(F32 _min,F32 _max) {
min = _min;
max = _max;
delta = _max - _min;
};
F32 min,max;
F32 delta;
};more...
#9
12/15/2005 (8:09 am)
/// Main player state
enum ActionState {
NullState,
MoveState,
RecoverState,
KipupState,
LeanbackState,
LeanforwardState,
KipdownState,
NumStateBits = 3
};
ActionState mState;
bool mFalling;
S32 mJumpDelay;
S32 mContactTimer;
struct Death {
F32 lastPos;
Point3F posAdd;
VectorF rotate;
VectorF curNormal;
F32 curSink;
void clear() {dMemset(this, 0, sizeof(*this)); initFall();}
VectorF getPosAdd() {VectorF ret(posAdd); posAdd.set(0,0,0); return ret;}
bool haveVelocity() {return posAdd.x != 0 || posAdd.y != 0;}
void initFall() {curNormal.set(0,0,1); curSink = 0;}
Death() {clear();}
MatrixF* fallToGround(F32 adjust, const Point3F& pos, F32 zrot, F32 boxRad);
} mDeath;
struct ActionAnimation {
U32 action;
TSThread* thread;
S32 delayTicks; // before picking another.
bool forward;
bool firstPerson;
bool waitForEnd;
bool holdAtEnd;
bool animateOnServer;
bool atEnd;
} mActionAnimation;
struct ArmAnimation {
U32 action;
TSThread* thread;
} mArmAnimation;
TSThread* mArmThread;
TSThread* mHeadVThread;
TSThread* mHeadHThread;
TSThread* mRecoilThread;
static Range mArmRange;
static Range mHeadVRange;
static Range mHeadHRange;
/// @}
U32 mRecoverTicks;
U32 mReversePending;
S32 mImpactSound;
VectorF mVelocity;
S32 mMountPending;
Box3F mWorkingQueryBox;
bool onAdd();
void onRemove();
void processTick(const Move *move);
void interpolateTick(F32 delta);
void advanceTime(F32 dt);
bool onNewDataBlock(GameBaseData* dptr);
U32 packUpdate (NetConnection *conn, U32 mask, BitStream *stream);
void unpackUpdate(NetConnection *conn, BitStream *stream);
void setState(ActionState state, U32 ticks=0);
void updateState();
const char* getStateName();
bool inDeathAnim();
void updateAnimation(F32 dt);
void updateAnimationTree(bool firstPerson);
bool inSittingAnim();
bool setArmThread(const char* sequence);
bool setArmThread(U32 action);
virtual void setActionThread(U32 action,bool forward,bool hold = false,bool wait = false,bool fsp = false, bool forceSet = false);
virtual void updateActionThread();
virtual void pickActionAnimation();
void renderImage(SceneState *state, SceneRenderImage *image);
public:
AnimatedVehicle();
bool setActionThread(const char* sequence,bool hold,bool wait,bool fsp = false);
DECLARE_CONOBJECT(AnimatedVehicle);
};
#endif
#10
So my question is, is this a valuable way to go with this? If not, rhetorically, then why did the Player class go this route?
Thanks, any thoughts appreciated. BTW, the darn thing doesn't work yet. :=(
12/15/2005 (8:12 am)
All,So my question is, is this a valuable way to go with this? If not, rhetorically, then why did the Player class go this route?
Thanks, any thoughts appreciated. BTW, the darn thing doesn't work yet. :=(
#11
BTW, in addtion to what Oziman said, continuous looping animations can be triggered in the 'onAdd' function at the end of the vehicle script... if that helps at all.
12/15/2005 (9:24 am)
I don't completely understand what you're attempting. You've said you got animations working in your model and confirmed them in Show Tool. But with your code are you trying to implement a whole other way of executing animations? BTW, in addtion to what Oziman said, continuous looping animations can be triggered in the 'onAdd' function at the end of the vehicle script... if that helps at all.
#12
If Player class was based on something like an AnimatedShapeBase class, which contained all that functionality, then Vehicle class could have been derived from AnimatedShapeBase and have all the goodies except for what needs to be overridden.
Anyway, I'm trying to get to a "Transformer-like' set of wheeled robots, that operate in their world much like the Player class. In that sense their more like players than vehicles.
12/15/2005 (9:53 am)
I'm trying to implement the exact animation functionality for a vehicle that is in the player class. So the result should be, in the extreme, that if I have heeled vehicle that has a spine, arms etc., it can behave just like the ORK. Now granted I might be able to do much of that with additions here and there to the wheeled vehicle class, but it just seemed interesting and more general to go this way. Played with the other approach a bit but, being a newbie, thought I might use the player class, which I know works, as a model.If Player class was based on something like an AnimatedShapeBase class, which contained all that functionality, then Vehicle class could have been derived from AnimatedShapeBase and have all the goodies except for what needs to be overridden.
Anyway, I'm trying to get to a "Transformer-like' set of wheeled robots, that operate in their world much like the Player class. In that sense their more like players than vehicles.
#13
That is true and would make a good resource when you have it working. For me, if I need a script fired animation, I would just add the console-method because its quick and easy. However, your needs are different and may justify the time you are spending.
12/15/2005 (11:35 am)
Quote:
If Player class was based on something like an AnimatedShapeBase class, which contained all that functionality, then Vehicle class could have been derived from AnimatedShapeBase and have all the goodies except for what needs to be overridden.
That is true and would make a good resource when you have it working. For me, if I need a script fired animation, I would just add the console-method because its quick and easy. However, your needs are different and may justify the time you are spending.
#14
This leaves the front wheel shapes on the ground, however. :o(
I have the gyro code working so I can balance this bot and drive him around and follow paths, etc., but his front wheels are going to trundle along on the ground unless I can figure out how to get 'em back up on the hubs! Unfortunately, near the ground is exactly where the engine thinks the hubs are.
Does anyone know how to extract the hub position information from a buggy dts animation on the fly?
12/20/2005 (2:49 pm)
Ok, I have my new class, AnimatedVehicles working now so I have "Player-like" animations. But this raises a new question. I have a 4-wheel robot that bends in the middle (like the letter A) and kips up onto its rear wheels, presenting its front wheels as though the are now on arms.This leaves the front wheel shapes on the ground, however. :o(
I have the gyro code working so I can balance this bot and drive him around and follow paths, etc., but his front wheels are going to trundle along on the ground unless I can figure out how to get 'em back up on the hubs! Unfortunately, near the ground is exactly where the engine thinks the hubs are.
Does anyone know how to extract the hub position information from a buggy dts animation on the fly?
#15
02/24/2006 (7:43 am)
Juan, I'll email it to you today. It works but is not of the quality yet of a resource that I would publish. We'll work out whatever issues you encounter and maybe, from that, I'll publish it.
#17
I think I could use something like this in my vehicle hitbox system I have been working at and I think it would look a lot better if I just assigned a very short sequence to show damage in an area of the vehicle. Kind of like a deformation system that is based on animation sequences.
09/26/2006 (10:47 pm)
Hi Tim are you interested in releasing this code as a resource yet?I think I could use something like this in my vehicle hitbox system I have been working at and I think it would look a lot better if I just assigned a very short sequence to show damage in an area of the vehicle. Kind of like a deformation system that is based on animation sequences.
Torque Owner N R Bharathae