Allow NIF rotation matrices that include scale values (Fixes #2052)

pull/350/head
scrawl 10 years ago
parent e48dc45ede
commit f57ddec6a2

@ -272,7 +272,7 @@ class NiSkinData : public Record
public: public:
struct BoneTrafo struct BoneTrafo
{ {
Ogre::Matrix3 rotation; // Rotation offset from bone? Ogre::Matrix3 rotationScale; // Rotation offset from bone, non-uniform scale
Ogre::Vector3 trans; // Translation Ogre::Vector3 trans; // Translation
float scale; // Probably scale (always 1) float scale; // Probably scale (always 1)
}; };
@ -295,7 +295,7 @@ public:
void read(NIFStream *nif) void read(NIFStream *nif)
{ {
trafo.rotation = nif->getMatrix3(); trafo.rotationScale = nif->getMatrix3();
trafo.trans = nif->getVector3(); trafo.trans = nif->getVector3();
trafo.scale = nif->getFloat(); trafo.scale = nif->getFloat();
@ -307,7 +307,7 @@ public:
{ {
BoneInfo &bi = bones[i]; BoneInfo &bi = bones[i];
bi.trafo.rotation = nif->getMatrix3(); bi.trafo.rotationScale = nif->getMatrix3();
bi.trafo.trans = nif->getVector3(); bi.trafo.trans = nif->getVector3();
bi.trafo.scale = nif->getFloat(); bi.trafo.scale = nif->getFloat();
bi.unknown = nif->getVector4(); bi.unknown = nif->getVector4();

@ -133,7 +133,7 @@ public:
{ {
Transformation t; Transformation t;
t.pos = getVector3(); t.pos = getVector3();
t.rotation = getMatrix3(); t.rotationScale = getMatrix3();
t.scale = getFloat(); t.scale = getFloat();
return t; return t;
} }

@ -35,7 +35,7 @@ namespace Nif
struct Transformation struct Transformation
{ {
Ogre::Vector3 pos; Ogre::Vector3 pos;
Ogre::Matrix3 rotation; Ogre::Matrix3 rotationScale;
float scale; float scale;
static const Transformation& getIdentity() static const Transformation& getIdentity()

@ -42,8 +42,9 @@ void Node::getProperties(const Nif::NiTexturingProperty *&texprop,
Ogre::Matrix4 Node::getLocalTransform() const Ogre::Matrix4 Node::getLocalTransform() const
{ {
Ogre::Matrix4 mat4 = Ogre::Matrix4(Ogre::Matrix4::IDENTITY); Ogre::Matrix4 mat4 = Ogre::Matrix4(trafo.rotationScale);
mat4.makeTransform(trafo.pos, Ogre::Vector3(trafo.scale), Ogre::Quaternion(trafo.rotation)); mat4.setTrans(trafo.pos);
mat4.setScale(Ogre::Vector3(trafo.rotationScale[0][0], trafo.rotationScale[1][1], trafo.rotationScale[2][2]) * trafo.scale);
return mat4; return mat4;
} }

@ -138,9 +138,10 @@ void NIFMeshLoader::createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape
const Nif::NodeList &bones = skin->bones; const Nif::NodeList &bones = skin->bones;
for(size_t b = 0;b < bones.length();b++) for(size_t b = 0;b < bones.length();b++)
{ {
Ogre::Matrix4 mat; const Ogre::Matrix3& rotationScale = data->bones[b].trafo.rotationScale;
mat.makeTransform(data->bones[b].trafo.trans, Ogre::Vector3(data->bones[b].trafo.scale), Ogre::Matrix4 mat (rotationScale);
Ogre::Quaternion(data->bones[b].trafo.rotation)); mat.setTrans(data->bones[b].trafo.trans);
mat.setScale(Ogre::Vector3(rotationScale[0][0], rotationScale[1][1], rotationScale[2][2]) * data->bones[b].trafo.scale);
mat = bones[b]->getWorldTransform() * mat; mat = bones[b]->getWorldTransform() * mat;
const std::vector<Nif::NiSkinData::VertWeight> &weights = data->bones[b].weights; const std::vector<Nif::NiSkinData::VertWeight> &weights = data->bones[b].weights;

@ -36,9 +36,17 @@ void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node,
if(parent) parent->addChild(bone); if(parent) parent->addChild(bone);
mNifToOgreHandleMap[node->recIndex] = bone->getHandle(); mNifToOgreHandleMap[node->recIndex] = bone->getHandle();
bone->setOrientation(node->trafo.rotation); // decompose the local transform into position, scale and orientation.
bone->setPosition(node->trafo.pos); // this is required for cases where the rotationScale matrix includes scaling, which the NIF format allows :(
bone->setScale(Ogre::Vector3(node->trafo.scale)); // the code would look a bit nicer if Ogre allowed setting the transform matrix of a Bone directly, but we can't do that.
Ogre::Matrix4 mat(node->getLocalTransform());
Ogre::Vector3 position, scale;
Ogre::Quaternion orientation;
mat.decomposition(position, scale, orientation);
bone->setOrientation(orientation);
bone->setPosition(position);
bone->setScale(scale);
bone->setBindingPose(); bone->setBindingPose();
if(!(node->recType == Nif::RC_NiNode || /* Nothing special; children traversed below */ if(!(node->recType == Nif::RC_NiNode || /* Nothing special; children traversed below */

Loading…
Cancel
Save