Advertisement

Making a node attached to a node hierarchy face the camera (billboard)

Started by June 23, 2013 02:44 PM
-1 comments, last by Chananya Freiman 11 years, 8 months ago

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;
}

This topic is closed to new replies.

Advertisement