]> git.mxchange.org Git - simgear.git/blob - simgear/sky/skysun.cxx
Working on ssg-ifying sky.
[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 <stdio.h>
28 #include <iostream>
29
30 #include <plib/ssg.h>
31
32 #include <simgear/constants.h>
33 #include <simgear/misc/fgpath.hxx>
34
35 #include "sphere.hxx"
36 #include "skysun.hxx"
37
38
39 // Constructor
40 FGSkySun::FGSkySun( void ) {
41 }
42
43
44 // Destructor
45 FGSkySun::~FGSkySun( void ) {
46 }
47
48
49 #if 0
50 static GLuint makeHalo( GLubyte *sun_texbuf, int width ) {
51     int texSize;
52     GLuint texid;
53     GLubyte *p;
54     int i,j;
55     double radius;
56   
57     // create a texture id
58 #ifdef GL_VERSION_1_1
59     glGenTextures(1, &texid);
60     glBindTexture(GL_TEXTURE_2D, texid);
61 #elif GL_EXT_texture_object
62     glGenTexturesEXT(1, &texid);
63     glBindTextureEXT(GL_TEXTURE_2D, texid);
64 #else
65 #   error port me
66 #endif
67
68     glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
69     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
70     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
71     glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ;
72  
73     // create the actual texture contents
74     texSize = width * width;
75   
76     if ( !sun_texbuf ) {
77         cout << "ouch ..." << endl;
78         exit(-1);  // Ugly!
79     }
80
81     p = sun_texbuf;
82   
83     radius = (double)(width / 2);
84   
85     GLubyte value;
86     double x, y, d;
87     for ( i = 0; i < width; i++ ) {
88         for ( j = 0; j < width; j++ ) {
89             x = fabs((double)(i - (width / 2)));
90             y = fabs((double)(j - (width / 2)));
91             d = sqrt((x * x) + (y * y));
92             if (d < radius) {
93                 // t is 1.0 at center, 0.0 at edge
94                 double t = 1.0 - (d / radius);
95
96                 // inverse square looks nice 
97                 value = (int)((double) 0xff * (t*t));
98             } else {
99                 value = 0x00;
100             }
101             *p = value;
102             *(p+1) = value;
103             *(p+2) = value;
104             // *(p+3) = value;
105
106             p += 3;
107         }
108     }
109
110     /* glTexImage2D( GL_TEXTURE_2D,
111                   0,
112                   GL_RGBA,
113                   width, width,
114                   0,
115                   GL_RGBA, GL_UNSIGNED_BYTE,
116                   sun_texbuf ); */
117
118     return texid;
119 }
120
121
122 #define RGB  3                  // 3 bytes of color info per pixel
123 #define RGBA 4                  // 4 bytes of color+alpha info
124 void my_glWritePPMFile(const char *filename, GLubyte *buffer, int win_width, int win_height, int mode)
125 {
126     int i, j, k, q;
127     unsigned char *ibuffer;
128     FILE *fp;
129     int pixelSize = mode==GL_RGBA?4:3;
130
131     ibuffer = (unsigned char *) malloc(win_width*win_height*RGB);
132
133     fp = fopen(filename, "wb");
134     fprintf(fp, "P6\n# CREATOR: glReadPixel()\n%d %d\n%d\n",
135             win_width, win_height, UCHAR_MAX);
136     q = 0;
137     for (i = 0; i < win_height; i++) {
138         for (j = 0; j < win_width; j++) {
139             for (k = 0; k < RGB; k++) {
140                 ibuffer[q++] = (unsigned char)
141                     *(buffer + (pixelSize*((win_height-1-i)*win_width+j)+k));
142             }
143         }
144     }
145
146     // *(buffer + (pixelSize*((win_height-1-i)*win_width+j)+k));
147
148     fwrite(ibuffer, sizeof(unsigned char), RGB*win_width*win_height, fp);
149     fclose(fp);
150     free(ibuffer);
151
152     printf("wrote file (%d x %d pixels, %d bytes)\n",
153            win_width, win_height, RGB*win_width*win_height);
154 }
155 #endif
156
157
158 // initialize the sun object and connect it into our scene graph root
159 bool FGSkySun::initialize( const FGPath& path ) {
160     // create the scene graph for the sun/halo
161     skysun = new ssgRoot;
162     skysun->setName( "Sky Sun" );
163
164     // set up the orb state
165     orb_state = new ssgSimpleState();
166     orb_state->setShadeModel( GL_SMOOTH );
167     orb_state->disable( GL_LIGHTING );
168     orb_state->disable( GL_CULL_FACE );
169     orb_state->disable( GL_TEXTURE_2D );
170     orb_state->enable( GL_COLOR_MATERIAL );
171     orb_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
172     orb_state->disable( GL_BLEND );
173     orb_state->disable( GL_ALPHA_TEST );
174
175     cl = new ssgColourArray( 1 );
176     sgVec4 color;
177     sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 );
178     cl->add( color );
179
180     ssgBranch *orb = ssgMakeSphere( orb_state, cl, 550.0, 10, 10 );
181
182     // force a repaint of the sun colors with arbitrary defaults
183     repaint( 0.0 );
184
185     // build the halo
186     // sun_texbuf = new GLubyte[64*64*3];
187     // sun_texid = makeHalo( sun_texbuf, 64 );
188     // my_glWritePPMFile("sunhalo.ppm", sun_texbuf, 64, 64, RGB);
189
190     // set up the halo state
191     FGPath halo_path = path;
192     halo_path.append( "halo.rgba" );
193
194     halo_state = new ssgSimpleState();
195     halo_state->setTexture( (char *)halo_path.c_str() );
196     // halo_state->setTexture( sun_texid );
197     halo_state->enable( GL_TEXTURE_2D );
198     halo_state->disable( GL_LIGHTING );
199     halo_state->setShadeModel( GL_SMOOTH );
200     halo_state->disable( GL_CULL_FACE );
201
202     halo_state->disable( GL_COLOR_MATERIAL );
203     halo_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
204     halo_state->setMaterial ( GL_AMBIENT_AND_DIFFUSE, 1, 1, 1, 1 ) ;
205     halo_state -> setMaterial ( GL_EMISSION, 0, 0, 0, 1 ) ;
206     halo_state -> setMaterial ( GL_SPECULAR, 0, 0, 0, 1 ) ;
207     // halo_state -> setShininess ( 0 ) ;
208
209     halo_state->setTranslucent();
210     halo_state->enable( GL_ALPHA_TEST );
211     halo_state->setAlphaClamp(0.01);
212     halo_state->enable ( GL_BLEND ) ;
213
214
215     // Build ssg structure
216     sgVec3 v3;
217     halo_vl = new ssgVertexArray;
218     sgSetVec3( v3, -5000.0, 0.0, -5000.0 );
219     halo_vl->add( v3 );
220     sgSetVec3( v3, 5000.0, 0.0, -5000.0 );
221     halo_vl->add( v3 );
222     sgSetVec3( v3, -5000.0, 0.0,  5000.0 );
223     halo_vl->add( v3 );
224     sgSetVec3( v3, 5000.0, 0.0,  5000.0 );
225     halo_vl->add( v3 );
226
227     sgVec2 v2;
228     halo_tl = new ssgTexCoordArray;
229     sgSetVec2( v2, 0.0f, 0.0f );
230     halo_tl->add( v2 );
231     sgSetVec2( v2, 1.0, 0.0 );
232     halo_tl->add( v2 );
233     sgSetVec2( v2, 0.0, 1.0 );
234     halo_tl->add( v2 );
235     sgSetVec2( v2, 1.0, 1.0 );
236     halo_tl->add( v2 );
237
238     ssgLeaf *halo = 
239         new ssgVtxTable ( GL_TRIANGLE_STRIP, halo_vl, NULL, halo_tl, cl );
240     halo->setState( halo_state );
241
242     // build the ssg scene graph sub tree for the sky and connected
243     // into the provide scene graph branch
244     sun_selector = new ssgSelector;
245     sun_transform = new ssgTransform;
246
247     sun_selector->addKid( sun_transform );
248     sun_selector->clrTraversalMaskBits( SSGTRAV_HOT );
249
250     skysun->addKid( sun_selector );
251
252     sun_transform->addKid( halo );
253     sun_transform->addKid( orb );
254
255     return true;
256 }
257
258
259 // repaint the sun colors based on current value of sun_angle in
260 // degrees relative to verticle
261 // 0 degrees = high noon
262 // 90 degrees = sun rise/set
263 // 180 degrees = darkest midnight
264 bool FGSkySun::repaint( double sun_angle ) {
265     if ( sun_angle * RAD_TO_DEG < 100 ) {
266         // else sun is well below horizon (so no point in repainting it)
267     
268         // x_10 = sun_angle^10
269         double x_10 = sun_angle * sun_angle * sun_angle * sun_angle * sun_angle
270             * sun_angle * sun_angle * sun_angle * sun_angle * sun_angle;
271
272         float ambient = (float)(0.4 * pow (1.1, - x_10 / 30.0));
273         if (ambient < 0.3) { ambient = 0.3; }
274         if (ambient > 1.0) { ambient = 1.0; }
275
276         sgVec4 color;
277         sgSetVec4( color,
278                    (ambient * 6.0)  - 1.0, // minimum value = 0.8
279                    (ambient * 11.0) - 3.0, // minimum value = 0.3
280                    (ambient * 12.0) - 3.6, // minimum value = 0.0
281                    1.0 );
282     
283         if (color[0] > 1.0) color[0] = 1.0;
284         if (color[1] > 1.0) color[1] = 1.0;
285         if (color[2] > 1.0) color[2] = 1.0;
286
287         // cout << "color = " << color[0] << " " << color[1] << " " 
288         //      << color[2] << endl;
289
290         float *ptr;
291         ptr = cl->get( 0 );
292         sgCopyVec4( ptr, color );
293     }
294
295     return true;
296 }
297
298
299 // reposition the sun at the specified right ascension and
300 // declination, offset by our current position (p) so that it appears
301 // fixed at a great distance from the viewer.  Also add in an optional
302 // rotation (i.e. for the current time of day.)
303 bool FGSkySun::reposition( sgVec3 p, double angle,
304                            double rightAscension, double declination )
305 {
306     sgMat4 T1, T2, GST, RA, DEC;
307     sgVec3 axis;
308     sgVec3 v;
309
310     sgMakeTransMat4( T1, p );
311
312     sgSetVec3( axis, 0.0, 0.0, -1.0 );
313     sgMakeRotMat4( GST, angle, axis );
314
315     // xglRotatef(((RAD_TO_DEG * rightAscension)- 90.0), 0.0, 0.0, 1.0);
316     sgSetVec3( axis, 0.0, 0.0, 1.0 );
317     sgMakeRotMat4( RA, (rightAscension * RAD_TO_DEG) - 90.0, axis );
318
319     // xglRotatef((RAD_TO_DEG * declination), 1.0, 0.0, 0.0);
320     sgSetVec3( axis, 1.0, 0.0, 0.0 );
321     sgMakeRotMat4( DEC, declination * RAD_TO_DEG, axis );
322
323     // xglTranslatef(0,60000,0);
324     sgSetVec3( v, 0.0, 60000.0, 0.0 );
325     sgMakeTransMat4( T2, v );
326
327     sgMat4 TRANSFORM;
328     sgCopyMat4( TRANSFORM, T1 );
329     sgPreMultMat4( TRANSFORM, GST );
330     sgPreMultMat4( TRANSFORM, RA );
331     sgPreMultMat4( TRANSFORM, DEC );
332     sgPreMultMat4( TRANSFORM, T2 );
333
334     sgCoord skypos;
335     sgSetCoord( &skypos, TRANSFORM );
336
337     sun_transform->setTransform( &skypos );
338
339     return true;
340 }
341
342
343 // Draw the sun
344 bool FGSkySun::draw() {
345     ssgCullAndDraw( skysun );
346
347     return true;
348 }