diff --git a/src/client/content_mapblock.cpp b/src/client/content_mapblock.cpp index 3edba95e3..f5b528287 100644 --- a/src/client/content_mapblock.cpp +++ b/src/client/content_mapblock.cpp @@ -1676,7 +1676,7 @@ void MapblockMeshGenerator::drawMeshNode() if (cur_node.f->mesh_ptr) { // clone and rotate mesh - mesh = cloneStaticMesh(cur_node.f->mesh_ptr); + mesh = cloneMesh(cur_node.f->mesh_ptr); bool modified = true; if (facedir) rotateMeshBy6dFacedir(mesh, facedir); diff --git a/src/client/mesh.cpp b/src/client/mesh.cpp index 808dcdd18..a2c0ae327 100644 --- a/src/client/mesh.cpp +++ b/src/client/mesh.cpp @@ -3,8 +3,6 @@ // Copyright (C) 2010-2013 celeron55, Perttu Ahola #include "mesh.h" -#include "IMeshBuffer.h" -#include "SSkinMeshBuffer.h" #include "debug.h" #include "log.h" #include @@ -104,21 +102,6 @@ scene::IAnimatedMesh* createCubeMesh(v3f scale) return anim_mesh; } -template -inline static void transformMeshBuffer(scene::IMeshBuffer *buf, - const F &transform_vertex) -{ - const u32 stride = getVertexPitchFromType(buf->getVertexType()); - u32 vertex_count = buf->getVertexCount(); - u8 *vertices = (u8 *)buf->getVertices(); - for (u32 i = 0; i < vertex_count; i++) { - auto *vertex = (video::S3DVertex *)(vertices + i * stride); - transform_vertex(vertex); - } - buf->setDirty(scene::EBT_VERTEX); - buf->recalculateBoundingBox(); -} - void scaleMesh(scene::IMesh *mesh, v3f scale) { if (mesh == NULL) @@ -129,9 +112,14 @@ void scaleMesh(scene::IMesh *mesh, v3f scale) u32 mc = mesh->getMeshBufferCount(); for (u32 j = 0; j < mc; j++) { scene::IMeshBuffer *buf = mesh->getMeshBuffer(j); - transformMeshBuffer(buf, [scale](video::S3DVertex *vertex) { - vertex->Pos *= scale; - }); + const u32 stride = getVertexPitchFromType(buf->getVertexType()); + u32 vertex_count = buf->getVertexCount(); + u8 *vertices = (u8 *)buf->getVertices(); + for (u32 i = 0; i < vertex_count; i++) + ((video::S3DVertex *)(vertices + i * stride))->Pos *= scale; + + buf->setDirty(scene::EBT_VERTEX); + buf->recalculateBoundingBox(); // calculate total bounding box if (j == 0) @@ -152,9 +140,14 @@ void translateMesh(scene::IMesh *mesh, v3f vec) u32 mc = mesh->getMeshBufferCount(); for (u32 j = 0; j < mc; j++) { scene::IMeshBuffer *buf = mesh->getMeshBuffer(j); - transformMeshBuffer(buf, [vec](video::S3DVertex *vertex) { - vertex->Pos += vec; - }); + const u32 stride = getVertexPitchFromType(buf->getVertexType()); + u32 vertex_count = buf->getVertexCount(); + u8 *vertices = (u8 *)buf->getVertices(); + for (u32 i = 0; i < vertex_count; i++) + ((video::S3DVertex *)(vertices + i * stride))->Pos += vec; + + buf->setDirty(scene::EBT_VERTEX); + buf->recalculateBoundingBox(); // calculate total bounding box if (j == 0) @@ -337,40 +330,44 @@ bool checkMeshNormals(scene::IMesh *mesh) return true; } -template -static scene::IMeshBuffer *cloneMeshBuffer(scene::IMeshBuffer *mesh_buffer) -{ - auto *v = static_cast(mesh_buffer->getVertices()); - u16 *indices = mesh_buffer->getIndices(); - auto *cloned_buffer = new SMeshBufferType(); - cloned_buffer->append(v, mesh_buffer->getVertexCount(), indices, - mesh_buffer->getIndexCount()); - // Rigidly animated meshes may have transformation matrices that need to be applied - if (auto *sbuf = dynamic_cast(mesh_buffer)) { - transformMeshBuffer(cloned_buffer, [sbuf](video::S3DVertex *vertex) { - sbuf->Transformation.transformVect(vertex->Pos); - vertex->Normal = sbuf->Transformation.rotateAndScaleVect(vertex->Normal); - vertex->Normal.normalize(); - }); - } - return cloned_buffer; -} - scene::IMeshBuffer* cloneMeshBuffer(scene::IMeshBuffer *mesh_buffer) { switch (mesh_buffer->getVertexType()) { - case video::EVT_STANDARD: - return cloneMeshBuffer(mesh_buffer); - case video::EVT_2TCOORDS: - return cloneMeshBuffer(mesh_buffer); - case video::EVT_TANGENTS: - return cloneMeshBuffer(mesh_buffer); + case video::EVT_STANDARD: { + video::S3DVertex *v = (video::S3DVertex *) mesh_buffer->getVertices(); + u16 *indices = mesh_buffer->getIndices(); + scene::SMeshBuffer *cloned_buffer = new scene::SMeshBuffer(); + cloned_buffer->append(v, mesh_buffer->getVertexCount(), indices, + mesh_buffer->getIndexCount()); + return cloned_buffer; } + case video::EVT_2TCOORDS: { + video::S3DVertex2TCoords *v = + (video::S3DVertex2TCoords *) mesh_buffer->getVertices(); + u16 *indices = mesh_buffer->getIndices(); + scene::SMeshBufferLightMap *cloned_buffer = + new scene::SMeshBufferLightMap(); + cloned_buffer->append(v, mesh_buffer->getVertexCount(), indices, + mesh_buffer->getIndexCount()); + return cloned_buffer; + } + case video::EVT_TANGENTS: { + video::S3DVertexTangents *v = + (video::S3DVertexTangents *) mesh_buffer->getVertices(); + u16 *indices = mesh_buffer->getIndices(); + scene::SMeshBufferTangents *cloned_buffer = + new scene::SMeshBufferTangents(); + cloned_buffer->append(v, mesh_buffer->getVertexCount(), indices, + mesh_buffer->getIndexCount()); + return cloned_buffer; + } + } + // This should not happen. sanity_check(false); return NULL; } -scene::SMesh* cloneStaticMesh(scene::IMesh *src_mesh) +scene::SMesh* cloneMesh(scene::IMesh *src_mesh) { scene::SMesh* dst_mesh = new scene::SMesh(); for (u16 j = 0; j < src_mesh->getMeshBufferCount(); j++) { diff --git a/src/client/mesh.h b/src/client/mesh.h index 53c54fc51..d8eb6080e 100644 --- a/src/client/mesh.h +++ b/src/client/mesh.h @@ -93,8 +93,10 @@ void rotateMeshYZby (scene::IMesh *mesh, f64 degrees); */ scene::IMeshBuffer* cloneMeshBuffer(scene::IMeshBuffer *mesh_buffer); -/// Clone a mesh. For an animated mesh, this will clone the static pose. -scene::SMesh* cloneStaticMesh(scene::IMesh *src_mesh); +/* + Clone the mesh. +*/ +scene::SMesh* cloneMesh(scene::IMesh *src_mesh); /* Convert nodeboxes to mesh. Each tile goes into a different buffer. diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index bdd24a727..baa72f1d9 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -255,7 +255,7 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename, dim = core::dimension2d(dim.Width, frame_height); } scene::IMesh *original = g_extrusion_mesh_cache->create(dim); - scene::SMesh *mesh = cloneStaticMesh(original); + scene::SMesh *mesh = cloneMesh(original); original->drop(); //set texture mesh->getMeshBuffer(0)->getMaterial().setTexture(0, @@ -639,7 +639,7 @@ scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, // get mesh core::dimension2d dim = texture->getSize(); scene::IMesh *original = g_extrusion_mesh_cache->create(dim); - scene::SMesh *mesh = cloneStaticMesh(original); + scene::SMesh *mesh = cloneMesh(original); original->drop(); //set texture diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 2339423e9..d4dc16a61 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -13,7 +13,6 @@ #include "client/texturesource.h" #include "client/tile.h" #include -#include #include #endif #include "log.h" @@ -960,28 +959,23 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc palette = tsrc->getPalette(palette_name); if (drawtype == NDT_MESH && !mesh.empty()) { - // Note: By freshly reading, we get an unencumbered mesh. - if (scene::IMesh *src_mesh = client->getMesh(mesh)) { - f32 mesh_scale = 1.0f; - if (auto *static_mesh = dynamic_cast(src_mesh)) { - mesh_ptr = static_mesh; - // Compatibility: Only apply BS scaling to static meshes (.obj). See #15811. - mesh_scale = 10.0f; - } else { - // We only want to consider static meshes from here on. - mesh_ptr = cloneStaticMesh(src_mesh); - src_mesh->drop(); - } - scaleMesh(mesh_ptr, v3f(mesh_scale * visual_scale)); + // Read the mesh and apply scale + mesh_ptr = client->getMesh(mesh); + if (mesh_ptr) { + v3f scale = v3f(BS) * visual_scale; + scaleMesh(mesh_ptr, scale); recalculateBoundingBox(mesh_ptr); if (!checkMeshNormals(mesh_ptr)) { - // TODO this should be done consistently when the mesh is loaded infostream << "ContentFeatures: recalculating normals for mesh " << mesh << std::endl; meshmanip->recalculateNormals(mesh_ptr, true, false); + } else { + // Animation is not supported, but we need to reset it to + // default state if it is animated. + // Note: recalculateNormals() also does this hence the else-block + if (mesh_ptr->getMeshType() == scene::EAMT_SKINNED) + ((scene::SkinnedMesh*) mesh_ptr)->resetAnimation(); } - } else { - mesh_ptr = nullptr; } } } diff --git a/src/nodedef.h b/src/nodedef.h index 967e3fcd4..71a61896b 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -342,7 +342,7 @@ struct ContentFeatures enum NodeDrawType drawtype; std::string mesh; #if CHECK_CLIENT_BUILD() - scene::SMesh *mesh_ptr; // mesh in case of mesh node + scene::IMesh *mesh_ptr; // mesh in case of mesh node video::SColor minimap_color; #endif float visual_scale; // Misc. scale parameter