Thanks for the report, it does indeed look to be broken (the implementation tries to reference Z
which is actually a closure variable only available in script nodes - it’s possible this wasn’t the case when the code was written and no one has noticed before, our set of regression tests don’t exercise this function).
The simplest approach is just to avoid Z.Mat.anglesFromRotationMatrix()
and just include the function locally instead:
function anglesFromRotationMatrix(mat, compare?) {
if (!compare) { compare = [0,0,0]; };
var x1 = 0;
var y1 = 0;
var z1 = 0;
var x2 = 0;
var y2 = 0;
var z2 = 0;
var m00 = mat[0];
var m01 = mat[1];
var m02 = mat[2];
var m12 = mat[5];
var m22 = mat[8];
var m10 = mat[3];
var m20 = mat[6];
if (Math.abs(m02) < 0.99999 ) {
y1 = Math.asin(m02);
y2 = Math.PI - y1;
x1 = Math.atan2( -m12 / Math.cos(y1), m22 / Math.cos(y1) );
x2 = Math.atan2( -m12 / Math.cos(y2), m22 / Math.cos(y2) );
z1 = Math.atan2( -m01 / Math.cos(y1), m00 / Math.cos(y1) );
z2 = Math.atan2( -m01 / Math.cos(y2), m00 / Math.cos(y2) );
} else if (m02<0) {
// m10 = cx * sz - sx * cz = sin(z - x);
// m20 = sx * sz + cx * cz = cos(z - x);
y1 = y2 = -Math.PI / 2;
x1 = x2 = compare[0];
z1 = z2 = x1 + Math.atan2(m10, m20);
} else {
// m10 = cx * sz + sx * cz = sin(x + z);
// m20 = sx * sz - cx * cz = -cos(x + z);
y1 = y2 = Math.PI / 2;
x1 = x2 = compare[0];
z1 = z2 = Math.atan2(m10, -m20) - x1;
}
var v1 = [x1, y1, z1];
var v2 = [x2, y2, z2];
v1[0] += (2 * Math.PI) * Math.round((compare[0] - v1[0]) / (2 * Math.PI));
v1[1] += (2 * Math.PI) * Math.round((compare[1] - v1[1]) / (2 * Math.PI));
v1[2] += (2 * Math.PI) * Math.round((compare[2] - v1[2]) / (2 * Math.PI));
v2[0] += (2 * Math.PI) * Math.round((compare[0] - v2[0]) / (2 * Math.PI));
v2[1] += (2 * Math.PI) * Math.round((compare[1] - v2[1]) / (2 * Math.PI));
v2[2] += (2 * Math.PI) * Math.round((compare[2] - v2[2]) / (2 * Math.PI));
var distV1 = Z.Vec3.magnitude( Z.Vec3.subtract(v1, compare) );
var distV2 = Z.Vec3.magnitude( Z.Vec3.subtract(v2, compare) );
if (distV1 > distV2) {
return v2;
}
return v1;
}
I think the idea of “compare” is you can pass in the current rotation angles and it should give you the minimum rotation, so if you’re already at [0, 0, 350] and the result needs to be [0, 0, 10] it will give you [0, 0, 370] instead.
Leaving this here for anyone who needs to do a “look at” within a scene. For Instant Tracking / World Tracking placement though there is an easier way - will reply to the other thread on that.