• Advertisement
Sign in to follow this  

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

This topic is 1670 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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
Sign in to follow this  

  • Advertisement