Don't recalculate meshnode normals unnecessarily

This commit is contained in:
sfan5 2024-12-07 12:59:40 +01:00
parent eb6731bdc6
commit 21437090b8
4 changed files with 23 additions and 18 deletions

@ -1644,7 +1644,6 @@ void MapblockMeshGenerator::drawMeshNode()
{ {
u8 facedir = 0; u8 facedir = 0;
scene::IMesh* mesh; scene::IMesh* mesh;
bool private_mesh; // as a grab/drop pair is not thread-safe
int degrotate = 0; int degrotate = 0;
if (cur_node.f->param_type_2 == CPT2_FACEDIR || if (cur_node.f->param_type_2 == CPT2_FACEDIR ||
@ -1664,32 +1663,37 @@ void MapblockMeshGenerator::drawMeshNode()
if (cur_node.f->mesh_ptr) { if (cur_node.f->mesh_ptr) {
// clone and rotate mesh // clone and rotate mesh
private_mesh = true;
mesh = cloneMesh(cur_node.f->mesh_ptr); mesh = cloneMesh(cur_node.f->mesh_ptr);
bool modified = true;
if (facedir) if (facedir)
rotateMeshBy6dFacedir(mesh, facedir); rotateMeshBy6dFacedir(mesh, facedir);
else if (degrotate) else if (degrotate)
rotateMeshXZby(mesh, 1.5f * degrotate); rotateMeshXZby(mesh, 1.5f * degrotate);
recalculateBoundingBox(mesh); else
meshmanip->recalculateNormals(mesh, true, false); modified = false;
if (modified) {
recalculateBoundingBox(mesh);
// FIXME: we should rotate the normals too, instead of recalculating
meshmanip->recalculateNormals(mesh, true, false);
}
} else { } else {
warningstream << "drawMeshNode(): missing mesh" << std::endl; warningstream << "drawMeshNode(): missing mesh" << std::endl;
return; return;
} }
int mesh_buffer_count = mesh->getMeshBufferCount(); for (u32 j = 0; j < mesh->getMeshBufferCount(); j++) {
for (int j = 0; j < mesh_buffer_count; j++) {
// Only up to 6 tiles are supported // Only up to 6 tiles are supported
const auto tile = mesh->getTextureSlot(j); const u32 tile = mesh->getTextureSlot(j);
useTile(MYMIN(tile, 5)); useTile(MYMIN(tile, 5));
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j); scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
video::S3DVertex *vertices = (video::S3DVertex *)buf->getVertices(); video::S3DVertex *vertices = (video::S3DVertex *)buf->getVertices();
int vertex_count = buf->getVertexCount(); u32 vertex_count = buf->getVertexCount();
if (data->m_smooth_lighting) { if (data->m_smooth_lighting) {
// Mesh is always private here. So the lighting is applied to each // Mesh is always private here. So the lighting is applied to each
// vertex right here. // vertex right here.
for (int k = 0; k < vertex_count; k++) { for (u32 k = 0; k < vertex_count; k++) {
video::S3DVertex &vertex = vertices[k]; video::S3DVertex &vertex = vertices[k];
vertex.Color = blendLightColor(vertex.Pos, vertex.Normal); vertex.Color = blendLightColor(vertex.Pos, vertex.Normal);
vertex.Pos += cur_node.origin; vertex.Pos += cur_node.origin;
@ -1697,15 +1701,13 @@ void MapblockMeshGenerator::drawMeshNode()
collector->append(cur_node.tile, vertices, vertex_count, collector->append(cur_node.tile, vertices, vertex_count,
buf->getIndices(), buf->getIndexCount()); buf->getIndices(), buf->getIndexCount());
} else { } else {
// Don't modify the mesh, it may not be private here. // Let the collector process colors, etc.
// Instead, let the collector process colors, etc.
collector->append(cur_node.tile, vertices, vertex_count, collector->append(cur_node.tile, vertices, vertex_count,
buf->getIndices(), buf->getIndexCount(), cur_node.origin, buf->getIndices(), buf->getIndexCount(), cur_node.origin,
cur_node.color, cur_node.f->light_source); cur_node.color, cur_node.f->light_source);
} }
} }
if (private_mesh) mesh->drop();
mesh->drop();
} }
// also called when the drawtype is known but should have been pre-converted // also called when the drawtype is known but should have been pre-converted

@ -272,9 +272,9 @@ void rotateMeshYZby(scene::IMesh *mesh, f64 degrees)
rotateMesh<&v3f::Y, &v3f::Z>(mesh, degrees); rotateMesh<&v3f::Y, &v3f::Z>(mesh, degrees);
} }
void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir) void rotateMeshBy6dFacedir(scene::IMesh *mesh, u8 facedir)
{ {
int axisdir = facedir >> 2; u8 axisdir = facedir >> 2;
facedir &= 0x03; facedir &= 0x03;
switch (facedir) { switch (facedir) {
case 1: rotateMeshXZby(mesh, -90); break; case 1: rotateMeshXZby(mesh, -90); break;

@ -68,7 +68,7 @@ void setMeshColorByNormal(scene::IMesh *mesh, const v3f &normal,
Rotate the mesh by 6d facedir value. Rotate the mesh by 6d facedir value.
Method only for meshnodes, not suitable for entities. Method only for meshnodes, not suitable for entities.
*/ */
void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir); void rotateMeshBy6dFacedir(scene::IMesh *mesh, u8 facedir);
/* /*
Rotate the mesh around the axis and given angle in degrees. Rotate the mesh around the axis and given angle in degrees.

@ -943,14 +943,17 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
palette = tsrc->getPalette(palette_name); palette = tsrc->getPalette(palette_name);
if (drawtype == NDT_MESH && !mesh.empty()) { if (drawtype == NDT_MESH && !mesh.empty()) {
// Meshnode drawtype
// Read the mesh and apply scale // Read the mesh and apply scale
mesh_ptr = client->getMesh(mesh); mesh_ptr = client->getMesh(mesh);
if (mesh_ptr) { if (mesh_ptr) {
v3f scale = v3f(BS) * visual_scale; v3f scale = v3f(BS) * visual_scale;
scaleMesh(mesh_ptr, scale); scaleMesh(mesh_ptr, scale);
recalculateBoundingBox(mesh_ptr); recalculateBoundingBox(mesh_ptr);
meshmanip->recalculateNormals(mesh_ptr, true, false); if (!checkMeshNormals(mesh_ptr)) {
infostream << "ContentFeatures: recalculating normals for mesh "
<< mesh << std::endl;
meshmanip->recalculateNormals(mesh_ptr, true, false);
}
} }
} }
} }