Topic category: Help with Minecraft modding (Java Edition)
Hello everyone,
I'm currently working with GeckoLib and I've encountered an issue while trying to retrieve the global coordinates of a bone in a 3D model. Specifically, I'm trying to find the coordinates of a bone relative to the model's root, taking into account its local transformations such as translation, rotation, and scaling.
Here is a general breakdown of what I'm trying to achieve:
- I want to get the position of a bone in global coordinates, which involves combining the bone's local transformations (pivot, rotation, etc.) with its parent's transformations, all the way up the bone hierarchy.
- I'm using GeckoLib's
GeoBone
class, and I am currently applying thegetPivotX()
,getPivotY()
, andgetPivotZ()
methods to retrieve translation values, along with rotation methods for local transforms. - After applying the local transformations to a
Matrix4f
object, I'm multiplying them by the parent's transforms recursively.
Despite this approach, the results aren't as expected — the bone's global position doesn't seem correct in some cases, and I believe I may be overlooking something.
import org.joml.Matrix4f;
import org.joml.Vector3f;
private Vec3 getBoneWorldPosition(CoreGeoBone bone) {
// Initialize the transformation matrix
Matrix4f transform = new Matrix4f().identity();
// Traverse up the bone hierarchy
CoreGeoBone currentBone = bone;
while (currentBone != null) {
Matrix4f localTransform = new Matrix4f().identity();
// Apply local transformations (translation, rotation)
localTransform.translate(currentBone.getPivotX(), currentBone.getPivotY(), currentBone.getPivotZ());
localTransform.rotateX((float) Math.toRadians(currentBone.getRotX()));
localTransform.rotateY((float) Math.toRadians(currentBone.getRotY()));
localTransform.rotateZ((float) Math.toRadians(currentBone.getRotZ()));
// Apply the local transform to the accumulated global transform
transform.mulLocal(localTransform);
// Move to the parent bone
currentBone = currentBone.getParent();
}
// Extract the global position from the final transformation matrix
Vector3f worldPosition = transform.getTranslation(new Vector3f());
return new Vec3(worldPosition.x(), worldPosition.y(), worldPosition.z());
}
Vec3 localPos = getBoneWorldPosition(bone);
Vec3 globalPosition = new Vec3(
animatable.getX() + localPos.x,
animatable.getY() + localPos.y,
animatable.getZ() + localPos.z
);
However, the results are not always accurate(the numbers are too big), especially when dealing with complex bone hierarchies or non-zero rotations. I’m wondering if there’s a better approach or a common pitfall I might be missing.
I also tried another approach but it didn't help either:
private Vec3 getBoneGlobalPosition(CoreGeoBone bone) {
Vec3 localPosition = new Vec3(bone.getPivotX(), bone.getPivotY(), bone.getPivotZ());
CoreGeoBone parentBone = bone.getParent();
// We go through the parents, adding their positions
while (parentBone != null) {
Vec3 parentPosition = new Vec3(parentBone.getPivotX(), parentBone.getPivotY(), parentBone.getPivotZ());
localPosition = localPosition.add(parentPosition);
parentBone = parentBone.getParent(); // Go to the parent bone
}
// Return global position
return localPosition;
}
Has anyone here worked with GeckoLib and dealt with similar issues? Any suggestions or insights on how to correctly calculate the bone’s global position in world space would be greatly appreciated!
Thank you in advance!