]> git.mxchange.org Git - simgear.git/blob - simgear/sky/skysun.cxx
Working on separating out ephemeris code from the actual rendering code
[simgear.git] / simgear / sky / skysun.cxx
1 // skysun.hxx -- draw a sun object
2 //
3 // Written by Durk Talsma. Originally started October 1997, for distribution  
4 // with the FlightGear project. Version 2 was written in August and 
5 // September 1998. This code is based upon algorithms and data kindly 
6 // provided by Mr. Paul Schlyter. (pausch@saaf.se). 
7 //
8 // Separated out rendering pieces and converted to ssg by Curt Olson,
9 // March 2000
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License as
12 // published by the Free Software Foundation; either version 2 of the
13 // License, or (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 // General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 //
24 // $Id$
25
26
27 #include <plib/ssg.h>
28
29 #include <simgear/constants.h>
30
31 #include "sphere.hxx"
32 #include "skysun.hxx"
33
34
35 // Constructor
36 FGSkySun::FGSkySun( void ) {
37 }
38
39
40 // Destructor
41 FGSkySun::~FGSkySun( void ) {
42 }
43
44
45 // initialize the sun object and connect it into our scene graph root
46 bool FGSkySun::initialize() {
47
48     // create the scene graph for the dome
49     skysun = new ssgRoot;
50     skysun->setName( "Sky Sun" );
51
52     // set up the state
53     orb_state = new ssgSimpleState();
54     orb_state->setShadeModel( GL_SMOOTH );
55     orb_state->disable( GL_LIGHTING );
56     orb_state->disable( GL_DEPTH_TEST );
57     orb_state->disable( GL_CULL_FACE );
58     orb_state->disable( GL_TEXTURE_2D );
59     orb_state->disable( GL_COLOR_MATERIAL );
60     orb_state->setMaterial( GL_AMBIENT_AND_DIFFUSE, 1.0, 1.0, 1.0, 1.0 );
61
62     ssgBranch *orb = ssgMakeSphere( orb_state, 550.0, 10, 10 );
63
64     // force a repaint of the sun colors with arbitrary defaults
65     repaint( 0.0 );
66
67     // build the ssg scene graph sub tree for the sky and connected
68     // into the provide scene graph branch
69     sun_selector = new ssgSelector;
70     sun_transform = new ssgTransform;
71
72     // orb->setState( orb_state );
73
74     sun_transform->addKid( orb );
75
76     sun_selector->addKid( sun_transform );
77     sun_selector->clrTraversalMaskBits( SSGTRAV_HOT );
78
79     skysun->addKid( sun_selector );
80
81     return true;
82 }
83
84
85 // repaint the sun colors based on current value of sun_angle in
86 // degrees relative to verticle
87 // 0 degrees = high noon
88 // 90 degrees = sun rise/set
89 // 180 degrees = darkest midnight
90 bool FGSkySun::repaint( double sun_angle ) {
91     if ( sun_angle * RAD_TO_DEG < 100 ) {
92         // else sun is well below horizon (so no point in repainting it)
93     
94         // x_10 = sun_angle^10
95         double x_10 = sun_angle * sun_angle * sun_angle * sun_angle * sun_angle
96             * sun_angle * sun_angle * sun_angle * sun_angle * sun_angle;
97
98         float ambient = (float)(0.4 * pow (1.1, - x_10 / 30.0));
99         if (ambient < 0.3) { ambient = 0.3; }
100         if (ambient > 1.0) { ambient = 1.0; }
101
102         sgVec3 color;
103         sgSetVec3( color,
104                    (ambient * 6.0)  - 1.0, // minimum value = 0.8
105                    (ambient * 11.0) - 3.0, // minimum value = 0.3
106                    (ambient * 12.0) - 3.6  // minimum value = 0.0
107                    );
108     
109         if (color[0] > 1.0) color[0] = 1.0;
110         if (color[1] > 1.0) color[1] = 1.0;
111         if (color[2] > 1.0) color[2] = 1.0;
112
113         orb_state->setMaterial( GL_AMBIENT_AND_DIFFUSE, 
114                                 color[0], color[1], color[2], 1.0 );
115     }
116
117     return true;
118 }
119
120
121 // reposition the sun at the specified right ascension and declination
122 bool FGSkySun::reposition( double rightAscension, double declination ) {
123     sgMat4 T, RA, DEC;
124     sgVec3 axis;
125     sgVec3 v;
126
127     // xglRotatef(((RAD_TO_DEG * rightAscension)- 90.0), 0.0, 0.0, 1.0);
128     sgSetVec3( axis, 0.0, 0.0, 1.0 );
129     sgMakeRotMat4( RA, (rightAscension * RAD_TO_DEG) - 90.0, axis );
130
131     // xglRotatef((RAD_TO_DEG * declination), 1.0, 0.0, 0.0);
132     sgSetVec3( axis, 1.0, 0.0, 0.0 );
133     sgMakeRotMat4( DEC, declination * RAD_TO_DEG, axis );
134
135     // xglTranslatef(0,60000,0);
136     sgSetVec3( v, 0.0, 60000.0, 0.0 );
137     sgMakeTransMat4( T, v );
138
139     sgMat4 TRANSFORM;
140     sgCopyMat4( TRANSFORM, RA );
141     sgPreMultMat4( TRANSFORM, DEC );
142     sgPreMultMat4( TRANSFORM, T );
143
144     sgCoord skypos;
145     sgSetCoord( &skypos, TRANSFORM );
146
147     sun_transform->setTransform( &skypos );
148
149     return true;
150 }
151
152
153 // Draw the sun
154 bool FGSkySun::draw() {
155     ssgCullAndDraw( skysun );
156
157     return true;
158 }
159
160
161 #if 0
162 /*************************************************************************
163  * Star::Star(FGTime *t)
164  * Public constructor for class Star
165  * Argument: The current time.
166  * the hard coded orbital elements our sun are passed to 
167  * CelestialBody::CelestialBody();
168  * note that the word sun is avoided, in order to prevent some compilation
169  * problems on sun systems 
170  ************************************************************************/
171 Star::Star(FGTime *t) :
172   CelestialBody (0.000000,  0.0000000000,
173                  0.0000,    0.00000,
174                  282.9404,  4.7093500E-5,       
175                  1.0000000, 0.000000,   
176                  0.016709,  -1.151E-9,
177                  356.0470,  0.98560025850, t)
178 {
179     
180   FG_LOG( FG_GENERAL, FG_INFO, "Initializing Sun Texture");
181 #ifdef GL_VERSION_1_1
182   xglGenTextures(1, &sun_texid);
183   xglBindTexture(GL_TEXTURE_2D, sun_texid);
184 #elif GL_EXT_texture_object
185   xglGenTexturesEXT(1, &sun_texid);
186   xglBindTextureEXT(GL_TEXTURE_2D, sun_texid);
187 #else
188 #  error port me
189 #endif
190
191   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
192   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
193   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
194   setTexture();
195   glTexImage2D( GL_TEXTURE_2D,
196                 0,
197                 GL_RGBA,
198                 256, 256,
199                 0,
200                 GL_RGBA, GL_UNSIGNED_BYTE,
201                 sun_texbuf);
202      
203   SunObject = gluNewQuadric();
204   if(SunObject == NULL)
205     {
206       printf("gluNewQuadric(SunObject) failed  !\n");
207       exit(0);
208     }
209   
210   //SunList = 0;
211   distance = 0.0;
212 }
213
214 Star::~Star()
215 {
216   //delete SunObject;
217   delete [] sun_texbuf;
218 }
219
220
221
222 static int texWidth = 256;      /* 64x64 is plenty */
223
224 void Star::setTexture()
225 {
226   int texSize;
227   //void *textureBuf;
228   GLubyte *p;
229   int i,j;
230   double radius;
231   
232   texSize = texWidth*texWidth;
233   
234   sun_texbuf = new GLubyte[texSize*4];
235   if (!sun_texbuf) 
236     return;  // Ugly!
237   
238   p = sun_texbuf;
239   
240   radius = (double)(texWidth / 2);
241   
242   for (i=0; i < texWidth; i++) {
243     for (j=0; j < texWidth; j++) {
244       double x, y, d;
245             
246       *p = 0xff;
247       *(p+1) = 0xff;
248       *(p+2) = 0xff;
249
250       x = fabs((double)(i - (texWidth / 2)));
251       y = fabs((double)(j - (texWidth / 2)));
252
253       d = sqrt((x * x) + (y * y));
254       if (d < radius) {
255           double t = 1.0 - (d / radius); // t is 1.0 at center, 0.0 at edge */
256           // inverse square looks nice 
257           *(p+3) = (int)((double) 0xff * (t*t));
258       } else {
259           *(p+3) = 0x00;
260       }
261       p += 4;
262     }
263   }
264   //gluBuild2DMipmaps(GL_TEXTURE_2D, 1, texWidth, texWidth, 
265   //        GL_LUMINANCE,
266   //        GL_UNSIGNED_BYTE, textureBuf);
267   //free(textureBuf);
268 }
269 /*************************************************************************
270  * void Jupiter::updatePosition(FGTime *t, Star *ourSun)
271  * 
272  * calculates the current position of our sun.
273  *************************************************************************/
274 void Star::updatePosition(FGTime *t)
275 {
276   double 
277     actTime, eccAnom, 
278     xv, yv, v, r,
279     xe, ye, ze, ecl;
280
281   updateOrbElements(t);
282   
283   actTime = fgCalcActTime(t);
284   ecl = DEG_TO_RAD * (23.4393 - 3.563E-7 * actTime); // Angle in Radians
285   eccAnom = fgCalcEccAnom(M, e);  // Calculate the eccentric Anomaly (also known as solving Kepler's equation)
286   
287   xv = cos(eccAnom) - e;
288   yv = sqrt (1.0 - e*e) * sin(eccAnom);
289   v = atan2 (yv, xv);                   // the sun's true anomaly
290   distance = r = sqrt (xv*xv + yv*yv);  // and its distance
291
292   lonEcl = v + w; // the sun's true longitude
293   latEcl = 0;
294
295   // convert the sun's true longitude to ecliptic rectangular 
296   // geocentric coordinates (xs, ys)
297   xs = r * cos (lonEcl);
298   ys = r * sin (lonEcl);
299
300   // convert ecliptic coordinates to equatorial rectangular
301   // geocentric coordinates
302
303   xe = xs;
304   ye = ys * cos (ecl);
305   ze = ys * sin (ecl);
306
307   // And finally, calculate right ascension and declination
308   rightAscension = atan2 (ye, xe);
309   declination = atan2 (ze, sqrt (xe*xe + ye*ye));
310 }
311   
312 void Star::newImage(void)
313 {
314   /*static float stars[3];
315   stars[0] = 0.0;
316   stars[1] = 0.0;
317   stars[2] = 1.0;*/
318
319   fgLIGHT *l = &cur_light_params;
320   float sun_angle = l->sun_angle;
321   
322   if( sun_angle*RAD_TO_DEG < 100 ) { // else no need to draw sun
323     
324     
325     double x_2, x_4, x_8, x_10;
326     GLfloat ambient;
327     GLfloat amb[4];
328     int sun_size = 550;
329     
330     // daily variation sun gets larger near horizon
331     /*if(sun_angle*RAD_TO_DEG > 84.0 && sun_angle*RAD_TO_DEG < 95)
332       {
333       double sun_grow = 9*fabs(94-sun_angle*RAD_TO_DEG);
334       sun_size = (int)(sun_size + sun_size * cos(sun_grow*DEG_TO_RAD));
335       }*/
336     x_2 = sun_angle * sun_angle;
337     x_4 = x_2 * x_2;
338     x_8 = x_4 * x_4;
339     x_10 = x_8 * x_2;
340     ambient = (float)(0.4 * pow (1.1, - x_10 / 30.0));
341     if (ambient < 0.3) ambient = 0.3;
342     if (ambient > 1.0) ambient = 1.0;
343     
344     amb[0] = ((ambient * 6.0)  - 1.0); // minimum value = 0.8
345     amb[1] = ((ambient * 11.0) - 3.0); // minimum value = 0.3
346     amb[2] = ((ambient * 12.0) - 3.6); // minimum value = 0.0
347     amb[3] = 1.00;
348     
349     if (amb[0] > 1.0) amb[0] = 1.0;
350     if (amb[1] > 1.0) amb[1] = 1.0;
351     if (amb[2] > 1.0) amb[2] = 1.0;
352     xglColor3fv(amb);
353     glPushMatrix();
354     {
355       xglRotatef(((RAD_TO_DEG * rightAscension)- 90.0), 0.0, 0.0, 1.0);
356       xglRotatef((RAD_TO_DEG * declination), 1.0, 0.0, 0.0);
357       xglTranslatef(0,60000,0);
358       if (current_options.get_textures())
359         {
360           glEnable(GL_TEXTURE_2D); // TEXTURE ENABLED
361           glEnable(GL_BLEND);   // BLEND ENABLED
362           
363           // glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
364           glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
365           glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);  
366           glBindTexture(GL_TEXTURE_2D, sun_texid);
367
368           glBegin(GL_QUADS);
369           glTexCoord2f(0.0f, 0.0f); glVertex3f(-5000, 0.0, -5000);
370           glTexCoord2f(1.0f, 0.0f); glVertex3f( 5000, 0.0, -5000);
371           glTexCoord2f(1.0f, 1.0f); glVertex3f( 5000, 0.0,  5000);
372           glTexCoord2f(0.0f, 1.0f); glVertex3f(-5000, 0.0,  5000);
373           glEnd();
374         }
375       xglDisable(GL_TEXTURE_2D); // TEXTURE DISABLED
376       xglDisable(GL_BLEND);     // BLEND DISABLED
377     }
378
379     glPopMatrix();
380     glDisable(GL_LIGHTING);     // LIGHTING DISABLED
381     glDisable(GL_BLEND);        // BLEND DISABLED
382     glPushMatrix();
383     {     
384       xglRotatef(((RAD_TO_DEG * rightAscension)- 90.0), 0.0, 0.0, 1.0);
385       xglRotatef((RAD_TO_DEG * declination), 1.0, 0.0, 0.0);
386       xglColor4fv(amb);
387       xglTranslatef(0,60000,0);
388       gluSphere( SunObject,  sun_size, 10, 10 );
389       }
390     glPopMatrix();
391     glDisable(GL_TEXTURE_2D);   // TEXTURE DISABLED
392     glDisable(GL_BLEND);        // BLEND DISABLED  
393   }
394 }
395 #endif