How to avoid rotation around itself provided by lookAt method

Good day everyone and thank you for spending time on this read.

The illustration of problem from project.

Notes: I need to create camera, wich will follow player on sphere surface in any point and restrictions, so the gimble lock should be blocked, that’s why I can not use arc rotate camera.

Here I create emulation of camera parent and child, add axes to them and record the problem: when I am moving from hexagon to hexagon in minor circumferences of the sphere, it’s works fine. Each 5th render call I am making parent to look at center of the sphere:

  this.scene.registerBeforeRender( ()=>  {
     if(this.renderCount !== 5){
        this.renderCount++;
} else {
       this.testMesh.lookAt(BABYLON.Vector3.Zero());
       this.renderCount = 0;
}

});
This making Z axis (face direction) be perpendicular all the time to sphere surface.
Moving of parent (in the video it presented like plane-sphere under green hexagons).
This is function, which I calls to provide movement of cameras parent.

let testingMovement = function(whatMoving, finishPosition)
 let scene = whatMoving.getScene();
 let intensity = 15;
 let start = whatMoving.position;
 let end = finishPosition;
 let keys = [];

 keys.push({frame:0, value: start});
 keys.push({frame:intensity, value: end});
 let easingFunctionInOut = new BABYLON.ExponentialEase();
 easingFunctionInOut.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT);

 let smoothAnimation = new BABYLON.Animation("move", "position", 15,
 BABYLON.Animation.ANIMATIONTYPE_VECTOR3,
 BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
 smoothAnimation.setKeys(keys);
 smoothAnimation.setEasingFunction(easingFunctionInOut);
 let animator = scene.beginDirectAnimation(whatMoving, [smoothAnimation], 0, intensity, false);
 whatMoving.animator = animator;
 animator.syncWith(null); //this animation should be asynchronous;
 animator.onAnimationEnd = function(){
 whatMoving.animator = null;
 whatMoving.animations = [];
 animator.stop();
 }
};

The problem is, when I am moving in certain points, which probably gimble-lock based (like y = 0), it rotates parent around itself, and this rotating, probably, provided by mesh.lookAt method, so, when here is not mesh, but camera attached as child to parented mesh, it rotates around itself and makes ugly vision, changing angle of view.

I do not know how to fix camera rotation, but I need to achieve movement without changing angle of view by 180 degrees. Like here: Prosecution
But in site source code is extremely hard architecture (for me), that I can not understand when and how they calculating this movement. I will be immensely grateful to some one, who can explain to me how to achieve camera movement like this?

1 Like

You are right, the camera will rotate around itself when reaching specific angles (like perpendicular to its target).
You can consider using a test to make sure that camera.position.y !== camera.target.position.y

The overall idea is to make sure to avoid Gimbal locks

Other option: camera.rotationQuaternion?

1 Like

Thank you for the answer, @Deltakosh , when last time I tried to use quaternions, I did it though parent transformNode in the center of sphere. I set both camera and pivot quaternions to identity, then connect them with this part of code:
I will provide playground example downward

this.pivot.rotationQuaternion =  new BABYLON.Quaternion(0, 0, 0, 1);
this.myCamera.parent = this.pivot;
this.pivot.lookAt(startPositionAsVector3);

Then each turn I used BABYLON.Animation, to provide result:

let smoothMoveCamera = function(pivot, pivotNewTargetAsVector3, cam){
let intensity =      30;
let scene = pivot.getScene();
let looker = pivot.clone();
let start = pivot.rotationQuaternion.clone(true);
looker.lookAt(pivotNewTargetAsVector3);
let end = looker.rotationQuaternion;
let keys = [];
keys.push({frame:0, value: start});
keys.push({frame:intensity, value: end});
let easingFunctionInOut = new BABYLON.ExponentialEase();
easingFunctionInOut.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT);

