1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-10 03:39:55 +00:00

Reduce code duplication further

This commit is contained in:
capostrophic 2019-08-08 19:26:50 +03:00
parent 91efdf18a9
commit 7fc3153f62
3 changed files with 68 additions and 151 deletions

View File

@ -96,7 +96,6 @@ void NiTriStripsData::read(NIFStream *nif)
// Every strip with n points defines n-2 triangles, so this should be unnecessary.
/*int tris =*/ nif->getUShort();
// Number of triangle strips
int numStrips = nif->getUShort();
// Number of points in each strip

View File

@ -58,28 +58,17 @@ void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriStripsD
{
const std::vector<osg::Vec3f> &vertices = data.vertices;
const std::vector<std::vector<unsigned short>> &strips = data.strips;
if (vertices.empty() || strips.empty())
// Can't make a triangle from less than three vertices. All strips have the same size.
if (vertices.empty() || strips.empty() || strips[0].size() < 3)
return;
// Assume every strip has the same size
const int singleStripSize = static_cast<int>(strips[0].size());
// Can't make a triangle from less than three vertices.
if (singleStripSize < 3)
return;
mesh.preallocateVertices(static_cast<int>(data.vertices.size()));
// There are N+2*M vertex indices in sum in all strips
// where N is the number of triangles and M is the number of strips
mesh.preallocateIndices(static_cast<int>((strips.size()-2) * singleStripSize));
// There are N+2*M vertex indices overall, so we must substract 2*M (N triangles, M strips)
mesh.preallocateIndices(static_cast<int>((strips.size()-2) * strips[0].size()));
// It's triangulation time. Totally not a NifSkope spell ripoff.
for (const std::vector<unsigned short>& strip : strips)
{
unsigned short a = strip[0];
unsigned short b = strip[0];
unsigned short c = strip[1];
bool flip = false;
unsigned short a = strip[0], b = strip[0], c = strip[1];
for (int i = 2; i < static_cast<int>(strip.size()); i++)
{
a = b;
@ -87,24 +76,26 @@ void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriStripsD
c = strip[i];
if (a != b && b != c && a != c)
{
if (!flip)
if (i%2==0)
mesh.addTriangle(getbtVector(vertices[a]), getbtVector(vertices[b]), getbtVector(vertices[c]));
else
mesh.addTriangle(getbtVector(vertices[a]), getbtVector(vertices[c]), getbtVector(vertices[b]));
}
flip = !flip;
}
}
}
void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiTriShapeData& data)
void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::Node* nifNode, const osg::Matrixf &transform)
{
fillTriangleMeshWithTransform(mesh, data, 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::NiTriStripsData& data)
void fillTriangleMesh(btTriangleMesh& mesh, const Nif::Node* node)
{
fillTriangleMeshWithTransform(mesh, data, osg::Matrixf());
fillTriangleMeshWithTransform(mesh, node, osg::Matrixf());
}
}
@ -326,9 +317,7 @@ void BulletNifLoader::handleNiTriShape(const Nif::Node *nifNode, int flags, cons
const Nif::NiTriShape* shape = static_cast<const Nif::NiTriShape*>(nifNode);
if (!shape->skin.empty())
isAnimated = false;
if (shape->data.empty())
return;
if (shape->data->triangles.empty())
if (shape->data.empty() || shape->data->triangles.empty())
return;
}
else
@ -336,9 +325,7 @@ void BulletNifLoader::handleNiTriShape(const Nif::Node *nifNode, int flags, cons
const Nif::NiTriStrips* shape = static_cast<const Nif::NiTriStrips*>(nifNode);
if (!shape->skin.empty())
isAnimated = false;
if (shape->data.empty())
return;
if (shape->data->strips.empty())
if (shape->data.empty() || shape->data->strips.empty())
return;
}
@ -350,10 +337,7 @@ void BulletNifLoader::handleNiTriShape(const Nif::Node *nifNode, int flags, cons
std::unique_ptr<btTriangleMesh> childMesh(new btTriangleMesh);
if (nifNode->recType == Nif::RC_NiTriShape)
fillTriangleMesh(*childMesh, static_cast<const Nif::NiTriShape*>(nifNode)->data.get());
else
fillTriangleMesh(*childMesh, static_cast<const Nif::NiTriStrips*>(nifNode)->data.get());
fillTriangleMesh(*childMesh, nifNode);
std::unique_ptr<Resource::TriangleMeshShape> childShape(new Resource::TriangleMeshShape(childMesh.get(), true));
childMesh.release();
@ -381,16 +365,7 @@ void BulletNifLoader::handleNiTriShape(const Nif::Node *nifNode, int flags, cons
if (!mAvoidStaticMesh)
mAvoidStaticMesh.reset(new btTriangleMesh(false));
if (nifNode->recType == Nif::RC_NiTriShape)
{
const Nif::NiTriShape* shape = static_cast<const Nif::NiTriShape*>(nifNode);
fillTriangleMeshWithTransform(*mAvoidStaticMesh, shape->data.get(), transform);
}
else
{
const Nif::NiTriStrips* shape = static_cast<const Nif::NiTriStrips*>(nifNode);
fillTriangleMeshWithTransform(*mAvoidStaticMesh, shape->data.get(), transform);
}
fillTriangleMeshWithTransform(*mAvoidStaticMesh, nifNode, transform);
}
else
{
@ -398,17 +373,7 @@ void BulletNifLoader::handleNiTriShape(const Nif::Node *nifNode, int flags, cons
mStaticMesh.reset(new btTriangleMesh(false));
// Static shape, just transform all vertices into position
if (nifNode->recType == Nif::RC_NiTriShape)
{
const Nif::NiTriShape* shape = static_cast<const Nif::NiTriShape*>(nifNode);
fillTriangleMeshWithTransform(*mStaticMesh, shape->data.get(), transform);
}
else
{
const Nif::NiTriStrips* shape = static_cast<const Nif::NiTriStrips*>(nifNode);
fillTriangleMeshWithTransform(*mStaticMesh, shape->data.get(), transform);
}
fillTriangleMeshWithTransform(*mStaticMesh, nifNode, transform);
}
}

View File

@ -576,8 +576,7 @@ namespace NifOsg
node->setDataVariance(osg::Object::DYNAMIC);
}
// Same thing for animated shapes
if ((nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips) && isAnimated)
if ((nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips) && isAnimated) // Same thing for animated shapes
{
node->setDataVariance(osg::Object::DYNAMIC);
}
@ -1038,85 +1037,55 @@ namespace NifOsg
}
}
void triShapeToGeometry(const Nif::NiTriShape *triShape, osg::Geometry *geometry, osg::Node* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int>& boundTextures, int animflags)
void triCommonToGeometry(osg::Geometry *geometry, const std::vector<osg::Vec3f>& vertices, const std::vector<osg::Vec3f>& normals, const std::vector<std::vector<osg::Vec2f>>& uvlist, const std::vector<osg::Vec4f>& colors, const std::vector<int>& boundTextures, const std::string& name)
{
const Nif::NiTriShapeData* data = triShape->data.getPtr();
if (!data->vertices.empty())
geometry->setVertexArray(new osg::Vec3Array(data->vertices.size(), data->vertices.data()));
if (!data->normals.empty())
geometry->setNormalArray(new osg::Vec3Array(data->normals.size(), data->normals.data()), osg::Array::BIND_PER_VERTEX);
int textureStage = 0;
for (std::vector<int>::const_iterator it = boundTextures.begin(); it != boundTextures.end(); ++it,++textureStage)
{
int uvSet = *it;
if (uvSet >= (int)data->uvlist.size())
{
Log(Debug::Verbose) << "Out of bounds UV set " << uvSet << " on TriShape \"" << triShape->name << "\" in " << mFilename;
if (!data->uvlist.empty())
geometry->setTexCoordArray(textureStage, new osg::Vec2Array(data->uvlist[0].size(), data->uvlist[0].data()), osg::Array::BIND_PER_VERTEX);
continue;
}
geometry->setTexCoordArray(textureStage, new osg::Vec2Array(data->uvlist[uvSet].size(), data->uvlist[uvSet].data()), osg::Array::BIND_PER_VERTEX);
}
if (!data->colors.empty())
geometry->setColorArray(new osg::Vec4Array(data->colors.size(), data->colors.data()), osg::Array::BIND_PER_VERTEX);
if (!data->triangles.empty())
geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES,
data->triangles.size(),
(unsigned short*)data->triangles.data()));
// osg::Material properties are handled here for two reasons:
// - if there are no vertex colors, we need to disable colorMode.
// - there are 3 "overlapping" nif properties that all affect the osg::Material, handling them
// above the actual renderable would be tedious.
std::vector<const Nif::Property*> drawableProps;
collectDrawableProperties(triShape, drawableProps);
applyDrawableProperties(parentNode, drawableProps, composite, !data->colors.empty(), animflags, false);
}
void triStripsToGeometry(const Nif::NiTriStrips *triStrips, osg::Geometry *geometry, osg::Node* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int>& boundTextures, int animflags)
{
const Nif::NiTriStripsData* data = triStrips->data.getPtr();
if (!data->vertices.empty())
geometry->setVertexArray(new osg::Vec3Array(data->vertices.size(), data->vertices.data()));
if (!data->normals.empty())
geometry->setNormalArray(new osg::Vec3Array(data->normals.size(), data->normals.data()), osg::Array::BIND_PER_VERTEX);
if (!vertices.empty())
geometry->setVertexArray(new osg::Vec3Array(vertices.size(), vertices.data()));
if (!normals.empty())
geometry->setNormalArray(new osg::Vec3Array(normals.size(), normals.data()), osg::Array::BIND_PER_VERTEX);
if (!colors.empty())
geometry->setColorArray(new osg::Vec4Array(colors.size(), colors.data()), osg::Array::BIND_PER_VERTEX);
int textureStage = 0;
for (const int uvSet : boundTextures)
{
if (uvSet >= (int)data->uvlist.size())
if (uvSet >= (int)uvlist.size())
{
Log(Debug::Verbose) << "Out of bounds UV set " << uvSet << " on TriStrips \"" << triStrips->name << "\" in " << mFilename;
if (!data->uvlist.empty())
geometry->setTexCoordArray(textureStage, new osg::Vec2Array(data->uvlist[0].size(), data->uvlist[0].data()), osg::Array::BIND_PER_VERTEX);
Log(Debug::Verbose) << "Out of bounds UV set " << uvSet << " on shape \"" << name << "\" in " << mFilename;
if (!uvlist.empty())
geometry->setTexCoordArray(textureStage, new osg::Vec2Array(uvlist[0].size(), uvlist[0].data()), osg::Array::BIND_PER_VERTEX);
continue;
}
geometry->setTexCoordArray(textureStage, new osg::Vec2Array(data->uvlist[uvSet].size(), data->uvlist[uvSet].data()), osg::Array::BIND_PER_VERTEX);
geometry->setTexCoordArray(textureStage, new osg::Vec2Array(uvlist[uvSet].size(), uvlist[uvSet].data()), osg::Array::BIND_PER_VERTEX);
textureStage++;
}
}
if (!data->colors.empty())
geometry->setColorArray(new osg::Vec4Array(data->colors.size(), data->colors.data()), osg::Array::BIND_PER_VERTEX);
if (!data->strips.empty())
void triShapeToGeometry(const Nif::Node *nifNode, osg::Geometry *geometry, osg::Node* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int>& boundTextures, int animflags)
{
bool vertexColorsPresent = false;
if (nifNode->recType == Nif::RC_NiTriShape)
{
for (const std::vector<unsigned short>& strip : data->strips)
{
// Can't make a triangle from less than three vertices.
// All strips have the same size.
if (strip.size() < 3)
break;
geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP,
strip.size(), (unsigned short*)strip.data()));
}
const Nif::NiTriShape* triShape = static_cast<const Nif::NiTriShape*>(nifNode);
const Nif::NiTriShapeData* data = triShape->data.getPtr();
vertexColorsPresent = !data->colors.empty();
triCommonToGeometry(geometry, data->vertices, data->normals, data->uvlist, data->colors, boundTextures, triShape->name);
if (!data->triangles.empty())
geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES, data->triangles.size(),
(unsigned short*)data->triangles.data()));
}
else
{
const Nif::NiTriStrips* triStrips = static_cast<const Nif::NiTriStrips*>(nifNode);
const Nif::NiTriStripsData* data = triStrips->data.getPtr();
vertexColorsPresent = !data->colors.empty();
triCommonToGeometry(geometry, data->vertices, data->normals, data->uvlist, data->colors, boundTextures, triStrips->name);
// Can't make a triangle from less than three vertices. All strips have the same size.
if (!data->strips.empty() && data->strips[0].size() < 3)
for (const std::vector<unsigned short>& strip : data->strips)
geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP, strip.size(),
(unsigned short*)strip.data()));
}
// osg::Material properties are handled here for two reasons:
@ -1124,34 +1093,26 @@ namespace NifOsg
// - there are 3 "overlapping" nif properties that all affect the osg::Material, handling them
// above the actual renderable would be tedious.
std::vector<const Nif::Property*> drawableProps;
collectDrawableProperties(triStrips, drawableProps);
applyDrawableProperties(parentNode, drawableProps, composite, !data->colors.empty(), animflags, false);
collectDrawableProperties(nifNode, drawableProps);
applyDrawableProperties(parentNode, drawableProps, composite, vertexColorsPresent, animflags, false);
}
void handleTriShape(const Nif::Node* nifNode, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int>& boundTextures, int animflags)
{
assert(nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips);
osg::ref_ptr<osg::Drawable> drawable;
osg::ref_ptr<osg::Geometry> geom (new osg::Geometry);
triShapeToGeometry(nifNode, geom, parentNode, composite, boundTextures, animflags);
Nif::ControllerPtr ctrl;
if (nifNode->recType == Nif::RC_NiTriShape)
{
const Nif::NiTriShape* triShape = static_cast<const Nif::NiTriShape*>(nifNode);
triShapeToGeometry(triShape, geom, parentNode, composite, boundTextures, animflags);
handleMorphController(triShape->controller, drawable, geom, parentNode, composite, boundTextures, animflags);
}
ctrl = static_cast<const Nif::NiTriShape*>(nifNode)->controller;
else
{
const Nif::NiTriStrips* triStrips = static_cast<const Nif::NiTriStrips*>(nifNode);
triStripsToGeometry(triStrips, geom, parentNode, composite, boundTextures, animflags);
handleMorphController(triStrips->controller, drawable, geom, parentNode, composite, boundTextures, animflags);
}
ctrl = static_cast<const Nif::NiTriStrips*>(nifNode)->controller;
handleMorphController(ctrl, drawable, geom, parentNode, composite, boundTextures, animflags);
if (!drawable.get())
drawable = geom;
drawable->setName(nifNode->name);
parentNode->addChild(drawable);
}
@ -1193,21 +1154,8 @@ namespace NifOsg
const std::vector<int>& boundTextures, int animflags)
{
assert(nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips);
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
Nif::NiSkinInstancePtr skinPtr;
if (nifNode->recType == Nif::RC_NiTriShape)
{
const Nif::NiTriShape* triShape = static_cast<const Nif::NiTriShape*>(nifNode);
triShapeToGeometry(triShape, geometry, parentNode, composite, boundTextures, animflags);
skinPtr = triShape->skin;
}
else
{
const Nif::NiTriStrips* triStrips = static_cast<const Nif::NiTriStrips*>(nifNode);
triStripsToGeometry(triStrips, geometry, parentNode, composite, boundTextures, animflags);
skinPtr = triStrips->skin;
}
triShapeToGeometry(nifNode, geometry, parentNode, composite, boundTextures, animflags);
osg::ref_ptr<SceneUtil::RigGeometry> rig(new SceneUtil::RigGeometry);
rig->setSourceGeometry(geometry);
rig->setName(nifNode->name);
@ -1215,6 +1163,11 @@ namespace NifOsg
// Assign bone weights
osg::ref_ptr<SceneUtil::RigGeometry::InfluenceMap> map (new SceneUtil::RigGeometry::InfluenceMap);
Nif::NiSkinInstancePtr skinPtr;
if (nifNode->recType == Nif::RC_NiTriShape)
skinPtr = static_cast<const Nif::NiTriShape*>(nifNode)->skin;
else
skinPtr = static_cast<const Nif::NiTriStrips*>(nifNode)->skin;
const Nif::NiSkinInstance *skin = skinPtr.getPtr();
const Nif::NiSkinData *data = skin->data.getPtr();
const Nif::NodeList &bones = skin->bones;