Positive and negative numbers of Camera.Rotation

Good day!
I always use a keyboard and Pascale code to rotate camera to fixed positions (i use static scenes in project, like in visual novels and classic quests, but in 3D).
But now I want to add mouse like a option for free observe the scene. I looked to Camera.Rotation in engine window, and see, that Rotation.W is from 0 to 6.28 (in radians), independent of side of rotation… But Rotation.Y changes between 1 and -1.
But in my code Rotation.W can be from 0 to 6.28 in one side and from 0 to -6.28 in another side… And Y always 1. And it works good.
So, for combine fixed rotation from keyboard to 8 sides (soutr, south-west and others…) and free observe from mouse, I must rewrite my code with:
Rotation.W is always positive number;
Rotation.Y is a 1 or -1 (for left/right looking)?

Why in CGE window Rotation.W always positive, but my code works wint negative numbers?..

Thanks for attention

Rotation.XYZ is “axis” of the rotation. (0,0,1) is the axis that looks upwards, (0,0,-1) is the axis that looks downwards.

Rotation.W is “angle” of the rotation around that axis counterclockwise (if I remember correctly). This way rotation (0,0,1,angle) is absolutely equal to (0,0,-1,-angle). This way you can use anything that is more convenient for you. Most often it makes sense to keep (0,0,1) axis to have “up” vector like the one inverse to the gravity.

Finally, you can assign any number to Rotation.W. Be it “Pi”, “-Pi” or “1000 * Pi”. Rotating by an angle > 2*Pi will just make one full circle and rotate by “what angle remains above 2*Pi”. If something is far above 2*Pi, it’ll make multiple circles. It’s trigonometric formulas and it doesn’t literally make “multiple circles” just “removes everything above 2 * Pi” and "converts negative angles into “0..2 * Pi” range exactly the same way. So, sometimes you may even e.g. assign Rotation.W := 2 * Pi + Pi / 3 and in a frame read just “Pi / 3” instead of what you’ve assigned to it.

This way you can also set Rotation.W := Rotation.W + Pi * SecondsPassed to slowly rotate some object around its axis, without worrying to “go above 2 * Pi”, the Engine will do everything correcly.

2 Likes

Thanks for help.
So, if I need static camera location, I must set XYZ in optimal position, forget they and work only with W?

WriteLn(Trunc(Viewport.Camera.Rotation.W));

and see, how this value grown to 20+, its ~Pi * 5. Program still work, but, in theory, after millions rotations variable will full of and game broke?

If you only want to rotate camera around the same vector (like up = (0,1,0)) then yes, it makes most sense to just always set the same XYZ (axis of rotation) and only tweak the angle (W) of Camera.Rotation.

It’s a floating point value, but indeed, at some point it will loose precision. You should not increase it into infinity. Instead from time to time bring it back into “regular range” e.g. using FloatModulo ( Castle Game Engine: CastleUtils ).

For example

Rotation := Viewport.Camera.Rotation;
Rotation.W := FloatModulo(Rotation.W + Pi * SecondsPassed, 2 * Pi);
Viewport.Camera.Rotation := Rotation;

You don’t need to be very strict about when do you use this FloatModulo, as @eugeneloza mentioned above actually all numbers (even outside 0…2pi) work. You can as well e.g. do

Rotation := Viewport.Camera.Rotation;
Rotation.W := Rotation.W + Pi * SecondsPassed;
if Abs(Rotation.W) > 100 then // avoid Rotation.W from growing too large
Rotation.W := FloatModulo(Rotation.W, 2 * Pi);
Viewport.Camera.Rotation := Rotation;
1 Like