let smoothAnimation = new BABYLON.Animation("move", "rotationQuaternion", 15,
                                          BABYLON.Animation.ANIMATIONTYPE_QUATERNION,
                                          BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
smoothAnimation.setKeys(keys);
smoothAnimation.setEasingFunction(easingFunctionInOut);
let animator = scene.beginDirectAnimation(pivot, [smoothAnimation], 0, intensity, false);
cam.animator = animator;
animator.syncWith(null); //this animation should be asynchronous;
animator.onAnimationEnd = function(){
  pivot.rotationQuaternion = end;
  cam.animator = null;
  pivot.animations = [];
  animator.stop();
  looker.dispose();
  looker = null;
}

But this provides much worse result: camera rotates around itself smoothly and drawing an arc in gimble lock points:
Playground example:

https://www.babylonjs-playground.com/#AI1MQC#12

All points data got from real project, it is not random numbers
Am I doing something wrong with quaternions?
I know about p'=q^(-1)*p*q , but isn’t it the same, as I doing though BABYLON engine?

I took a deeper look at quaternion math. So, I have one more question:
to provide orientation through quaternions for camera, I do not need any parent, am I correct?

For example, I have identity quaternion of rotation and starting position setted by camera.position = someVector3,

Now I should get normal to 2 vectors: one vectors is my current position, second is my new position, and multiply current rotationQuaternion of my camera on new quaternion, which coordinates is normalized normal to those 2 vectors, and w component is cos/2 of angle between start and end vectors, am I correct? And product of multiplying should be end parameter in animations keys, right?

But I can’t understand from this, will camera look at center of sphere or not? Is it connected methods both rotation and lookAt or is each independent?

You are correct about the camera not needing parent to set the rotation quaternion.

About the rest of the question, could you create a playground highlighting the issue ? (Sorry but I am stupid at understanding maths from sentences)

1 Like

@sebavan, thank you for the reply.
Yes, sure, I can create that:
https://www.babylonjs-playground.com/#AI1MQC#15 - this playground illustrates my attemp to rotate pseudo-camera around sphere, and
https://www.babylonjs-playground.com/#AI1MQC#16 - this playground illustrates issue, which I faced at start of topic.

In the first one it rotates around itself, maybe, I should change pivot of rotation from center of mesh to somewhere else, but for now I have no idea how to do this in BABYLON and will it give any result or not, in the second one you can look only at first function, anything downward is just scene and data preset. As you can see, it rotates around itself and makes additional arc when moves.

Can we agree the expected result should be : https://www.babylonjs-playground.com/#AI1MQC#17 ?

1 Like

Yes, it should look like this: smooth movement without any rotation around itself or by additional arc movement.

The main goal is to move camera around sphere surface to follow player and to be perpendicular too him (player moving on sphere surface), without gimble locks and and without changes of angle of view.

Great this will help a lot others to jump in the thread. But with the holliday season you might expect a bit of delay on this one :frowning:

1 Like

You did not solve his problem as I see. You just moved the camera to the different route. It’s not solution, because he want to make camera work at the EXACT route he defined in code. Because, if I get it right he need to have ability to avoid such unexpected rotation in exactly these points.

1 Like

Yup I just collected all the necessary info to get help from others :slight_smile: This might speed things up a little bit.

2 Likes

Oh, ok. Interesting problem, it will be not easy to solve. Because, if I understand all correct, he needs to have camera, which has lookAt method, which working based on quaternions, not rotation matrices.

1 Like

Adding @jerome and @JohnK

I made a little of tests, and I have some questions about rotationQuaternion field.
From mathematics I know that if I need to rotate some object around axis, I need to multiply his coordinates vector to q and q^-1 from both sides, this will provide new result, as vector3, but when I am using rotation quaternion, BABYLON engine changes position of object on his own, but if I changing position of the object manually, it provides issues like without quaternions using.

So: the question is, what exactly BABYLON doing inside, to prevent issues, provided by coordinates?

Thanks everyone for time spent on reading this questions.

p.s.s All previous questions still actual, I am looking for solutions, but I have no ideas.

Rotating around an axis not does change position expect if the axis is in the object “center”. It is the expected behavior.

The documentation I am always referring to if it can help are:
https://doc.babylonjs.com/babylon101/position
https://doc.babylonjs.com/features/position,_rotation,_scaling
https://doc.babylonjs.com/how_to/rotate
https://doc.babylonjs.com/how_to/pivot#how-to-use-transformnode-as-a-center-of-rotation
https://doc.babylonjs.com/resources/rotation_conventions

and Babylon.js Documentation

I hope it might help clarifying your quaternion questions.

About the 2 first questions they are still pending but you might expect delays due to the holidays.

1 Like

Thank you for the data, I will read it.

I know about delay, I just posting my progress and don’t await immediately answer

2 Likes

Try to use rotate function calculating cross product and angle.

1 Like

Well, I finally found the solution of my problem, I need to test it a little, but this provides needed result:
https://www.babylonjs-playground.com/#AI1MQC#24
https://www.babylonjs-playground.com/#AI1MQC#22

The problem was in the lookAt method.

Notes: 1) Animation should be looped as false, while camera attached to animatable parent otherwise it will provide glitches and spikes in movement
2) If camera moves in wrong direction, swap angle vector3-arguments

3 Likes

Merry Christmas :slight_smile:

1 Like

Thanks, and you :slight_smile:
p.s How can I mark post as solved?