Smoothly Rotating Objects with Mouse

Yesterday, I was following this tutorial about Rotating Objects with Mouse. (This:
https://developer.playcanvas.com/en/tutorials/rotating-objects-with-mouse/)

The thing is that it isn’t smooth at all. It doesn’t ease-in and ease-out. So I wanted to try out making it smooth. What came into my mind was to add Lerp to the script of it. But I had no idea how to make it work. After some hours of searching on Lerp and Quat mathematics, I came up with this code: (FYI, surprisingly it doesn’t work either :relieved:)

Rotate.horizontalQuat = new pc.Quat();
Rotate.verticalQuat = new pc.Quat();
Rotate.resultQuat = new pc.Quat();
Rotate.resultQuatAfterLerp = new pc.Quat();  //for storing the data after the Lerp

Rotate.prototype.rotate = function (dx, dy) {
    var horzQuat = Rotate.horizontalQuat;
    var vertQuat = Rotate.verticalQuat;
    var resultQuat = Rotate.resultQuat;

    // Create a rotation around the camera's orientation in order for them to be in 
    // screen space  
    horzQuat.setFromAxisAngle(this.cameraEntity.up, dx * this.orbitSensitivity);
    vertQuat.setFromAxisAngle(this.cameraEntity.right, dy * this.orbitSensitivity);

    // Apply both the rotations to the existing entity rotation
    resultQuatAfterLerp.mul2 = pc.math.lerp((resultQuat.mul2()),(resultQuat.mul2(horzQuat, vertQuat)));
    resultQuatAfterLerp.mul = pc.math.lerp((resultQuat.mul(this.entity.getRotation())), (resultQuat.mul(this.entity.getRotation())), dt / 0.2);

    this.entity.setRotation(resultQuatAfterLerp);    
};

What is this issue?
Oh, and what does resultQuat.mul2() mean? I took it as, :thinking: mul2 is kinda a sub variable of reasultQuat and that piece of code creates it. Another question I have in my mind is that what are horizontalQuat, verticalQuat, and resultQuat? Do they work like sub-variables too? :thinking:

You should refer to the API docs to see how quaternions can be multiplied with each other.

a.mul(b) will change the a to a result of multiplying a on b; no change to b
c.mul2(a, b) will change c to a result of multiplying a on b; no change to a and b

About horizontalQuat and others. It is an optimization technique. If you know that you will need to temporarily store an intermediate result, before calculating a final result of some math calculation, you would want to use a temp variable. For example, to calculate A and B, you also need C for some temp result. You do your math, get result and now you no longer need C. You can now use it as a temp variable in some other calculation, instead of creating a completely new one again.

Instead:

Script.prototype.myMethod = function() {
  var a = new pc.Vec2();         
  var b = new pc.Vec2(2, 2);   
  var temp = new pc.Vec2();      // new memory allocation
  temp.copy(b);                  // some math
  a.set(temp);                   // result
};
Script.prototype.myOtherMethod = function() {
  var a = new pc.Vec2();         
  var b = new pc.Vec2(2, 2);   
  var anotherTemp = new pc.Vec2();     // new memory allocation
  anotherTemp.copy(b);                 // some math
  a.set(temp);                         // result
};

You can pre-allocate memory beforehand and re-use the temp objects:

Script.temp = new pc.Vec2();        // new memory allocation
Script.prototype.myMethod = function() {
  var temp = Script.temp;  
  var a = new pc.Vec2();         
  var b = new pc.Vec2(2, 2);   
  temp.copy(b);                  // some math
  a.set(temp);                   // result
};
Script.prototype.myOtherMethod = function() {
  var temp = Script.temp; 
  var a = new pc.Vec2();         
  var b = new pc.Vec2(2, 2);   
  temp.copy(b);                  // some math
  a.set(temp);                   // result
};

Edit: updated example to make it a little more obvious.

1 Like