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!
Hi everyone,
After spending some time working with GeckoLib and trying to calculate the global coordinates of a bone, I found a simpler and more efficient solution. Initially, I was attempting to manually apply local transformations and recursively multiply them with parent bone transformations. However, I encountered issues with accuracy, especially when dealing with complex bone hierarchies and rotations.
Instead of manually combining the transformations, I realized that GeckoLib provides a more straightforward approach by using the
GeoBone
class'sgetWorldPosition()
method. This method automatically calculates the global position of a bone, taking into account all local transformations and its parent's transformations.Here’s the simplified solution:
In this code:
getWorldPosition()
method returns the bone’s global position as aVector3d
.Vector3d
toVec3
(which is a custom class for your project, based on the context) for further use.This approach directly gives you the correct global position without having to manually combine transformations, and it resolves issues like large or inaccurate values when using complex bone hierarchies.
I hope this helps others who are facing similar challenges with GeckoLib!