Panning a level horizon

The place to discuss creating, porting and modifying Celestia's source code.
Topic author
guest

Panning a level horizon

Post #1by guest » 05.10.2002, 20:52

Recently, I started tinkering with Celestia 1.2.4 source, and one of the first things I wanted to try was to simulate standing, say at an elevation of 100 meters on Mars, and panning the horizon. At first, I thought this would be quite simple, but now I've changed my opinion, and come to you, Celestia developers, on bended knee, for help.

As a first step toward panning with a level horizon, I added a simple command to one of the menus which asks for an object to look at and places the string in a variable named 'strObjectPath', then executes the following code:



Simulation* sim = appCore->getSimulation();

Observer& observer = sim->getObserver();

double simTime = sim->getTime();

Selection& targetObject = sim->findObjectFromPath(strObjectPath);

Point3f from = observer.getPosition();

Selection& location = sim->getSelection(); // could be Moon, Mars...

Point3f to = targetObject.getPosition(simTime);

//get vector up from center of object to observer on surface
Vec3f up = from - location.getPosition(simTime);

// following lines from 'lookAt' in simulation.cpp
Vec3f n = to - from; n.normalize();
Vec3f v = n ^ up; v.normalize();
Vec3f u = v ^ n;

Quatf orientation(Mat3f(v, u, -n));

sim->setObserverOrientation(orientation);


It seems that this code should give me a level horizon on the selected object, looking at the object in 'strObjectPath'. Well, it certainly "looks at" 'strObjectPath', and it's USUALLY reasonably level, but never PERFECTLY level.

How can I get a level horizon ????

Matt McIrvin
Posts: 312
Joined: 04.03.2002
With us: 22 years 8 months

Panning a level horizon

Post #2by Matt McIrvin » 07.10.2002, 02:59

guest wrote:
//get vector up from center of object to observer on surface
Vec3f up = from - location.getPosition(simTime);

// following lines from 'lookAt' in simulation.cpp
Vec3f n = to - from; n.normalize();
Vec3f v = n ^ up; v.normalize();
Vec3f u = v ^ n;

Quatf orientation(Mat3f(v, u, -n));

sim->setObserverOrientation(orientation);


It seems that this code should give me a level horizon on the selected object, looking at the object in 'strObjectPath'. Well, it certainly "looks at" 'strObjectPath', and it's USUALLY reasonably level, but never PERFECTLY level.

How can I get a level horizon ????


Caret ^ is like a vector cross product, right?

If so, then it seems to me that there's a problem if the planet is oblate, because then the line from the center of the planet doesn't correspond to the vertical. You would need to adjust "up" to take the local horizon tilt into account.

If the planet is perfectly spherical (and I recall that some were set to spherical so that atmospheres would work right-- I don't know if that's the case in the latest code) then I don't know what the problem is here.

Rassilon
Posts: 1887
Joined: 29.01.2002
With us: 22 years 9 months
Location: Altair

Post #3by Rassilon » 08.10.2002, 15:56

I just had a thought on how this can be done...Program the viewport to pan the horizion as if it were directly in the center...I believe you already know that the horizion stays perfectly level when its directly in the center...using a hotkey maybe...With this mode enabled the software will 'think' the horizion is in the center of the viewport but will display the eyeshot as configured manually using the up and down arrows...Rotation of the camera will in affect be disabled while using this mode...You will however be able to pan left and right...Sort of like Tracking with that extra umph ;)

btw the horizion can be fixed as level just figure what the procedure chris uses to formulate the horizion and figure that as a constant when viewing the horizion level...Then add the variables of angle of eyeshot + or - from this constant and that should in affect work...Not sure 100% but fairly sure...
I'm trying to teach the cavemen how to play scrabble, its uphill work. The only word they know is Uhh and they dont know how to spell it!

Agamemnon
Posts: 2
Joined: 08.10.2002
With us: 22 years 1 month
Location: East Coast USA

Post #4by Agamemnon » 08.10.2002, 16:42

Hi all, I'm the original poster of this thread, and have since registered as Agamemnon.

To Matt McIrvin, thanks for responding and yes, the caret is a vector cross product operator. It seems to me that your idea about a body's elliptical shape causing the tilted horizon might explain a very small deviations from level, but what I am seeing is too large a tilt to be attributable to that.

To Rassilon, thank you for responding -- an intriguing idea ! But I'm afraid I don't quite understand it... could you flesh it out some more?

Rassilon
Posts: 1887
Joined: 29.01.2002
With us: 22 years 9 months
Location: Altair

Panning a level horizon

Post #5by Rassilon » 08.10.2002, 17:02

Well Ill try...

