Sign in to follow this  
Chananya Freiman

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

Recommended Posts

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?)



// 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;
Edited by Chananya Freiman

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this