csontváz animáció third person camera physx character controller
TRANSCRIPT
Csontváz animációThird person camera
PhysX character controller
Kezdeti teendők
OgreCharacterBase.zip letöltéseKicsomagolásInclude és library könyvtárak módosításaWorking directory : $(SolutionDir)/binFordításFuttatás
Futtatás
Ogre skeleton fileNézzük meg a media/soldier.skeleton.xml fájlt, ami
a media/soldier.skeleton szöveges (xml) változata.Mit tartalmaz:
Izület (bone) nevek és a hozzájuk tartozó transzformáció (eltolás és kvaternió)
Izület hierarchia (kinek ki a szülő izülete)Animációs adatok:
Minden animációra (névvel ellátottak): Minden animációban résztvevő csontra (név szerint):
Kulcskeret adatok: időpillanat, aktuális transzformáció Fontos, hogy nem minden csont adatait, és nem minden
frame-ben tárolunk, hanem csak akkor, ha változnak!
Új osztály: PlayerCharacter#include "playerCharacter.h "…PhysicsHandler* physxHandler;PlayerCharacter* playerCharacter;…class mainFrameListener{
…bool frameStarted(const FrameEvent& evt){
…if(!physxHandler->update(t, dt))
return false;playerCharacter->update(t, dt);
return true;}
};void init(){
…new Level(sceneManager, physxHandler->getScene());playerCharacter = new PlayerCharacter(sceneManager, physxHandler->getScene());
…}
OgreCharacter.cpp:
PlayerCharacter.h#pragma once#include "Ogre.h"#include "NxPhysics.h"
class PlayerCharacter{public:
PlayerCharacter(Ogre::SceneManager* sm, NxScene* nxs);~PlayerCharacter(void);void update(float t, float dt);Ogre::Vector3 getDirection(){return node->getOrientation() * Ogre::Vector3::UNIT_Z;}Ogre::Vector3 getPosition(){return node->getPosition();}
protected:
Ogre::Entity* entity;Ogre::SceneNode* node;Ogre::AnimationState* animations[2];
};
PlayerCharacter.cpp#include "stdafx.h"#include "PlayerCharacter.h„
PlayerCharacter::PlayerCharacter(Ogre::SceneManager* sm, NxScene* nxs)
{}
PlayerCharacter::~PlayerCharacter(void){}
void PlayerCharacter::update(float t, float dt){
}
KonstruktorPlayerCharacter::PlayerCharacter(Ogre::SceneManager* sm, NxScene* nxs){
entity = sm->createEntity("player", "soldier.mesh");node = sm->getRootSceneNode()->createChildSceneNode();node->attachObject(entity);
entity->getSkeleton()->
setBlendMode(Ogre::SkeletonAnimationBlendMode::ANIMBLEND_CUMULATIVE);animations[0] = entity->getAnimationState("leg_stand");animations[1] = entity->getAnimationState("up_stand");animations[0]->setEnabled(true);animations[1]->setEnabled(true);animations[0]->setWeight(1);animations[1]->setWeight(1);animations[0]->setLoop(true);animations[1]->setLoop(true);
}
leg_standup_standleg_runup_run
update
void PlayerCharacter::update(float t, float dt){
animations[0]->addTime(dt);animations[1]->addTime(dt);
}
Próba
Új osztály: ThirdPersonCamera#include " ThirdPersonCamera.h "…ThirdPersonCamera* TPCamera; …class mainFrameListener{
…bool frameStarted(const FrameEvent& evt){
…playerCharacter->update(t, dt);TPCamera->update(t, dt);
return true;}
};void init(){
…playerCharacter = new PlayerCharacter(sceneManager, physxHandler->getScene());TPCamera = new ThirdPersonCamera();TPCamera->setCamera(camera);TPCamera->setCharacter(playerCharacter);
…}
OgreCharacter.cpp:
ThirdPersonCamera.h#pragma once#include "Ogre.h"#include "PlayerCharacter.h"
class ThirdPersonCamera{public:
ThirdPersonCamera();~ThirdPersonCamera(void);void setCharacter(PlayerCharacter* c){ character = c; reset();}void setCamera(Ogre::Camera* camera){ this->camera = camera; reset();}void update(float t, float dt);
protected:Ogre::Camera* camera;PlayerCharacter* character;void reset();Ogre::Radian angle1;Ogre::Radian angle2;Ogre::Quaternion rot;float camHeight;float camDist;float targetHeight;float motionBlend;
};
ThirdPersonCamera.cpp#include "StdAfx.h"#include "ThirdPersonCamera.h"
using namespace Ogre;
ThirdPersonCamera::ThirdPersonCamera(void){
camera = 0;character = 0;angle1 = 0;angle2 = 0;rot = Quaternion::IDENTITY;camHeight = 1.0f;camDist = 25;targetHeight = 10;motionBlend = 2.0f;
}
ThirdPersonCamera::~ThirdPersonCamera(void){
}
ThirdPersonCamera.cppvoid ThirdPersonCamera::reset(){
if(camera == 0 || character == 0)return;
Vector3 dir = character->getDirection();dir.y = 0;dir.normalise();dir.y = -camHeight;
camera->setPosition(character->getPosition() - dir * camDist);camera->lookAt(character->getPosition() + Vector3(0,targetHeight,0));
}
void ThirdPersonCamera::update(float t, float dt){
reset();}
Próba
PlayerCharacter osztálybakét új publikus függvény:
void PlayerCharacter::move(float amount){
node->translate(amount * Ogre::Vector3::UNIT_Z, Ogre::Node::TS_LOCAL);
}
void PlayerCharacter::turn(float amount){
node->rotate(Ogre::Vector3::UNIT_Y, Ogre::Radian(amount));}
Új osztály: PlayerController#pragma once#include "PlayerCharacter.h"#define OIS_DYNAMIC_LIB#include <OIS/OIS.h>
class PlayerController{public:
PlayerController(PlayerCharacter* c);~PlayerController(void);
void update(float t, float dt, OIS::Keyboard* keyboard, OIS::Mouse* mouse);float mTimeUntilNextToggle;
protected:PlayerCharacter* character;
};
#include "StdAfx.h"#include "PlayerController.h"
PlayerController::PlayerController(PlayerCharacter* c){
character = c;}
PlayerController::~PlayerController(void){}
void PlayerController::update(float t, float dt, OIS::Keyboard* keyboard, OIS::Mouse* mouse)
{if (mTimeUntilNextToggle >= 0)
mTimeUntilNextToggle -= dt;
const OIS::MouseState &ms = mouse->getMouseState();
if( keyboard->isKeyDown(OIS::KC_UP))character->move(20 * dt);
if( keyboard->isKeyDown(OIS::KC_DOWN))character->move(20 * -dt);
if( keyboard->isKeyDown(OIS::KC_RIGHT))character->turn(-dt);
if( keyboard->isKeyDown(OIS::KC_LEFT))character->turn(dt);
}
InputHandler.h…#include "PlayerController.h„…class InputHandler : public Ogre::FrameListener{…
float mTimeUntilNextToggle;std::list<PlayerController*> controllers;…bool update(float t, float dt){…
std::list<PlayerController*>::iterator it = controllers.begin();std::list<PlayerController*>::iterator itend = controllers.end();while(it != itend){
(*it)->update(t, dt, mKeyboard, mMouse);it++;
}return true;
}
void addPlayerController(PlayerController* c){
controllers.push_back(c);}
}
OgreCharacter.cpp#include "PlayerController.h"…ThirdPersonCamera* TPCamera;PlayerController* playerController;…void init(){
…playerController = new PlayerController(playerCharacter);inputHandler->addPlayerController(playerController);
ogreRoot->addFrameListener(new mainFrameListener());}
Próba
PlayerCharacter.hprotected:
enum PlayerAction{
PA_BASE,PA_NONE,PA_WEAPON_HOLD,PA_SHOOT
};enum PlayerPose{
PP_BASE,PP_STAND,PP_RUN
};PlayerAction action;PlayerAction lastAction;PlayerPose pose;PlayerPose lastPose;
bool inAction();
PlayerCharacter.cppPlayerCharacter:: PlayerCharacter(…){
… lastAction = action = PA_NONE;
lastPose = pose = PP_STAND;}
bool PlayerCharacter::inAction(){
return !animations[1]->getLoop() && !animations[1]->hasEnded();
}
void PlayerCharacter::move(float amount){
if(inAction())return;
node->translate(amount * Vector3::UNIT_Z, Node::TS_LOCAL);action = PA_NONE;pose = PP_RUN;
}
void PlayerCharacter::turn(float amount){
if(inAction())return;
node->rotate(Vector3::UNIT_Y, Radian(amount));}
void PlayerCharacter::update(float t, float dt){
if(action != lastAction || pose != lastPose){
if(!animations[0]->getLoop() && animations[0]->hasEnded())pose =PP_STAND;
if(!animations[1]->getLoop() && animations[1]->hasEnded())action = PA_NONE;
animations[0]->setEnabled(false);animations[1]->setEnabled(false);animations[0] = 0;animations[1] = 0;
if(action == PA_NONE){
if(pose == PP_STAND)animations[1] = entity->getAnimationState("up_stand");
if(pose == PP_RUN)animations[1] = entity->getAnimationState("up_run");
animations[1]->setLoop(true);}else if(action == PA_WEAPON_HOLD){
animations[1] = entity->getAnimationState("up_weapon_hold");animations[1]->setLoop(true);
}
…//következő dia
else if(action == PA_SHOOT){
animations[1] = entity->getAnimationState("up_shoot");animations[1]->setLoop(false);animations[1]->setTimePosition(0);
}
if(pose == PP_STAND){
animations[0] = entity->getAnimationState("leg_stand");animations[0]->setLoop(true);
}else if(pose == PP_RUN){
animations[0] = entity->getAnimationState("leg_run");animations[0]->setLoop(true);
}
if(animations[0])animations[0]->setEnabled(true);
if(animations[1])animations[1]->setEnabled(true);
lastAction = action;lastPose = pose;
}
Update vége
animations[0]->addTime(dt);animations[1]->addTime(dt);
if(!inAction())action = PA_NONE;
pose = PP_STAND;}
Próba
Lövésúj publikus függvényvoid PlayerCharacter::shoot(){
if(inAction())return;
action = PA_SHOOT;}
void PlayerController::update(float t, float dt, OIS::Keyboard* keyboard, OIS::Mouse* mouse)
{…
if( ms.buttonDown(OIS::MB_Left))character->shoot();
}
Próba
Fegyvert a kézbe!!class PlayerCharacter
{
…
protected:
bool hasWeapon;
};
PlayerCharacter::PlayerCharacter(Ogre::SceneManager* sm, NxScene* nxs)
{
…
hasWeapon = true;
}
void PlayerCharacter::update(float t, float dt)
{
…
if(!inAction())
{
if(hasWeapon)
action = PA_WEAPON_HOLD;
else
action = PA_NONE;
}
pose = PP_STAND;
}
void PlayerCharacter::move(float amount)
{
if(inAction())
return;
node->translate(amount * Vector3::UNIT_Z, Node::TS_LOCAL);
if(hasWeapon)
action = PA_WEAPON_HOLD;
else
action = PA_NONE;
pose = PP_RUN;
}
Próba
De hol a fegyver?class PlayerCharacter
{
…
protected:
Ogre::SceneNode* weaponNode;
};
PlayerCharacter::PlayerCharacter(Ogre::SceneManager* sm, NxScene* nxs){
…
hasWeapon = true;
Ogre::Entity* weapon = sm->createEntity("weapon", "rifle.mesh");
weaponNode = node->createChildSceneNode();
Ogre::SceneNode* tempNode = weaponNode->createChildSceneNode();
tempNode->rotate(Ogre::Vector3::UNIT_X, Ogre::Radian(Ogre::Degree(90)));tempNode->attachObject(weapon);
}
void PlayerCharacter::update(float t, float dt){…
if(hasWeapon){weaponNode->setVisible(true);Ogre::Bone* rightHand = entity->getSkeleton()->getBone("hand_r");weaponNode->setPosition(rightHand->_getDerivedPosition());weaponNode->setOrientation(rightHand->_getDerivedOrientation());}elseweaponNode->setVisible(false);
}
Próba
Finomabb kamera mozgásvoid ThirdPersonCamera::update(float t, float dt){
Vector3 currentPos = camera->getPosition();
Vector3 dir = character->getDirection();dir.y = 0;dir.normalise();dir.y = -camHeight;
Vector3 newPos = character->getPosition() - dir * camDist;camera->setPosition(motionBlend * dt * newPos + (1.0f - motionBlend * dt) * currentPos);camera->lookAt(character->getPosition() + Vector3(0,targetHeight,0));
}
Próba
FizikaÚj include könyvtár:
…\PhysX\SDKs\NxCharacter\includeÚj link library
NxCharacter.libMásoljuk:
…\PhysX\Bin\win32\NxCharacter.dll –t bin-be
PlayerCharacter.h…#include "NxCapsuleController.h"
class PlayerCharacter{…public:…
static void updateAllCharacters();…protected.:…
NxCapsuleController* mController;};
PlayerCharacter.cpp#include "ControllerManager.h"static ControllerManager gCM;
void PlayerCharacter::updateAllCharacters(){
gCM.updateControllers();}
PlayerCharacter::PlayerCharacter()NxCapsuleControllerDesc desc;desc.setToDefault();desc.radius = 2.0f;desc.height = 5.0f;desc.upDirection = NX_Y;desc.slopeLimit = 0.707;desc.stepOffset = 0.5;desc.skinWidth = 0.1;desc.callback = NULL;desc.position.set(0,5,0);
mController = (NxCapsuleController*)gCM.createController(nxs, desc);mController->setCollision(true);
PlayerCharacter::move(){
//node->translate(amount * Vector3::UNIT_Z, Node::TS_LOCAL);
NxU32 collisionFlags;Ogre::Vector3 m = amount * getDirection();mController->move(NxVec3(m.x,m.y,m.z), 1, 0.001, collisionFlags);node->setPosition(mController->getPosition().x,
mController->getPosition().y - 5,mController->getPosition().z);
…}
OgreCharacter.cppclass mainFrameListener{
…bool frameStarted(const FrameEvent& evt){
…if(!physxHandler->update(t, dt))
return false;playerCharacter->update(t, dt);TPCamera->update(t, dt);PlayerCharacter::updateAllCharacters();
return true;}
};
Próba
Vége