Set rotation of gltf asset using degrees like in 3d software [Houdini]

Hi,

So I cannot figure it out… How should I set the rotation of gltf asset to have an exact rotation in my 3d software? I’ve been trying to use quaternions, flipping axes, converting to radians… And after few hours of testing I just can’t figure it out.

There’s also additional diffuculty, because babylon and the 3d software I use have different coordinate (one is left-handed the other right-handed). For the position it’s super easy:

root.position = new Vector3(
   -data.position[0], 
   data.position[1], 
   data.position[2],
)

This makes sure the positions are correct. But with rotations… I have no idea anymore.

So how can I set the rotations in babylon to exactly what I have in the 3d software? Assuming that:

x: data.rotation[0] // rotation of X in degrees
y: data.rotation[1] // rotation of Y in degrees
z: data.rotation[2] // rotation of Z in degrees

And in the 3d software the rotation order is Rx Ry Rz.

Hello :slight_smile:

Two things :

  • On your 3D software you must have an option when you export you GLTF asset, such as “Y up”. For example I use Blender, which is Z up. I check “Y up” at export, so that final export is Y up, just like BabylonJS is.
  • By default, the BabylonJS GLTF import sets the rotation to quaternion, which means mesh.rotation[0], or mesh.rotation.x which are euler angles, won’t work. To switch back to euler, you can do this in your GLTF import callback :
meshes.forEach((mesh)=>{
    if(mesh.rotationQuaternion){
        const rotation = mesh.rotationQuaternion.toEulerAngles();
        mesh.rotationQuaternion = null;
        mesh.rotation = rotation;
    }
})

I’m using Houdini, and it’s GLTF exporter for some reason is quite bad, it doesn’t even have nice options like in Blender. Anyways this Y axis should be easily flipped in Babylon as well, right?

So I also tried to use rotations like that:

                root.rotationQuaternion = null
                root.rotationQuaternion = Quaternion.FromEulerAngles(
                    data.rotation[0],
                    data.rotation[1],
                    data.rotation[2],
                )

But this is nothing close to what I have in Houdini. I’m quite lost…

Another Houdini user :heart_eyes:


Yeah, Houdini is Y up so you should not have any problem on that side


Would you mind sharing a reproduction ? Like a .hip + your exported .gltf ? :slight_smile:

Ok, I fixed it! But not on Babylon side, but in Houdini. My scene is too complex to share, it’s using custom HDAs, external assets, so it won’t work on your side.

So what I did…

Before I used each asset rotation (x, y, z) - that all was exported to JSON, from that I can instantiate containters to proper place, rotation, scale.

Instead doing that I just converted the rotation to quaternion in a wrangle:

vector rot = v@rotation;
vector4 q = eulertoquaternion(radians(rot), XFORM_XYZ);
p@orient = q;

So once I have that, on Babylon side I have to invert the incomming values:

root.rotationQuaternion = new Quaternion(
   -data.orient[0],
   data.orient[1],
   data.orient[2],
   -data.orient[3],
)

Now it even matches the rotation conversion I use when sending/receiving data to the Go server (which by default is using whatever the rotation and position I use in Houdini).

Phew… I can’t believe I’ve spend so many hours on this…