I have a node hierarchy, and I need to make some nodes inside it billboards.
Every time I update the hierarchy, I get the local translation and rotation of each node. I then use it to get the world matrix and world rotation of this node.
The rotation is stored as a quaternion, and it gets multiplied by the parent's rotation if a parent exists.
After this, the billboarding part begins.
What I tried is getting the difference between the camera's quaternion and the world rotation of the current node, and then simply adding that to the node via a rotation matrix.
This sounds like it should work to me, but it didn't.
No matter what other variations I tried, I simply can't get this to work.
Can you spot some errors of any sort in my code? (or is this calculation not even right in the first place?)
Thanks!
// The posotion of the node
var pivot = node.pivot;
// Local translation and rotation
var translation = this.localTranslation(node, time);
var rotation = this.localRotation(node, time);
var rotationMatrix = [];
var localMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
math.Quaternion.toRotationMatrix4(rotation, rotationMatrix);
// Create this node's local transformation matrix
math.Mat4.translate(localMatrix, translation[0], translation[1], translation[2]);
math.Mat4.translate(localMatrix, pivot[0], pivot[1], pivot[2]);
math.Mat4.multMat(localMatrix, rotationMatrix, localMatrix);
math.Mat4.translate(localMatrix, -pivot[0], -pivot[1], -pivot[2]);
// World matrix + accumulated rotation
if (node.parent) {
math.Mat4.multMat(node.parent.worldMatrix, localMatrix, node.worldMatrix);
math.Quaternion.concat(rotation, node.parent.worldRotation, node.worldRotation);
} else {
node.worldMatrix = localMatrix;
node.worldRotation = Object.copy(rotation);
}
if (node.billboarded) {
// This is the camera's quaternion
var cam = Object.copy(camera.rotate);
// And the node's quaternion
var initial = Object.copy(node.worldRotation);
// Negate it because I want the difference which is Camera * Node^-1
math.Quaternion.conjugate(initial, initial);
var difference = [];
// The difference
math.Quaternion.concat(cam, initial, difference);
var rotationMatrix2 = [];
// Get a rotation matrix from the difference
math.Quaternion.toRotationMatrix4(difference, rotationMatrix2);
var finalMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
// Finally calculate final matrix that rotates in the same vector space
math.Mat4.translate(finalMatrix, pivot[0], pivot[1], pivot[2]);
math.Mat4.multMat(finalMatrix, rotationMatrix2, finalMatrix);
math.Mat4.translate(finalMatrix, -pivot[0], -pivot[1], -pivot[2]);
// And apply it
math.Mat4.multMat(node.worldMatrix, finalMatrix, node.worldMatrix);
}
Not sure if this matters, but this is the code that moves the camera (it simply orbits around the center when you grab your mouse, in the same direction your mouse moves):
if (mouse.left) {
var anglez = math.toRad(mouse.x - mouse.x2);
var nrotz = math.Quaternion.fromAxisAngle([0, 0, 1], anglez, [0, 0, 0, 0]);
math.Quaternion.concat(camera.rotate, nrotz, camera.rotate);
var anglex = math.toRad(mouse.y - mouse.y2);
var nrotx = math.Quaternion.fromAxisAngle([1, 0, 0], anglex, [0, 0, 0, 0]);
math.Quaternion.concat(nrotx, camera.rotate, camera.rotate);
transform.rotation[2] += mouse.x - mouse.x2;
transform.rotation[0] += mouse.y - mouse.y2;
}