thru debugging figure out what the value of location.getPosition(simTime); is when horizion is level this means 50% land 50% sky...When you pan left - right you should be able to stay level...With some tweaking you can make this perfectly level through programming...

Then have const horizion = location.getPosition(simTime);

depending on the value of location.getPosition(simTime) that is...Not sure as I havent coded any of Celestia...

then with this constant value implement it as the viewport is locked to this position at all times...in affect disabling the normal routine the engine does when the eyeshot/camera is moved into a different position...

Now implement a whole new function/class[s] to incorperate your camera mode maybe invoked using a hotkey...As far as how on that bit maybe someone else can help as Im limited in what commands do what in chris's defined class structure....

Looking at the above variables it is all geared to a 3d representation...If you implement a more simplistic 2d representation you may get the results you desire...Not sure how this may play using world coordinates in OpenGL...Its just a theroy...May not even work...
I'm trying to teach the cavemen how to play scrabble, its uphill work. The only word they know is Uhh and they dont know how to spell it!

chris
Site Admin
Posts: 4211
Joined: 28.01.2002
With us: 22 years 9 months
Location: Seattle, Washington, USA

Post #6by chris » 08.10.2002, 17:16

I think that I figured out what your problem is . . . It's probably a precision issue. Single precision floating point (what you get when you use the Point3f type) is not adequate for the positions, although it's fine for the directions. In general in Celestia, absolute positions need to be in high precision coordinates (UniversalCoord type, 128-bit per component fixed point), solar system coordinates need to be double precision, and the eye-relative coordinates passed down to OpenGL are single precision. When simulating the universe, only use lower precision for the difference between two points.

Things should work out if you use UniversalCoords for the positions from and to:

Code: Select all

Simulation* sim = appCore->getSimulation();
 
Observer& observer = sim->getObserver();

double simTime = sim->getTime();

Selection& targetObject = sim->findObjectFromPath(strObjectPath);

UniversalCoord from = observer.getPosition();

Selection& location = sim->getSelection(); // could be Moon, Mars...

UniversalCoord to = targetObject.getPosition(simTime);

//get vector up from center of object to observer on surface
Vec3f up = from - location.getPosition(simTime);

// following lines from 'lookAt' in simulation.cpp
Vec3f n = to - from; n.normalize();
Vec3f v = n ^ up; v.normalize();
Vec3f u = v ^ n;

Quatf orientation(Mat3f(v, u, -n));

sim->setObserverOrientation(orientation);


I think that should work . . . Let me know if you get compiler errors.

--Chris

Agamemnon
Posts: 2
Joined: 08.10.2002
With us: 22 years 1 month
Location: East Coast USA

Post #7by Agamemnon » 08.10.2002, 18:39

Bingo! Thanks Chris, works perfectly -- here's the code:

Code: Select all

Simulation* sim = appCore->getSimulation();
Observer& observer = sim->getObserver();
double simTime = sim->getTime();   

Selection& location = sim->getSelection();
Selection& targetObject = sim->findObjectFromPath(strObjectPath);

UniversalCoord from = observer.getPosition();
UniversalCoord to = targetObject.getPosition(simTime);
UniversalCoord loc = location.getPosition(simTime);

Vec3d up = from - loc;

Vec3d n = to - from; n.normalize();
Vec3d v = n ^ up; v.normalize();
Vec3d u = v ^ n;
 
Quatf orientation(Mat3f(Vec3f(v.x,v.y,v.z), Vec3f(u.x,u.y,u.z), Vec3f(-n.x,-n.y,-n.z)));

sim->setObserverOrientation(orientation);


As you said, Chris, I don't need the high-precision vectors, but as you anticipated, there were some casting problems (Visual C++ 6), so I went to single-precision at the last possible moment.

Which brings me to the next step -- how to pan the horizon continuously using, say, the left and right arrow keys, or stated another way, hold the "lookAt" altitude constant, while varying the azimuth 0-360? Although I find Rassilon's idea interesting, I'm afraid that even after clarification, I don't understand how it would work -- besides, I'd like to accomplish the panning without messing about with the internals of Celestia's OpenGL implementation. Looks like I'll need to brush up on my spherical trigonometry 8O

Rassilon
Posts: 1887
Joined: 29.01.2002
With us: 22 years 9 months
Location: Altair

Post #8by Rassilon » 08.10.2002, 21:20

Thats the problem with programming something new it takes a bit to play with the code to get it to function the way you want...If I were to start right now I might have it in a month or two ;)
I'm trying to teach the cavemen how to play scrabble, its uphill work. The only word they know is Uhh and they dont know how to spell it!


Return to “Development”