Stellarium / stellarium

Stellarium is a free GPL software which renders realistic skies in real time with OpenGL. It is available for Linux/Unix, Windows and macOS. With Stellarium, you really see what you can see with your eyes, binoculars or a small telescope.
https://stellarium.org
GNU General Public License v2.0
7.84k stars 832 forks source link

Zenith/Nadir Search window issue #3502

Open MagnuzBinder opened 1 year ago

MagnuzBinder commented 1 year ago

Expected Behaviour

When moving to zenith or nadir (±90° altitude) in Search window : Position : Horizontal, azimuth is expected to be unchanged in main view and Search window.

Actual Behaviour

When moving to abs(altitude) > arcsin(0.99) ≈ 81.890386° in Search window : Position : Horizontal, azimuth jumps to some other value in main view but is unchanged and thereby faulty in Search window.

Steps to reproduce

Set FOV to 180°, enter e.g. 0°, 90°, 180° or 270° in Search window : Position : Horizontal, azimuth field and then e.g. 85° in altitude field, and see the view and cardinal points suddenly jump to unexpected directions after the initial correct rotation (cardinal points N S E W should be and stay up down right left).

System

Comment

The cause is most probably stellarium/src/core/StelMovementMgr.cpp line 1151 in Stellarium 23.3: if (fabs((fabs(viewDirectionMountFrame.v[2]) - 1.)) < 0.01 ) Introduced in PR #2659 2022-09-18 Not a problem in Stellarium 0.19.1.

The above causes azimuth to jump if abs(sin(altitude)) > 1 - 0.01, i.e. abs(altitude) > arcsin(1 - 0.01) ≈ 81.890386°

If it is possible to lower the difference below 0.01, it would reduce this problem, but I'm not sure it won't cause instability elsewhere, unless precision is consistently double: 0.01 => 81.890386° 0.001 => 87.437441° 0.0001 => 89.189709° 0.00001 => 89.743765° 0.000001 => 89.918972° 0.0000001 => 89.974377° 0.00000001 => 89.991897°

I read the Zenith scripting issue #754, so I know this is a can of worms you may not want to dig into again, but this bug is a new, non-script-related, manifestation of the same basic problem with sub-optimally written geometric projection handling.

Also, the extra space between "0.01" and ")" could be removed for consistency if you do something about the code.

github-actions[bot] commented 1 year ago

Thanks for adding your first issue to Stellarium. If you have questions, please do not hesitate to contact us.

gzotti commented 1 year ago

Can of worms, yes. We can probably remedy to 0.0001 but not much closer, or do what has to be done also for these movements. Who wants to rewrite StelMovementMgr with quaternions?

github-actions[bot] commented 1 year ago

Hello @MagnuzBinder!

OK, developers can reproduce the issue. Thanks for the report!

10110111 commented 1 year ago

Who wants to rewrite StelMovementMgr with quaternions?

Anyone who's going to do this: don't even think of using QQuaternion! It's limited to float precision.

MagnuzBinder commented 1 year ago

Lowering the difference from 0.01 to 0.0001 reduces the problem area by 99%, which would be welcome. I just wonder, why not 0.000001? This would still mean a vector perpendicular to zenith/nadir that is 0.001414 units long, meaning a relative precision better than 0.0001, if assuming unit vectors and there being some single float calculation somewhere processing it.

As for quaternion libraries, would ferd36's quaternion ( https://github.com/ferd36/quaternions ) do, at least as a starting point? It may be a bit old (2015), but quaternions haven't changed any since 1843 (or 1819 if we give credit to their first real inventor Gauss instead of Hamilton), it seems mathematically correct and sanely written at a first glance, supports both single, double and long double precision, and it's MIT open source, so it can be modified if needed.

As for rewriting StelMovementMgr, I wish I could help, but I'm no C++ programmer, even if I can read the code. I agree the best would be to rewrite StelMovementMgr to proper geometric projection handling, using e.g. quaternions. However, there is a simple and ugly hack that can mitigate the problem, pseudocode: Init: upVectorLastValid = upVectorMountFrame; Main: if (abs(upVectorMountFrame[2]) > 0.000001) upVectorLastValid = upVectorMountFrame; else upVectorMountFrame = upVectorLastValid;

It can also be good knowing what the up vector is used for. I haven't gone through the Stellarium code base, but in two other 3D projects I've worked with, the up vector is only used to calculate the camera transform matrix like: Camera front vector = normalized(front vector) Camera side vector = normalized(front vector X up vector) Camera up vector = Camera side vector X Camera front vector) Used in this way, the up vector doesn't need to be "up" at all, just in the vertical plane the front vector is in and with z/[2] > 0, which makes it easier to form a usable up vector.