1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-07-22 17:18:39 +00:00

Refine node mesh scaling logic

We now do scale static meshes, as the bug that caused meshes not to be scaled was limited to skeletally animated meshes,
hence we ought not to reproduce it for skinned meshes that do not take advantage of skeletal animations (e.g. current MTG doors).

However, gltf models (e.g. Wuzzy's eyeballs) up until recently were always affected due to technical reasons
(using skeletal animation for rigid animation).

Thus, to preserve behavior, we:

1. Do not apply 10x scale to glTF models.
2. Apply 10x scale to obj models.
3. Apply 10x scale to static x or b3d models, but not to animated ones.
This commit is contained in:
Lars Mueller 2025-05-15 02:53:33 +02:00
parent 511c637c2a
commit 740223d30c
4 changed files with 33 additions and 12 deletions

View file

@ -10172,9 +10172,12 @@ Used by `core.register_node`.
mesh = "",
-- File name of mesh when using "mesh" drawtype
-- The center of the node is the model origin.
-- For legacy reasons, models in OBJ format use a scale of 1 node = 1 unit;
-- all other model file formats use a scale of 1 node = 10 units,
-- consistent with the scale used for entities.
-- For legacy reasons, this uses a different scale depending on the mesh:
-- 1. For glTF models: 10 units = 1 node (consistent with the scale for entities).
-- 2. For obj models: 1 unit = 1 node.
-- 3. For b3d and x models: 1 unit = 1 node if static, otherwise 10 units = 1 node.
-- Using static glTF or obj models is recommended.
-- You can use the `visual_scale` multiplier to achieve the expected scale.
selection_box = {
-- see [Node boxes] for possibilities

View file

@ -339,6 +339,10 @@ public:
return AllJoints;
}
//! Whether the mesh originated from a glTF file.
//! This is important for legacy reasons.
bool isGltf() const { return IsGltf; }
protected:
void checkForAnimation();
@ -382,12 +386,14 @@ protected:
bool PreparedForSkinning;
bool AnimateNormals;
bool HardwareSkinning;
bool IsGltf = false;
};
// Interface for mesh loaders
class SkinnedMeshBuilder : public SkinnedMesh {
public:
SkinnedMeshBuilder() : SkinnedMesh() {}
SkinnedMeshBuilder(bool is_gltf = false) : SkinnedMesh() { IsGltf = is_gltf; }
//! loaders should call this after populating the mesh
// returns *this, so do not try to drop the mesh builder instance

View file

@ -347,7 +347,7 @@ IAnimatedMesh* SelfType::createMesh(io::IReadFile* file)
const char *filename = file->getFileName().c_str();
try {
tiniergltf::GlTF model = parseGLTF(file);
irr_ptr<SkinnedMeshBuilder> mesh(new SkinnedMeshBuilder());
irr_ptr<SkinnedMeshBuilder> mesh(new SkinnedMeshBuilder(true));
MeshExtractor extractor(std::move(model), mesh.get());
try {
extractor.load();

View file

@ -4,6 +4,7 @@
#include "nodedef.h"
#include "SAnimatedMesh.h"
#include "itemdef.h"
#if CHECK_CLIENT_BUILD()
#include "client/mesh.h"
@ -962,17 +963,28 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
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<scene::SMesh *>(src_mesh)) {
mesh_ptr = static_mesh;
// Compatibility: Only apply BS scaling to static meshes (.obj). See #15811.
mesh_scale = 10.0f;
} else {
bool apply_bs = false;
// Unpack the possible matrjoshka of frame-animated meshes
while (auto *src_meshes = dynamic_cast<scene::SAnimatedMesh *>(src_mesh)) {
src_mesh = src_meshes->getMesh(0);
src_mesh->grab();
src_meshes->drop();
}
if (auto *skinned_mesh = dynamic_cast<scene::SkinnedMesh *>(src_mesh)) {
// Compatibility: Animated meshes, as well as static gltf meshes, are not scaled by BS.
// See https://github.com/luanti-org/luanti/pull/16112#issuecomment-2881860329
apply_bs = skinned_mesh->isStatic() && !skinned_mesh->isGltf();
// We only want to consider static meshes from here on.
mesh_ptr = cloneStaticMesh(src_mesh);
src_mesh->drop();
} else {
auto *static_mesh = dynamic_cast<scene::SMesh *>(src_mesh);
assert(static_mesh);
mesh_ptr = static_mesh;
// Compatibility: Apply BS scaling to static meshes (.obj). See #15811.
apply_bs = true;
}
scaleMesh(mesh_ptr, v3f(mesh_scale * visual_scale));
scaleMesh(mesh_ptr, v3f((apply_bs ? BS : 1.0f) * visual_scale));
recalculateBoundingBox(mesh_ptr);
if (!checkMeshNormals(mesh_ptr)) {
// TODO this should be done consistently when the mesh is loaded