1 // skysun.hxx -- draw a sun object
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).
8 // Separated out rendering pieces and converted to ssg by Curt Olson,
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.
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.
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.
31 #include <simgear/constants.h>
38 FGSkySun::FGSkySun( void ) {
43 FGSkySun::~FGSkySun( void ) {
47 static GLuint makeHalo( GLubyte *sun_texbuf ) {
48 int texWidth = 64; // 64x64 is plenty
55 // create a texture id
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);
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 ) ;
71 // create the actual texture contents
72 texSize = texWidth * texWidth;
74 sun_texbuf = new GLubyte[texSize*4];
81 radius = (double)(texWidth / 2);
83 for (i=0; i < texWidth; i++) {
84 for (j=0; j < texWidth; j++) {
91 x = fabs((double)(i - (texWidth / 2)));
92 y = fabs((double)(j - (texWidth / 2)));
94 d = sqrt((x * x) + (y * y));
96 // t is 1.0 at center, 0.0 at edge
97 double t = 1.0 - (d / radius);
99 // inverse square looks nice
100 *(p+3) = (int)((double) 0xff * (t*t));
108 glTexImage2D( GL_TEXTURE_2D,
113 GL_RGBA, GL_UNSIGNED_BYTE,
120 // initialize the sun object and connect it into our scene graph root
121 bool FGSkySun::initialize() {
123 // create the scene graph for the sun/halo
124 skysun = new ssgRoot;
125 skysun->setName( "Sky Sun" );
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 );
137 cl = new ssgColourArray( 1 );
138 ssgBranch *orb = ssgMakeSphere( orb_state, cl, 550.0, 10, 10 );
140 // force a repaint of the sun colors with arbitrary defaults
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;
148 // orb->setState( orb_state );
150 sun_transform->addKid( orb );
152 sun_selector->addKid( sun_transform );
153 sun_selector->clrTraversalMaskBits( SSGTRAV_HOT );
155 skysun->addKid( sun_selector );
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();
169 sun_texid = makeHalo( sun_texbuf );
170 halo_state->setTexture( sun_texid );
171 cout << "set texture" << endl;;
173 // Build ssg structure
175 halo_vl = new ssgVertexArray;
176 sgSetVec3( v3, -5000.0, 0.0, -5000.0 );
178 sgSetVec3( v3, 5000.0, 0.0, -5000.0 );
180 sgSetVec3( v3, 5000.0, 0.0, 5000.0 );
182 sgSetVec3( v3, -5000.0, 0.0, 5000.0 );
186 halo_tl = new ssgTexCoordArray;
187 sgSetVec2( v2, 0.0f, 0.0f );
189 sgSetVec2( v2, 1.0, 0.0 );
191 sgSetVec2( v2, 1.0, 1.0 );
193 sgSetVec2( v2, 0.0, 1.0 );
197 new ssgVtxTable ( GL_QUADS, halo_vl, NULL, halo_tl, cl );
198 halo->setState( halo_state);
200 sun_transform->addKid( halo );
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)
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;
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; }
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
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;
234 // cout << "color = " << color[0] << " " << color[1] << " "
235 // << color[2] << endl;
239 sgCopyVec3( ptr, color );
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 )
253 sgMat4 T1, T2, GST, RA, DEC;
257 sgMakeTransMat4( T1, p );
259 sgSetVec3( axis, 0.0, 0.0, -1.0 );
260 sgMakeRotMat4( GST, angle, axis );
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 );
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 );
270 // xglTranslatef(0,60000,0);
271 sgSetVec3( v, 0.0, 60000.0, 0.0 );
272 sgMakeTransMat4( T2, v );
275 sgCopyMat4( TRANSFORM, T1 );
276 sgPreMultMat4( TRANSFORM, GST );
277 sgPreMultMat4( TRANSFORM, RA );
278 sgPreMultMat4( TRANSFORM, DEC );
279 sgPreMultMat4( TRANSFORM, T2 );
282 sgSetCoord( &skypos, TRANSFORM );
284 sun_transform->setTransform( &skypos );
291 bool FGSkySun::draw() {
292 ssgCullAndDraw( skysun );
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,
311 282.9404, 4.7093500E-5,
314 356.0470, 0.98560025850, t)
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);
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);
332 glTexImage2D( GL_TEXTURE_2D,
337 GL_RGBA, GL_UNSIGNED_BYTE,
340 SunObject = gluNewQuadric();
341 if(SunObject == NULL)
343 printf("gluNewQuadric(SunObject) failed !\n");
354 delete [] sun_texbuf;
359 static int texWidth = 256; /* 64x64 is plenty */
361 void Star::setTexture()
369 texSize = texWidth*texWidth;
371 sun_texbuf = new GLubyte[texSize*4];
377 radius = (double)(texWidth / 2);
379 for (i=0; i < texWidth; i++) {
380 for (j=0; j < texWidth; j++) {
387 x = fabs((double)(i - (texWidth / 2)));
388 y = fabs((double)(j - (texWidth / 2)));
390 d = sqrt((x * x) + (y * y));
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));
401 //gluBuild2DMipmaps(GL_TEXTURE_2D, 1, texWidth, texWidth,
403 // GL_UNSIGNED_BYTE, textureBuf);
406 /*************************************************************************
407 * void Jupiter::updatePosition(FGTime *t, Star *ourSun)
409 * calculates the current position of our sun.
410 *************************************************************************/
411 void Star::updatePosition(FGTime *t)
418 updateOrbElements(t);
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)
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
429 lonEcl = v + w; // the sun's true longitude
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);
437 // convert ecliptic coordinates to equatorial rectangular
438 // geocentric coordinates
444 // And finally, calculate right ascension and declination
445 rightAscension = atan2 (ye, xe);
446 declination = atan2 (ze, sqrt (xe*xe + ye*ye));
449 void Star::newImage(void)
451 /*static float stars[3];
456 fgLIGHT *l = &cur_light_params;
457 float sun_angle = l->sun_angle;
459 if( sun_angle*RAD_TO_DEG < 100 ) { // else no need to draw sun
462 double x_2, x_4, x_8, x_10;
467 // daily variation sun gets larger near horizon
468 /*if(sun_angle*RAD_TO_DEG > 84.0 && sun_angle*RAD_TO_DEG < 95)
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));
473 x_2 = sun_angle * sun_angle;
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;
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
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;
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())
497 glEnable(GL_TEXTURE_2D); // TEXTURE ENABLED
498 glEnable(GL_BLEND); // BLEND ENABLED
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);
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);
512 glDisable(GL_TEXTURE_2D); // TEXTURE DISABLED
513 glDisable(GL_BLEND); // BLEND DISABLED
517 glDisable(GL_LIGHTING); // LIGHTING DISABLED
518 glDisable(GL_BLEND); // BLEND DISABLED
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);
524 glTranslatef(0,60000,0);
525 gluSphere( SunObject, sun_size, 10, 10 );
528 glDisable(GL_TEXTURE_2D); // TEXTURE DISABLED
529 glDisable(GL_BLEND); // BLEND DISABLED