Create collision shape for all avoided nodes

pull/541/head
elsid 7 years ago
parent e24d4d7052
commit f6a60790f8
No known key found for this signature in database
GPG Key ID: B845CB9FEE18AB40

@ -142,6 +142,7 @@ namespace Resource
static bool operator ==(const Resource::BulletShape& lhs, const Resource::BulletShape& rhs)
{
return compareObjects(lhs.mCollisionShape, rhs.mCollisionShape)
&& compareObjects(lhs.mAvoidCollisionShape, rhs.mAvoidCollisionShape)
&& lhs.mCollisionBoxHalfExtents == rhs.mCollisionBoxHalfExtents
&& lhs.mCollisionBoxTranslate == rhs.mCollisionBoxTranslate
&& lhs.mAnimatedShapes == rhs.mAnimatedShapes;
@ -151,6 +152,7 @@ namespace Resource
{
return stream << "Resource::BulletShape {"
<< value.mCollisionShape << ", "
<< value.mAvoidCollisionShape << ", "
<< value.mCollisionBoxHalfExtents << ", "
<< value.mAnimatedShapes
<< "}";
@ -837,7 +839,10 @@ namespace
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
const auto result = mLoader.load(mNifFile);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
Resource::BulletShape expected;
expected.mAvoidCollisionShape = new Resource::TriangleMeshShape(triangles.release(), false);
EXPECT_EQ(*result, expected);
}

@ -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);
}
}

@ -11,6 +11,8 @@
#include <osg/ref_ptr>
#include <osg/Referenced>
#include <BulletCollision/CollisionShapes/btCompoundShape.h>
#include <components/debug/debuglog.hpp>
#include <components/nif/niffile.hpp>
#include <components/resource/bulletshape.hpp>
@ -35,10 +37,6 @@ namespace NifBullet
class BulletNifLoader
{
public:
BulletNifLoader();
virtual ~BulletNifLoader();
void warn(const std::string &msg)
{
Log(Debug::Warning) << "NIFLoader: Warn:" << msg;
@ -55,16 +53,19 @@ public:
private:
bool findBoundingBox(const Nif::Node* node);
void handleNode(const std::string& fileName, Nif::Node const *node, int flags, bool isCollisionNode, bool isAnimated=false, bool autogenerated=false);
void handleNode(const std::string& fileName, Nif::Node const *node, int flags, bool isCollisionNode,
bool isAnimated=false, bool autogenerated=false, bool avoid=false);
const Nif::Node* getCollisionNode(const Nif::Node* rootNode);
void handleNiTriShape(const Nif::NiTriShape *shape, int flags, const osg::Matrixf& transform, bool isAnimated);
void handleNiTriShape(const Nif::NiTriShape *shape, int flags, const osg::Matrixf& transform, bool isAnimated, bool avoid);
std::unique_ptr<btCompoundShape> mCompoundShape;
std::unique_ptr<btTriangleMesh> mStaticMesh;
std::unique_ptr<btTriangleMesh> mAvoidStaticMesh;
osg::ref_ptr<Resource::BulletShape> mShape;
};

@ -13,12 +13,14 @@ namespace Resource
BulletShape::BulletShape()
: mCollisionShape(nullptr)
, mAvoidCollisionShape(nullptr)
{
}
BulletShape::BulletShape(const BulletShape &copy, const osg::CopyOp &copyop)
: mCollisionShape(duplicateCollisionShape(copy.mCollisionShape))
, mAvoidCollisionShape(duplicateCollisionShape(copy.mAvoidCollisionShape))
, mCollisionBoxHalfExtents(copy.mCollisionBoxHalfExtents)
, mCollisionBoxTranslate(copy.mCollisionBoxTranslate)
, mAnimatedShapes(copy.mAnimatedShapes)
@ -27,6 +29,7 @@ BulletShape::BulletShape(const BulletShape &copy, const osg::CopyOp &copyop)
BulletShape::~BulletShape()
{
deleteShape(mAvoidCollisionShape);
deleteShape(mCollisionShape);
}
@ -82,6 +85,11 @@ btCollisionShape *BulletShape::getCollisionShape()
return mCollisionShape;
}
btCollisionShape *BulletShape::getAvoidCollisionShape()
{
return mAvoidCollisionShape;
}
osg::ref_ptr<BulletShapeInstance> BulletShape::makeInstance() const
{
osg::ref_ptr<BulletShapeInstance> instance (new BulletShapeInstance(this));
@ -99,6 +107,9 @@ BulletShapeInstance::BulletShapeInstance(osg::ref_ptr<const BulletShape> source)
if (source->mCollisionShape)
mCollisionShape = duplicateCollisionShape(source->mCollisionShape);
if (source->mAvoidCollisionShape)
mAvoidCollisionShape = duplicateCollisionShape(source->mAvoidCollisionShape);
}
}

@ -25,6 +25,7 @@ namespace Resource
META_Object(Resource, BulletShape)
btCollisionShape* mCollisionShape;
btCollisionShape* mAvoidCollisionShape;
// Used for actors. Note, ideally actors would use a separate loader - as it is
// we have to keep a redundant copy of the actor model around in mCollisionShape, which isn't used.
@ -44,6 +45,8 @@ namespace Resource
btCollisionShape* getCollisionShape();
btCollisionShape* getAvoidCollisionShape();
private:
void deleteShape(btCollisionShape* shape);

Loading…
Cancel
Save