Misc NIF loader improvements

Bullet NIF loader cleanup
Collect all extra records of a node
Remove code duplication in geometry type detection in OSG-side NIF loader
pull/3030/head
Alexei Dobrohotov 4 years ago
parent 7e63afdecf
commit c79f509652

@ -8,6 +8,7 @@
#include <components/debug/debuglog.hpp>
#include <components/misc/convert.hpp>
#include <components/misc/stringops.hpp>
#include <components/nif/node.hpp>
@ -24,11 +25,6 @@ osg::Matrixf getWorldTransform(const Nif::Node *node)
return node->trafo.toMatrix();
}
btVector3 getbtVector(const osg::Vec3f &v)
{
return btVector3(v.x(), v.y(), v.z());
}
bool pathFileNameStartsWithX(const std::string& path)
{
const std::size_t slashpos = path.find_last_of("/\\");
@ -36,7 +32,7 @@ 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)
void fillTriangleMesh(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()));
@ -47,20 +43,20 @@ void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriShapeDa
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)
Misc::Convert::toBullet(vertices[triangles[i + 0]] * transform),
Misc::Convert::toBullet(vertices[triangles[i + 1]] * transform),
Misc::Convert::toBullet(vertices[triangles[i + 2]] * transform)
);
}
}
void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriStripsData& data, const osg::Matrixf &transform)
void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiTriStripsData& data, const osg::Matrixf &transform)
{
const std::vector<osg::Vec3f> &vertices = data.vertices;
const std::vector<std::vector<unsigned short>> &strips = data.strips;
if (vertices.empty() || strips.empty())
return;
mesh.preallocateVertices(static_cast<int>(data.vertices.size()));
mesh.preallocateVertices(static_cast<int>(vertices.size()));
int numTriangles = 0;
for (const std::vector<unsigned short>& strip : strips)
{
@ -88,17 +84,17 @@ void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriStripsD
if (i%2==0)
{
mesh.addTriangle(
getbtVector(vertices[a] * transform),
getbtVector(vertices[b] * transform),
getbtVector(vertices[c] * transform)
Misc::Convert::toBullet(vertices[a] * transform),
Misc::Convert::toBullet(vertices[b] * transform),
Misc::Convert::toBullet(vertices[c] * transform)
);
}
else
{
mesh.addTriangle(
getbtVector(vertices[a] * transform),
getbtVector(vertices[c] * transform),
getbtVector(vertices[b] * transform)
Misc::Convert::toBullet(vertices[a] * transform),
Misc::Convert::toBullet(vertices[c] * transform),
Misc::Convert::toBullet(vertices[b] * transform)
);
}
}
@ -106,17 +102,12 @@ void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriStripsD
}
}
void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::Node* nifNode, const osg::Matrixf &transform)
void fillTriangleMesh(btTriangleMesh& mesh, const Nif::Node* nifNode, const osg::Matrixf &transform = osg::Matrixf())
{
if (nifNode->recType == Nif::RC_NiTriShape)
fillTriangleMeshWithTransform(mesh, static_cast<const Nif::NiTriShape*>(nifNode)->data.get(), transform);
else // if (nifNode->recType == Nif::RC_NiTriStrips)
fillTriangleMeshWithTransform(mesh, static_cast<const Nif::NiTriStrips*>(nifNode)->data.get(), transform);
}
void fillTriangleMesh(btTriangleMesh& mesh, const Nif::Node* node)
{
fillTriangleMeshWithTransform(mesh, node, osg::Matrixf());
fillTriangleMesh(mesh, static_cast<const Nif::NiTriShape*>(nifNode)->data.get(), transform);
else if (nifNode->recType == Nif::RC_NiTriStrips)
fillTriangleMesh(mesh, static_cast<const Nif::NiTriStrips*>(nifNode)->data.get(), transform);
}
}
@ -149,10 +140,12 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
if (findBoundingBox(node))
{
const btVector3 halfExtents = Misc::Convert::toBullet(mShape->mCollisionBoxHalfExtents);
const btVector3 origin = Misc::Convert::toBullet(mShape->mCollisionBoxTranslate);
std::unique_ptr<btCompoundShape> compound (new btCompoundShape);
std::unique_ptr<btBoxShape> boxShape(new btBoxShape(getbtVector(mShape->mCollisionBoxHalfExtents)));
std::unique_ptr<btBoxShape> boxShape(new btBoxShape(halfExtents));
btTransform transform = btTransform::getIdentity();
transform.setOrigin(getbtVector(mShape->mCollisionBoxTranslate));
transform.setOrigin(origin);
compound->addChildShape(transform, boxShape.get());
boxShape.release();
@ -383,7 +376,7 @@ void BulletNifLoader::handleNiTriShape(const Nif::Node *nifNode, int flags, cons
if (!mAvoidStaticMesh)
mAvoidStaticMesh.reset(new btTriangleMesh(false));
fillTriangleMeshWithTransform(*mAvoidStaticMesh, nifNode, transform);
fillTriangleMesh(*mAvoidStaticMesh, nifNode, transform);
}
else
{
@ -391,7 +384,7 @@ void BulletNifLoader::handleNiTriShape(const Nif::Node *nifNode, int flags, cons
mStaticMesh.reset(new btTriangleMesh(false));
// Static shape, just transform all vertices into position
fillTriangleMeshWithTransform(*mStaticMesh, nifNode, transform);
fillTriangleMesh(*mStaticMesh, nifNode, transform);
}
}

@ -60,6 +60,18 @@ namespace
}
}
bool isTypeGeometry(int type)
{
switch (type)
{
case Nif::RC_NiTriShape:
case Nif::RC_NiTriStrips:
case Nif::RC_NiLines:
return true;
}
return false;
}
// Collect all properties affecting the given drawable that should be handled on drawable basis rather than on the node hierarchy above it.
void collectDrawableProperties(const Nif::Node* nifNode, std::vector<const Nif::Property*>& out)
{
@ -528,7 +540,19 @@ namespace NifOsg
// - finding a random child NiNode in NiBspArrayController
node->setUserValue("recIndex", nifNode->recIndex);
std::vector<Nif::ExtraPtr> extraCollection;
for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->next)
extraCollection.emplace_back(e);
for (size_t i = 0; i < nifNode->extralist.length(); ++i)
{
Nif::ExtraPtr e = nifNode->extralist[i];
if (!e.empty())
extraCollection.emplace_back(e);
}
for (const auto& e : extraCollection)
{
if(e->recType == Nif::RC_NiTextKeyExtraData && textKeys)
{
@ -584,7 +608,7 @@ namespace NifOsg
applyNodeProperties(nifNode, node, composite, imageManager, boundTextures, animflags);
const bool isGeometry = nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips || nifNode->recType == Nif::RC_NiLines;
const bool isGeometry = isTypeGeometry(nifNode->recType);
if (isGeometry && !skipMeshes)
{
@ -1175,7 +1199,7 @@ namespace NifOsg
void handleGeometry(const Nif::Node* nifNode, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<unsigned int>& boundTextures, int animflags)
{
assert(nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips || nifNode->recType == Nif::RC_NiLines);
assert(isTypeGeometry(nifNode->recType));
osg::ref_ptr<osg::Drawable> drawable;
osg::ref_ptr<osg::Geometry> geom (new osg::Geometry);
handleNiGeometry(nifNode, geom, parentNode, composite, boundTextures, animflags);
@ -1220,7 +1244,7 @@ namespace NifOsg
void handleSkinnedGeometry(const Nif::Node *nifNode, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite,
const std::vector<unsigned int>& boundTextures, int animflags)
{
assert(nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips || nifNode->recType == Nif::RC_NiLines);
assert(isTypeGeometry(nifNode->recType));
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
handleNiGeometry(nifNode, geometry, parentNode, composite, boundTextures, animflags);
osg::ref_ptr<SceneUtil::RigGeometry> rig(new SceneUtil::RigGeometry);

Loading…
Cancel
Save