1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-07-02 16:38:41 +00:00

Fix handling of skinned meshes for nodes

- Rigidly animated models (e.g. the gltf frog node) were not working correctly,
  since cloning the mesh ignored the transformation matrices.
  Note that scaling the mesh needs to occur *after* transforming the vertices.
- Visual scale did not apply to skinned models,
  as resetting the animation overwrote scaled vertex data with static positions & normals.
  For backwards compatibility, we only apply a 10x scale to static (.obj) models.
This commit is contained in:
Lars Mueller 2025-05-04 19:57:23 +02:00 committed by Lars Müller
parent 57c1ab905c
commit 612db5b2ca
6 changed files with 72 additions and 65 deletions

View file

@ -13,6 +13,7 @@
#include "client/texturesource.h"
#include "client/tile.h"
#include <IMeshManipulator.h>
#include <SMesh.h>
#include <SkinnedMesh.h>
#endif
#include "log.h"
@ -959,23 +960,28 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
palette = tsrc->getPalette(palette_name);
if (drawtype == NDT_MESH && !mesh.empty()) {
// Read the mesh and apply scale
mesh_ptr = client->getMesh(mesh);
if (mesh_ptr) {
v3f scale = v3f(BS) * visual_scale;
scaleMesh(mesh_ptr, scale);
// 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<scene::SMesh *>(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));
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;
}
}
}