Skip to content

Commit

Permalink
GRAPHICS: Add support for animations in NWN models
Browse files Browse the repository at this point in the history
  • Loading branch information
DrMcCoy committed Mar 20, 2014
1 parent 71cbc5d commit 6707d14
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 10 deletions.
5 changes: 1 addition & 4 deletions src/graphics/aurora/cube.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,7 @@ Cube::~Cube() {

Ogre::SceneManager &scene = getOgreSceneManager();

if (scene.hasAnimationState(_rootNode->getName()))
scene.destroyAnimationState(_rootNode->getName());
if (scene.hasAnimation(_rootNode->getName()))
scene.destroyAnimation(_rootNode->getName());
destroyAnimation(_rootNode->getName().c_str());

while (_rootNode->numAttachedObjects() > 0) {
Ogre::MovableObject *object = _rootNode->detachObject((unsigned short) 0);
Expand Down
44 changes: 38 additions & 6 deletions src/graphics/aurora/model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include <OgreSceneNode.h>
#include <OgreSceneManager.h>
#include <OgreEntity.h>
#include <OgreAnimation.h>
#include <OgreAnimationState.h>

#include "common/stream.h"

Expand All @@ -41,7 +43,7 @@ namespace Graphics {

namespace Aurora {

Model::NodeEntity::NodeEntity() : node(0), entity(0), dontRender(false) {
Model::NodeEntity::NodeEntity() : node(0), entity(0), dontRender(false), inheritedPosition(false) {
position[0] = 0.0;
position[1] = 0.0;
position[2] = 0.0;
Expand All @@ -53,7 +55,7 @@ Model::NodeEntity::NodeEntity() : node(0), entity(0), dontRender(false) {
}


Model::State::State(const Common::UString &n) : name(n) {
Model::State::State(const Common::UString &n) : name(n), animation(0), animationState(0) {
}


Expand All @@ -69,10 +71,8 @@ Model::~Model() {

Ogre::SceneManager &scene = getOgreSceneManager();

if (scene.hasAnimationState(_rootNode->getName()))
scene.destroyAnimationState(_rootNode->getName());
if (scene.hasAnimation(_rootNode->getName()))
scene.destroyAnimation(_rootNode->getName());
for (StateMap::iterator s = _states.begin(); s != _states.end(); ++s)
destroyAnimation(s->second->animation);

for (EntityList::iterator e = _entities.begin(); e != _entities.end(); ++e)
scene.destroyMovableObject(*e);
Expand Down Expand Up @@ -111,6 +111,8 @@ void Model::setState(State *state) {
n->second.node->setPosition(n->second.position[0], n->second.position[1], n->second.position[2]);
n->second.node->setOrientation(n->second.orientation[0], n->second.orientation[1],
n->second.orientation[2], n->second.orientation[3]);
if (n->second.inheritedPosition)
n->second.node->setInitialState();

if (n->second.entity && !n->second.dontRender) {
n->second.entity->setVisible(_visible);
Expand All @@ -120,6 +122,36 @@ void Model::setState(State *state) {
}
}

bool Model::playAnimation(bool loop) {
if (!_currentState || !_currentState->animation || !_currentState->animationState)
return false;

LOCK_FRAME();

_currentState->animationState->setLoop(loop);
_currentState->animationState->setEnabled(true);
return true;
}

bool Model::playAnimation(const Common::UString &name, bool loop) {
LOCK_FRAME();

if (setState(name))
return false;

return playAnimation(loop);
}

bool Model::stopAnimation() {
if (!_currentState || !_currentState->animation || !_currentState->animationState)
return false;

LOCK_FRAME();

_currentState->animationState->setEnabled(false);
return true;
}

void Model::readValue(Common::SeekableReadStream &stream, uint32 &value) {
value = stream.readUint32LE();
}
Expand Down
15 changes: 15 additions & 0 deletions src/graphics/aurora/model.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
namespace Ogre {
class SceneNode;
class Entity;
class Animation;
class AnimationState;
}

namespace Common {
Expand All @@ -56,8 +58,16 @@ class Model : public Renderable {
Model();
~Model();

/** Set the model into a different state. */
bool setState(const Common::UString &name);

/** Play the animation associated with the current state. */
bool playAnimation(bool loop);
/** Set the model into a different state and play its animation. */
bool playAnimation(const Common::UString &name, bool loop);
/** Stop any currently playing animation. */
bool stopAnimation();

protected:
struct NodeEntity {
Ogre::SceneNode *node;
Expand All @@ -68,6 +78,8 @@ class Model : public Renderable {
float position[3];
float orientation[4];

bool inheritedPosition;

NodeEntity();
};

Expand All @@ -79,6 +91,9 @@ class Model : public Renderable {

NodeEntities nodeEntities;

Ogre::Animation *animation;
Ogre::AnimationState *animationState;

State(const Common::UString &n = "");
};

Expand Down
22 changes: 22 additions & 0 deletions src/graphics/aurora/model_nwn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,8 @@ void Model_NWN::nodeInherit(ParserContext &ctx, const Common::UString &name) {
memcpy(ctx.nodeEntity->position, rootNodeEntity->second.position, 3 * sizeof(float));
if (!ctx.hasOrientation)
memcpy(ctx.nodeEntity->orientation, rootNodeEntity->second.orientation, 4 * sizeof(float));

ctx.nodeEntity->inheritedPosition = !ctx.hasPosition;
}

void Model_NWN::readBinaryMesh(ParserContext &ctx) {
Expand Down Expand Up @@ -765,6 +767,8 @@ void Model_NWN::readBinaryNodeControllers(ParserContext &ctx, uint32 offset, uin
// TODO: readNodeControllers: Implement this properly :P

for (uint32 i = 0; i < count; i++) {
Ogre::NodeAnimationTrack *track = 0;

uint32 type = ctx.mdl->readUint32LE();
uint16 rowCount = ctx.mdl->readUint16LE();
uint16 timeIndex = ctx.mdl->readUint16LE();
Expand All @@ -779,12 +783,19 @@ void Model_NWN::readBinaryNodeControllers(ParserContext &ctx, uint32 offset, uin
if (type == kControllerTypePosition) {
if (columnCount != 3)
throw Common::Exception("Position controller with %d values", columnCount);

if (ctx.state->animation)
track = ctx.state->animation->createNodeTrack(ctx.state->animation->getNumNodeTracks(), ctx.nodeEntity->node);

for (int r = 0; r < rowCount; r++) {
float pT = data[timeIndex + r];
float pX = data[dataIndex + (r * columnCount) + 0];
float pY = data[dataIndex + (r * columnCount) + 1];
float pZ = data[dataIndex + (r * columnCount) + 2];

if (track)
track->createNodeKeyFrame(pT)->setTranslate(Ogre::Vector3(pX, pY, pZ));

// Starting position
if (pT == 0.0) {
ctx.hasPosition = true;
Expand All @@ -799,13 +810,19 @@ void Model_NWN::readBinaryNodeControllers(ParserContext &ctx, uint32 offset, uin
if (columnCount != 4)
throw Common::Exception("Orientation controller with %d values", columnCount);

if (ctx.state->animation)
track = ctx.state->animation->createNodeTrack(ctx.state->animation->getNumNodeTracks(), ctx.nodeEntity->node);

for (int r = 0; r < rowCount; r++) {
float qT = data[timeIndex + r];
float qX = data[dataIndex + (r * columnCount) + 0];
float qY = data[dataIndex + (r * columnCount) + 1];
float qZ = data[dataIndex + (r * columnCount) + 2];
float qQ = data[dataIndex + (r * columnCount) + 3];

if (track)
track->createNodeKeyFrame(qT)->setRotation(Ogre::Quaternion(qQ, qX, qY, qZ));

// Starting orientation
if (qT == 0.0) {
ctx.hasOrientation = true;
Expand Down Expand Up @@ -856,6 +873,8 @@ void Model_NWN::readBinaryAnim(ParserContext &ctx, uint32 offset) {
float animLength = ctx.mdl->readIEEEFloatLE();
float transTime = ctx.mdl->readIEEEFloatLE();

ctx.state->animation = getOgreSceneManager().createAnimation(Common::generateIDRandomString().c_str(), animLength);

Common::UString animRoot;
animRoot.readFixedASCII(*ctx.mdl, 64);

Expand All @@ -864,6 +883,9 @@ void Model_NWN::readBinaryAnim(ParserContext &ctx, uint32 offset) {

ctx.mdl->seek(ctx.offModelData + nodeHeadPointer);
loadBinaryNode(ctx, _rootNode);

ctx.state->animationState = getOgreSceneManager().createAnimationState(ctx.state->animation->getName());
ctx.state->animationState->setEnabled(false);
}

void Model_NWN::skipASCIIAnim(ParserContext &ctx) {
Expand Down
17 changes: 17 additions & 0 deletions src/graphics/aurora/renderable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@
*/

#include <OgreSceneNode.h>
#include <OgreAnimation.h>
#include <OgreSceneManager.h>

#include "graphics/aurora/renderable.h"
#include "graphics/aurora/sceneman.h"
#include "graphics/aurora/meshutil.h"

namespace Graphics {

Expand Down Expand Up @@ -171,6 +174,20 @@ void Renderable::scale(float x, float y, float z) {
_rootNode->scale(x, y, z);
}

void Renderable::destroyAnimation(const Common::UString &name) {
if (getOgreSceneManager().hasAnimationState(name.c_str()))
getOgreSceneManager().destroyAnimationState(name.c_str());
if (getOgreSceneManager().hasAnimation(name.c_str()))
getOgreSceneManager().destroyAnimation(name.c_str());
}

void Renderable::destroyAnimation(Ogre::Animation *anim) {
if (!anim)
return;

destroyAnimation(anim->getName().c_str());
}

} // End of namespace Aurora

} // End of namespace Graphics
9 changes: 9 additions & 0 deletions src/graphics/aurora/renderable.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@

namespace Ogre {
class SceneNode;
class Animation;
}

namespace Common {
class UString;
}

namespace Graphics {
Expand Down Expand Up @@ -85,6 +90,10 @@ class Renderable {
float _basePosition[3];
float _baseOrientation[4];
float _baseScale[3];


void destroyAnimation(const Common::UString &name);
void destroyAnimation(Ogre::Animation *anim);
};

} // End of namespace Aurora
Expand Down

0 comments on commit 6707d14

Please sign in to comment.