Weird behavior with UniversalCamera and rotation property

I found a weird behavior when setting the camera rotation property.
This is reproducible in the playground, I have prepared a few scenarios:

(is setting camera.Rotation even the correct way to rotate the UniversalCamera?)

Full playground:
https://playground.babylonjs.com/#F68Z6N

preamble

    var scene = new BABYLON.Scene(engine);
    var camera = new BABYLON.UniversalCamera("camera1", new BABYLON.Vector3(0, 20, 0), scene);
    camera.setTarget(BABYLON.Vector3.Zero());
    camera.attachControl(canvas, true);

    var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
    light.intensity = 0.7;

    var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter: 2, segments: 32}, scene);
    sphere.position.y = 1;
    sphere.position.x = 3;

    var ground = BABYLON.MeshBuilder.CreateGround("ground", {width: 5, height: 10}, scene);

Scenario A: default
image

Scenario B:

camera.rotation = new BABYLON.Vector3(Math.PI / 2, 0, 0);

image

Scenario C:

camera.rotation = new BABYLON.Vector3(Math.PI / 2, 0, Math.PI);

Scenario D:

camera.rotation = new BABYLON.Vector3(Math.PI / 2, 0, 0.001);

Scenario E:

camera.rotation = new BABYLON.Vector3(Math.PI / 2, 0, 0.001);
scene.render()
camera.rotation = new BABYLON.Vector3(Math.PI / 2, 0, 0);


This does not just affect the Z-Axis:

Scenario F

camera.rotation = new BABYLON.Vector3(Math.PI / 2, 1, 0);

image

Scenario G

camera.rotation = new BABYLON.Vector3(Math.PI / 2, 0, 1);
scene.render()
camera.rotation = new BABYLON.Vector3(Math.PI / 2, 1, 0);


Note: just calling scene.render beforehand is not enough, you actually need to set it to a different value, then render, then change the value again.


Now, I haven’t though too long about what the correct behavior actually should be, but the fact alone that B and E (or F and G) are different should show that something is wrong.

Hello!
Are you sure of scenario B? Because I’ve just run it and:

Here is your screenshot:
image

Same applies for scenario F. :slight_smile:

lol, for me it depends on the browser. Works in Edge, doesn’t work in Firefox.
Screenshots from initial post are from Firefox.

I only thought about testing another browser after you said it works for you.

1 Like

@PolygonalSun would be great if you can have a quick look ?

Decreasing the x rotation by a small value makes it working on FF.

    camera.rotation = new BABYLON.Vector3(Math.PI / 2 - 0.001, 1, 0);

Whattahell?! :smiley:

I can take a look and see what’s going on.

1 Like

That was exactly my reaction as well :smiley:

Thank y’all for taking a look, I’m really excited to find out what weird corner case causes this lol.

@PolygonalSun this would be great as I am really wondering if we introduced smthg weird here :slight_smile:

So I just wanted to provide an update here. I haven’t found the root cause yet but after testing on a bunch of different browsers, it looks like this behavior is exclusively in Firefox. I tried the suggested modification by @roland and it does work for me. Maybe there’s some kind of issue related to how floats are being handled by FF? In any case, I’m going to keep digging to see what’s going on.

1 Like

Hi @PolygonalSun!

Look at this weird stuff in FF and Chrome. It’s broken it both browsers:
https://playground.babylonjs.com/#F68Z6N#4

After you apply the ‘fix’, it starts to work in both.

    camera.rotation.x = Math.PI / 2 - 0.00000000001

I am confused… :smiley:

3 Likes

Well, now that is some interesting behavior! Thanks for the find. That is definitely not supposed to be how it’s supposed to work.

This reminds me an issue I had a few months ago. I was animating the position and the target of an ArcRotateCamera. When you set the position right above the target so their x and z values are the same and let position y be 20 and target y 0,and you change the z value of both position and target just by a very very small value, the camera gets flipped over and it seems that it is mirrored on the x axis. After being lame for an hour or two I have realized that it’s because the camera would be upside down so it is an expected behavior that it seems that it is mirroring the view. Now I know there is a property which allows the camera be upside down. Couldn’t the camera targeting code somehow alter the rotation in this case too?

The first thing I have tried is to compare the value of Math.PI in both browsers :smiley: Obviously they are the same. Actually this is quite scary to have different results in different browsers while the code is the same! :ghost:

This is highlighting Gimbal locks issues and why quaternions should be used for rotations.

1 Like

Ok, but the weird thing here is that it is behaving differently in different browsers. :see_no_evil:

1 Like

I did a quick test, and it’s the same with Quaternions:

FF:

    var q = BABYLON.Quaternion.FromEulerAngles(Math.PI / 2, 0, 0.01);
    camera.rotationQuaternion = q;


    var q = BABYLON.Quaternion.FromEulerAngles(Math.PI / 2, 0, 0);
    camera.rotationQuaternion = q;


In Edge(chrome) the ball is always at the right side for both cases.


The quaternions differ only at the 16th number after the dot between FF and Edge, "_x":0.7071067811865476 vs "_x":0.7071067811865475, so it’s (probably) not related to FromEulerAngles

1 Like

Using Quaternion.FromEulerAngles like this seems to fix the scenario F issue in Chrome and FF thou at least. Also from testing on the older versions in the PG this behavior seems to go back all the way to version 3.3…
https://playground.babylonjs.com/#F68Z6N#5

Also I did the other test with quaternions and on FF the ball is on the right side in both cases, the same as on Chrome, so seems to be working as far as I can tell.
https://playground.babylonjs.com/#F68Z6N#13