Merge branch 'mantlingtalos' into 'master'

Copy triangle data from NiSkinPartition, a.k.a. SKYRIM TREES

See merge request OpenMW/openmw!3235
revert-6246b479
psi29a 1 year ago
commit 466b2f1b74

@ -446,6 +446,39 @@ namespace Nif
} }
} }
std::vector<unsigned short> NiSkinPartition::Partition::getTrueTriangles() const
{
if (!trueTriangles.empty())
return trueTriangles;
std::vector<unsigned short> remappedTriangles;
if (vertexMap.empty() || triangles.empty())
return remappedTriangles;
remappedTriangles = triangles;
for (unsigned short& index : remappedTriangles)
index = vertexMap[index];
return remappedTriangles;
}
std::vector<std::vector<unsigned short>> NiSkinPartition::Partition::getTrueStrips() const
{
if (!trueTriangles.empty())
return {};
std::vector<std::vector<unsigned short>> remappedStrips;
if (vertexMap.empty() || strips.empty())
return remappedStrips;
remappedStrips = strips;
for (auto& strip : remappedStrips)
for (auto& index : strip)
index = vertexMap[index];
return remappedStrips;
}
void NiMorphData::read(NIFStream* nif) void NiMorphData::read(NIFStream* nif)
{ {
int morphCount = nif->getInt(); int morphCount = nif->getInt();

@ -222,7 +222,10 @@ namespace Nif
std::vector<unsigned short> trueTriangles; std::vector<unsigned short> trueTriangles;
std::vector<char> boneIndices; std::vector<char> boneIndices;
BSVertexDesc mVertexDesc; BSVertexDesc mVertexDesc;
void read(NIFStream* nif); void read(NIFStream* nif);
std::vector<unsigned short> getTrueTriangles() const;
std::vector<std::vector<unsigned short>> getTrueStrips() const;
}; };
unsigned int mPartitionNum; unsigned int mPartitionNum;
std::vector<Partition> mPartitions; std::vector<Partition> mPartitions;

@ -385,6 +385,7 @@ namespace NifBullet
if (!niGeometry.skin.empty()) if (!niGeometry.skin.empty())
args.mAnimated = false; args.mAnimated = false;
// TODO: handle NiSkinPartition
std::unique_ptr<btTriangleMesh> childMesh = makeChildMesh(niGeometry); std::unique_ptr<btTriangleMesh> childMesh = makeChildMesh(niGeometry);
if (childMesh == nullptr || childMesh->getNumTriangles() == 0) if (childMesh == nullptr || childMesh->getNumTriangles() == 0)

@ -1378,45 +1378,86 @@ namespace NifOsg
const Nif::NiGeometry* niGeometry = static_cast<const Nif::NiGeometry*>(nifNode); const Nif::NiGeometry* niGeometry = static_cast<const Nif::NiGeometry*>(nifNode);
if (niGeometry->data.empty()) if (niGeometry->data.empty())
return; return;
const Nif::NiGeometryData* niGeometryData = niGeometry->data.getPtr();
if (niGeometry->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_BSLODTriShape) bool hasPartitions = false;
{ if (!niGeometry->skin.empty())
if (niGeometryData->recType != Nif::RC_NiTriShapeData)
return;
auto triangles = static_cast<const Nif::NiTriShapeData*>(niGeometryData)->triangles;
if (triangles.empty())
return;
geometry->addPrimitiveSet(new osg::DrawElementsUShort(
osg::PrimitiveSet::TRIANGLES, triangles.size(), (unsigned short*)triangles.data()));
}
else if (niGeometry->recType == Nif::RC_NiTriStrips)
{ {
if (niGeometryData->recType != Nif::RC_NiTriStripsData) const Nif::NiSkinInstance* skin = niGeometry->skin.getPtr();
return; const Nif::NiSkinData* data = nullptr;
auto data = static_cast<const Nif::NiTriStripsData*>(niGeometryData); const Nif::NiSkinPartition* partitions = nullptr;
bool hasGeometry = false; if (!skin->data.empty())
for (const auto& strip : data->strips)
{ {
if (strip.size() < 3) data = skin->data.getPtr();
continue; if (!data->partitions.empty())
geometry->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP, partitions = data->partitions.getPtr();
strip.size(), reinterpret_cast<const unsigned short*>(strip.data()))); }
hasGeometry = true; if (!partitions && !skin->partitions.empty())
partitions = skin->partitions.getPtr();
hasPartitions = partitions != nullptr;
if (hasPartitions)
{
std::vector<unsigned short> trueTriangles;
for (const Nif::NiSkinPartition::Partition& partition : partitions->mPartitions)
{
trueTriangles = partition.getTrueTriangles();
if (!trueTriangles.empty())
{
geometry->addPrimitiveSet(new osg::DrawElementsUShort(
osg::PrimitiveSet::TRIANGLES, trueTriangles.size(), trueTriangles.data()));
}
const std::vector<std::vector<unsigned short>> trueStrips = partition.getTrueStrips();
for (const auto& strip : trueStrips)
{
geometry->addPrimitiveSet(new osg::DrawElementsUShort(
osg::PrimitiveSet::TRIANGLE_STRIP, strip.size(), strip.data()));
}
}
} }
if (!hasGeometry)
return;
} }
else if (niGeometry->recType == Nif::RC_NiLines)
const Nif::NiGeometryData* niGeometryData = niGeometry->data.getPtr();
if (!hasPartitions)
{ {
if (niGeometryData->recType != Nif::RC_NiLinesData) if (niGeometry->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_BSLODTriShape)
return; {
auto data = static_cast<const Nif::NiLinesData*>(niGeometryData); if (niGeometryData->recType != Nif::RC_NiTriShapeData)
const auto& line = data->lines; return;
if (line.empty()) auto data = static_cast<const Nif::NiTriShapeData*>(niGeometryData);
return; const std::vector<unsigned short>& triangles = data->triangles;
geometry->addPrimitiveSet(new osg::DrawElementsUShort( if (triangles.empty())
osg::PrimitiveSet::LINES, line.size(), reinterpret_cast<const unsigned short*>(line.data()))); return;
geometry->addPrimitiveSet(
new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES, triangles.size(), triangles.data()));
}
else if (niGeometry->recType == Nif::RC_NiTriStrips)
{
if (niGeometryData->recType != Nif::RC_NiTriStripsData)
return;
auto data = static_cast<const Nif::NiTriStripsData*>(niGeometryData);
bool hasGeometry = false;
for (const std::vector<unsigned short>& strip : data->strips)
{
if (strip.size() < 3)
continue;
geometry->addPrimitiveSet(
new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP, strip.size(), strip.data()));
hasGeometry = true;
}
if (!hasGeometry)
return;
}
else if (niGeometry->recType == Nif::RC_NiLines)
{
if (niGeometryData->recType != Nif::RC_NiLinesData)
return;
auto data = static_cast<const Nif::NiLinesData*>(niGeometryData);
const auto& line = data->lines;
if (line.empty())
return;
geometry->addPrimitiveSet(
new osg::DrawElementsUShort(osg::PrimitiveSet::LINES, line.size(), line.data()));
}
} }
handleNiGeometryData(geometry, niGeometryData, boundTextures, nifNode->name); handleNiGeometryData(geometry, niGeometryData, boundTextures, nifNode->name);

Loading…
Cancel
Save