Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
star.cpp
Go to the documentation of this file.
1 #include "star.h"
2 #include "ani_texture.h"
3 #include <assert.h>
4 #include "vegastrike.h"
5 #include "vs_globals.h"
6 #include "gfx/camera.h"
7 #include "gfx/cockpit.h"
8 #include "config_xml.h"
9 #include "lin_time.h"
10 #include "galaxy_xml.h"
11 
12 #if defined (__APPLE__) || defined (MACOSX)
13  #include <OpenGL/gl.h>
14 #else
15  #include <GL/gl.h>
16 #endif
17 
18 //#include "cmd/unit.h"
19 #define SINX 1
20 #define SINY 2
21 #define SINZ 4
22 
23 unsigned int NumStarsInGalaxy()
24 {
25  unsigned int count = 0;
26  vsUMap< std::string, GalaxyXML::SGalaxy >::iterator i = _Universe->getGalaxy()->getHeirarchy().begin();
27  vsUMap< std::string, GalaxyXML::SGalaxy >::iterator e = _Universe->getGalaxy()->getHeirarchy().end();
28  for (; i != e; ++i)
29  count += (*i).second.getHeirarchy().size();
30  return count;
31 }
32 
33 class StarIter
34 {
35  vsUMap< std::string, GalaxyXML::SGalaxy >::iterator sector;
36  vsUMap< std::string, GalaxyXML::SGalaxy >::iterator system;
37 public:
38  bool Done() const
39  {
40  return sector == _Universe->getGalaxy()->getHeirarchy().end();
41  }
43  {
44  sector = _Universe->getGalaxy()->getHeirarchy().begin();
45  if ( !Done() ) {
46  system = (*sector).second.getHeirarchy().begin();
47  if ( system == (*sector).second.getHeirarchy().end() )
48  ++(*this);
49  }
50  }
51  void operator++()
52  {
53  if ( !Done() )
54  if ( system != (*sector).second.getHeirarchy().end() )
55  ++system;
56  while ( !Done() && system == (*sector).second.getHeirarchy().end() ) {
57  ++sector;
58  if ( !Done() )
59  system = (*sector).second.getHeirarchy().begin();
60  }
61  }
63  {
64  if ( !Done() )
65  return &(*system).second;
66  else
67  return NULL;
68  }
69  std::string GetSystem() const
70  {
71  if ( !Done() )
72  return (*system).first;
73  else
74  return "Nowhere";
75  }
76  std::string GetSector() const
77  {
78  if ( !Done() )
79  return (*sector).first;
80  else
81  return "NoSector";
82  }
83 };
84 
85 //bool shouldwedraw
86 static void saturate( float &r, float &g, float &b )
87 {
88  static float conemin = XMLSupport::parse_float( vs_config->getVariable( "graphics", "starmincolorval", ".3" ) );
89  static float colorpower = XMLSupport::parse_float( vs_config->getVariable( "graphics", "starcolorpower", ".25" ) );
90  if (r < conemin)
91  r += conemin;
92  if (g < conemin)
93  g += conemin;
94  if (b < conemin)
95  b += conemin;
96  r = pow( r, colorpower );
97  g = pow( g, colorpower );
98  b = pow( b, colorpower );
99 }
100 
101 bool computeStarColor( float &r, float &g, float &b, Vector luminmax, float distance, float maxdistance )
102 {
103  saturate( r, g, b );
104  static float luminscale = XMLSupport::parse_float( vs_config->getVariable( "graphics", "starluminscale", ".001" ) );
105  static float starcoloraverage = XMLSupport::parse_float( vs_config->getVariable( "graphics", "starcoloraverage", ".6" ) );
106  static float starcolorincrement = XMLSupport::parse_float( vs_config->getVariable( "graphics", "starcolorincrement", "100" ) );
107  float dissqr = distance*distance/(maxdistance*maxdistance);
108  float lum = 100*luminmax.i/(luminmax.k*dissqr);
109  lum = log( (double) luminmax.i*10./(double) luminmax.j )*luminscale/dissqr;
110 //VSFileSystem::vs_fprintf (stderr,"luminmax %f lumnow %f\n",luminmax.i/(luminmax.k*dissqr),lum);
111  float clamp = starcoloraverage+lum/starcolorincrement;
112  if (clamp > 1)
113  clamp = 1;
114  if (lum > clamp)
115  lum = clamp;
116  r *= lum;
117  g *= lum;
118  b *= lum;
119  static float starcolorcutoff = XMLSupport::parse_float( vs_config->getVariable( "graphics", "starcolorcutoff", ".1" ) );
120  if (lum > starcolorcutoff) {
121  //printf ("lum %f",lum);
122  }
123  return lum > starcolorcutoff;
124 }
125 
126 namespace StarSystemGent
127 {
128 extern GFXColor getStarColorFromRadius( float radius );
129 }
130 
131 StarVlist::StarVlist( float spread )
132 {
133  lasttime = 0;
135  newcamr = camr;
136  newcamq = camq;
137  this->spread = spread;
138 }
139 
140 static GFXColorVertex * AllocVerticesForSystem( std::string our_system_name, float spread, int *num, int repetition )
141 {
142  static float staroverlap = XMLSupport::parse_float( vs_config->getVariable( "graphics", "star_overlap", "1" ) );
143  float xyzspread = spread*2*staroverlap;
144  static string allowedSectors = vs_config->getVariable( "graphics", "star_allowable_sectors", "Vega Sol" );
145  if (our_system_name.size() > 0) {
146  string lumi = _Universe->getGalaxyProperty( our_system_name, "luminosity" );
147  if (lumi.length() == 0 || strtod( lumi.c_str(), NULL ) == 0) {
148  our_system_name = "";
149  } else {
150  string::size_type slash = our_system_name.find( "/" );
151  if (slash != string::npos) {
152  string sec = our_system_name.substr( 0, slash );
153  if (allowedSectors.find( sec ) == string::npos)
154  our_system_name = "";
155  } else {
156  our_system_name = "";
157  }
158  }
159  }
160  if ( !our_system_name.empty() )
161  *num = NumStarsInGalaxy();
162  GFXColorVertex *tmpvertex = new GFXColorVertex[(*num)*repetition];
163  memset( tmpvertex, 0, sizeof (GFXVertex)*(*num)*repetition );
164  StarIter si;
165  int starcount = 0;
166  int j = 0;
167  float xcent = 0;
168  float ycent = 0;
169  float zcent = 0;
170  Vector starmin( 0, 0, 0 );
171  Vector starmax( 0, 0, 0 );
172  float minlumin = 1;
173  float maxlumin = 1;
174  float maxdistance = -1;
175  float mindistance = -1;
176  if (our_system_name.size() > 0) {
177  sscanf( _Universe->getGalaxyProperty( our_system_name, "xyz" ).c_str(),
178  "%f %f %f",
179  &xcent,
180  &ycent,
181  &zcent );
182  for (StarIter i; !i.Done(); ++i) {
183  float xx, yy, zz;
184  if ( 3 == sscanf( ( *i.Get() )["xyz"].c_str(), "%f %f %f", &xx, &yy, &zz ) ) {
185  xx -= xcent;
186  yy -= ycent;
187  zz -= zcent;
188  if (xx < starmin.i)
189  starmin.i = xx;
190  if (yy < starmin.j)
191  starmin.j = yy;
192  if (zz < starmin.k)
193  starmin.k = zz;
194  if (xx > starmax.i)
195  starmax.i = xx;
196  if (yy > starmax.j)
197  starmax.j = yy;
198  if (zz > starmax.k)
199  starmax.k = zz;
200  float magsqr = xx*xx+yy*yy+zz*zz;
201  if ( (maxdistance < 0) || (maxdistance < magsqr) ) maxdistance = magsqr;
202  if ( (mindistance < 0) || (mindistance > magsqr) ) mindistance = magsqr;
203  float lumin;
204  if ( 1 == sscanf( ( *i.Get() )["luminosity"].c_str(), "%f", &lumin ) ) {
205  if (lumin > maxlumin)
206  maxlumin = lumin;
207  if (lumin < minlumin)
208  if (lumin > 0)
209  minlumin = lumin;
210  }
211  }
212  }
213  }
214  if (maxdistance < 0) maxdistance = 0;
215  if (mindistance < 0) mindistance = 0;
216  maxdistance = sqrt( maxdistance );
217  mindistance = sqrt( mindistance );
218  VSFileSystem::vs_fprintf( stderr, "Min (%f, %f, %f) Max(%f, %f, %f) MinLumin %f, MaxLumin %f",
219  starmin.i, starmin.j, starmin.k, starmax.i, starmax.j, starmax.k, minlumin, maxlumin );
220  for (int y = 0; y < *num; ++y) {
221  tmpvertex[j+repetition-1].x = -.5*xyzspread+rand()*( (float) xyzspread/RAND_MAX );
222  tmpvertex[j+repetition-1].y = -.5*xyzspread+rand()*( (float) xyzspread/RAND_MAX );
223  tmpvertex[j+repetition-1].z = -.5*xyzspread+rand()*( (float) xyzspread/RAND_MAX );
224  float brightness = .1+.9*( (float) rand() )/RAND_MAX;
225  tmpvertex[j+repetition-1].r = brightness;
226  tmpvertex[j+repetition-1].g = brightness;
227  tmpvertex[j+repetition-1].b = brightness;
228  tmpvertex[j+repetition-1].a = 1;
229  tmpvertex[j+repetition-1].i = .57735;
230  tmpvertex[j+repetition-1].j = .57735;
231  tmpvertex[j+repetition-1].k = .57735;
232  int incj = repetition;
233  if ( our_system_name.size() > 0 && !si.Done() ) {
234  starcount++;
235  float xorig, yorig, zorig;
236  if ( 3 == sscanf( ( *si.Get() )["xyz"].c_str(),
237  "%f %f %f",
238  &xorig,
239  &yorig,
240  &zorig ) ) {
241  if (xcent != xorig)
242  tmpvertex[j+repetition-1].x = xorig-xcent;
243  if (ycent != yorig)
244  tmpvertex[j+repetition-1].y = yorig-ycent;
245  if (zcent != zorig)
246  tmpvertex[j+repetition-1].z = zorig-zcent;
247  }
248  std::string radstr = ( *si.Get() )["sun_radius"];
249  if ( radstr.size() ) {
250  float rad = XMLSupport::parse_float( radstr );
252  tmpvertex[j+repetition-1].r = suncolor.r;
253  tmpvertex[j+repetition-1].g = suncolor.g;
254  tmpvertex[j+repetition-1].b = suncolor.b;
255  }
256  float lumin = 1;
257  sscanf( ( *si.Get() )["luminosity"].c_str(), "%f", &lumin );
258 
259  float distance = Vector( tmpvertex[j+repetition-1].x,
260  tmpvertex[j+repetition-1].y,
261  tmpvertex[j+repetition-1].z ).Magnitude();
262  if ( !computeStarColor( tmpvertex[j+repetition-1].r,
263  tmpvertex[j+repetition-1].g,
264  tmpvertex[j+repetition-1].b,
265  Vector( lumin, minlumin, maxlumin ),
266  distance, maxdistance ) )
267  incj = 0;
268  ++si;
269  }
270  for (int LC = repetition-2; LC >= 0; --LC) {
271  tmpvertex[j+LC].i = tmpvertex[j+repetition-1].i;
272  tmpvertex[j+LC].j = tmpvertex[j+repetition-1].j;
273  tmpvertex[j+LC].k = tmpvertex[j+repetition-1].k;
274  tmpvertex[j+LC].x = tmpvertex[j+repetition-1].x; //+spread*.01;
275  tmpvertex[j+LC].y = tmpvertex[j+repetition-1].y; //;+spread*.01;
276  tmpvertex[j+LC].z = tmpvertex[j+repetition-1].z;
277  tmpvertex[j+LC].r = 0;
278  tmpvertex[j+LC].g = 0;
279  tmpvertex[j+LC].b = 0;
280  tmpvertex[j+LC].a = 0;
281  }
282  if (incj) {
283  //printf ("%f %f %f\n",tmpvertex[j+repetition-1].r,tmpvertex[j+repetition-1].g,tmpvertex[j+repetition-1].b);
284  }
285  j += incj;
286  }
287  VSFileSystem::vs_fprintf( stderr, "Read In Star Count %d used: %d\n", starcount, j/2 );
288  *num = j;
289  return tmpvertex;
290 }
291 
292 PointStarVlist::PointStarVlist( int num, float spread, const std::string &sysnam ) : StarVlist( spread )
293 {
294  smoothstreak = 0;
295  //static bool StarStreaks=XMLSupport::parse_bool(vs_config->getVariable("graphics","star_streaks","false"));
296  GFXColorVertex *tmpvertex = AllocVerticesForSystem( sysnam, this->spread, &num, 2 );
297  //if(StarStreaks) {
298  vlist = new GFXVertexList( GFXLINE, num, tmpvertex, num, true, 0 );
299  //}else {
300  for (int i = 0, j = 1; i < num/2; ++i, j += 2)
301  tmpvertex[i] = tmpvertex[j];
302  nonstretchvlist = new GFXVertexList( GFXPOINT, num/2, tmpvertex, num/2, false, 0 );
303  //}
304  delete[] tmpvertex;
305 }
306 
308 {
309  double time = getNewTime();
310  if (time != lasttime) {
311  camr = newcamr;
312  camq = newcamq;
313  Vector newcamp;
314  _Universe->AccessCamera()->GetPQR( newcamp, newcamq, newcamr );
315  lasttime = time;
316  }
317 }
318 
320  const Vector &velocity,
321  const Vector &torque,
322  bool roll,
323  bool yawpitch,
324  int whichTexture )
325 {
326  UpdateGraphics();
327  static bool StarStreaks = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "star_streaks", "false" ) );
329  bool ret = false;
330  if (StarStreaks) {
331  Matrix rollMatrix;
332  static float velstreakscale =
333  XMLSupport::parse_float( vs_config->getVariable( "graphics", "velocity_star_streak_scale", "5" ) );
334  static float minstreak = XMLSupport::parse_float( vs_config->getVariable( "graphics", "velocity_star_streak_min", "1" ) );
335  static float fov_smoothing =
336  XMLSupport::parse_float( vs_config->getVariable( "graphics", "warp.fovlink.smoothing", ".4" ) );
337  float fov_smoot = pow( double(fov_smoothing), GetElapsedTime() );
338  Vector vel( -velocity*velstreakscale );
339  float speed = vel.Magnitude();
340  if ( (smoothstreak >= minstreak || vel.MagnitudeSquared() >= minstreak*minstreak) && (speed > 1.0e-7) ) {
341  ret = true;
342  vel *= 1./speed;
343  speed = fov_smoot*speed+(1-fov_smoot)*smoothstreak;
344  if (speed < minstreak) speed = minstreak;
345  static float streakcap =
346  XMLSupport::parse_float( vs_config->getVariable( "graphics", "velocity_star_streak_max", "100" ) );
347  if (speed > streakcap)
348  speed = streakcap;
349  vel = vel*speed;
350  smoothstreak = speed;
351  GFXColorVertex *v = vlist->BeginMutate( 0 )->colors;
352  int numvertices = vlist->GetNumVertices();
353 
354  static float torquestreakscale =
355  XMLSupport::parse_float( vs_config->getVariable( "graphics", "torque_star_streak_scale", "1" ) );
356  for (int j = 0; j < numvertices-1; j += 2) {
357  int i = j;
358 //if (SlowStarStreaks)
359 //i=((rand()%numvertices)/2)*2;
360  Vector vpoint( v[i+1].x, v[i+1].y, v[i+1].z );
361  Vector recenter = ( vpoint-center.Cast() );
362  if (roll) {
363  RotateAxisAngle( rollMatrix, torque, torque.Magnitude()*torquestreakscale*.003 );
364  vpoint = Transform( rollMatrix, recenter )+center.Cast();
365  }
366  v[i].x = vpoint.i-vel.i;
367  v[i].y = vpoint.j-vel.j;
368  v[i].z = vpoint.k-vel.k;
369 //static float NumSlowStarStreaks=XMLSupport::parse_float(vs_config->getVariable("graphics","num_star_streaks",".05"));
370 //if (SlowStarStreaks&&j<NumSlowStarStreaks*numvertices)
371 //break;
372  }
373  vlist->EndMutate();
374  }
375  }
376  if (ret) {
377  vlist->LoadDrawState();
378  vlist->BeginDrawState();
379  } else {
380  nonstretchvlist->LoadDrawState();
381  nonstretchvlist->BeginDrawState();
382  }
383  return ret;
384 }
385 
386 void PointStarVlist::Draw( bool stretch, int whichTexture )
387 {
388  if (stretch) {
389  vlist->Draw();
390  vlist->Draw( GFXPOINT, vlist->GetNumVertices() );
391  } else {
392  nonstretchvlist->Draw();
393  }
394 }
395 
396 void PointStarVlist::EndDrawState( bool stretch, int whichTexture )
397 {
398  if (stretch)
399  vlist->EndDrawState();
400  else
401  nonstretchvlist->EndDrawState();
402  GFXColorMaterial( 0 );
403 }
404 
406 {
407  delete vlist;
408  delete nonstretchvlist;
409 }
410 
411 Stars::Stars( int num, float spread ) : vlist( NULL )
412  , spread( spread )
413 {
414  static string starspritetextures = vs_config->getVariable( "graphics", "near_stars_sprite_texture", "" );
415  static float starspritesize =
416  XMLSupport::parse_float( vs_config->getVariable( "graphics", "near_stars_sprite_size", "2" ) );
417  if (starspritetextures.length() == 0)
418  vlist = new PointStarVlist( (num/STARnumvlist)+1, spread, "" );
419  else
420  vlist = new SpriteStarVlist( (num/STARnumvlist)+1, spread, "", starspritetextures, starspritesize );
421  fade = blend = true;
422  ResetPosition( QVector( 0, 0, 0 ) );
423 }
424 
425 void Stars::SetBlend( bool blendit, bool fadeit )
426 {
427  blend = true; //blendit;
428  fade = true; //fadeit;
429 }
430 
432 {
433  static bool stars_dont_move = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "stars_dont_move", "false" ) );
434  if (stars_dont_move) return;
435  const QVector cp( _Universe->AccessCamera()->GetPosition() );
436  UpdatePosition( cp );
437  //GFXLightContextAmbient(GFXColor(0,0,0,1));
438  GFXColor( 1, 1, 1, 1 );
441  GFXDisable( TEXTURE0 );
442  GFXDisable( TEXTURE1 );
443  GFXEnable( DEPTHTEST );
444  static bool near_stars_alpha =
445  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "near_stars_alpha", "false" ) );
446  static bool near_stars_alpha_blend =
447  XMLSupport::parse_bool( vs_config->getVariable( "graphics", "near_stars_alpha_blend", "false" ) );
448  static float AlphaTestingCutoff =
449  XMLSupport::parse_float( vs_config->getVariable( "graphics", "stars_alpha_test_cutoff", ".2" ) );
450  if (near_stars_alpha) {
451  GFXAlphaTest( GREATER, AlphaTestingCutoff );
452  if (!near_stars_alpha_blend)
453  GFXBlendMode( ONE, ZERO );
454  else
457  } else {
458  if (blend)
459  GFXBlendMode( ONE, ONE );
460  else
461  GFXBlendMode( ONE, ZERO );
462  }
463  int ligh;
464  GFXSelectMaterial( 0 );
465  if (fade) {
466  static float star_spread_attenuation =
467  XMLSupport::parse_float( vs_config->getVariable( "graphics", "star_spread_attenuation", ".2" ) );
469  GFXLight fadeLight( true, GFXColor( cp.i, cp.j, cp.k ),
470  GFXColor( 0, 0, 0, 1 ),
471  GFXColor( 0, 0, 0, 1 ),
472  GFXColor( 1, 1, 1, 1 ),
473  GFXColor( .01, 0, 1/(star_spread_attenuation*star_spread_attenuation*spread*spread) ) );
474  GFXCreateLight( ligh, fadeLight, true );
475  GFXEnable( LIGHTING );
476  } else {
477  GFXDisable( LIGHTING );
478  }
480  int LC = 0, LN = vlist->NumTextures();
481  for (LC = 0; LC < LN; ++LC) {
482  bool stretch = vlist->BeginDrawState( _Universe->AccessCamera()->GetR().Scale(
483  -spread ).Cast(), _Universe->AccessCamera()->GetVelocity(),
484  _Universe->AccessCamera()->GetAngularVelocity(), false, false, LC );
485  int i;
486  for (i = 0; i < STARnumvlist; i++) {
487  if (i >= 1)
488  GFXTranslateModel( pos[i]-pos[i-1] );
489  else
490  GFXTranslateModel( pos[i] );
491  vlist->Draw( stretch, LC );
492  }
493  GFXTranslateModel( -pos[i-1] );
494  vlist->EndDrawState( stretch, LC );
495  }
496  if (near_stars_alpha)
497  GFXAlphaTest( ALWAYS, 0 );
498  else
500  GFXBlendMode( ONE, ZERO );
502 
503  GFXEnable( TEXTURE0 );
504  GFXEnable( TEXTURE1 );
505  if (fade) {
506  GFXDeleteLight( ligh );
508  }
510 }
511 
512 static void upd( double &a,
513  double &b,
514  double &c,
515  double &d,
516  double &e,
517  double &f,
518  double &g,
519  double &h,
520  double &i,
521  const double cp,
522  const float spread )
523 {
524  //assert (a==b&&b==c&&c==d&&d==e&&e==f);
525  if ( a != b || a != c || a != d || a != e || a != f || !FINITE( a ) )
526  a = b = c = d = e = f = 0;
527  while (a-cp > 1.5*spread) {
528  a -= 3*spread;
529  b -= 3*spread;
530  c -= 3*spread;
531  d -= 3*spread;
532  e -= 3*spread;
533  f -= 3*spread;
534  g -= 3*spread;
535  h -= 3*spread;
536  i -= 3*spread;
537  }
538  while (a-cp < -1.5*spread) {
539  a += 3*spread;
540  b += 3*spread;
541  c += 3*spread;
542  d += 3*spread;
543  e += 3*spread;
544  f += 3*spread;
545  g += 3*spread;
546  h += 3*spread;
547  i += 3*spread;
548  }
549 }
550 
551 void Stars::ResetPosition( const QVector &cent )
552 {
553  for (int i = 0; i < 3; i++)
554  for (int j = 0; j < 3; j++)
555  for (int k = 0; k < 3; k++) {
556  pos[i*9+j*3+k].Set( (i-1)*spread, (j-1)*spread, (k-1)*spread );
557  pos[i*9+j*3+k] += cent;
558  }
559 }
560 
561 void Stars::UpdatePosition( const QVector &cp )
562 {
563  if (fabs( pos[0].i-cp.i ) > 3*spread || fabs( pos[0].j-cp.j ) > 3*spread || fabs( pos[0].k-cp.k ) > 3*spread) {
564  ResetPosition( cp );
565  return;
566  }
567  upd( pos[0].i, pos[1].i, pos[2].i, pos[3].i, pos[4].i, pos[5].i, pos[6].i, pos[7].i, pos[8].i, cp.i, spread );
568  upd( pos[9].i, pos[10].i, pos[11].i, pos[12].i, pos[13].i, pos[14].i, pos[15].i, pos[16].i, pos[17].i, cp.i, spread );
569  upd( pos[18].i, pos[19].i, pos[20].i, pos[21].i, pos[22].i, pos[23].i, pos[24].i, pos[25].i, pos[26].i, cp.i, spread );
570 
571  upd( pos[0].j, pos[1].j, pos[2].j, pos[9].j, pos[10].j, pos[11].j, pos[18].j, pos[19].j, pos[20].j, cp.j, spread );
572  upd( pos[3].j, pos[4].j, pos[5].j, pos[12].j, pos[13].j, pos[14].j, pos[21].j, pos[22].j, pos[23].j, cp.j, spread );
573  upd( pos[6].j, pos[7].j, pos[8].j, pos[15].j, pos[16].j, pos[17].j, pos[24].j, pos[25].j, pos[26].j, cp.j, spread );
574 
575  upd( pos[0].k, pos[3].k, pos[6].k, pos[9].k, pos[12].k, pos[15].k, pos[18].k, pos[21].k, pos[24].k, cp.k, spread );
576  upd( pos[1].k, pos[4].k, pos[7].k, pos[10].k, pos[13].k, pos[16].k, pos[19].k, pos[22].k, pos[25].k, cp.k, spread );
577  upd( pos[2].k, pos[5].k, pos[8].k, pos[11].k, pos[14].k, pos[17].k, pos[20].k, pos[23].k, pos[26].k, cp.k, spread );
578 }
579 
581 {
582  delete vlist;
583 }
584 
586 {
587  return Vector( c.x, c.y, c.z );
588 }
589 
590 SpriteStarVlist::SpriteStarVlist( int num, float spread, std::string sysnam, std::string texturenames,
591  float size ) : StarVlist( spread )
592 {
593  int curtexture = 0;
594  vector< AnimatedTexture* >animations;
595  static bool near_stars_alpha = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "near_stars_alpha", "false" ) );
596  for (curtexture = 0; curtexture < NUM_ACTIVE_ANIMATIONS; ++curtexture) {
597  std::string::size_type where = texturenames.find( " " );
598  string texturename = texturenames.substr( 0, where );
599  if (where != string::npos)
600  texturenames = texturenames.substr( where+1 );
601  else texturenames = "";
602  if (texturename.find( ".ani" ) != string::npos) {
603  animations.push_back( new AnimatedTexture( texturename.c_str(), 0, near_stars_alpha ? NEAREST : BILINEAR ) );
604  decal[curtexture] = animations.back();
605  } else if (texturename.length() == 0) {
606  if (curtexture == 0) {
607  decal[curtexture] = new Texture( "white.bmp", 0, near_stars_alpha ? NEAREST : BILINEAR );
608  } else {
609  if ( animations.size() ) {
610  AnimatedTexture *tmp = static_cast< AnimatedTexture* > ( animations[curtexture%animations.size()]->Clone() );
611  int num = tmp->numFrames();
612  if (num) {
613  num = rand()%num;
614  tmp->setTime( num/tmp->framesPerSecond() );
615  }
616  decal[curtexture] = tmp;
617  } else {
618  decal[curtexture] = decal[rand()%curtexture]->Clone();
619  }
620  }
621  } else {
622  decal[curtexture] = new Texture( texturename.c_str() );
623  }
624  }
625  int numVerticesPer = near_stars_alpha ? 4 : 12;
626  GFXColorVertex *tmpvertex = AllocVerticesForSystem( sysnam, this->spread, &num, numVerticesPer );
627  for (int LC = 0; LC < num; LC += numVerticesPer) {
628  int LAST = LC+numVerticesPer-1;
629  for (int i = LC; i <= LAST; ++i) {
630  tmpvertex[i].r = tmpvertex[LAST].r;
631  tmpvertex[i].g = tmpvertex[LAST].g;
632  tmpvertex[i].b = tmpvertex[LAST].b;
633  tmpvertex[i].a = tmpvertex[LAST].a;
634  }
635  Vector I( rand()*2.0/RAND_MAX-1,
636  rand()*2.0/RAND_MAX-1,
637  rand()*2.0/RAND_MAX-1 );
638  Vector J( rand()*2.0/RAND_MAX-1,
639  rand()*2.0/RAND_MAX-1,
640  rand()*2.0/RAND_MAX-1 );
641  Vector K( rand()*2.0/RAND_MAX-1,
642  rand()*2.0/RAND_MAX-1,
643  rand()*2.0/RAND_MAX-1 );
644  if (I.MagnitudeSquared() < .00001)
645  I.i += .5;
646  if (J.MagnitudeSquared() < .00001)
647  J.j += .5;
648  if (K.MagnitudeSquared() < .00001)
649  K.k += .5;
650  Orthogonize( I, J, K );
651  I = I*size;
652  J = J*size;
653  K = K*size;
654  tmpvertex[LC+0].SetVertex( GetConstVertex( tmpvertex[LC+0] )-I+J );
655  tmpvertex[LC+0].s = 0.15625;
656  tmpvertex[LC+0].t = .984375;
657  tmpvertex[LC+1].SetVertex( GetConstVertex( tmpvertex[LC+1] )+I+J );
658  tmpvertex[LC+1].s = .984375;
659  tmpvertex[LC+1].t = .984375;
660  tmpvertex[LC+2].SetVertex( GetConstVertex( tmpvertex[LC+2] )+I-J );
661  tmpvertex[LC+2].s = .984375;
662  tmpvertex[LC+2].t = .015625;
663  tmpvertex[LC+3].SetVertex( GetConstVertex( tmpvertex[LC+3] )-I-J );
664  tmpvertex[LC+3].s = .015625;
665  tmpvertex[LC+3].t = .015625;
666  if (numVerticesPer > 4) {
667  tmpvertex[LC+4].SetVertex( GetConstVertex( tmpvertex[LC+4] )-I+K );
668  tmpvertex[LC+4].s = .015625;
669  tmpvertex[LC+4].t = .984375;
670  tmpvertex[LC+5].SetVertex( GetConstVertex( tmpvertex[LC+5] )+I+K );
671  tmpvertex[LC+5].s = .984375;
672  tmpvertex[LC+5].t = .984375;
673  tmpvertex[LC+6].SetVertex( GetConstVertex( tmpvertex[LC+6] )+I-K );
674  tmpvertex[LC+6].s = .984375;
675  tmpvertex[LC+6].t = .015625;
676  tmpvertex[LC+7].SetVertex( GetConstVertex( tmpvertex[LC+7] )-I-K );
677  tmpvertex[LC+7].s = .015625;
678  tmpvertex[LC+7].t = .015625;
679  }
680  if (numVerticesPer > 8) {
681  tmpvertex[LC+8].SetVertex( GetConstVertex( tmpvertex[LC+8] )-J+K );
682  tmpvertex[LC+8].s = .015625;
683  tmpvertex[LC+8].t = .984375;
684  tmpvertex[LC+9].SetVertex( GetConstVertex( tmpvertex[LC+9] )+J+K );
685  tmpvertex[LC+9].s = .984375;
686  tmpvertex[LC+9].t = .984375;
687  tmpvertex[LC+10].SetVertex( GetConstVertex( tmpvertex[LC+10] )+J-K );
688  tmpvertex[LC+10].s = .984375;
689  tmpvertex[LC+10].t = .015625;
690  tmpvertex[LC+11].SetVertex( GetConstVertex( tmpvertex[LC+11] )-J-K );
691  tmpvertex[LC+11].s = .015625;
692  tmpvertex[LC+11].t = .015625;
693  }
694  }
695  {
696  int start = 0;
697  int inc = num/NUM_ACTIVE_ANIMATIONS;
698  inc -= inc%numVerticesPer;
699  for (int i = 0; i < NUM_ACTIVE_ANIMATIONS; ++i, start += inc) {
700  int later = start+inc;
701  if (i == NUM_ACTIVE_ANIMATIONS-1)
702  later = num;
703  vlist[i] = new GFXVertexList( GFXQUAD, later-start, tmpvertex+start, later-start, true, 0 );
704  }
705  }
706  delete[] tmpvertex;
707 }
708 
710 {
711  return NUM_ACTIVE_ANIMATIONS;
712 }
713 
715  const Vector &velocity,
716  const Vector &torque,
717  bool roll,
718  bool yawpitch,
719  int whichTex )
720 {
721  UpdateGraphics();
722  GFXEnable( TEXTURE0 );
723  decal[whichTex]->MakeActive();
724  GFXDisable( CULLFACE );
726  vlist[whichTex]->LoadDrawState();
727  vlist[whichTex]->BeginDrawState();
728  return false;
729 }
730 
731 void SpriteStarVlist::EndDrawState( bool stretch, int whichTex )
732 {
733  vlist[whichTex]->EndDrawState();
734  GFXDisable( TEXTURE0 );
735  GFXEnable( CULLFACE );
736  GFXColorMaterial( 0 );
737 }
738 
739 extern bool isVista;
740 
741 void SpriteStarVlist::Draw( bool strertch, int whichTexture )
742 {
743  static bool force_draw = XMLSupport::parse_bool( vs_config->getVariable( "graphics", "vista_draw_stars", "false" ) );
744  if (force_draw || !isVista)
745  vlist[whichTexture]->Draw();
746 }
747 
749 {
750  for (int i = 0; i < NUM_ACTIVE_ANIMATIONS; ++i)
751  if (decal[i])
752  delete decal[i];
753  for (int j = 0; j < NUM_ACTIVE_ANIMATIONS; ++j)
754  if (vlist[j])
755  delete vlist[j];
756 }
757