question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

GLTFLoader: Morph targets only work for matching accessor types

See original GitHub issue

glTF files assume that morph target data is specified as relative adjustments, and three.js assumes that the data in morph target buffers is absolute.

This leads to a few obvious memory/performance caveats - the morph target data needs to be duplicated and modified during import - but also leads to inability to use a very narrow type for position deltas.

For example, when data is quantized with gltfpack (which makes the glTF files technically invalid right now but this will change soon: https://github.com/KhronosGroup/glTF/pull/1673), the positions typically use UInt16 and morph target deltas use Int16. However, very frequently the morph target delta range is small enough to fit in Int8 - because three.js attempts to reconstruct the absolute position however, attempting to encode Int8 deltas leads to decoding issues on three.js side. Babylon.JS handles files like this perfectly.

I’d like to fix this - the obvious tactical fix is changing the morph target attribute cloning to assume the type of the base attribute, not morph target. However, I’d like to check - what are the thoughts of fixing this by adding support to three.js for relative morph target data?

In theory, the formulas are compatible to not require any shader code duplication - specifically, this equation that three.js currently uses:

basePosition
+ weight0 * ( morphPosition0 - basePosition )
+ weight1 * ( morphPosition1 - basePosition )

and this equation that glTF assumes:

basePosition
+ weight0 * glTFmorphPosition0
+ weight1 * glTFmorphPosition1

can be reformulated as:

weightBase * basePosition
+ weight0 * morphPosition0
+ weight1 * morphPosition1

After which for glTF style files the shader needs [1, weight0, weight1, ...] as an input, whereas normally you’d pass [1 - weight0 - weight1 - ..., weight0, weight1, ...] as an input. So by adding some sort of flag to three.js mesh (e.g. morphTargetsAreDeltas) and a bit of JS code to compute the weights correctly, we could support both with minimal cost.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:3
  • Comments:10 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
zeuxcommented, Sep 30, 2019

Just to give a basic idea, here’s how first-class relative morph target support may look like: https://github.com/mrdoob/three.js/compare/dev...zeux:morph-relative

1reaction
zeuxcommented, Sep 30, 2019

Note that the bug itself can be fixed without a relative mode — that would purely be to improve parsing performance of loaders with relative morph targets.

Yeah - definitely. This is why I mentioned the tactical fix as a possibility. However, with both GLTF and FBX storing deltas and having to reconstruct absolute positions at load time it seems like the core change may be more appropriate. This will also lead to being able to - eventually, conditional on something close to #17089 getting done at some point - directly load the buffer data for geometry buffers into large ArrayBuffers with no need for extra processing which is nice.

Read more comments on GitHub >

github_iconTop Results From Across the Web

glTF™ 2.0 Specification - Khronos Registry
Extensions MAY add additional attribute names, accessor types, and/or component types. 3.7.2.2. Morph Targets. Morph targets are defined by ...
Read more >
GltfMeshPrimitive.Targets Property - Microsoft Learn
An array of Morph Targets, each Morph Target is a dictionary mapping attributes (only "POSITION" and "NORMAL" supported) to their deviations in the...
Read more >
Morph Target Previewer | Unreal Engine 4.27 Documentation
The Search Bar filters the list of Morph Targets to quickly find the one you need. Type the first few letters of the...
Read more >
3ds Max - Morph Compound Object
You can morph one seed into multiple targets; the seed object's form changes successively to match the forms of the target objects as...
Read more >
Morph Targets with GLTF Gui - Questions - three.js forum
I created a GLTF model with 2 Morph Targets. One Sphere => which Morphs to suzanne and also to a Cone. I loaded...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found