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