Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
StarSystem.cpp
Go to the documentation of this file.
1 /* Project Starshatter 4.5
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: Stars.exe
6  FILE: StarSystem.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Various Heavenly Bodies
13 */
14 
15 #include "MemDebug.h"
16 #include "StarSystem.h"
17 #include "Galaxy.h"
18 #include "Sky.h"
19 #include "Starshatter.h"
20 #include "TerrainRegion.h"
21 #include "TerrainHaze.h"
22 #include "Weather.h"
23 
24 #include "Game.h"
25 #include "Sound.h"
26 #include "Solid.h"
27 #include "Light.h"
28 #include "Bitmap.h"
29 #include "DataLoader.h"
30 #include "Scene.h"
31 #include "ParseUtil.h"
32 
33 const double epoch = 0.5e9;
34 double StarSystem::stardate = 0;
35 
36 // +====================================================================+
37 
38 static double base_time = 0;
39 static WORD oldcw = 0;
40 static WORD fpcw = 0;
41 
43 {
44  _asm { fstcw oldcw }
45  fpcw = oldcw | 0x0300; // set 80-bit precision mode
46  _asm { fldcw fpcw }
47 }
48 
49 void FPURestore()
50 {
51  // well, I don't actually WANT single-precision mode
52  // so I think I'll just ignore this...
53 
54  //_asm { fldcw oldcw }
55 }
56 
57 void StarSystem::SetBaseTime(double t, bool absolute)
58 {
59  FPU2Extended();
60 
61  if (absolute) {
62  base_time = t;
63  CalcStardate();
64  }
65 
66  else if (t > 0) {
67  if (t > epoch) t -= epoch;
68  base_time = t;
69  CalcStardate();
70  }
71 }
72 
74 {
75  return base_time;
76 }
77 
79 {
80  if (base_time < 1) {
81  time_t clock_seconds;
82  time(&clock_seconds);
83 
84  base_time = clock_seconds;
85 
86  while (base_time < 0)
87  base_time += epoch;
88  }
89 
90  FPU2Extended();
91 
92  double gtime = (double) Game::GameTime() / 1000.0;
93  double sdate = gtime + base_time + epoch;
94 
95  stardate = sdate;
96 
97  FPURestore();
98 }
99 
100 static const double GRAV = 6.673e-11;
101 static const int NAMELEN = 64;
102 
103 // +====================================================================+
104 
105 StarSystem::StarSystem(const char* sys_name, Point l, int iff, int s)
106 : name(sys_name), affiliation(iff), sky_stars(0), sky_dust(0), loc(l), seq(s),
107 active_region(0), instantiated(false), ambient(0,0,0),
108 sun_color(255,255,255), sun_scale(1), point_stars(0), poly_stars(0),
109 nebula(0), haze(0)
110 {
111  center = new(__FILE__,__LINE__) Orbital(this, "CG", Orbital::NOTHING, 1.0e35f, 0.0f, 0.0f, 0);
112  radius = 0.0f;
113 }
114 
115 // +--------------------------------------------------------------------+
116 
118 {
119  Print(" Destroying Star System %s\n", (const char*) name);
120 
121  if (instantiated) {
122  Deactivate();
123  Destroy();
124  }
125 
126  bodies.destroy();
127  regions.destroy();
128  all_regions.clear(); // do not destroy these!
129 
130  delete center;
131 }
132 
133 // +--------------------------------------------------------------------+
134 
135 static OrbitalBody* primary_star = 0;
136 static OrbitalBody* primary_planet = 0;
137 static OrbitalBody* primary_moon = 0;
138 
139 void
141 {
142  CalcStardate();
143  active_region = 0;
144 
145  BYTE* block = 0;
146  DataLoader* loader = DataLoader::GetLoader();
147  datapath = loader->GetDataPath();
148 
149  sprintf_s(filename, "%s/%s.def", (const char*) name, (const char*) name);
150 
151  Print("Loading StarSystem: %s\n", filename);
152  loader->LoadBuffer(filename, block, true);
153 
154  if (!block) {
155  Print("ERROR: invalid star system file '%s'\n", filename);
156  exit(-2);
157  return;
158  }
159 
160  Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block));
161 
162  Term* term = parser.ParseTerm();
163 
164  if (!term) {
165  Print("ERROR: could not parse '%s'\n", filename);
166  exit(-3);
167  return;
168  }
169  else {
170  TermText* file_type = term->isText();
171  if (!file_type || file_type->value() != "STARSYSTEM") {
172  Print("ERROR: invalid star system file '%s'\n", filename);
173  term->print(10);
174  exit(-4);
175  return;
176  }
177  }
178 
179  // parse the system:
180  do {
181  delete term;
182  term = parser.ParseTerm();
183 
184  if (term) {
185  TermDef* def = term->isDef();
186  if (def) {
187  if (def->name()->value() == "name") {
188  char namebuf[NAMELEN];
189  namebuf[0] = 0;
190  GetDefText(namebuf, def, filename);
191 
192  if (namebuf[0])
193  name = namebuf;
194  }
195 
196  else if (def->name()->value() == "sky") {
197  if (!def->term() || !def->term()->isStruct()) {
198  Print("WARNING: sky struct missing in '%s'\n", filename);
199  }
200  else {
201  TermStruct* val = def->term()->isStruct();
202 
203  char imgname[NAMELEN];
204  char magname[NAMELEN];
205  char hazname[NAMELEN];
206 
207  imgname[0] = 0;
208  magname[0] = 0;
209  hazname[0] = 0;
210 
211  for (int i = 0; i < val->elements()->size(); i++) {
212  TermDef* pdef = val->elements()->at(i)->isDef();
213  if (pdef) {
214  if (pdef->name()->value() == "poly_stars")
215  GetDefText(imgname, pdef, filename);
216 
217  else if (pdef->name()->value() == "nebula")
218  GetDefText(magname, pdef, filename);
219 
220  else if (pdef->name()->value() == "haze")
221  GetDefText(hazname, pdef, filename);
222  }
223  }
224 
225  if (imgname[0])
226  sky_poly_stars = imgname;
227 
228  if (magname[0])
229  sky_nebula = magname;
230 
231  if (hazname[0])
232  sky_haze = hazname;
233  }
234  }
235 
236  else if (def->name()->value() == "stars") {
238  }
239 
240  else if (def->name()->value() == "ambient") {
241  Vec3 a;
242  GetDefVec(a, def, filename);
243 
244  ambient = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z) * 2.5;
245  }
246 
247  else if (def->name()->value() == "dust") {
249  }
250 
251  else if (def->name()->value() == "star") {
252  if (!def->term() || !def->term()->isStruct()) {
253  Print("WARNING: star struct missing in '%s'\n", filename);
254  }
255  else {
256  TermStruct* val = def->term()->isStruct();
257  ParseStar(val);
258  }
259  }
260 
261  else if (def->name()->value() == "planet") {
262  if (!def->term() || !def->term()->isStruct()) {
263  Print("WARNING: planet struct missing in '%s'\n", filename);
264  }
265  else {
266  TermStruct* val = def->term()->isStruct();
267  ParsePlanet(val);
268  }
269  }
270 
271  else if (def->name()->value() == "moon") {
272  if (!def->term() || !def->term()->isStruct()) {
273  Print("WARNING: moon struct missing in '%s'\n", filename);
274  }
275  else {
276  TermStruct* val = def->term()->isStruct();
277  ParseMoon(val);
278  }
279  }
280 
281  else if (def->name()->value() == "region") {
282  if (!def->term() || !def->term()->isStruct()) {
283  Print("WARNING: region struct missing in '%s'\n", filename);
284  }
285  else {
286  TermStruct* val = def->term()->isStruct();
287  ParseRegion(val);
288  }
289  }
290 
291  else if (def->name()->value() == "terrain") {
292  if (!def->term() || !def->term()->isStruct()) {
293  Print("WARNING: terrain struct missing in '%s'\n", filename);
294  }
295  else {
296  TermStruct* val = def->term()->isStruct();
297  ParseTerrain(val);
298  }
299  }
300 
301  }
302  }
303  }
304  while (term);
305 
306  loader->ReleaseBuffer(block);
307 }
308 
309 // +--------------------------------------------------------------------+
310 
311 void
313 {
314  char star_name[NAMELEN];
315  char img_name[NAMELEN];
316  char map_name[NAMELEN];
317  double light = 0.0;
318  double radius = 0.0;
319  double rot = 0.0;
320  double mass = 0.0;
321  double orbit = 0.0;
322  double tscale = 1.0;
323  bool retro = false;
324  Color color;
325  Color back;
326 
327  for (int i = 0; i < val->elements()->size(); i++) {
328  TermDef* pdef = val->elements()->at(i)->isDef();
329  if (pdef) {
330  if (pdef->name()->value() == "name")
331  GetDefText(star_name, pdef, filename);
332 
333  else if (pdef->name()->value() == "map" || pdef->name()->value() == "icon")
334  GetDefText(map_name, pdef, filename);
335 
336  else if (pdef->name()->value() == "image")
337  GetDefText(img_name, pdef, filename);
338 
339  else if (pdef->name()->value() == "mass")
340  GetDefNumber(mass, pdef, filename);
341 
342  else if (pdef->name()->value() == "orbit")
343  GetDefNumber(orbit, pdef, filename);
344 
345  else if (pdef->name()->value() == "radius")
346  GetDefNumber(radius, pdef, filename);
347 
348  else if (pdef->name()->value() == "rotation")
349  GetDefNumber(rot, pdef, filename);
350 
351  else if (pdef->name()->value() == "tscale")
352  GetDefNumber(tscale, pdef, filename);
353 
354  else if (pdef->name()->value() == "light")
355  GetDefNumber(light, pdef, filename);
356 
357  else if (pdef->name()->value() == "retro")
358  GetDefBool(retro, pdef, filename);
359 
360  else if (pdef->name()->value() == "color") {
361  Vec3 a;
362  GetDefVec(a, pdef, filename);
363  color = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z);
364  }
365 
366  else if (pdef->name()->value() == "back" || pdef->name()->value() == "back_color") {
367  Vec3 a;
368  GetDefVec(a, pdef, filename);
369  back = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z);
370  }
371  }
372  }
373 
374  OrbitalBody* star = new(__FILE__,__LINE__) OrbitalBody(this, star_name, Orbital::STAR, mass, radius, orbit, center);
375  star->map_name = map_name;
376  star->tex_name = img_name;
377  star->light = light;
378  star->tscale = tscale;
379  star->subtype = Star::G;
380  star->retro = retro;
381  star->rotation = rot * 3600;
382  star->color = color;
383  star->back = back;
384 
385  // map icon:
386  if (*map_name) {
388  }
389 
390  bodies.append(star);
391  primary_star = star;
392  primary_planet = 0;
393  primary_moon = 0;
394 
395  if (orbit > StarSystem::radius)
396  StarSystem::radius = orbit;
397 }
398 
399 // +--------------------------------------------------------------------+
400 
401 void
403 {
404  char pln_name[NAMELEN];
405  char img_name[NAMELEN];
406  char map_name[NAMELEN];
407  char hi_name[NAMELEN];
408  char img_ring[NAMELEN];
409  char glo_name[NAMELEN];
410  char glo_hi_name[NAMELEN];
411  char gloss_name[NAMELEN];
412 
413  double radius = 0.0;
414  double mass = 0.0;
415  double orbit = 0.0;
416  double rot = 0.0;
417  double minrad = 0.0;
418  double maxrad = 0.0;
419  double tscale = 1.0;
420  double tilt = 0.0;
421  bool retro = false;
422  bool lumin = false;
423  Color atmos = Color::Black;
424 
425  ZeroMemory(pln_name, NAMELEN);
426  ZeroMemory(hi_name, NAMELEN);
427  ZeroMemory(img_ring, NAMELEN);
428  ZeroMemory(glo_name, NAMELEN);
429  ZeroMemory(glo_hi_name, NAMELEN);
430  ZeroMemory(gloss_name, NAMELEN);
431  ZeroMemory(map_name, NAMELEN);
432 
433  for (int i = 0; i < val->elements()->size(); i++) {
434  TermDef* pdef = val->elements()->at(i)->isDef();
435  if (pdef) {
436  if (pdef->name()->value() == "name")
437  GetDefText(pln_name, pdef, filename);
438 
439  else if (pdef->name()->value() == "map" || pdef->name()->value() == "icon")
440  GetDefText(map_name, pdef, filename);
441 
442  else if (pdef->name()->value() == "image")
443  GetDefText(img_name, pdef, filename);
444 
445  else if (pdef->name()->value() == "image_west")
446  GetDefText(img_name, pdef, filename);
447 
448  else if (pdef->name()->value() == "image_east")
449  GetDefText(img_name, pdef, filename);
450 
451  else if (pdef->name()->value() == "glow")
452  GetDefText(glo_name, pdef, filename);
453 
454  else if (pdef->name()->value() == "gloss")
455  GetDefText(gloss_name, pdef, filename);
456 
457  else if (pdef->name()->value() == "high_res")
458  GetDefText(hi_name, pdef, filename);
459 
460  else if (pdef->name()->value() == "high_res_west")
461  GetDefText(hi_name, pdef, filename);
462 
463  else if (pdef->name()->value() == "high_res_east")
464  GetDefText(hi_name, pdef, filename);
465 
466  else if (pdef->name()->value() == "glow_high_res")
467  GetDefText(glo_hi_name, pdef, filename);
468 
469  else if (pdef->name()->value() == "mass")
470  GetDefNumber(mass, pdef, filename);
471 
472  else if (pdef->name()->value() == "orbit")
473  GetDefNumber(orbit, pdef, filename);
474 
475  else if (pdef->name()->value() == "retro")
476  GetDefBool(retro, pdef, filename);
477 
478  else if (pdef->name()->value() == "luminous")
479  GetDefBool(lumin, pdef, filename);
480 
481  else if (pdef->name()->value() == "rotation")
482  GetDefNumber(rot, pdef, filename);
483 
484  else if (pdef->name()->value() == "radius")
485  GetDefNumber(radius, pdef, filename);
486 
487  else if (pdef->name()->value() == "ring")
488  GetDefText(img_ring, pdef, filename);
489 
490  else if (pdef->name()->value() == "minrad")
491  GetDefNumber(minrad, pdef, filename);
492 
493  else if (pdef->name()->value() == "maxrad")
494  GetDefNumber(maxrad, pdef, filename);
495 
496  else if (pdef->name()->value() == "tscale")
497  GetDefNumber(tscale, pdef, filename);
498 
499  else if (pdef->name()->value() == "tilt")
500  GetDefNumber(tilt, pdef, filename);
501 
502  else if (pdef->name()->value() == "atmosphere") {
503  Vec3 a;
504  GetDefVec(a, pdef, filename);
505  atmos = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z);
506  }
507  }
508  }
509 
510  OrbitalBody* planet = new(__FILE__,__LINE__) OrbitalBody(this, pln_name, Orbital::PLANET, mass, radius, orbit, primary_star);
511  planet->map_name = map_name;
512  planet->tex_name = img_name;
513  planet->tex_high_res = hi_name;
514  planet->tex_ring = img_ring;
515  planet->tex_glow = glo_name;
516  planet->tex_glow_high_res = glo_hi_name;
517  planet->tex_gloss = gloss_name;
518  planet->ring_min = minrad;
519  planet->ring_max = maxrad;
520  planet->tscale = tscale;
521  planet->tilt = tilt;
522  planet->retro = retro;
523  planet->luminous = lumin;
524  planet->rotation = rot * 3600;
525  planet->atmosphere = atmos;
526 
527  if (primary_star)
528  primary_star->satellites.append(planet);
529  else
530  bodies.append(planet);
531 
532  primary_planet = planet;
533  primary_moon = 0;
534 
535  if (orbit > StarSystem::radius)
536  StarSystem::radius = orbit;
537 
538  // map icon:
539  if (map_name[0]) {
541  }
542 }
543 
544 // +--------------------------------------------------------------------+
545 
546 void
548 {
549  char map_name[NAMELEN];
550  char pln_name[NAMELEN];
551  char img_name[NAMELEN];
552  char hi_name[NAMELEN];
553  char glo_name[NAMELEN];
554  char glo_hi_name[NAMELEN];
555  char gloss_name[NAMELEN];
556 
557  double radius = 0.0;
558  double mass = 0.0;
559  double orbit = 0.0;
560  double rot = 0.0;
561  double tscale = 1.0;
562  double tilt = 0.0;
563  bool retro = false;
564  Color atmos = Color::Black;
565 
566  ZeroMemory(map_name, NAMELEN);
567  ZeroMemory(pln_name, NAMELEN);
568  ZeroMemory(hi_name, NAMELEN);
569  ZeroMemory(img_name, NAMELEN);
570  ZeroMemory(glo_name, NAMELEN);
571  ZeroMemory(glo_hi_name, NAMELEN);
572  ZeroMemory(gloss_name, NAMELEN);
573 
574  for (int i = 0; i < val->elements()->size(); i++) {
575  TermDef* pdef = val->elements()->at(i)->isDef();
576  if (pdef) {
577  if (pdef->name()->value() == "name")
578  GetDefText(pln_name, pdef, filename);
579 
580  else if (pdef->name()->value() == "map" || pdef->name()->value() == "icon")
581  GetDefText(map_name, pdef, filename);
582 
583  else if (pdef->name()->value() == "image")
584  GetDefText(img_name, pdef, filename);
585 
586  else if (pdef->name()->value() == "glow")
587  GetDefText(glo_name, pdef, filename);
588 
589  else if (pdef->name()->value() == "high_res")
590  GetDefText(hi_name, pdef, filename);
591 
592  else if (pdef->name()->value() == "glow_high_res")
593  GetDefText(glo_hi_name, pdef, filename);
594 
595  else if (pdef->name()->value() == "gloss")
596  GetDefText(gloss_name, pdef, filename);
597 
598  else if (pdef->name()->value() == "mass")
599  GetDefNumber(mass, pdef, filename);
600 
601  else if (pdef->name()->value() == "orbit")
602  GetDefNumber(orbit, pdef, filename);
603 
604  else if (pdef->name()->value() == "rotation")
605  GetDefNumber(rot, pdef, filename);
606 
607  else if (pdef->name()->value() == "retro")
608  GetDefBool(retro, pdef, filename);
609 
610  else if (pdef->name()->value() == "radius")
611  GetDefNumber(radius, pdef, filename);
612 
613  else if (pdef->name()->value() == "tscale")
614  GetDefNumber(tscale, pdef, filename);
615 
616  else if (pdef->name()->value() == "inclination")
617  GetDefNumber(tilt, pdef, filename);
618 
619  else if (pdef->name()->value() == "atmosphere") {
620  Vec3 a;
621  GetDefVec(a, pdef, filename);
622  atmos = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z);
623  }
624  }
625  }
626 
627  OrbitalBody* moon = new(__FILE__,__LINE__) OrbitalBody(this, pln_name, Orbital::MOON, mass, radius, orbit, primary_planet);
628  moon->map_name = map_name;
629  moon->tex_name = img_name;
630  moon->tex_high_res = hi_name;
631  moon->tex_glow = glo_name;
632  moon->tex_glow_high_res = glo_hi_name;
633  moon->tex_gloss = gloss_name;
634  moon->tscale = tscale;
635  moon->retro = retro;
636  moon->rotation = rot * 3600;
637  moon->tilt = tilt;
638  moon->atmosphere = atmos;
639 
640  if (primary_planet)
641  primary_planet->satellites.append(moon);
642  else {
643  Print("WARNING: no planet for moon %s in '%s', deleted.\n", pln_name, filename);
644  delete moon;
645  moon = 0;
646  }
647 
648  primary_moon = moon;
649 
650  // map icon:
651  if (map_name[0]) {
653  }
654 }
655 
656 // +--------------------------------------------------------------------+
657 
658 void
660 {
661  char rgn_name[NAMELEN];
662  char lnk_name[NAMELEN];
663  double size = 1.0e6;
664  double orbit = 0.0;
665  double grid = 25000;
666  double inclination = 0.0;
667  int asteroids = 0;
668 
669  List<Text> links;
670 
671  for (int i = 0; i < val->elements()->size(); i++) {
672  TermDef* pdef = val->elements()->at(i)->isDef();
673  if (pdef) {
674  if (pdef->name()->value() == "name")
675  GetDefText(rgn_name, pdef, filename);
676 
677  else if (pdef->name()->value() == "link") {
678  GetDefText(lnk_name, pdef, filename);
679  if (lnk_name[0]) {
680  links.append(new(__FILE__,__LINE__) Text(lnk_name));
681  }
682  }
683 
684  else if (pdef->name()->value() == "orbit")
685  GetDefNumber(orbit, pdef, filename);
686 
687  else if (pdef->name()->value() == "size")
688  GetDefNumber(size, pdef, filename);
689 
690  else if (pdef->name()->value() == "radius")
691  GetDefNumber(size, pdef, filename);
692 
693  else if (pdef->name()->value() == "grid")
694  GetDefNumber(grid, pdef, filename);
695 
696  else if (pdef->name()->value() == "inclination")
697  GetDefNumber(inclination, pdef, filename);
698 
699  else if (pdef->name()->value() == "asteroids")
700  GetDefNumber(asteroids, pdef, filename);
701  }
702  }
703 
704  Orbital* primary = primary_moon;
705  if (!primary) primary = primary_planet;
706  if (!primary) primary = primary_star;
707 
708  OrbitalRegion* region = new(__FILE__,__LINE__) OrbitalRegion(this, rgn_name, 0, size, orbit, primary);
709  region->grid = grid;
710  region->inclination = inclination;
711  region->asteroids = asteroids;
712  region->links.append(links);
713 
714  if (primary)
715  primary->regions.append(region);
716  else
717  regions.append(region);
718 
719  all_regions.append(region);
720 
721  if (orbit > StarSystem::radius)
722  StarSystem::radius = orbit;
723 }
724 
725 // +--------------------------------------------------------------------+
726 
727 void
729 {
730  Orbital* primary = primary_moon;
731  if (!primary) primary = primary_planet;
732 
733  if (!primary) {
734  Print("WARNING: Terrain region with no primary ignored in '%s'\n", filename);
735  return;
736  }
737 
738  TerrainRegion* region = 0;
739 
740  Text rgn_name;
741  Text patch_name;
742  Text patch_texture;
743  Text noise_tex0;
744  Text noise_tex1;
745  Text apron_name;
746  Text apron_texture;
747  Text water_texture;
748  Text env_texture_positive_x;
749  Text env_texture_negative_x;
750  Text env_texture_positive_y;
751  Text env_texture_negative_y;
752  Text env_texture_positive_z;
753  Text env_texture_negative_z;
754  Text haze_name;
755  Text sky_name;
756  Text clouds_high;
757  Text clouds_low;
758  Text shades_high;
759  Text shades_low;
760 
761  double size = 1.0e6;
762  double grid = 25000;
763  double inclination = 0.0;
764  double scale = 10e3;
765  double mtnscale = 1e3;
766  double fog_density = 0;
767  double fog_scale = 0;
768  double haze_fade = 0;
769  double clouds_alt_high= 0;
770  double clouds_alt_low= 0;
771  double w_period = 0;
772  double w_chances[Weather::NUM_STATES];
773 
774  ZeroMemory(w_chances, sizeof(w_chances));
775 
776  for (int i = 0; i < val->elements()->size(); i++) {
777  TermDef* pdef = val->elements()->at(i)->isDef();
778  if (pdef) {
779  if (pdef->name()->value() == "name")
780  GetDefText(rgn_name, pdef, filename);
781 
782  else if (pdef->name()->value() == "patch")
783  GetDefText(patch_name, pdef, filename);
784 
785  else if (pdef->name()->value() == "patch_texture")
786  GetDefText(patch_texture, pdef, filename);
787 
788  else if (pdef->name()->value() == "detail_texture_0")
789  GetDefText(noise_tex0, pdef, filename);
790 
791  else if (pdef->name()->value() == "detail_texture_1")
792  GetDefText(noise_tex1, pdef, filename);
793 
794  else if (pdef->name()->value() == "apron")
795  GetDefText(apron_name, pdef, filename);
796 
797  else if (pdef->name()->value() == "apron_texture")
798  GetDefText(apron_texture, pdef, filename);
799 
800  else if (pdef->name()->value() == "water_texture")
801  GetDefText(water_texture, pdef, filename);
802 
803  else if (pdef->name()->value() == "env_texture_positive_x")
804  GetDefText(env_texture_positive_x, pdef, filename);
805 
806  else if (pdef->name()->value() == "env_texture_negative_x")
807  GetDefText(env_texture_negative_x, pdef, filename);
808 
809  else if (pdef->name()->value() == "env_texture_positive_y")
810  GetDefText(env_texture_positive_y, pdef, filename);
811 
812  else if (pdef->name()->value() == "env_texture_negative_y")
813  GetDefText(env_texture_negative_y, pdef, filename);
814 
815  else if (pdef->name()->value() == "env_texture_positive_z")
816  GetDefText(env_texture_positive_z, pdef, filename);
817 
818  else if (pdef->name()->value() == "env_texture_negative_z")
819  GetDefText(env_texture_negative_z, pdef, filename);
820 
821  else if (pdef->name()->value() == "clouds_high")
822  GetDefText(clouds_high, pdef, filename);
823 
824  else if (pdef->name()->value() == "shades_high")
825  GetDefText(shades_high, pdef, filename);
826 
827  else if (pdef->name()->value() == "clouds_low")
828  GetDefText(clouds_low, pdef, filename);
829 
830  else if (pdef->name()->value() == "shades_low")
831  GetDefText(shades_low, pdef, filename);
832 
833  else if (pdef->name()->value() == "haze")
834  GetDefText(haze_name, pdef, filename);
835 
836  else if (pdef->name()->value() == "sky_color")
837  GetDefText(sky_name, pdef, filename);
838 
839  else if (pdef->name()->value() == "size" ||
840  pdef->name()->value() == "radius")
841  GetDefNumber(size, pdef, filename);
842 
843  else if (pdef->name()->value() == "grid")
844  GetDefNumber(grid, pdef, filename);
845 
846  else if (pdef->name()->value() == "inclination")
847  GetDefNumber(inclination, pdef, filename);
848 
849  else if (pdef->name()->value() == "scale")
850  GetDefNumber(scale, pdef, filename);
851 
852  else if (pdef->name()->value() == "mtnscale" ||
853  pdef->name()->value() == "mtn_scale")
854  GetDefNumber(mtnscale, pdef, filename);
855 
856  else if (pdef->name()->value() == "fog_density")
857  GetDefNumber(fog_density, pdef, filename);
858 
859  else if (pdef->name()->value() == "fog_scale")
860  GetDefNumber(fog_scale, pdef, filename);
861 
862  else if (pdef->name()->value() == "haze_fade")
863  GetDefNumber(haze_fade, pdef, filename);
864 
865  else if (pdef->name()->value() == "clouds_alt_high")
866  GetDefNumber(clouds_alt_high, pdef, filename);
867 
868  else if (pdef->name()->value() == "clouds_alt_low")
869  GetDefNumber(clouds_alt_low, pdef, filename);
870 
871  else if (pdef->name()->value() == "weather_period")
872  GetDefNumber(w_period, pdef, filename);
873 
874  else if (pdef->name()->value() == "weather_clear")
875  GetDefNumber(w_chances[0], pdef, filename);
876  else if (pdef->name()->value() == "weather_high_clouds")
877  GetDefNumber(w_chances[1], pdef, filename);
878  else if (pdef->name()->value() == "weather_moderate_clouds")
879  GetDefNumber(w_chances[2], pdef, filename);
880  else if (pdef->name()->value() == "weather_overcast")
881  GetDefNumber(w_chances[3], pdef, filename);
882  else if (pdef->name()->value() == "weather_fog")
883  GetDefNumber(w_chances[4], pdef, filename);
884  else if (pdef->name()->value() == "weather_storm")
885  GetDefNumber(w_chances[5], pdef, filename);
886 
887  else if (pdef->name()->value() == "layer") {
888  if (!pdef->term() || !pdef->term()->isStruct()) {
889  Print("WARNING: terrain layer struct missing in '%s'\n", filename);
890  }
891  else {
892 
893  if (!region)
894  region = new(__FILE__,__LINE__) TerrainRegion(this, rgn_name, size, primary);
895 
896  TermStruct* val = pdef->term()->isStruct();
897  ParseLayer(region, val);
898  }
899  }
900  }
901  }
902 
903  if (!region)
904  region = new(__FILE__,__LINE__) TerrainRegion(this, rgn_name, size, primary);
905 
906  region->grid = grid;
907  region->inclination = inclination;
908  region->patch_name = patch_name;
909  region->patch_texture = patch_texture;
910  region->noise_tex0 = noise_tex0;
911  region->noise_tex1 = noise_tex1;
912  region->apron_name = apron_name;
913  region->apron_texture = apron_texture;
914  region->water_texture = water_texture;
915  region->haze_name = haze_name;
916  region->clouds_high = clouds_high;
917  region->shades_high = shades_high;
918  region->clouds_low = clouds_low;
919  region->shades_low = shades_low;
920  region->scale = scale;
921  region->mtnscale = mtnscale;
922  region->fog_density = fog_density;
923  region->fog_scale = fog_scale;
924  region->haze_fade = haze_fade;
925  region->clouds_alt_high = clouds_alt_high;
926  region->clouds_alt_low = clouds_alt_low;
927 
928  region->env_texture_positive_x = env_texture_positive_x;
929  region->env_texture_negative_x = env_texture_negative_x;
930  region->env_texture_positive_y = env_texture_positive_y;
931  region->env_texture_negative_y = env_texture_negative_y;
932  region->env_texture_positive_z = env_texture_positive_z;
933  region->env_texture_negative_z = env_texture_negative_z;
934 
935  Weather& weather = region->GetWeather();
936 
937  weather.SetPeriod(w_period);
938 
939  for (int i = 0; i < Weather::NUM_STATES; i++)
940  weather.SetChance(i, w_chances[i]);
941 
942  region->LoadSkyColors(sky_name);
943 
944  primary->regions.append(region);
945  all_regions.append(region);
946 }
947 
948 // +--------------------------------------------------------------------+
949 
950 void
952 {
953  Text tile_name;
954  Text detail_name;
955  double height = 0;
956 
957 
958  for (int i = 0; i < val->elements()->size(); i++) {
959  TermDef* pdef = val->elements()->at(i)->isDef();
960  if (pdef) {
961  if (pdef->name()->value().indexOf("tile") == 0)
962  GetDefText(tile_name, pdef, filename);
963 
964  else if (pdef->name()->value().indexOf("detail") == 0)
965  GetDefText(detail_name, pdef, filename);
966 
967  else if (pdef->name()->value().contains("height") ||
968  pdef->name()->value().contains("alt"))
969  GetDefNumber(height, pdef, filename);
970  }
971  }
972 
973  if (rgn)
974  rgn->AddLayer(height, tile_name, detail_name);
975 }
976 
977 // +--------------------------------------------------------------------+
978 
979 void
981 {
982  if (Game::Server())
983  return;
984 
985  if (!instantiated) {
986  Print("Creating Star System %s\n", (const char*) name);
987 
988  DataLoader* loader = DataLoader::GetLoader();
989  loader->SetDataPath(datapath);
990 
991  // poly star shell:
992  if (sky_poly_stars.length()) {
993  poly_stars = new(__FILE__,__LINE__) Solid;
995  poly_stars->SetLuminous(true);
996  poly_stars->SetInfinite(true);
997 
998  Print("Celestial Sphere '%s' loaded\n", (const char*) sky_poly_stars);
999  Print(" radius: %f\n", poly_stars->Radius());
1000  }
1001 
1002  if (sky_stars) {
1003  Print("Point Stars: %d\n", sky_stars);
1004  point_stars = new(__FILE__,__LINE__) Stars(sky_stars);
1005  }
1006 
1007  loader->SetDataPath(datapath);
1008 
1009  // nebula:
1010  if (sky_nebula.length()) {
1011  nebula = new(__FILE__,__LINE__) Solid;
1012  nebula->Load(sky_nebula, 100);
1013  nebula->SetLuminous(true);
1014  nebula->SetInfinite(true);
1015 
1016  Print("Nebular Sky '%s' loaded\n", (const char*) sky_nebula);
1017  Print(" radius: %f\n", nebula->Radius());
1018  }
1019 
1020  // atmospheric haze:
1021  if (sky_haze.length()) {
1022  loader->SetDataPath(datapath);
1023  haze = new(__FILE__,__LINE__) TerrainHaze();
1024  haze->Load(sky_haze, 120);
1025 
1026  haze->SetInfinite(true);
1027 
1028  Print("Atmospheric Haze '%s' loaded\n", (const char*) sky_haze);
1029  Print(" radius: %f\n", haze->Radius());
1030 
1031  haze->Hide();
1032  }
1033 
1034  loader->SetDataPath(0);
1035 
1037  while (++star) {
1038  CreateBody(*star);
1039 
1040  ListIter<OrbitalBody> planet = star->Satellites();
1041  while (++planet) {
1042  CreateBody(*planet);
1043 
1044  ListIter<OrbitalBody> moon = planet->Satellites();
1045  while (++moon) {
1046  CreateBody(*moon);
1047  }
1048  }
1049  }
1050  }
1051 
1052  instantiated = true;
1053 }
1054 
1055 // +--------------------------------------------------------------------+
1056 
1057 void
1059 {
1060  DataLoader* loader = DataLoader::GetLoader();
1061  loader->SetDataPath(datapath);
1062 
1063  // stars:
1064  if (body.type == Orbital::STAR) {
1065  Point starloc = body.loc;
1066  starloc = starloc.OtherHand();
1067 
1068  PlanetRep* rep = new(__FILE__,__LINE__) PlanetRep(body.tex_name,
1069  0,
1070  body.radius,
1071  starloc,
1072  body.tscale);
1073 
1074  rep->SetLuminous(true);
1075  rep->MoveTo(loc);
1076  body.rep = rep;
1077 
1078  sun_brightness = body.light;
1079  sun_color = body.color;
1080 
1081  Light* sun_light = new(__FILE__,__LINE__) Light(1.1f);
1082  sun_light->SetColor(sun_color);
1083  sun_light->SetShadow(true);
1084  sun_light->MoveTo(body.loc);
1085  sun_light->SetType(Light::LIGHT_DIRECTIONAL);
1086 
1087  sun_lights.append(sun_light);
1088  body.light_rep = sun_light;
1089 
1090  if (body.back != Color::Black) {
1091  Light* back_light = new(__FILE__,__LINE__) Light(0.6f);
1092  back_light->SetColor(body.back);
1093  back_light->SetShadow(false);
1094  back_light->MoveTo(body.loc * -1);
1095  back_light->SetType(Light::LIGHT_DIRECTIONAL);
1096 
1097  back_lights.append(back_light);
1098  body.back_light = back_light;
1099  }
1100  }
1101 
1102  // planets and moons:
1103  else {
1104  Point planetloc = body.loc;
1105  planetloc = planetloc.OtherHand();
1106 
1107  double rmax = 0;
1108  double rmin = 0;
1109 
1110  if (body.ring_max > 0) {
1111  rmax = body.ring_max*body.radius;
1112  rmin = body.ring_min*body.radius;
1113  }
1114 
1115  Text surface = body.tex_name;
1116  Text glow = body.tex_glow;
1117 
1118  if (Game::MaxTexSize() >= 512) {
1119  if (body.tex_high_res.length())
1120  surface = body.tex_high_res;
1121 
1122  if (body.tex_glow_high_res.length())
1123  glow = body.tex_glow_high_res;
1124  }
1125 
1126  PlanetRep* rep = new(__FILE__,__LINE__) PlanetRep(surface,
1127  glow,
1128  body.radius,
1129  planetloc,
1130  body.tscale,
1131  body.tex_ring,
1132  rmin,
1133  rmax,
1134  body.atmosphere,
1135  body.tex_gloss);
1136 
1137  rep->SetStarSystem(this);
1138 
1139  /***
1140  if (body.luminous) {
1141  rep->SetLuminous(1);
1142  }
1143  ***/
1144 
1145  if (body.tilt != 0) {
1146  Matrix m;
1147  m.Pitch(body.tilt);
1148 
1149  rep->SetOrientation(m);
1150  }
1151 
1152  body.rep = rep;
1153  }
1154 }
1155 
1156 // +--------------------------------------------------------------------+
1157 
1158 void
1160 {
1161  if (instantiated) {
1162  ListIter<OrbitalBody> star_iter = bodies;
1163  while (++star_iter) {
1164  OrbitalBody* star = star_iter.value();
1165 
1166  GRAPHIC_DESTROY(star->rep);
1167  LIGHT_DESTROY(star->light_rep);
1168  LIGHT_DESTROY(star->back_light);
1169 
1170  ListIter<OrbitalBody> planet = star->Satellites();
1171  while (++planet) {
1172  GRAPHIC_DESTROY(planet->rep);
1173 
1174  ListIter<OrbitalBody> moon = planet->Satellites();
1175  while (++moon) {
1176  GRAPHIC_DESTROY(moon->rep);
1177  }
1178  }
1179  }
1180 
1185 
1186  sun_lights.clear();
1187  back_lights.clear();
1188  }
1189 
1190  instantiated = false;
1191  sun_scale = 1;
1192 }
1193 
1194 // +--------------------------------------------------------------------+
1195 
1196 void
1198 {
1199  if (!instantiated)
1200  Create();
1201 
1203 
1204  if (!stars)
1205  return;
1206 
1207  if (point_stars) {
1208  scene.AddBackground(point_stars);
1209  point_stars->Hide();
1210  }
1211 
1212  if (poly_stars) {
1213  scene.AddBackground(poly_stars);
1214  }
1215 
1216  if (stars->Nebula() && nebula) {
1217  scene.AddBackground(nebula);
1218  }
1219 
1220  if (haze) {
1221  scene.AddBackground(haze);
1222  haze->Hide();
1223  }
1224 
1225  ListIter<OrbitalBody> star_iter = bodies;
1226  while (++star_iter) {
1227  OrbitalBody* star = star_iter.value();
1228  scene.AddGraphic(star->rep);
1229  scene.AddLight(star->light_rep);
1230  if (nebula && stars && stars->Nebula()) {
1231  star->back_light->SetColor(star->back);
1232  }
1233  else {
1234  Color c = Color(60,60,65);
1235  star->back_light->SetColor(c);
1236  }
1237  scene.AddLight(star->back_light);
1238 
1239  if (nebula && stars && stars->Nebula()) {
1240  scene.SetAmbient(ambient);
1241  }
1242  else {
1243  Color c = ambient;
1244  int n = (c.Red() + c.Green() + c.Blue()) / 3;
1245 
1246  c = Color(n,n,n);
1247  scene.SetAmbient(c);
1248  }
1249 
1250  ListIter<OrbitalBody> planet = star->Satellites();
1251  while (++planet) {
1252  scene.AddGraphic(planet->rep);
1253 
1254  ListIter<OrbitalBody> moon = planet->Satellites();
1255  while (++moon) {
1256  scene.AddGraphic(moon->rep);
1257  }
1258  }
1259  }
1260 
1261  ExecFrame();
1262 }
1263 
1264 // +--------------------------------------------------------------------+
1265 
1266 void
1268 {
1269  if (!instantiated)
1270  return;
1271 
1272  active_region = 0;
1273 
1274  if (point_stars && point_stars->GetScene())
1276 
1277  if (poly_stars && poly_stars->GetScene())
1279 
1280  if (nebula && nebula->GetScene())
1282 
1283  if (haze && haze->GetScene()) {
1285  haze->Hide();
1286  }
1287 
1289  while (++star) {
1290  if (star->rep && star->rep->GetScene())
1291  star->rep->GetScene()->DelGraphic(star->rep);
1292 
1293  if (star->light_rep && star->light_rep->GetScene())
1294  star->light_rep->GetScene()->DelLight(star->light_rep);
1295 
1296  if (star->back_light && star->back_light->GetScene())
1297  star->back_light->GetScene()->DelLight(star->back_light);
1298 
1299  ListIter<OrbitalBody> planet = star->Satellites();
1300  while (++planet) {
1301  if (planet->rep && planet->rep->GetScene())
1302  planet->rep->GetScene()->DelGraphic(planet->rep);
1303 
1304  ListIter<OrbitalBody> moon = planet->Satellites();
1305  while (++moon) {
1306  if (moon->rep && moon->rep->GetScene())
1307  moon->rep->GetScene()->DelGraphic(moon->rep);
1308  }
1309  }
1310  }
1311 }
1312 
1313 // +--------------------------------------------------------------------+
1314 
1315 void
1317 {
1318  Scene* scene = 0;
1319 
1320  if (active_region != rgn) {
1321  active_region = rgn;
1322 
1323  if (active_region) {
1324  if (active_region->Type() != Orbital::TERRAIN) {
1325  if (point_stars) point_stars->Hide();
1326  if (poly_stars) poly_stars->Show();
1327  if (nebula) nebula->Show();
1328  if (haze) haze->Hide();
1329  }
1330  else {
1331  if (point_stars) point_stars->Show();
1332  if (poly_stars) poly_stars->Hide();
1333  if (nebula) nebula->Hide();
1334  if (haze) haze->Show();
1335  }
1336 
1337  if (poly_stars) {
1338  scene = poly_stars->GetScene();
1339  if (scene)
1340  scene->SetAmbient(ambient);
1341  }
1342  else if (nebula) {
1343  scene = nebula->GetScene();
1344  if (scene)
1345  scene->SetAmbient(ambient);
1346  }
1347 
1349  while (++star) {
1350  if (star->rep)
1351  star->rep->Show();
1352  }
1353 
1354  ExecFrame();
1355  }
1356  else {
1357  if (point_stars) point_stars->Hide();
1358  if (poly_stars) poly_stars->Hide();
1359  if (nebula) nebula->Hide();
1360  if (haze) haze->Hide();
1361 
1362 
1364  while (++star) {
1365  if (star->rep)
1366  star->rep->Hide();
1367 
1368  if (star->light_rep) {
1369  scene = star->light_rep->GetScene();
1370  if (scene)
1371  scene->DelLight(star->light_rep);
1372  }
1373 
1374  if (star->back_light) {
1375  scene = star->back_light->GetScene();
1376  if (scene)
1377  scene->DelLight(star->back_light);
1378  }
1379  }
1380  }
1381  }
1382 }
1383 
1384 // +--------------------------------------------------------------------+
1385 
1386 static BYTE max3(BYTE a, BYTE b, BYTE c)
1387 {
1388  if (a > b)
1389  if (a > c) return a;
1390  else return c;
1391  else
1392  if (b > c) return b;
1393  else return c;
1394 }
1395 
1396 static BYTE min3(BYTE a, BYTE b, BYTE c)
1397 {
1398  if (a < b)
1399  if (a < c) return a;
1400  else return c;
1401  else
1402  if (b < c) return b;
1403  else return c;
1404 }
1405 
1406 void
1408 {
1409  CalcStardate();
1410 
1412  while (++star)
1413  star->Update();
1414 
1416  while (++region)
1417  region->Update();
1418 
1419  // update the graphic reps, relative to the active region:
1420  if (instantiated && active_region) {
1421  Point active_loc = active_region->Location();
1422  active_loc = active_loc.OtherHand();
1423 
1424  Scene* scene = 0;
1425  TerrainRegion* trgn = 0;
1426  bool terrain = (active_region->Type() == Orbital::TERRAIN);
1427  Matrix terrain_orientation;
1428  Matrix terrain_transformation;
1429 
1430  if (terrain) {
1431  trgn = (TerrainRegion*) active_region;
1432  Color tmp = trgn->SkyColor();
1433  Game::SetScreenColor(tmp);
1434 
1436  tvpn.Normalize();
1437  tvup = Point(0,0,-1);
1438  tvrt = tvpn.cross(tvup);
1439  tvrt.Normalize();
1440 
1441  terrain_orientation.Rotate(0, PI/2, 0);
1442  terrain_transformation = Matrix(tvrt, tvup, tvpn);
1443 
1444  if (point_stars) {
1445  point_stars->SetOrientation(terrain_transformation);
1446 
1447  Color sky_color = trgn->SkyColor();
1448  BYTE sky_red = (BYTE) sky_color.Red();
1449  BYTE sky_green = (BYTE) sky_color.Green();
1450  BYTE sky_blue = (BYTE) sky_color.Blue();
1451 
1452  BYTE Max = max3(sky_red, sky_green, sky_blue);
1453  BYTE Min = min3(sky_red, sky_green, sky_blue);
1454 
1455  BYTE lum = (BYTE) (240.0 * (Max + Min) / 510.0);
1456 
1457  if (lum > 50) {
1458  point_stars->Hide();
1459  }
1460  else {
1461  Stars* pstars = (Stars*) point_stars;
1462 
1463  pstars->Illuminate(1.0 - lum / 50.0);
1464  pstars->Show();
1465  }
1466 
1467  scene = point_stars->GetScene();
1468  }
1469 
1470  if (haze) {
1471  ((TerrainHaze*)haze)->UseTerrainRegion(trgn);
1472  scene = haze->GetScene();
1473  }
1474 
1475  if (scene) {
1476  scene->SetAmbient(ambient);
1477  }
1478 
1479  }
1480  else {
1482  }
1483 
1484  double star_alt = 0;
1485 
1486  ListIter<OrbitalBody> star_iter = bodies;
1487  while (++star_iter) {
1488  OrbitalBody* star = star_iter.value();
1489 
1490  if (active_region->Inclination() != 0) {
1491  double distance = (active_region->Location() - star->Location()).length();
1492  star_alt = sin(active_region->Inclination()) * distance;
1493  }
1494 
1495  if (terrain) {
1496  Point sloc = TerrainTransform(star->Location());
1497 
1498  if (star->rep) {
1499  star->rep->MoveTo(sloc);
1500 
1501  PlanetRep* pr = (PlanetRep*) star->rep;
1502  pr->SetDaytime(true);
1503  }
1504 
1505  if (star->light_rep) {
1506  star->light_rep->MoveTo(sloc);
1507  star->light_rep->SetActive(sloc.y > -100);
1508  }
1509 
1510  if (star->back_light) {
1511  star->back_light->MoveTo(sloc * -1);
1512  star->back_light->SetActive(sloc.y > -100);
1513  }
1514 
1515  if (trgn && star->rep) {
1516  if (trgn->IsEclipsed())
1517  star->rep->Hide();
1518  else
1519  star->rep->Show();
1520  }
1521  }
1522 
1523  else {
1524  Point sloc = Point(star->Location() - active_region->Location()).OtherHand();
1525  sloc.y = star_alt;
1526 
1527  if (star->rep) {
1528  star->rep->MoveTo(sloc);
1529 
1530  PlanetRep* pr = (PlanetRep*) star->rep;
1531  pr->SetDaytime(false);
1532  }
1533 
1534  if (star->light_rep) {
1535  star->light_rep->MoveTo(sloc);
1536  star->light_rep->SetActive(true);
1537  }
1538 
1539  if (star->back_light) {
1540  star->back_light->MoveTo(sloc * -1);
1541  star->back_light->SetActive(true);
1542  }
1543  }
1544 
1545  ListIter<OrbitalBody> planet_iter = star->Satellites();
1546  while (++planet_iter) {
1547  OrbitalBody* planet = planet_iter.value();
1548 
1549  if (planet->rep) {
1550  PlanetRep* pr = (PlanetRep*) planet->rep;
1551 
1552  if (terrain) {
1553  pr->MoveTo(TerrainTransform(planet->Location()));
1554  pr->SetOrientation(terrain_orientation);
1555 
1556  if (planet == active_region->Primary()) {
1557  pr->Hide();
1558  }
1559 
1560  else {
1561  pr->Show();
1562  pr->SetDaytime(true);
1563  }
1564  }
1565  else {
1566  pr->Show();
1567  pr->TranslateBy(active_loc);
1568  pr->SetDaytime(false);
1569  }
1570  }
1571 
1572  ListIter<OrbitalBody> moon_iter = planet->Satellites();
1573  while (++moon_iter) {
1574  OrbitalBody* moon = moon_iter.value();
1575 
1576  if (moon->rep) {
1577  PlanetRep* pr = (PlanetRep*) moon->rep;
1578 
1579  if (terrain) {
1580  pr->MoveTo(TerrainTransform(moon->Location()));
1581  pr->SetOrientation(terrain_orientation);
1582 
1583  if (moon == active_region->Primary()) {
1584  pr->Hide();
1585  }
1586 
1587  else {
1588  pr->Show();
1589  pr->SetDaytime(true);
1590  }
1591  }
1592  else {
1593  pr->Show();
1594  pr->TranslateBy(active_loc);
1595  pr->SetDaytime(false);
1596  }
1597  }
1598  }
1599  }
1600  }
1601  }
1602 }
1603 
1604 // +--------------------------------------------------------------------+
1605 
1606 Orbital*
1607 StarSystem::FindOrbital(const char* name)
1608 {
1609  if (!name || !name[0])
1610  return 0;
1611 
1613  while (++star) {
1614  if (!_stricmp(star->Name(), name))
1615  return star.value();
1616 
1617  ListIter<OrbitalRegion> star_rgn = star->Regions();
1618  while (++star_rgn) {
1619  if (!_stricmp(star_rgn->Name(), name))
1620  return star_rgn.value();
1621  }
1622 
1623  ListIter<OrbitalBody> planet = star->Satellites();
1624  while (++planet) {
1625  if (!_stricmp(planet->Name(), name))
1626  return planet.value();
1627 
1628  ListIter<OrbitalRegion> planet_rgn = planet->Regions();
1629  while (++planet_rgn) {
1630  if (!_stricmp(planet_rgn->Name(), name))
1631  return planet_rgn.value();
1632  }
1633 
1634  ListIter<OrbitalBody> moon = planet->Satellites();
1635  while (++moon) {
1636  if (!_stricmp(moon->Name(), name))
1637  return moon.value();
1638 
1639  ListIter<OrbitalRegion> moon_rgn = moon->Regions();
1640  while (++moon_rgn) {
1641  if (!_stricmp(moon_rgn->Name(), name))
1642  return moon_rgn.value();
1643  }
1644  }
1645  }
1646  }
1647 
1649  while (++region) {
1650  if (!_stricmp(region->Name(), name))
1651  return region.value();
1652  }
1653 
1654  return 0;
1655 }
1656 
1657 // +--------------------------------------------------------------------+
1658 
1660 StarSystem::FindRegion(const char* name)
1661 {
1662  if (!name || !name[0])
1663  return 0;
1664 
1666  while (++region) {
1667  if (!_stricmp(region->Name(), name))
1668  return region.value();
1669  }
1670 
1671  return 0;
1672 }
1673 
1674 // +--------------------------------------------------------------------+
1675 
1676 bool
1678 {
1679  ListIter<OrbitalRegion> iter = ((StarSystem*) this)->all_regions;
1680  while (++iter) {
1681  OrbitalRegion* rgn = iter.value();
1682 
1683  ListIter<Text> lnk_iter = rgn->Links();
1684  while (++lnk_iter) {
1685  Text* t = lnk_iter.value();
1686 
1687  if (s->FindRegion(*t))
1688  return true;
1689  }
1690  }
1691 
1692  return false;
1693 }
1694 
1695 // +--------------------------------------------------------------------+
1696 
1697 Point
1699 {
1700  Point result;
1701 
1702  Point tmp = loc - active_region->Location();
1703 
1704  result.x = tmp * tvrt;
1705  result.z = tmp * tvup;
1706  result.y = tmp * tvpn;
1707 
1708  return result;
1709 }
1710 
1711 Color
1713 {
1714  Color result = ambient;
1715  bool terrain = (active_region && active_region->Type() == Orbital::TERRAIN);
1716 
1717  if (terrain) {
1719  result = trgn->Ambient();
1720 
1721  if (trgn->IsEclipsed())
1722  result = result * 0.3;
1723  }
1724 
1725  return result;
1726 }
1727 
1728 void
1729 StarSystem::SetSunlight(Color color, double brightness)
1730 {
1731  sun_color = color;
1732  sun_scale = brightness;
1733 
1734  ListIter<Light> sun_iter = sun_lights;
1735  while (++sun_iter) {
1736  Light* sun_light = sun_iter.value();
1737  sun_light->SetColor(color);
1738  sun_light->SetIntensity((float) (1.1 * sun_scale));
1739  }
1740 
1741  ListIter<Light> back_iter = back_lights;
1742  while (++back_iter) {
1743  Light* back_light = back_iter.value();
1744  back_light->SetIntensity((float) (0.5 * sun_scale));
1745  }
1746 }
1747 
1748 void
1749 StarSystem::SetBacklight(Color color, double brightness)
1750 {
1751  ListIter<Light> back_iter = back_lights;
1752  while (++back_iter) {
1753  Light* back_light = back_iter.value();
1754  back_light->SetColor(color);
1755  back_light->SetIntensity((float) (0.5 * brightness));
1756  }
1757 }
1758 
1759 void
1761 {
1763  while (++iter) {
1764  OrbitalBody* star = iter.value();
1765 
1766  if (star) {
1767  if (star->light_rep) {
1768  star->light_rep->SetColor(star->LightColor());
1769  star->light_rep->SetIntensity(1.1f);
1770  }
1771 
1772  if (star->back_light) {
1773  star->back_light->SetColor(star->back);
1774  star->back_light->SetIntensity(0.5f);
1775  }
1776  }
1777  }
1778 }
1779 
1780 // +====================================================================+
1781 
1782 Color
1784 {
1785  return GetColor(seq);
1786 }
1787 
1788 int
1790 {
1791  return GetSize(seq);
1792 }
1793 
1794 Color
1796 {
1797  switch (s) {
1798  case O: return Color(128,128,255); break;
1799  case B: return Color(192,192,255); break;
1800  case A: return Color(220,220,255); break;
1801  case F: return Color(255,255,255); break;
1802  case G: return Color(255,255,128); break;
1803  case K: return Color(255,192,100); break;
1804  case M: return Color(255,100,100); break;
1805 
1806  case RED_GIANT: return Color(255, 80, 80); break;
1807  case WHITE_DWARF: return Color(255,255,255); break;
1808  case BLACK_HOLE: return Color( 0, 0, 0); break;
1809  }
1810 
1811  return Color::White;
1812 }
1813 
1814 int
1816 {
1817  switch (s) {
1818  case O: return 4; break;
1819  case B: return 4; break;
1820  case A: return 3; break;
1821  case F: return 3; break;
1822  case G: return 2; break;
1823  case K: return 2; break;
1824  case M: return 1; break;
1825 
1826  case RED_GIANT: return 4; break;
1827  case WHITE_DWARF: return 1; break;
1828  case BLACK_HOLE: return 3; break;
1829  }
1830 
1831  return 3;
1832 }
1833 
1834 // +====================================================================+
1835 
1836 Orbital::Orbital(StarSystem* s, const char* n, OrbitalType t, double m, double r, double o, Orbital* p)
1837 : name(n), type(t), subtype(0), radius(r), mass(m), orbit(o),
1838 phase(0), period(0), rotation(0), retro(false),
1839 system(s), primary(p), loc(0, 0, 0), rep(0), velocity(0)
1840 {
1841  if (system && primary && orbit > 0) {
1842  velocity = sqrt(GRAV * primary->Mass() / orbit);
1843  period = 2 * PI * orbit / velocity;
1844  }
1845 
1846  Update();
1847 }
1848 
1849 // +--------------------------------------------------------------------+
1850 
1852 {
1853  delete rep;
1854  regions.destroy();
1855 }
1856 
1857 // +--------------------------------------------------------------------+
1858 
1859 void
1861 {
1862  if (system && primary && orbit > 0) {
1863  double grade = (retro) ? -1 : 1;
1864 
1865  // orbits are counter clockwise:
1866  phase = -2 * PI * grade * StarSystem::Stardate() / period;
1867 
1868  loc = primary->Location() + Point((double) (orbit * cos(phase)),
1869  (double) (orbit * sin(phase)),
1870  0);
1871  }
1872 
1874  while (++region)
1875  region->Update();
1876 
1877  if (rep)
1878  rep->MoveTo(loc.OtherHand());
1879 }
1880 
1881 // +--------------------------------------------------------------------+
1882 
1883 Point
1885 {
1886  Point predicted_loc = Location();
1887 
1888  if (system && primary && orbit > 0) {
1889  predicted_loc = primary->PredictLocation(delta_t);
1890 
1891  double grade = (retro) ? -1 : 1;
1892 
1893  // orbits are(?) counter clockwise:
1894  double predicted_phase = (double) (-2 * PI * grade * (StarSystem::Stardate()+delta_t) / period);
1895 
1896  predicted_loc += Point((double) (orbit * cos(predicted_phase)),
1897  (double) (orbit * sin(predicted_phase)),
1898  0);
1899  }
1900 
1901  return predicted_loc;
1902 }
1903 
1904 void
1906 {
1907  if (img.Width() >=64 && img.Height() >= 64) {
1908  map_icon.CopyBitmap(img);
1909  map_icon.AutoMask();
1911  }
1912 }
1913 
1914 // +====================================================================+
1915 
1916 OrbitalBody::OrbitalBody(StarSystem* s, const char* n, OrbitalType t, double m, double r, double o, Orbital* p)
1917 : Orbital(s, n, t, m, r, o, p), light(0), light_rep(0), back_light(0),
1918 ring_min(0), ring_max(0), tilt(0), luminous(false)
1919 {
1920  Update();
1921 }
1922 
1923 // +--------------------------------------------------------------------+
1924 
1926 {
1927  satellites.destroy();
1928 }
1929 
1930 // +--------------------------------------------------------------------+
1931 
1932 void
1934 {
1935  Orbital::Update();
1936 
1937  theta = 0;
1938 
1939  if (rotation > 0)
1940  theta = -2 * PI * StarSystem::Stardate() / rotation;
1941 
1943  while (++body)
1944  body->Update();
1945 
1946  if (rep && theta != 0) {
1947  Matrix m;
1948  m.Pitch(tilt);
1949  m.Roll(tilt/2);
1950  m.Yaw(theta);
1951  rep->SetOrientation(m);
1952  }
1953 
1954  if (light_rep) {
1955  Point bodyloc = loc;
1956  bodyloc = bodyloc.OtherHand();
1957  light_rep->MoveTo(bodyloc);
1958  }
1959 }
1960 
1961 // +====================================================================+
1962 
1963 OrbitalRegion::OrbitalRegion(StarSystem* s, const char* n, double m, double r, double o, Orbital* p)
1964 : Orbital(s, n, REGION, m, r, o, p), grid(25.0e3f), inclination(0)
1965 {
1966 }
1967 
1968 // +--------------------------------------------------------------------+
1969 
1971 {
1972  links.destroy();
1973 }
1974