Open jakezira opened 2 years ago
Related:
I think the issue remains that three.js implements skinning in world space, which means floating point precision is worse for positions much further from the origin. For now there is no workaround other than to avoid this scenario, e.g. by transforming the scene rather than the character.
Right. This is the same issue as #13288.
This is a three.js problem caused by skinning in world space.
The change to skinning in world space began in #4812:
Previously, we performed skinning in the local space of the SkinnedMesh. But now, since the objects/bones are not necessarily descendants, it is more natural to perform skinning in world space…
Hm. If we believe that skinning should be performed in a local space, then which local space? I'm not sure that the local space of the SkinnedMesh would be the right choice. It's a common use case to transform the root Bone instead of the SkinnedMesh when moving a character, and the Bones may not be descendants of the SkinnedMesh.
I wonder if we could allow the user to define an Object3D as the 'root' (possibly the SkinnedMesh, possibly not) such that skinning would be performed in the local space of that Object3D. We could require that all objects used as bones be descendants of that node, and consider it invalid if this requirement is broken. If no such root is identified, the root would implicitly continue to be the Scene, i.e. skinning in world space.
glTF files have a relevant hint, a skin.skeleton
node, that can optionally define a root of the joint hierarchy. I've always assumed that property was not relevant to three.js, but perhaps this is a good use case allowing us to guess the right local frame for a SkinnedMesh.
We really need a workaround ... moving scene instead of avatar doesn't make sense, especially when you're relying on physx etc. We need a consistence game space. Also other objects don't have this problem. It's the implementation limit of skinned mesh of bone chain. Better to provide a solution on skinned mesh.
@donmccurdy
I wonder if we could allow the user to define an Object3D as the 'root' (possibly the SkinnedMesh, possibly not) such that skinning would be performed in the local space of that Object3D. We could require that all objects used as bones be descendants of that node, and consider it invalid if this requirement is broken. If no such root is identified, the root would implicitly continue to be the Scene, i.e. skinning in world space.
This is what I was going to implement. :grin: Looking forward for this fix.
We really need a workaround ... moving scene instead of avatar doesn't make sense, especially when you're relying on physx etc. We need a consistence game space. Also other objects don't have this problem. It's the implementation limit of skinned mesh of bone chain. Better to provide a solution on skinned mesh.
It is not that uncommon to offset the world space for better floating point precision though. This will not be your only problem when you are trying to run floating point engines at high coordinates.
It is not that uncommon to offset the world space for better floating point precision though. This will not be your only problem when you are trying to run floating point engines at high coordinates.
We do at giro3d (because it's a geographic engine, dealing with coordinates in the millions sometimes). Yes there are other classes of problems, but so far they have been manageable without shifting the scene. Our use case is typically the same as @jakezira but worst. For instance, this is supposed to be the 3 Soldiers of https://threejs.org/examples/webgl_animation_multiple:
From what I understand the solution proposed by @jakezira should fix it for us as well.
Maybe a temporary solution can add an attribute vec3 globalPosition
after skinning_vertex
?
...
#include <skinning_vertex>
transformed += globalPosition;
...
I haven't tested it, but in my mint it should work...
It may be the joints rather than the mesh that have a large displacement. In the case of VRM or glTF I think it's more likely the joints; skinned mesh displacement should be ignored.
Environment
Code
Added
midObj
to set the offset.Test 1:
offset=0
==> CorrectTest 2:
offset=100000
==> Bad rendering