Rotation to Basic 0-360 pitch, roll, yaw

Maybe this will garner a better chance of a response.

How can I transform/convert the rotation to basic XYZ 0-360 degrees to match DCC I’m using like Blender and Terragen?

The formulas I have found don’t seem to work, and the angles are all wrong. I’ve been wracking my head on this since yesterday and have tried various methods of conversion but I don’t get the right result.

Here are a couple current attempts:

This one is close, but still wrong. Off by a factor of 90 degrees on Y, and X and Z seem just wrong, or incomprhensible to me when rotations applied other than 0

	cameraRotation = ( Math.round( THREE.Math.radToDeg( camera.rotation.x ) % 360 ) ) + ' ' + ( Math.round( THREE.Math.radToDeg( camera.rotation.y ) ) % 360 ) 
		+ ' ' + ( Math.round( THREE.Math.radToDeg( camera.rotation.z ) % 360 ) );

	cameraRotation = ( Math.round( camera.rotation.x * ( 180 / Math.PI ) ) ) + ' ' 
		+ ( Math.round( camera.rotation.y * ( 180 / Math.PI ) ) ) + ' ' 
		+ ( Math.round( camera.rotation.z * ( 180 / Math.PI ) ) );

None of this code is wrong, but “basic XYZ 0-360º to match DCC” is an ambiguous definition of an Euler rotation. I think you might be missing the consideration of the order? These are quite different transformations around the same axes:

var a = new Euler( 1, 1.57, 0, 'XYZ' );
var b = new Euler( 1, 1.57, 0, 'ZYX' );

Applying the .reorder method before you serialize your rotational transformation might help to match whatever convention you need for these DCC tools.


Order is set accordingly in the FBX “XYZ”, additionally, +Y is up and +Z is forward, matching the coordinate system of Terragen I am exporting to.

Additionally, the Euler in THREE.js confirms, set to to XYZ.

The first formula yields almost correect results, but the cameras aren’t facing center, but off by 90 degrees. If I add 90 degrees to Y, they all face the same direction (looking at 0,5,0 XYZ where Y is up). So I thought i had it figured out. But if I apply tilts to X/Y for each camera to look at the ground instead of each other, everything is wonky again except Y.

Here is an example rotation in THREE.js from a camera:

rotation: Object { _x: 4.891332953957229e-22, _y: -1.5707961325075248, _z: 0, … }
_onChangeCallback: function onRotationChange()
_order: "XYZ"
_x: 4.891332953957229e-22
_y: -1.5707961325075248
_z: 0

I even just tried setting it from quaternion before doing the conversion, in correct order for the same results

	const rot = new THREE.Euler( );				
	rot.setFromQuaternion( camera.quaternion.normalize(), 'XYZ' );

The coordinate system I am targetting in Terragen is specifically:

  • +X is Right
  • +Y is Up
  • +Z is Forward

The camera coordinates of X and Z just seem weird and wrong. Take a look at the source (blender dark theme) and Terragen (light theme)

This is with applying 90d to Y so they Y axis is correct.

Source (Blender)

Import (Terragen)

I thought maybe X and Z maybe swapped, so I swapped them, and that didn’t work either, it just literally swapped the cameras bad results

Ok. So I got the correct orientation, while again, having to add +90d to the UP axis, which is now X, I think.

	cameraRotation = ( Math.round( THREE.Math.radToDeg( camera.rotation.z ) % 360 ) ) + ' ' + ( Math.round( THREE.Math.radToDeg( camera.rotation.y ) ) + 90 % 360 ) 
		+ ' ' + ( Math.round( THREE.Math.radToDeg( camera.rotation.x ) % 360 ) );

This yields the correct result! But… why? Blender uses XYZ Euler and Terragen uses XYZ Euler just +Y UP and +Z Forward being the difference, but this is set in the FBX. So why is the order Three.js uses XYZ wrong?

What does this mean for people choosing any other Euler order and detecting this problem?

Possibly a difference in the default (0º 0º 0º) orientation of a camera? In both Blender and three.js a camera looks down its local -Z axis by default, but that’s “down” in Blender and not in three.js.

I gues when it comes to any other coordinate systems (from like Autodesk stuff, or what not) I probably should just expose the Euler Order as a global option, as well as a Rotation Offset vector for XYZ. I’ll default to Blender behaviour as I perceive that’s what most people will be using, but want to be sure the problelm can be corrected.