1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-13 12:40:04 +00:00

Bullet loader trafos changed to match NIFLoader

This commit is contained in:
Jason Hooks 2012-06-06 16:29:44 -04:00
parent d081f7ea83
commit 4ff36a9018
2 changed files with 82 additions and 23 deletions

View File

@ -1,4 +1,4 @@
/*
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com >
@ -51,19 +51,64 @@ using namespace Mangle::VFS;
using namespace NifBullet;
// Helper math functions. Reinventing linear algebra for the win!
// Computes B = AxB (matrix*matrix)
static void matrixMul(const Matrix &A, Matrix &B)
{
for (int i=0;i<3;i++)
{
float a = B.v[0].array[i];
float b = B.v[1].array[i];
float c = B.v[2].array[i];
B.v[0].array[i] = a*A.v[0].array[0] + b*A.v[0].array[1] + c*A.v[0].array[2];
B.v[1].array[i] = a*A.v[1].array[0] + b*A.v[1].array[1] + c*A.v[1].array[2];
B.v[2].array[i] = a*A.v[2].array[0] + b*A.v[2].array[1] + c*A.v[2].array[2];
}
}
// Computes C = B + AxC*scale
static void vectorMulAdd(const Matrix &A, const Vector &B, float *C, float scale)
{
// Keep the original values
float a = C[0];
float b = C[1];
float c = C[2];
// Perform matrix multiplication, scaling and addition
for (int i=0;i<3;i++)
C[i] = B.array[i] + (a*A.v[i].array[0] + b*A.v[i].array[1] + c*A.v[i].array[2])*scale;
}
// Computes B = AxB (matrix*vector)
static void vectorMul(const Matrix &A, float *C)
{
// Keep the original values
float a = C[0];
float b = C[1];
float c = C[2];
// Perform matrix multiplication, scaling and addition
for (int i=0;i<3;i++)
C[i] = a*A.v[i].array[0] + b*A.v[i].array[1] + c*A.v[i].array[2];
}
ManualBulletShapeLoader::~ManualBulletShapeLoader()
{
delete vfs;
}
Ogre::Matrix3 ManualBulletShapeLoader::getMatrix(Nif::Transformation* tr)
Ogre::Matrix3 ManualBulletShapeLoader::getMatrix(const Nif::Transformation* tr)
{
Ogre::Matrix3 rot(tr->rotation.v[0].array[0],tr->rotation.v[0].array[1],tr->rotation.v[0].array[2],
tr->rotation.v[1].array[0],tr->rotation.v[1].array[1],tr->rotation.v[1].array[2],
tr->rotation.v[2].array[0],tr->rotation.v[2].array[1],tr->rotation.v[2].array[2]);
return rot;
}
Ogre::Vector3 ManualBulletShapeLoader::getVector(Nif::Transformation* tr)
Ogre::Vector3 ManualBulletShapeLoader::getVector(const Nif::Transformation* tr)
{
Ogre::Vector3 vect3(tr->pos.array[0],tr->pos.array[1],tr->pos.array[2]);
return vect3;
@ -88,6 +133,7 @@ btVector3 ManualBulletShapeLoader::getbtVector(Nif::Vector v)
void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
{
std::cout << "Beginning physics\n";
cShape = static_cast<BulletShape *>(resource);
resourceName = cShape->getName();
cShape->collide = false;
@ -131,12 +177,12 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
bool hasCollisionNode = hasRootCollisionNode(node);
//do a first pass
handleNode(node,0,Ogre::Matrix3::IDENTITY,Ogre::Vector3::ZERO,1,hasCollisionNode,false,false);
handleNode(node,0,NULL,hasCollisionNode,false,false);
//if collide = false, then it does a second pass which create a shape for raycasting.
if(cShape->collide == false)
{
handleNode(node,0,Ogre::Matrix3::IDENTITY,Ogre::Vector3::ZERO,1,hasCollisionNode,false,true);
handleNode(node,0,NULL,hasCollisionNode,false,true);
}
cShape->collide = hasCollisionNode&&cShape->collide;
@ -157,6 +203,7 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource)
currentShape = new TriangleMeshShape(mTriMesh,true);
cShape->Shape = currentShape;
std::cout << "End bullet physics\n";
}
bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node* node)
@ -186,8 +233,9 @@ bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node* node)
}
void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
Ogre::Matrix3 parentRot,Ogre::Vector3 parentPos,float parentScale,bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly)
const Nif::Transformation *trafo,bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly)
{
std::cout << "Handle Node\n";
// Accumulate the flags from all the child nodes. This works for all
// the flags we currently use, at least.
flags |= node->flags;
@ -221,19 +269,30 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
}
}
//transfo of parents node + curent node
Ogre::Matrix3 finalRot;
Ogre::Vector3 finalPos;
float finalScale;
if (trafo)
{
std::cout << "Before trafo\n";
// Get a non-const reference to the node's data, since we're
// overwriting it. TODO: Is this necessary?
Transformation &final = *((Transformation*)node->trafo);
Nif::Transformation &final = *((Nif::Transformation*)node->trafo);
Ogre::Vector3 nodePos = getVector(&final);
Ogre::Matrix3 nodeRot = getMatrix(&final);
// For both position and rotation we have that:
// final_vector = old_vector + old_rotation*new_vector*old_scale
vectorMulAdd(trafo->rotation, trafo->pos, final.pos.array, trafo->scale);
vectorMulAdd(trafo->rotation, trafo->velocity, final.velocity.array, trafo->scale);
finalPos = nodePos + parentPos;
finalRot = parentRot*nodeRot;
finalScale = final.scale*parentScale;
// Merge the rotations together
matrixMul(trafo->rotation, final.rotation);
// Scalar values are so nice to deal with. Why can't everything
// just be scalar?
final.scale *= trafo->scale;
std::cout << "After Trafo\n";
}
std::cout << "After Trafo2\n";
// For NiNodes, loop through children
if (node->recType == Nif::RC_NiNode)
@ -244,14 +303,14 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
{
if (list.has(i))
{
handleNode(&list[i], flags,finalRot,finalPos,finalScale,hasCollisionNode,isCollisionNode,raycastingOnly);
handleNode(&list[i], flags,node->trafo,hasCollisionNode,isCollisionNode,raycastingOnly);
}
}
}
else if (node->recType == Nif::RC_NiTriShape && (isCollisionNode || !hasCollisionNode))
{
cShape->collide = true;
handleNiTriShape(dynamic_cast<Nif::NiTriShape*>(node), flags,finalRot,finalPos,parentScale,raycastingOnly);
handleNiTriShape(dynamic_cast<Nif::NiTriShape*>(node), flags,getMatrix(node->trafo),getVector(node->trafo),node->trafo->scale,raycastingOnly);
}
else if(node->recType == Nif::RC_RootCollisionNode)
{
@ -260,7 +319,7 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags,
for (int i=0; i<n; i++)
{
if (list.has(i))
handleNode(&list[i], flags,finalRot,finalPos,finalScale,hasCollisionNode,true,raycastingOnly);
handleNode(&list[i], flags,node->trafo, hasCollisionNode,true,raycastingOnly);
}
}
}

View File

@ -95,9 +95,9 @@ public:
void load(const std::string &name,const std::string &group);
private:
Ogre::Matrix3 getMatrix(Nif::Transformation* tr);
Ogre::Matrix3 getMatrix(const Nif::Transformation* tr);
Ogre::Vector3 getVector(Nif::Transformation* tr);
Ogre::Vector3 getVector(const Nif::Transformation* tr);
btQuaternion getbtQuat(Ogre::Matrix3 m);
@ -107,10 +107,10 @@ private:
*Parse a node.
*/
void handleNode(Nif::Node *node, int flags,
Ogre::Matrix3 parentRot,Ogre::Vector3 parentPos,float parentScale,bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly);
const Nif::Transformation *trafo, bool hasCollisionNode,bool isCollisionNode,bool raycastingOnly);
/**
*Helpler function
*Helper function
*/
bool hasRootCollisionNode(Nif::Node* node);