FlightGear next
light.cxx
Go to the documentation of this file.
1/*
2 * SPDX-FileName: light.cxx
3 * SPDX-FileComment: lighting routines
4 * SPDX-FileCopyrightText: Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8#include <cmath>
9
10#include <simgear/constants.h>
11#include <simgear/debug/logstream.hxx>
12#include <simgear/timing/sg_time.hxx>
13#include <simgear/structure/event_mgr.hxx>
14
15#include <Main/globals.hxx>
16#include <Main/fg_props.hxx>
17
18#include "light.hxx"
19#include "bodysolver.hxx"
20
22{
23 // update all solar system body positions of interest
24 globals->get_event_mgr()->addTask("updateObjects",
25 [this](){ this->updateObjects(); }, 0.5 );
26}
27
29{
30 init();
31 updateObjects();
32}
33
35{
36 SGPropertyNode *prop = globals->get_props();
37
38 _sunAngleRad = prop->getNode("/sim/time/sun-angle-rad", true);
39 _sunAngleRad->setDoubleValue(_sun_angle);
40 _moonAngleRad = prop->getNode("/sim/time/moon-angle-rad", true);
41 _moonAngleRad->setDoubleValue(_moon_angle);
42
43 // Sun vector
44 tie(prop,"/ephemeris/sun/local/x", SGRawValuePointer<float>(&_sun_vec[0]));
45 tie(prop,"/ephemeris/sun/local/y", SGRawValuePointer<float>(&_sun_vec[1]));
46 tie(prop,"/ephemeris/sun/local/z", SGRawValuePointer<float>(&_sun_vec[2]));
47
48 // Moon vector
49 tie(prop,"/ephemeris/moon/local/x", SGRawValuePointer<float>(&_moon_vec[0]));
50 tie(prop,"/ephemeris/moon/local/y", SGRawValuePointer<float>(&_moon_vec[1]));
51 tie(prop,"/ephemeris/moon/local/z", SGRawValuePointer<float>(&_moon_vec[2]));
52}
53
55{
56 _tiedProperties.Untie();
57 _sunAngleRad.reset();
58 _moonAngleRad.reset();
59}
60
61void FGLight::update(double dt)
62{
63 SG_UNUSED(dt);
64}
65
66void FGLight::updateObjects()
67{
68 // update the sun position
69 bool sun_not_moon = true;
70 updateBodyPos(sun_not_moon, _sun_lon, _sun_lat,
71 _sun_vec, _sun_vec_inv,
72 _sun_angle, _sunAngleRad,
73 _sun_rotation);
74
75 // update the moon position
76 sun_not_moon = false;
77 updateBodyPos(sun_not_moon, _moon_lon, _moon_gc_lat,
78 _moon_vec, _moon_vec_inv,
79 _moon_angle, _moonAngleRad,
80 _moon_rotation);
81}
82
83void FGLight::updateBodyPos(bool sun_not_moon, double& lon, double& lat,
84 SGVec4f& vec, SGVec4f& vec_inv,
85 double& angle, SGPropertyNode_ptr AngleRad,
86 double& rotation)
87{
88 SGTime *t = globals->get_time_params();
89
90 // returns lon and lat based on GST
91 fgBodyPositionGST(t->getGst(), lon, lat, sun_not_moon);
92
93 // It might seem that gc_lat needs to be converted to geodetic
94 // latitude here, but it doesn't. The body latitude is the latitude
95 // of the point on the earth where the up vector has the same
96 // angle from geocentric Z as the body direction. But geodetic
97 // latitude is defined as 90 - angle of up vector from Z!
98 SGVec3d bodypos = SGVec3d::fromGeoc(SGGeoc::fromRadM(lon, lat,
99 SGGeodesy::EQURAD));
100
101 // update the body vector
102 vec = SGVec4f(toVec3f(normalize(bodypos)), 0);
103 vec_inv = - vec;
104
105 // calculate the body's relative angle to local up
106 SGQuatd hlOr = SGQuatd::fromLonLat( globals->get_view_position() );
107 SGVec3d world_up = hlOr.backTransform( -SGVec3d::e3() );
108 // cout << "nup = " << nup[0] << "," << nup[1] << ","
109 // << nup[2] << endl;
110 // cout << "nbody = " << nbody[0] << "," << nbody[1] << ","
111 // << nbody[2] << endl;
112
113 SGVec3d nbody = normalize(bodypos);
114 SGVec3d nup = normalize(world_up);
115 angle = acos( dot( nup, nbody ) );
116
117 double signedPI = (angle < 0.0) ? -SGD_PI : SGD_PI;
118 angle = fmod(angle+signedPI, SGD_2PI) - signedPI;
119
120 // Get direction to the body in the local frame.
121 SGVec3d local_vec = hlOr.transform(nbody);
122
123 // Angle from South.
124 // atan2(y,x) returns the angle between the positive X-axis
125 // and the vector with the origin at 0, going through (x,y)
126 // Since the local frame coordinates have x-positive pointing Nord and
127 // y-positive pointing East we need to negate local_vec.x()
128 // rotation is positive counterclockwise from South (body in the East)
129 // and negative clockwise from South (body in the West)
130 rotation = atan2(local_vec.y(), -local_vec.x());
131
132 // cout << " Sky needs to rotate = " << rotation << " rads = "
133 // << rotation * SGD_RADIANS_TO_DEGREES << " degrees." << endl;
134
135 AngleRad->setDoubleValue(angle);
136}
137
138
139// Register the subsystem.
140SGSubsystemMgr::Registrant<FGLight> registrantFGLight(
141 SGSubsystemMgr::DISPLAY);
void fgBodyPositionGST(double gst, double &lon, double &lat, bool sun_not_moon)
given a particular time expressed in side real time at prime meridian (GST), compute position on the ...
SGTime * get_time_params() const
Definition globals.hxx:311
SGGeod get_view_position() const
Definition globals.cxx:632
void reinit() override
Definition light.cxx:28
void unbind() override
Definition light.cxx:54
void init() override
Definition light.cxx:21
void bind() override
Definition light.cxx:34
void update(double dt) override
Definition light.cxx:61
FGGlobals * globals
Definition globals.cxx:142
SGSubsystemMgr::Registrant< FGLight > registrantFGLight(SGSubsystemMgr::DISPLAY)