Fix multiple-strip NiTriStrips loading

pull/2481/head
capostrophic 5 years ago
parent fa910299d0
commit 9e93c9ecd2

@ -98,12 +98,14 @@ void NiTriStripsData::read(NIFStream *nif)
/*int tris =*/ nif->getUShort(); /*int tris =*/ nif->getUShort();
// Number of triangle strips // Number of triangle strips
int numStrips = nif->getUShort(); int numStrips = nif->getUShort();
// Number of points in each strip
int lengths = nif->getUShort(); std::vector<unsigned short> lengths;
nif->getUShorts(lengths, numStrips);
for (int i = 0; i < numStrips; i++) for (int i = 0; i < numStrips; i++)
{ {
std::vector<unsigned short> strip; std::vector<unsigned short> strip;
nif->getUShorts(strip, lengths); nif->getUShorts(strip, lengths[i]);
strips.emplace_back(strip); strips.emplace_back(strip);
} }
} }

@ -58,16 +58,25 @@ void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriStripsD
{ {
const std::vector<osg::Vec3f> &vertices = data.vertices; const std::vector<osg::Vec3f> &vertices = data.vertices;
const std::vector<std::vector<unsigned short>> &strips = data.strips; const std::vector<std::vector<unsigned short>> &strips = data.strips;
// Can't make a triangle from less than three vertices. All strips have the same size. if (vertices.empty() || strips.empty())
if (vertices.empty() || strips.empty() || strips[0].size() < 3)
return; return;
mesh.preallocateVertices(static_cast<int>(data.vertices.size())); mesh.preallocateVertices(static_cast<int>(data.vertices.size()));
// There are N+2*M vertex indices overall, so we must substract 2*M (N triangles, M strips) int numTriangles = 0;
mesh.preallocateIndices(static_cast<int>((strips.size()-2) * strips[0].size())); for (const std::vector<unsigned short>& strip : strips)
{
// Each strip with N points contains information about N-2 triangles.
if (strip.size() >= 3)
numTriangles += static_cast<int>(strip.size()-2);
}
mesh.preallocateIndices(static_cast<int>(numTriangles));
// It's triangulation time. Totally not a NifSkope spell ripoff. // It's triangulation time. Totally not a NifSkope spell ripoff.
for (const std::vector<unsigned short>& strip : strips) for (const std::vector<unsigned short>& strip : strips)
{ {
// Can't make a triangle from less than 3 points.
if (strip.size() < 3)
continue;
unsigned short a = strip[0], b = strip[0], c = strip[1]; unsigned short a = strip[0], b = strip[0], c = strip[1];
for (int i = 2; i < static_cast<int>(strip.size()); i++) for (int i = 2; i < static_cast<int>(strip.size()); i++)
{ {

@ -1081,11 +1081,17 @@ namespace NifOsg
const Nif::NiTriStripsData* data = triStrips->data.getPtr(); const Nif::NiTriStripsData* data = triStrips->data.getPtr();
vertexColorsPresent = !data->colors.empty(); vertexColorsPresent = !data->colors.empty();
triCommonToGeometry(geometry, data->vertices, data->normals, data->uvlist, data->colors, boundTextures, triStrips->name); 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())
if (!data->strips.empty() && data->strips[0].size() >= 3) {
for (const std::vector<unsigned short>& strip : data->strips) for (const std::vector<unsigned short>& strip : data->strips)
{
// Can't make a triangle from less than three vertices.
if (strip.size() < 3)
continue;
geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP, strip.size(), geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP, strip.size(),
(unsigned short*)strip.data())); (unsigned short*)strip.data()));
}
}
} }
// osg::Material properties are handled here for two reasons: // osg::Material properties are handled here for two reasons:

Loading…
Cancel
Save