|
|
|
@ -8,7 +8,6 @@
|
|
|
|
|
#include <BulletCollision/CollisionShapes/btBoxShape.h>
|
|
|
|
|
#include <BulletCollision/CollisionShapes/btTriangleMesh.h>
|
|
|
|
|
#include <BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h>
|
|
|
|
|
#include <BulletCollision/CollisionShapes/btCompoundShape.h>
|
|
|
|
|
|
|
|
|
|
#include <components/debug/debuglog.hpp>
|
|
|
|
|
|
|
|
|
@ -42,27 +41,41 @@ bool pathFileNameStartsWithX(const std::string& path)
|
|
|
|
|
return letterPos < path.size() && (path[letterPos] == 'x' || path[letterPos] == 'X');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriShapeData& data, const osg::Matrixf &transform)
|
|
|
|
|
{
|
|
|
|
|
mesh.preallocateVertices(static_cast<int>(data.vertices.size()));
|
|
|
|
|
mesh.preallocateIndices(static_cast<int>(data.triangles.size()));
|
|
|
|
|
|
|
|
|
|
const std::vector<osg::Vec3f> &vertices = data.vertices;
|
|
|
|
|
const std::vector<unsigned short> &triangles = data.triangles;
|
|
|
|
|
|
|
|
|
|
for (std::size_t i = 0; i < triangles.size(); i += 3)
|
|
|
|
|
{
|
|
|
|
|
mesh.addTriangle(
|
|
|
|
|
getbtVector(vertices[triangles[i + 0]] * transform),
|
|
|
|
|
getbtVector(vertices[triangles[i + 1]] * transform),
|
|
|
|
|
getbtVector(vertices[triangles[i + 2]] * transform)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace NifBullet
|
|
|
|
|
void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiTriShapeData& data)
|
|
|
|
|
{
|
|
|
|
|
fillTriangleMeshWithTransform(mesh, data, osg::Matrixf());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BulletNifLoader::BulletNifLoader()
|
|
|
|
|
: mCompoundShape()
|
|
|
|
|
, mStaticMesh()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BulletNifLoader::~BulletNifLoader()
|
|
|
|
|
namespace NifBullet
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
|
|
|
|
|
{
|
|
|
|
|
mShape = new Resource::BulletShape;
|
|
|
|
|
|
|
|
|
|
mCompoundShape = nullptr;
|
|
|
|
|
mStaticMesh = nullptr;
|
|
|
|
|
mCompoundShape.reset();
|
|
|
|
|
mStaticMesh.reset();
|
|
|
|
|
mAvoidStaticMesh.reset();
|
|
|
|
|
|
|
|
|
|
if (nif.numRoots() < 1)
|
|
|
|
|
{
|
|
|
|
@ -125,6 +138,9 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
|
|
|
|
|
mStaticMesh.release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mAvoidStaticMesh)
|
|
|
|
|
mShape->mAvoidCollisionShape = new Resource::TriangleMeshShape(mAvoidStaticMesh.release(), false);
|
|
|
|
|
|
|
|
|
|
return mShape;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -189,7 +205,7 @@ const Nif::Node* BulletNifLoader::getCollisionNode(const Nif::Node* rootNode)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node *node, int flags,
|
|
|
|
|
bool isCollisionNode, bool isAnimated, bool autogenerated)
|
|
|
|
|
bool isCollisionNode, bool isAnimated, bool autogenerated, bool avoid)
|
|
|
|
|
{
|
|
|
|
|
// Accumulate the flags from all the child nodes. This works for all
|
|
|
|
|
// the flags we currently use, at least.
|
|
|
|
@ -205,8 +221,7 @@ void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node *n
|
|
|
|
|
Log(Debug::Info) << "Found RootCollisionNode attached to non-root node in " << fileName << ". Treat it as a common NiTriShape.";
|
|
|
|
|
|
|
|
|
|
// Don't collide with AvoidNode shapes
|
|
|
|
|
if(node->recType == Nif::RC_AvoidNode)
|
|
|
|
|
flags |= 0x800;
|
|
|
|
|
avoid = avoid || (node->recType == Nif::RC_AvoidNode);
|
|
|
|
|
|
|
|
|
|
// Check for extra data
|
|
|
|
|
Nif::Extra const *e = node;
|
|
|
|
@ -242,7 +257,7 @@ void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node *n
|
|
|
|
|
// (occurs in tr_ex_imp_wall_arch_04.nif)
|
|
|
|
|
if(!node->hasBounds && node->recType == Nif::RC_NiTriShape)
|
|
|
|
|
{
|
|
|
|
|
handleNiTriShape(static_cast<const Nif::NiTriShape*>(node), flags, getWorldTransform(node), isAnimated);
|
|
|
|
|
handleNiTriShape(static_cast<const Nif::NiTriShape*>(node), flags, getWorldTransform(node), isAnimated, avoid);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -254,12 +269,13 @@ void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node *n
|
|
|
|
|
for(size_t i = 0;i < list.length();i++)
|
|
|
|
|
{
|
|
|
|
|
if(!list[i].empty())
|
|
|
|
|
handleNode(fileName, list[i].getPtr(), flags, isCollisionNode, isAnimated, autogenerated);
|
|
|
|
|
handleNode(fileName, list[i].getPtr(), flags, isCollisionNode, isAnimated, autogenerated, avoid);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BulletNifLoader::handleNiTriShape(const Nif::NiTriShape *shape, int flags, const osg::Matrixf &transform, bool isAnimated)
|
|
|
|
|
void BulletNifLoader::handleNiTriShape(const Nif::NiTriShape *shape, int flags, const osg::Matrixf &transform,
|
|
|
|
|
bool isAnimated, bool avoid)
|
|
|
|
|
{
|
|
|
|
|
assert(shape != nullptr);
|
|
|
|
|
|
|
|
|
@ -285,21 +301,7 @@ void BulletNifLoader::handleNiTriShape(const Nif::NiTriShape *shape, int flags,
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<btTriangleMesh> childMesh(new btTriangleMesh);
|
|
|
|
|
|
|
|
|
|
const Nif::NiTriShapeData *data = shape->data.getPtr();
|
|
|
|
|
|
|
|
|
|
childMesh->preallocateVertices(data->vertices.size());
|
|
|
|
|
childMesh->preallocateIndices(data->triangles.size());
|
|
|
|
|
|
|
|
|
|
const std::vector<osg::Vec3f> &vertices = data->vertices;
|
|
|
|
|
const std::vector<unsigned short> &triangles = data->triangles;
|
|
|
|
|
|
|
|
|
|
for(size_t i = 0;i < data->triangles.size();i+=3)
|
|
|
|
|
{
|
|
|
|
|
osg::Vec3f b1 = vertices[triangles[i+0]];
|
|
|
|
|
osg::Vec3f b2 = vertices[triangles[i+1]];
|
|
|
|
|
osg::Vec3f b3 = vertices[triangles[i+2]];
|
|
|
|
|
childMesh->addTriangle(getbtVector(b1), getbtVector(b2), getbtVector(b3));
|
|
|
|
|
}
|
|
|
|
|
fillTriangleMesh(*childMesh, shape->data.get());
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<Resource::TriangleMeshShape> childShape(new Resource::TriangleMeshShape(childMesh.get(), true));
|
|
|
|
|
childMesh.release();
|
|
|
|
@ -322,27 +324,20 @@ void BulletNifLoader::handleNiTriShape(const Nif::NiTriShape *shape, int flags,
|
|
|
|
|
mCompoundShape->addChildShape(trans, childShape.get());
|
|
|
|
|
childShape.release();
|
|
|
|
|
}
|
|
|
|
|
else if (avoid)
|
|
|
|
|
{
|
|
|
|
|
if (!mAvoidStaticMesh)
|
|
|
|
|
mAvoidStaticMesh.reset(new btTriangleMesh(false));
|
|
|
|
|
|
|
|
|
|
fillTriangleMeshWithTransform(*mAvoidStaticMesh, shape->data.get(), transform);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!mStaticMesh)
|
|
|
|
|
mStaticMesh.reset(new btTriangleMesh(false));
|
|
|
|
|
|
|
|
|
|
// Static shape, just transform all vertices into position
|
|
|
|
|
const Nif::NiTriShapeData *data = shape->data.getPtr();
|
|
|
|
|
const std::vector<osg::Vec3f> &vertices = data->vertices;
|
|
|
|
|
const std::vector<unsigned short> &triangles = data->triangles;
|
|
|
|
|
|
|
|
|
|
mStaticMesh->preallocateVertices(data->vertices.size());
|
|
|
|
|
mStaticMesh->preallocateIndices(data->triangles.size());
|
|
|
|
|
|
|
|
|
|
size_t numtris = data->triangles.size();
|
|
|
|
|
for(size_t i = 0;i < numtris;i+=3)
|
|
|
|
|
{
|
|
|
|
|
osg::Vec3f b1 = vertices[triangles[i+0]]*transform;
|
|
|
|
|
osg::Vec3f b2 = vertices[triangles[i+1]]*transform;
|
|
|
|
|
osg::Vec3f b3 = vertices[triangles[i+2]]*transform;
|
|
|
|
|
mStaticMesh->addTriangle(getbtVector(b1), getbtVector(b2), getbtVector(b3));
|
|
|
|
|
}
|
|
|
|
|
fillTriangleMeshWithTransform(*mStaticMesh, shape->data.get(), transform);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|