Recalculate mesh normals for CAOs (#10000)

This commit is contained in:
Danila Shutov 2020-06-07 19:14:00 +03:00 committed by GitHub
parent 8fc9e7eb11
commit fe1f72ab0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 0 deletions

@ -726,6 +726,14 @@ void GenericCAO::addToScene(ITextureSource *tsrc)
addAnimatedMeshSceneNode(mesh, m_matrixnode); addAnimatedMeshSceneNode(mesh, m_matrixnode);
m_animated_meshnode->grab(); m_animated_meshnode->grab();
mesh->drop(); // The scene node took hold of it 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->animateJoints(); // Needed for some animations
m_animated_meshnode->setScale(m_prop.visual_size); m_animated_meshnode->setScale(m_prop.visual_size);

@ -328,6 +328,26 @@ void recalculateBoundingBox(scene::IMesh *src_mesh)
src_mesh->setBoundingBox(bbox); 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) scene::IMeshBuffer* cloneMeshBuffer(scene::IMeshBuffer *mesh_buffer)
{ {
switch (mesh_buffer->getVertexType()) { switch (mesh_buffer->getVertexType()) {

@ -121,6 +121,12 @@ scene::IMesh* convertNodeboxesToMesh(const std::vector<aabb3f> &boxes,
*/ */
void recalculateBoundingBox(scene::IMesh *src_mesh); 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: Vertex cache optimization according to the Forsyth paper:
http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html