diff --git a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp index a12a49a466..7430ebdb60 100644 --- a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp +++ b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp @@ -317,17 +317,20 @@ namespace mNiTriShapeData.recType = Nif::RC_NiTriShapeData; mNiTriShapeData.vertices = { osg::Vec3f(0, 0, 0), osg::Vec3f(1, 0, 0), osg::Vec3f(1, 1, 0) }; + mNiTriShapeData.mNumTriangles = 1; mNiTriShapeData.triangles = { 0, 1, 2 }; mNiTriShape.data = Nif::NiGeometryDataPtr(&mNiTriShapeData); mNiTriShapeData2.recType = Nif::RC_NiTriShapeData; mNiTriShapeData2.vertices = { osg::Vec3f(0, 0, 1), osg::Vec3f(1, 0, 1), osg::Vec3f(1, 1, 1) }; + mNiTriShapeData2.mNumTriangles = 1; mNiTriShapeData2.triangles = { 0, 1, 2 }; mNiTriShape2.data = Nif::NiGeometryDataPtr(&mNiTriShapeData2); mNiTriStripsData.recType = Nif::RC_NiTriStripsData; mNiTriStripsData.vertices = { osg::Vec3f(0, 0, 0), osg::Vec3f(1, 0, 0), osg::Vec3f(1, 1, 0), osg::Vec3f(0, 1, 0) }; + mNiTriStripsData.mNumTriangles = 2; mNiTriStripsData.strips = { { 0, 1, 2, 3 } }; mNiTriStrips.data = Nif::NiGeometryDataPtr(&mNiTriStripsData); } diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 546f9e5279..eacf825fbf 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -40,26 +40,28 @@ namespace return letterPos < path.size() && (path[letterPos] == 'x' || path[letterPos] == 'X'); } + void prepareTriangleMesh(btTriangleMesh& mesh, const Nif::NiTriBasedGeomData& data) + { + // FIXME: copying vertices/indices individually is unreasonable + const std::vector& vertices = data.vertices; + mesh.preallocateVertices(static_cast(vertices.size())); + for (const osg::Vec3f& vertex : vertices) + mesh.findOrAddVertex(Misc::Convert::toBullet(vertex), false); + + mesh.preallocateIndices(static_cast(data.mNumTriangles * 3)); + } + void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiTriShapeData& data) { - const std::vector& vertices = data.vertices; + prepareTriangleMesh(mesh, data); const std::vector& triangles = data.triangles; - mesh.preallocateVertices(static_cast(vertices.size())); - mesh.preallocateIndices(static_cast(triangles.size())); - for (std::size_t i = 0; i < triangles.size(); i += 3) - { - mesh.addTriangle(Misc::Convert::toBullet(vertices[triangles[i + 0]]), - Misc::Convert::toBullet(vertices[triangles[i + 1]]), - Misc::Convert::toBullet(vertices[triangles[i + 2]])); - } + mesh.addTriangleIndices(triangles[i + 0], triangles[i + 1], triangles[i + 2]); } void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiTriStripsData& data) { - mesh.preallocateVertices(static_cast(data.vertices.size())); - mesh.preallocateIndices(static_cast(data.mNumTriangles)); - + prepareTriangleMesh(mesh, data); for (const std::vector& strip : data.strips) { if (strip.size() < 3) @@ -75,13 +77,10 @@ namespace c = strip[i]; if (a == b || b == c || a == c) continue; - const btVector3 vertexA = Misc::Convert::toBullet(data.vertices[a]); - const btVector3 vertexB = Misc::Convert::toBullet(data.vertices[b]); - const btVector3 vertexC = Misc::Convert::toBullet(data.vertices[c]); if (i % 2 == 0) - mesh.addTriangle(vertexA, vertexB, vertexC); + mesh.addTriangleIndices(a, b, c); else - mesh.addTriangle(vertexA, vertexC, vertexB); + mesh.addTriangleIndices(a, c, b); } } }