diff options
author | Danila Shutov <dcbrwn2@gmail.com> | 2020-06-07 19:14:00 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-07 18:14:00 +0200 |
commit | fe1f72ab0ac8bcc233c91eb5b2d71bd2d2574cf8 (patch) | |
tree | 4be77389e38c97dd1391439f212db642b16fac0b /src | |
parent | 8fc9e7eb117849202b87bf3d764cd3eac6f68c74 (diff) | |
download | minetest-fe1f72ab0ac8bcc233c91eb5b2d71bd2d2574cf8.tar.gz minetest-fe1f72ab0ac8bcc233c91eb5b2d71bd2d2574cf8.tar.bz2 minetest-fe1f72ab0ac8bcc233c91eb5b2d71bd2d2574cf8.zip |
Recalculate mesh normals for CAOs (#10000)
Diffstat (limited to 'src')
-rw-r--r-- | src/client/content_cao.cpp | 8 | ||||
-rw-r--r-- | src/client/mesh.cpp | 20 | ||||
-rw-r--r-- | src/client/mesh.h | 6 |
3 files changed, 34 insertions, 0 deletions
diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 855729642..a6ce06d20 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -726,6 +726,14 @@ void GenericCAO::addToScene(ITextureSource *tsrc) addAnimatedMeshSceneNode(mesh, m_matrixnode); m_animated_meshnode->grab(); mesh->drop(); // The scene node took hold of it + + if (!checkMeshNormals(mesh)) { + infostream << "GenericCAO: recalculating normals for mesh " + << m_prop.mesh << std::endl; + m_smgr->getMeshManipulator()-> + recalculateNormals(mesh, true, false); + } + m_animated_meshnode->animateJoints(); // Needed for some animations m_animated_meshnode->setScale(m_prop.visual_size); diff --git a/src/client/mesh.cpp b/src/client/mesh.cpp index 4d73ead8a..91781373c 100644 --- a/src/client/mesh.cpp +++ b/src/client/mesh.cpp @@ -328,6 +328,26 @@ void recalculateBoundingBox(scene::IMesh *src_mesh) src_mesh->setBoundingBox(bbox); } +bool checkMeshNormals(scene::IMesh *mesh) +{ + u32 buffer_count = mesh->getMeshBufferCount(); + + for (u32 i = 0; i < buffer_count; i++) { + scene::IMeshBuffer *buffer = mesh->getMeshBuffer(i); + + // Here we intentionally check only first normal, assuming that if buffer + // has it valid, then most likely all other ones are fine too. We can + // check all of the normals to have length, but it seems like an overkill + // hurting the performance and covering only really weird broken models. + f32 length = buffer->getNormal(0).getLength(); + + if (!isfinite(length) || fabs(length) < 1e-10) + return false; + } + + return true; +} + scene::IMeshBuffer* cloneMeshBuffer(scene::IMeshBuffer *mesh_buffer) { switch (mesh_buffer->getVertexType()) { diff --git a/src/client/mesh.h b/src/client/mesh.h index 0c4094de2..103c61e45 100644 --- a/src/client/mesh.h +++ b/src/client/mesh.h @@ -122,6 +122,12 @@ scene::IMesh* convertNodeboxesToMesh(const std::vector<aabb3f> &boxes, void recalculateBoundingBox(scene::IMesh *src_mesh); /* + Check if mesh has valid normals and return true if it does. + We assume normal to be valid when it's 0 < length < Inf. and not NaN + */ +bool checkMeshNormals(scene::IMesh *mesh); + +/* Vertex cache optimization according to the Forsyth paper: http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html Ported from irrlicht 1.8 |