1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Fix handling of skinned meshes for nodes

Second try after the revert in 8a28339 due to an unexpected regression.

- 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 now apply a 10x scale to static, non-glTF models.

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.

See also: #16141
This commit is contained in:
Lars Müller 2025-05-20 18:37:33 +02:00 committed by GitHub
parent 30e33d71cc
commit 7ac5502fdf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 118 additions and 75 deletions

View file

@ -26,12 +26,21 @@ class ISceneManager;
class SkinnedMesh : public IAnimatedMesh
{
public:
enum class SourceFormat {
B3D,
X,
GLTF,
OTHER,
};
//! constructor
SkinnedMesh() :
SkinnedMesh(SourceFormat src_format) :
EndFrame(0.f), FramesPerSecond(25.f),
LastAnimatedFrame(-1), SkinnedLastFrame(false),
HasAnimation(false), PreparedForSkinning(false),
AnimateNormals(true), HardwareSkinning(false)
AnimateNormals(true), HardwareSkinning(false),
SrcFormat(src_format)
{
SkinningBuffers = &LocalBuffers;
}
@ -39,6 +48,10 @@ public:
//! destructor
virtual ~SkinnedMesh();
//! The source (file) format the mesh was loaded from.
//! Important for legacy reasons pertaining to different mesh loader behavior.
SourceFormat getSourceFormat() const { return SrcFormat; }
//! If the duration is 0, it is a static (=non animated) mesh.
f32 getMaxFrameNumber() const override;
@ -382,12 +395,14 @@ protected:
bool PreparedForSkinning;
bool AnimateNormals;
bool HardwareSkinning;
SourceFormat SrcFormat;
};
// Interface for mesh loaders
class SkinnedMeshBuilder : public SkinnedMesh {
public:
SkinnedMeshBuilder() : SkinnedMesh() {}
SkinnedMeshBuilder(SourceFormat src_format) : SkinnedMesh(src_format) {}
//! loaders should call this after populating the mesh
// returns *this, so do not try to drop the mesh builder instance

View file

@ -48,7 +48,7 @@ IAnimatedMesh *CB3DMeshFileLoader::createMesh(io::IReadFile *file)
return 0;
B3DFile = file;
AnimatedMesh = new scene::SkinnedMeshBuilder();
AnimatedMesh = new scene::SkinnedMeshBuilder(SkinnedMesh::SourceFormat::B3D);
ShowWarning = true; // If true a warning is issued if too many textures are used
VerticesStart = 0;

View file

@ -347,7 +347,8 @@ 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(
SkinnedMesh::SourceFormat::GLTF));
MeshExtractor extractor(std::move(model), mesh.get());
try {
extractor.load();

View file

@ -762,7 +762,7 @@ ISceneManager *CSceneManager::createNewSceneManager(bool cloneContent)
//! Get a skinned mesh, which is not available as header-only code
SkinnedMesh *CSceneManager::createSkinnedMesh()
{
return new SkinnedMesh();
return new SkinnedMesh(SkinnedMesh::SourceFormat::OTHER);
}
// creates a scenemanager

View file

@ -54,7 +54,7 @@ IAnimatedMesh *CXMeshFileLoader::createMesh(io::IReadFile *file)
u32 time = os::Timer::getRealTime();
#endif
AnimatedMesh = new SkinnedMeshBuilder();
AnimatedMesh = new SkinnedMeshBuilder(SkinnedMesh::SourceFormat::X);
SkinnedMesh *res = nullptr;
if (load(file)) {