1 /*
2      PLIB - A Suite of Portable Game Libraries
3      Copyright (C) 1998,2002  Steve Baker
4 
5      This library is free software; you can redistribute it and/or
6      modify it under the terms of the GNU Library General Public
7      License as published by the Free Software Foundation; either
8      version 2 of the License, or (at your option) any later version.
9 
10      This library is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Library General Public License for more details.
14 
15      You should have received a copy of the GNU Library General Public
16      License along with this library; if not, write to the Free Software
17      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 
19      For further information visit http://plib.sourceforge.net
20 
21      $Id: ssgaStars.cxx 1798 2003-09-26 14:54:20Z sjbaker $
22 */
23 
24 // Written by Durk Talsma. Originally started October 1997, for distribution
25 // with the FlightGear project. Version 2 was written in August and
26 // September 1998. This code is based upon algorithms and data kindly
27 // provided by Mr. Paul Schlyter. (pausch@saaf.se).
28 //
29 // Separated out rendering pieces and converted to ssg by Curt Olson,
30 // March 2000
31 //
32 // Moved into ssgAux, July 2003.
33 
34 #include "ssgaSky.h"
35 
36 
ssgaStarPreDraw(ssgEntity * e)37 static int ssgaStarPreDraw( ssgEntity *e )
38 {
39   ssgLeaf *f = (ssgLeaf *)e;
40   if ( f -> hasState () ) f->getState()->apply() ;
41 
42   glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_FOG_BIT );
43 
44   //glDisable( GL_DEPTH_TEST );
45   glDisable( GL_FOG );
46   // glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
47 
48   return true;
49 }
50 
51 
ssgaStarPostDraw(ssgEntity * e)52 static int ssgaStarPostDraw( ssgEntity *e )
53 {
54     glPopAttrib();
55 
56     return true;
57 }
58 
59 
ssgaStars(void)60 ssgaStars::ssgaStars( void ) :
61   stars_transform(0),
62   old_phase(-1)
63 {
64 }
65 
66 
~ssgaStars(void)67 ssgaStars::~ssgaStars( void )
68 {
69   ssgDeRefDelete( stars_transform );
70 }
71 
72 
build(int num,sgdVec3 * star_data,double star_dist)73 ssgBranch * ssgaStars::build( int num, sgdVec3 *star_data, double star_dist )
74 {
75   sgVec4 color;
76 
77   // clean-up previous
78   ssgDeRefDelete( stars_transform );
79 
80   // create new
81   stars_transform = new ssgTransform;
82   stars_transform->ref();
83 
84   if ( star_data == NULL )
85     ulSetError(UL_WARNING, "null star data passed to ssgaStars::build()");
86 
87   // set up the orb state
88   state = new ssgSimpleState();
89   state->disable( GL_LIGHTING );
90   state->disable( GL_CULL_FACE );
91   state->disable( GL_TEXTURE_2D );
92   state->enable( GL_COLOR_MATERIAL );
93   state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
94   state->setMaterial( GL_EMISSION, 0, 0, 0, 1 );
95   state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 );
96   state->enable( GL_BLEND );
97   state->disable( GL_ALPHA_TEST );
98 
99   vl = new ssgVertexArray( num );
100   cl = new ssgColourArray( num );
101   // cl = new ssgColourArray( 1 );
102   // sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 );
103   // cl->add( color );
104 
105   // Build ssg structure
106   sgVec3 p;
107   for ( int i = 0; i < num; ++i ) {
108     // position seeded to arbitrary values
109     sgSetVec3( p,
110       (float)( star_dist * cos( star_data[i][0] )
111         * cos( star_data[i][1] )),
112       (float)( star_dist * sin( star_data[i][0] )
113         * cos( star_data[i][1] )),
114       (float)( star_dist * sin( star_data[i][1] )));
115     vl->add( p );
116 
117     // color (magnitude)
118     sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 );
119     cl->add( color );
120   }
121 
122   ssgLeaf *stars_obj =
123     new ssgVtxTable ( GL_POINTS, vl, NULL, NULL, cl );
124   stars_obj->setState( state );
125   stars_obj->setCallback( SSG_CALLBACK_PREDRAW, ssgaStarPreDraw );
126   stars_obj->setCallback( SSG_CALLBACK_POSTDRAW, ssgaStarPostDraw );
127 
128   stars_transform->addKid( stars_obj );
129 
130   return stars_transform;
131 }
132 
133 
reposition(sgVec3 p,double angle)134 bool ssgaStars::reposition( sgVec3 p, double angle )
135 {
136   sgMat4 T1, GST;
137   sgVec3 axis;
138 
139   sgMakeTransMat4( T1, p );
140 
141   sgSetVec3( axis, 0.0, 0.0, -1.0 );
142   sgMakeRotMat4( GST, (float)angle, axis );
143 
144   sgMat4 TRANSFORM;
145   sgCopyMat4( TRANSFORM, T1 );
146   sgPreMultMat4( TRANSFORM, GST );
147 
148   sgCoord skypos;
149   sgSetCoord( &skypos, TRANSFORM );
150 
151   stars_transform->setTransform( &skypos );
152 
153   return true;
154 }
155 
156 
repaint(double sol_angle,int num,sgdVec3 * star_data)157 bool ssgaStars::repaint( double sol_angle, int num, sgdVec3 *star_data )
158 {
159   double mag, nmag, alpha, factor, cutoff;
160   float *color;
161 
162   int phase;
163 
164   // determine which star structure to draw
165   if ( sol_angle > (0.5 * SGD_PI + 10.0 * SGD_DEGREES_TO_RADIANS ) ) {
166     // deep night
167     factor = 1.0;
168     cutoff = 4.5;
169     phase = 0;
170   }
171   else if ( sol_angle > (0.5 * SGD_PI + 8.8 * SGD_DEGREES_TO_RADIANS ) ) {
172     factor = 1.0;
173     cutoff = 3.8;
174     phase = 1;
175   }
176   else if ( sol_angle > (0.5 * SGD_PI + 7.5 * SGD_DEGREES_TO_RADIANS ) ) {
177     factor = 0.95;
178     cutoff = 3.1;
179     phase = 2;
180   }
181   else if ( sol_angle > (0.5 * SGD_PI + 7.0 * SGD_DEGREES_TO_RADIANS ) ) {
182     factor = 0.9;
183     cutoff = 2.4;
184     phase = 3;
185   }
186   else if ( sol_angle > (0.5 * SGD_PI + 6.5 * SGD_DEGREES_TO_RADIANS ) ) {
187     factor = 0.85;
188     cutoff = 1.8;
189     phase = 4;
190   }
191   else if ( sol_angle > (0.5 * SGD_PI + 6.0 * SGD_DEGREES_TO_RADIANS ) ) {
192     factor = 0.8;
193     cutoff = 1.2;
194     phase = 5;
195   }
196   else if ( sol_angle > (0.5 * SGD_PI + 5.5 * SGD_DEGREES_TO_RADIANS ) ) {
197     factor = 0.75;
198     cutoff = 0.6;
199     phase = 6;
200   }
201   else {
202     // early dusk or late dawn
203     factor = 0.7;
204     cutoff = 0.0;
205     phase = 7;
206   }
207 
208   if( phase != old_phase ) {
209     old_phase = phase;
210     for ( int i = 0; i < num; ++i ) {
211       // if ( star_data[i][2] < min ) { min = star_data[i][2]; }
212       // if ( star_data[i][2] > max ) { max = star_data[i][2]; }
213 
214       // magnitude ranges from -1 (bright) to 4 (dim).  The
215       // range of star and planet magnitudes can actually go
216       // outside of this, but for our purpose, if it is brighter
217       // that -1, we'll color it full white/alpha anyway and 4
218       // is a convenient cutoff point which keeps the number of
219       // stars drawn at about 500.
220 
221       // color (magnitude)
222       mag = star_data[i][2];
223       if ( mag < cutoff ) {
224         nmag = ( 4.5 - mag ) / 5.5; // translate to 0 ... 1.0 scale
225         // alpha = nmag * 0.7 + 0.3; // translate to a 0.3 ... 1.0 scale
226         alpha = nmag * 0.85 + 0.15; // translate to a 0.15 ... 1.0 scale
227         alpha *= factor;          // dim when the sun is brighter
228       }
229 	  else {
230         alpha = 0.0;
231       }
232 
233       if (alpha > 1.0) { alpha = 1.0; }
234       if (alpha < 0.0) { alpha = 0.0; }
235 
236       color = cl->get( i );
237       sgSetVec4( color, 1.0, 1.0, 1.0, (float)alpha );
238     }
239   }
240 
241   return true;
242 }
243