]> git.mxchange.org Git - simgear.git/blob - simgear/sky/skysun.cxx
Working on drawing sun and sun halo.
[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 <iostream>
28
29 #include <plib/ssg.h>
30
31 #include <simgear/constants.h>
32
33 #include "sphere.hxx"
34 #include "skysun.hxx"
35
36
37 // Constructor
38 FGSkySun::FGSkySun( void ) {
39 }
40
41
42 // Destructor
43 FGSkySun::~FGSkySun( void ) {
44 }
45
46
47 static GLuint makeHalo( GLubyte *sun_texbuf ) {
48     int texWidth = 64;          // 64x64 is plenty
49     int texSize;
50     GLuint texid;
51     GLubyte *p;
52     int i,j;
53     double radius;
54   
55     // create a texture id
56 #ifdef GL_VERSION_1_1
57     glGenTextures(1, &texid);
58     glBindTexture(GL_TEXTURE_2D, texid);
59 #elif GL_EXT_texture_object
60     glGenTexturesEXT(1, &texid);
61     glBindTextureEXT(GL_TEXTURE_2D, texid);
62 #else
63 #   error port me
64 #endif
65
66     glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
67     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
68     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
69     glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ;
70  
71     // create the actual texture contents
72     texSize = texWidth * texWidth;
73   
74     sun_texbuf = new GLubyte[texSize*4];
75     if ( !sun_texbuf ) {
76         return 0;  // Ugly!
77     }
78
79     p = sun_texbuf;
80   
81     radius = (double)(texWidth / 2);
82   
83     for (i=0; i < texWidth; i++) {
84         for (j=0; j < texWidth; j++) {
85             double x, y, d;
86             
87             *p = 0xff;
88             *(p+1) = 0xff;
89             *(p+2) = 0xff;
90
91             x = fabs((double)(i - (texWidth / 2)));
92             y = fabs((double)(j - (texWidth / 2)));
93
94             d = sqrt((x * x) + (y * y));
95             if (d < radius) {
96                 // t is 1.0 at center, 0.0 at edge
97                 double t = 1.0 - (d / radius);
98
99                 // inverse square looks nice 
100                 *(p+3) = (int)((double) 0xff * (t*t));
101             } else {
102                 *(p+3) = 0x00;
103             }
104             p += 4;
105         }
106     }
107
108     glTexImage2D( GL_TEXTURE_2D,
109                   0,
110                   GL_RGBA,
111                   texWidth, texWidth,
112                   0,
113                   GL_RGBA, GL_UNSIGNED_BYTE,
114                   sun_texbuf );
115
116     return texid;
117 }
118
119
120 // initialize the sun object and connect it into our scene graph root
121 bool FGSkySun::initialize() {
122
123     // create the scene graph for the sun/halo
124     skysun = new ssgRoot;
125     skysun->setName( "Sky Sun" );
126
127     // set up the orb state
128     orb_state = new ssgSimpleState();
129     orb_state->setShadeModel( GL_SMOOTH );
130     orb_state->disable( GL_LIGHTING );
131     orb_state->disable( GL_CULL_FACE );
132     orb_state->disable( GL_TEXTURE_2D );
133     orb_state->enable( GL_COLOR_MATERIAL );
134     orb_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
135     orb_state->disable( GL_BLEND );
136
137     cl = new ssgColourArray( 1 );
138     ssgBranch *orb = ssgMakeSphere( orb_state, cl, 550.0, 10, 10 );
139
140     // force a repaint of the sun colors with arbitrary defaults
141     repaint( 0.0 );
142
143     // build the ssg scene graph sub tree for the sky and connected
144     // into the provide scene graph branch
145     sun_selector = new ssgSelector;
146     sun_transform = new ssgTransform;
147
148     // orb->setState( orb_state );
149
150     sun_transform->addKid( orb );
151
152     sun_selector->addKid( sun_transform );
153     sun_selector->clrTraversalMaskBits( SSGTRAV_HOT );
154
155     skysun->addKid( sun_selector );
156
157     // set up the halo state
158     halo_state = new ssgSimpleState();
159     halo_state->setShadeModel( GL_SMOOTH );
160     halo_state->disable( GL_LIGHTING );
161     halo_state->disable( GL_CULL_FACE );
162     halo_state->enable( GL_TEXTURE_2D );
163     halo_state->enable( GL_COLOR_MATERIAL );
164     halo_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
165     halo_state->enable( GL_BLEND );
166     halo_state->setTranslucent();
167
168     // build the halo
169     sun_texid = makeHalo( sun_texbuf );
170     halo_state->setTexture( sun_texid );
171     cout << "set texture" << endl;;
172
173     // Build ssg structure
174     sgVec3 v3;
175     halo_vl = new ssgVertexArray;
176     sgSetVec3( v3, -5000.0, 0.0, -5000.0 );
177     halo_vl->add( v3 );
178     sgSetVec3( v3, 5000.0, 0.0, -5000.0 );
179     halo_vl->add( v3 );
180     sgSetVec3( v3, 5000.0, 0.0,  5000.0 );
181     halo_vl->add( v3 );
182     sgSetVec3( v3, -5000.0, 0.0,  5000.0 );
183     halo_vl->add( v3 );
184
185     sgVec2 v2;
186     halo_tl = new ssgTexCoordArray;
187     sgSetVec2( v2, 0.0f, 0.0f );
188     halo_tl->add( v2 );
189     sgSetVec2( v2, 1.0, 0.0 );
190     halo_tl->add( v2 );
191     sgSetVec2( v2, 1.0, 1.0 );
192     halo_tl->add( v2 );
193     sgSetVec2( v2, 0.0, 1.0 );
194     halo_tl->add( v2 );
195
196     ssgLeaf *halo = 
197         new ssgVtxTable ( GL_QUADS, halo_vl, NULL, halo_tl, cl );
198     halo->setState( halo_state);
199
200     sun_transform->addKid( halo );
201
202     return true;
203 }
204
205
206 // repaint the sun colors based on current value of sun_angle in
207 // degrees relative to verticle
208 // 0 degrees = high noon
209 // 90 degrees = sun rise/set
210 // 180 degrees = darkest midnight
211 bool FGSkySun::repaint( double sun_angle ) {
212     if ( sun_angle * RAD_TO_DEG < 100 ) {
213         // else sun is well below horizon (so no point in repainting it)
214     
215         // x_10 = sun_angle^10
216         double x_10 = sun_angle * sun_angle * sun_angle * sun_angle * sun_angle
217             * sun_angle * sun_angle * sun_angle * sun_angle * sun_angle;
218
219         float ambient = (float)(0.4 * pow (1.1, - x_10 / 30.0));
220         if (ambient < 0.3) { ambient = 0.3; }
221         if (ambient > 1.0) { ambient = 1.0; }
222
223         sgVec3 color;
224         sgSetVec3( color,
225                    (ambient * 6.0)  - 1.0, // minimum value = 0.8
226                    (ambient * 11.0) - 3.0, // minimum value = 0.3
227                    (ambient * 12.0) - 3.6  // minimum value = 0.0
228                    );
229     
230         if (color[0] > 1.0) color[0] = 1.0;
231         if (color[1] > 1.0) color[1] = 1.0;
232         if (color[2] > 1.0) color[2] = 1.0;
233
234         // cout << "color = " << color[0] << " " << color[1] << " " 
235         //      << color[2] << endl;
236
237         float *ptr;
238         ptr = cl->get( 0 );
239         sgCopyVec3( ptr, color );
240     }
241
242     return true;
243 }
244
245
246 // reposition the sun at the specified right ascension and
247 // declination, offset by our current position (p) so that it appears
248 // fixed at a great distance from the viewer.  Also add in an optional
249 // rotation (i.e. for the current time of day.)
250 bool FGSkySun::reposition( sgVec3 p, double angle,
251                            double rightAscension, double declination )
252 {
253     sgMat4 T1, T2, GST, RA, DEC;
254     sgVec3 axis;
255     sgVec3 v;
256
257     sgMakeTransMat4( T1, p );
258
259     sgSetVec3( axis, 0.0, 0.0, -1.0 );
260     sgMakeRotMat4( GST, angle, axis );
261
262     // xglRotatef(((RAD_TO_DEG * rightAscension)- 90.0), 0.0, 0.0, 1.0);
263     sgSetVec3( axis, 0.0, 0.0, 1.0 );
264     sgMakeRotMat4( RA, (rightAscension * RAD_TO_DEG) - 90.0, axis );
265
266     // xglRotatef((RAD_TO_DEG * declination), 1.0, 0.0, 0.0);
267     sgSetVec3( axis, 1.0, 0.0, 0.0 );
268     sgMakeRotMat4( DEC, declination * RAD_TO_DEG, axis );
269
270     // xglTranslatef(0,60000,0);
271     sgSetVec3( v, 0.0, 60000.0, 0.0 );
272     sgMakeTransMat4( T2, v );
273
274     sgMat4 TRANSFORM;
275     sgCopyMat4( TRANSFORM, T1 );
276     sgPreMultMat4( TRANSFORM, GST );
277     sgPreMultMat4( TRANSFORM, RA );
278     sgPreMultMat4( TRANSFORM, DEC );
279     sgPreMultMat4( TRANSFORM, T2 );
280
281     sgCoord skypos;
282     sgSetCoord( &skypos, TRANSFORM );
283
284     sun_transform->setTransform( &skypos );
285
286     return true;
287 }
288
289
290 // Draw the sun
291 bool FGSkySun::draw() {
292     ssgCullAndDraw( skysun );
293
294     return true;
295 }
296
297
298 #if 0
299 /*************************************************************************
300  * Star::Star(FGTime *t)
301  * Public constructor for class Star
302  * Argument: The current time.
303  * the hard coded orbital elements our sun are passed to 
304  * CelestialBody::CelestialBody();
305  * note that the word sun is avoided, in order to prevent some compilation
306  * problems on sun systems 
307  ************************************************************************/
308 Star::Star(FGTime *t) :
309   CelestialBody (0.000000,  0.0000000000,
310                  0.0000,    0.00000,
311                  282.9404,  4.7093500E-5,       
312                  1.0000000, 0.000000,   
313                  0.016709,  -1.151E-9,
314                  356.0470,  0.98560025850, t)
315 {
316     
317   FG_LOG( FG_GENERAL, FG_INFO, "Initializing Sun Texture");
318 #ifdef GL_VERSION_1_1
319   glGenTextures(1, &sun_texid);
320   glBindTexture(GL_TEXTURE_2D, sun_texid);
321 #elif GL_EXT_texture_object
322   glGenTexturesEXT(1, &sun_texid);
323   glBindTextureEXT(GL_TEXTURE_2D, sun_texid);
324 #else
325 #  error port me
326 #endif
327
328   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
329   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
330   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
331   setTexture();
332   glTexImage2D( GL_TEXTURE_2D,
333                 0,
334                 GL_RGBA,
335                 256, 256,
336                 0,
337                 GL_RGBA, GL_UNSIGNED_BYTE,
338                 sun_texbuf);
339      
340   SunObject = gluNewQuadric();
341   if(SunObject == NULL)
342     {
343       printf("gluNewQuadric(SunObject) failed  !\n");
344       exit(0);
345     }
346   
347   //SunList = 0;
348   distance = 0.0;
349 }
350
351 Star::~Star()
352 {
353   //delete SunObject;
354   delete [] sun_texbuf;
355 }
356
357
358
359 static int texWidth = 256;      /* 64x64 is plenty */
360
361 void Star::setTexture()
362 {
363   int texSize;
364   //void *textureBuf;
365   GLubyte *p;
366   int i,j;
367   double radius;
368   
369   texSize = texWidth*texWidth;
370   
371   sun_texbuf = new GLubyte[texSize*4];
372   if (!sun_texbuf) 
373     return;  // Ugly!
374   
375   p = sun_texbuf;
376   
377   radius = (double)(texWidth / 2);
378   
379   for (i=0; i < texWidth; i++) {
380     for (j=0; j < texWidth; j++) {
381       double x, y, d;
382             
383       *p = 0xff;
384       *(p+1) = 0xff;
385       *(p+2) = 0xff;
386
387       x = fabs((double)(i - (texWidth / 2)));
388       y = fabs((double)(j - (texWidth / 2)));
389
390       d = sqrt((x * x) + (y * y));
391       if (d < radius) {
392           double t = 1.0 - (d / radius); // t is 1.0 at center, 0.0 at edge */
393           // inverse square looks nice 
394           *(p+3) = (int)((double) 0xff * (t*t));
395       } else {
396           *(p+3) = 0x00;
397       }
398       p += 4;
399     }
400   }
401   //gluBuild2DMipmaps(GL_TEXTURE_2D, 1, texWidth, texWidth, 
402   //        GL_LUMINANCE,
403   //        GL_UNSIGNED_BYTE, textureBuf);
404   //free(textureBuf);
405 }
406 /*************************************************************************
407  * void Jupiter::updatePosition(FGTime *t, Star *ourSun)
408  * 
409  * calculates the current position of our sun.
410  *************************************************************************/
411 void Star::updatePosition(FGTime *t)
412 {
413   double 
414     actTime, eccAnom, 
415     xv, yv, v, r,
416     xe, ye, ze, ecl;
417
418   updateOrbElements(t);
419   
420   actTime = fgCalcActTime(t);
421   ecl = DEG_TO_RAD * (23.4393 - 3.563E-7 * actTime); // Angle in Radians
422   eccAnom = fgCalcEccAnom(M, e);  // Calculate the eccentric Anomaly (also known as solving Kepler's equation)
423   
424   xv = cos(eccAnom) - e;
425   yv = sqrt (1.0 - e*e) * sin(eccAnom);
426   v = atan2 (yv, xv);                   // the sun's true anomaly
427   distance = r = sqrt (xv*xv + yv*yv);  // and its distance
428
429   lonEcl = v + w; // the sun's true longitude
430   latEcl = 0;
431
432   // convert the sun's true longitude to ecliptic rectangular 
433   // geocentric coordinates (xs, ys)
434   xs = r * cos (lonEcl);
435   ys = r * sin (lonEcl);
436
437   // convert ecliptic coordinates to equatorial rectangular
438   // geocentric coordinates
439
440   xe = xs;
441   ye = ys * cos (ecl);
442   ze = ys * sin (ecl);
443
444   // And finally, calculate right ascension and declination
445   rightAscension = atan2 (ye, xe);
446   declination = atan2 (ze, sqrt (xe*xe + ye*ye));
447 }
448   
449 void Star::newImage(void)
450 {
451   /*static float stars[3];
452   stars[0] = 0.0;
453   stars[1] = 0.0;
454   stars[2] = 1.0;*/
455
456   fgLIGHT *l = &cur_light_params;
457   float sun_angle = l->sun_angle;
458   
459   if( sun_angle*RAD_TO_DEG < 100 ) { // else no need to draw sun
460     
461     
462     double x_2, x_4, x_8, x_10;
463     GLfloat ambient;
464     GLfloat amb[4];
465     int sun_size = 550;
466     
467     // daily variation sun gets larger near horizon
468     /*if(sun_angle*RAD_TO_DEG > 84.0 && sun_angle*RAD_TO_DEG < 95)
469       {
470       double sun_grow = 9*fabs(94-sun_angle*RAD_TO_DEG);
471       sun_size = (int)(sun_size + sun_size * cos(sun_grow*DEG_TO_RAD));
472       }*/
473     x_2 = sun_angle * sun_angle;
474     x_4 = x_2 * x_2;
475     x_8 = x_4 * x_4;
476     x_10 = x_8 * x_2;
477     ambient = (float)(0.4 * pow (1.1, - x_10 / 30.0));
478     if (ambient < 0.3) ambient = 0.3;
479     if (ambient > 1.0) ambient = 1.0;
480     
481     amb[0] = ((ambient * 6.0)  - 1.0); // minimum value = 0.8
482     amb[1] = ((ambient * 11.0) - 3.0); // minimum value = 0.3
483     amb[2] = ((ambient * 12.0) - 3.6); // minimum value = 0.0
484     amb[3] = 1.00;
485     
486     if (amb[0] > 1.0) amb[0] = 1.0;
487     if (amb[1] > 1.0) amb[1] = 1.0;
488     if (amb[2] > 1.0) amb[2] = 1.0;
489     glColor3fv(amb);
490     glPushMatrix();
491     {
492       glRotatef(((RAD_TO_DEG * rightAscension)- 90.0), 0.0, 0.0, 1.0);
493       glRotatef((RAD_TO_DEG * declination), 1.0, 0.0, 0.0);
494       glTranslatef(0,60000,0);
495       if (current_options.get_textures())
496         {
497           glEnable(GL_TEXTURE_2D); // TEXTURE ENABLED
498           glEnable(GL_BLEND);   // BLEND ENABLED
499           
500           // glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
501           glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
502           glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);  
503           glBindTexture(GL_TEXTURE_2D, sun_texid);
504
505           glBegin(GL_QUADS);
506           glTexCoord2f(0.0f, 0.0f); glVertex3f(-5000, 0.0, -5000);
507           glTexCoord2f(1.0f, 0.0f); glVertex3f( 5000, 0.0, -5000);
508           glTexCoord2f(1.0f, 1.0f); glVertex3f( 5000, 0.0,  5000);
509           glTexCoord2f(0.0f, 1.0f); glVertex3f(-5000, 0.0,  5000);
510           glEnd();
511         }
512       glDisable(GL_TEXTURE_2D); // TEXTURE DISABLED
513       glDisable(GL_BLEND);      // BLEND DISABLED
514     }
515
516     glPopMatrix();
517     glDisable(GL_LIGHTING);     // LIGHTING DISABLED
518     glDisable(GL_BLEND);        // BLEND DISABLED
519     glPushMatrix();
520     {     
521       glRotatef(((RAD_TO_DEG * rightAscension)- 90.0), 0.0, 0.0, 1.0);
522       glRotatef((RAD_TO_DEG * declination), 1.0, 0.0, 0.0);
523       glColor4fv(amb);
524       glTranslatef(0,60000,0);
525       gluSphere( SunObject,  sun_size, 10, 10 );
526       }
527     glPopMatrix();
528     glDisable(GL_TEXTURE_2D);   // TEXTURE DISABLED
529     glDisable(GL_BLEND);        // BLEND DISABLED  
530   }
531 }
532 #endif