#include #include #include class btCompoundShape; class btPairCachingGhostObject; class Character : public Ogre::FrameListener { enum AnimID { ANIM_IDLE = 0, ANIM_WALK, ANIM_RUN, NUM_ANIMS, ANIM_NONE = NUM_ANIMS }; Ogre::String mModelName; Ogre::Node *mRootBone; Ogre::SceneManager *mScnMgr; Ogre::SceneNode *mCameraPivot; Ogre::SceneNode *mCameraGoal, *mBodyNode; Ogre::Entity *mBodyEnt; Ogre::Real mPivotPitch; Ogre::Real mVerticalVelocity; Ogre::Vector3 mGoalDirection; // actual intended direction in world-space Ogre::AnimationState *mAnims[NUM_ANIMS]; // master animation list Ogre::Animation *mSkelAnimations[NUM_ANIMS]; Ogre::NodeAnimationTrack *mHipsTracks[NUM_ANIMS]; Ogre::NodeAnimationTrack *mRootTracks[NUM_ANIMS]; AnimID mAnimID; bool mFadingIn[NUM_ANIMS]; // which animations are fading in bool mFadingOut[NUM_ANIMS]; // which animations are fading out Ogre::Real mTimer; // general timer to see how long animations have been playing Ogre::Skeleton *mSkeleton; bool mRunning; Ogre::Vector3 rootMotion; Ogre::Quaternion rootRotation; // btRigidBody *mRigidBody; btCompoundShape *mCollisionShape; btPairCachingGhostObject *mGhostObject; Ogre::Bullet::DynamicsWorld *mWorld; bool mUpdate; public: Character(Ogre::SceneManager *scnMgr, const Ogre::String &modelName, Ogre::Bullet::DynamicsWorld *world); ~Character(); private: void setupBody(); void setupAnimations(); public: bool frameStarted(const Ogre::FrameEvent &evt) override; bool frameEnded(const Ogre::FrameEvent &evt) override; bool frameRenderingQueued(const Ogre::FrameEvent &evt) override; private: void updateBody(Ogre::Real deltaTime); void updateAnimations(Ogre::Real deltaTime); void updateRootMotion(Ogre::Real deltaTime); void fadeAnimations(Ogre::Real deltaTime); void setAnimation(AnimID id, bool reset = false); inline btQuaternion convert(const Ogre::Quaternion &q) { return btQuaternion(q.x, q.y, q.z, q.w); } inline btVector3 convert(const Ogre::Vector3 &v) { return btVector3(v.x, v.y, v.z); } inline btTransform convert(const Ogre::Quaternion &q, const Ogre::Vector3 &v) { btQuaternion mq = convert(q); btVector3 mv = convert(v); return btTransform(mq, mv); } inline Ogre::Quaternion convert(const btQuaternion &q) { return Ogre::Quaternion(q.w(), q.x(), q.y(), q.z()); } inline Ogre::Vector3 convert(const btVector3 &v) { return Ogre::Vector3(v.x(), v.y(), v.z()); } inline void convert(const btTransform &from, Ogre::Quaternion &q, Ogre::Vector3 &v) { q = convert(from.getRotation()); v = convert(from.getOrigin()); } public: bool isIdle() { return mAnimID == ANIM_IDLE; } bool act_run(); bool act_walk(); bool act_idle(); bool isRunning(); bool isWalking(); bool isMoving() { return isRunning() || isWalking(); } void setGoalDirection(const Ogre::Vector3 &goalDirection) { mGoalDirection = goalDirection; } Ogre::Vector3 getGoalDirection() { return mGoalDirection; } Ogre::Vector3 getPosition(); void enableUpdates() { mUpdate = true; } void disableUpdates() { mUpdate = false; } bool getUpdates() { return mUpdate; } };