From d17521c8b9085a91d08fecfd0b51bbbf7b1dccac Mon Sep 17 00:00:00 2001 From: "milo24x7@gmail.com" Date: Sun, 7 Jul 2013 22:08:49 +0000 Subject: Updated open source license declaration and fixed some formatting issues. --- Stars45/StarSystem.cpp | 3972 ++++++++++++++++++++++++------------------------ 1 file changed, 1998 insertions(+), 1974 deletions(-) (limited to 'Stars45/StarSystem.cpp') diff --git a/Stars45/StarSystem.cpp b/Stars45/StarSystem.cpp index e04225b..8daed31 100644 --- a/Stars45/StarSystem.cpp +++ b/Stars45/StarSystem.cpp @@ -1,1974 +1,1998 @@ -/* Project Starshatter 4.5 - Destroyer Studios LLC - Copyright © 1997-2004. All Rights Reserved. - - SUBSYSTEM: Stars.exe - FILE: StarSystem.cpp - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Various Heavenly Bodies -*/ - -#include "MemDebug.h" -#include "StarSystem.h" -#include "Galaxy.h" -#include "Sky.h" -#include "Starshatter.h" -#include "TerrainRegion.h" -#include "TerrainHaze.h" -#include "Weather.h" - -#include "Game.h" -#include "Sound.h" -#include "Solid.h" -#include "Light.h" -#include "Bitmap.h" -#include "DataLoader.h" -#include "Scene.h" -#include "ParseUtil.h" - -const double epoch = 0.5e9; -double StarSystem::stardate = 0; - -// +====================================================================+ - -static double base_time = 0; -static WORD oldcw = 0; -static WORD fpcw = 0; - -void FPU2Extended() -{ - _asm { fstcw oldcw } - fpcw = oldcw | 0x0300; // set 80-bit precision mode - _asm { fldcw fpcw } -} - -void FPURestore() -{ - // well, I don't actually WANT single-precision mode - // so I think I'll just ignore this... - - //_asm { fldcw oldcw } -} - -void StarSystem::SetBaseTime(double t, bool absolute) -{ - FPU2Extended(); - - if (absolute) { - base_time = t; - CalcStardate(); - } - - else if (t > 0) { - if (t > epoch) t -= epoch; - base_time = t; - CalcStardate(); - } -} - -double StarSystem::GetBaseTime() -{ - return base_time; -} - -void StarSystem::CalcStardate() -{ - if (base_time < 1) { - time_t clock_seconds; - time(&clock_seconds); - - base_time = clock_seconds; - - while (base_time < 0) - base_time += epoch; - } - - FPU2Extended(); - - double gtime = (double) Game::GameTime() / 1000.0; - double sdate = gtime + base_time + epoch; - - stardate = sdate; - - FPURestore(); -} - -static const double GRAV = 6.673e-11; -static const int NAMELEN = 64; - -// +====================================================================+ - -StarSystem::StarSystem(const char* sys_name, Point l, int iff, int s) -: name(sys_name), affiliation(iff), sky_stars(0), sky_dust(0), loc(l), seq(s), -active_region(0), instantiated(false), ambient(0,0,0), -sun_color(255,255,255), sun_scale(1), point_stars(0), poly_stars(0), -nebula(0), haze(0) -{ - center = new(__FILE__,__LINE__) Orbital(this, "CG", Orbital::NOTHING, 1.0e35f, 0.0f, 0.0f, 0); - radius = 0.0f; -} - -// +--------------------------------------------------------------------+ - -StarSystem::~StarSystem() -{ - Print(" Destroying Star System %s\n", (const char*) name); - - if (instantiated) { - Deactivate(); - Destroy(); - } - - bodies.destroy(); - regions.destroy(); - all_regions.clear(); // do not destroy these! - - delete center; -} - -// +--------------------------------------------------------------------+ - -static OrbitalBody* primary_star = 0; -static OrbitalBody* primary_planet = 0; -static OrbitalBody* primary_moon = 0; - -void -StarSystem::Load() -{ - CalcStardate(); - active_region = 0; - - BYTE* block = 0; - DataLoader* loader = DataLoader::GetLoader(); - datapath = loader->GetDataPath(); - - sprintf_s(filename, "%s/%s.def", (const char*) name, (const char*) name); - - Print("Loading StarSystem: %s\n", filename); - loader->LoadBuffer(filename, block, true); - - if (!block) { - Print("ERROR: invalid star system file '%s'\n", filename); - exit(-2); - return; - } - - Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block)); - - Term* term = parser.ParseTerm(); - - if (!term) { - Print("ERROR: could not parse '%s'\n", filename); - exit(-3); - return; - } - else { - TermText* file_type = term->isText(); - if (!file_type || file_type->value() != "STARSYSTEM") { - Print("ERROR: invalid star system file '%s'\n", filename); - term->print(10); - exit(-4); - return; - } - } - - // parse the system: - do { - delete term; - term = parser.ParseTerm(); - - if (term) { - TermDef* def = term->isDef(); - if (def) { - if (def->name()->value() == "name") { - char namebuf[NAMELEN]; - namebuf[0] = 0; - GetDefText(namebuf, def, filename); - - if (namebuf[0]) - name = namebuf; - } - - else if (def->name()->value() == "sky") { - if (!def->term() || !def->term()->isStruct()) { - Print("WARNING: sky struct missing in '%s'\n", filename); - } - else { - TermStruct* val = def->term()->isStruct(); - - char imgname[NAMELEN]; - char magname[NAMELEN]; - char hazname[NAMELEN]; - - imgname[0] = 0; - magname[0] = 0; - hazname[0] = 0; - - for (int i = 0; i < val->elements()->size(); i++) { - TermDef* pdef = val->elements()->at(i)->isDef(); - if (pdef) { - if (pdef->name()->value() == "poly_stars") - GetDefText(imgname, pdef, filename); - - else if (pdef->name()->value() == "nebula") - GetDefText(magname, pdef, filename); - - else if (pdef->name()->value() == "haze") - GetDefText(hazname, pdef, filename); - } - } - - if (imgname[0]) - sky_poly_stars = imgname; - - if (magname[0]) - sky_nebula = magname; - - if (hazname[0]) - sky_haze = hazname; - } - } - - else if (def->name()->value() == "stars") { - GetDefNumber(sky_stars, def, filename); - } - - else if (def->name()->value() == "ambient") { - Vec3 a; - GetDefVec(a, def, filename); - - ambient = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z) * 2.5; - } - - else if (def->name()->value() == "dust") { - GetDefNumber(sky_dust, def, filename); - } - - else if (def->name()->value() == "star") { - if (!def->term() || !def->term()->isStruct()) { - Print("WARNING: star struct missing in '%s'\n", filename); - } - else { - TermStruct* val = def->term()->isStruct(); - ParseStar(val); - } - } - - else if (def->name()->value() == "planet") { - if (!def->term() || !def->term()->isStruct()) { - Print("WARNING: planet struct missing in '%s'\n", filename); - } - else { - TermStruct* val = def->term()->isStruct(); - ParsePlanet(val); - } - } - - else if (def->name()->value() == "moon") { - if (!def->term() || !def->term()->isStruct()) { - Print("WARNING: moon struct missing in '%s'\n", filename); - } - else { - TermStruct* val = def->term()->isStruct(); - ParseMoon(val); - } - } - - else if (def->name()->value() == "region") { - if (!def->term() || !def->term()->isStruct()) { - Print("WARNING: region struct missing in '%s'\n", filename); - } - else { - TermStruct* val = def->term()->isStruct(); - ParseRegion(val); - } - } - - else if (def->name()->value() == "terrain") { - if (!def->term() || !def->term()->isStruct()) { - Print("WARNING: terrain struct missing in '%s'\n", filename); - } - else { - TermStruct* val = def->term()->isStruct(); - ParseTerrain(val); - } - } - - } - } - } - while (term); - - loader->ReleaseBuffer(block); -} - -// +--------------------------------------------------------------------+ - -void -StarSystem::ParseStar(TermStruct* val) -{ - char star_name[NAMELEN]; - char img_name[NAMELEN]; - char map_name[NAMELEN]; - double light = 0.0; - double radius = 0.0; - double rot = 0.0; - double mass = 0.0; - double orbit = 0.0; - double tscale = 1.0; - bool retro = false; - Color color; - Color back; - - for (int i = 0; i < val->elements()->size(); i++) { - TermDef* pdef = val->elements()->at(i)->isDef(); - if (pdef) { - if (pdef->name()->value() == "name") - GetDefText(star_name, pdef, filename); - - else if (pdef->name()->value() == "map" || pdef->name()->value() == "icon") - GetDefText(map_name, pdef, filename); - - else if (pdef->name()->value() == "image") - GetDefText(img_name, pdef, filename); - - else if (pdef->name()->value() == "mass") - GetDefNumber(mass, pdef, filename); - - else if (pdef->name()->value() == "orbit") - GetDefNumber(orbit, pdef, filename); - - else if (pdef->name()->value() == "radius") - GetDefNumber(radius, pdef, filename); - - else if (pdef->name()->value() == "rotation") - GetDefNumber(rot, pdef, filename); - - else if (pdef->name()->value() == "tscale") - GetDefNumber(tscale, pdef, filename); - - else if (pdef->name()->value() == "light") - GetDefNumber(light, pdef, filename); - - else if (pdef->name()->value() == "retro") - GetDefBool(retro, pdef, filename); - - else if (pdef->name()->value() == "color") { - Vec3 a; - GetDefVec(a, pdef, filename); - color = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z); - } - - else if (pdef->name()->value() == "back" || pdef->name()->value() == "back_color") { - Vec3 a; - GetDefVec(a, pdef, filename); - back = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z); - } - } - } - - OrbitalBody* star = new(__FILE__,__LINE__) OrbitalBody(this, star_name, Orbital::STAR, mass, radius, orbit, center); - star->map_name = map_name; - star->tex_name = img_name; - star->light = light; - star->tscale = tscale; - star->subtype = Star::G; - star->retro = retro; - star->rotation = rot * 3600; - star->color = color; - star->back = back; - - // map icon: - if (*map_name) { - DataLoader::GetLoader()->LoadBitmap(map_name, star->map_icon, Bitmap::BMP_TRANSLUCENT, true); - } - - bodies.append(star); - primary_star = star; - primary_planet = 0; - primary_moon = 0; - - if (orbit > StarSystem::radius) - StarSystem::radius = orbit; -} - -// +--------------------------------------------------------------------+ - -void -StarSystem::ParsePlanet(TermStruct* val) -{ - char pln_name[NAMELEN]; - char img_name[NAMELEN]; - char map_name[NAMELEN]; - char hi_name[NAMELEN]; - char img_ring[NAMELEN]; - char glo_name[NAMELEN]; - char glo_hi_name[NAMELEN]; - char gloss_name[NAMELEN]; - - double radius = 0.0; - double mass = 0.0; - double orbit = 0.0; - double rot = 0.0; - double minrad = 0.0; - double maxrad = 0.0; - double tscale = 1.0; - double tilt = 0.0; - bool retro = false; - bool lumin = false; - Color atmos = Color::Black; - - ZeroMemory(pln_name, NAMELEN); - ZeroMemory(hi_name, NAMELEN); - ZeroMemory(img_ring, NAMELEN); - ZeroMemory(glo_name, NAMELEN); - ZeroMemory(glo_hi_name, NAMELEN); - ZeroMemory(gloss_name, NAMELEN); - ZeroMemory(map_name, NAMELEN); - - for (int i = 0; i < val->elements()->size(); i++) { - TermDef* pdef = val->elements()->at(i)->isDef(); - if (pdef) { - if (pdef->name()->value() == "name") - GetDefText(pln_name, pdef, filename); - - else if (pdef->name()->value() == "map" || pdef->name()->value() == "icon") - GetDefText(map_name, pdef, filename); - - else if (pdef->name()->value() == "image") - GetDefText(img_name, pdef, filename); - - else if (pdef->name()->value() == "image_west") - GetDefText(img_name, pdef, filename); - - else if (pdef->name()->value() == "image_east") - GetDefText(img_name, pdef, filename); - - else if (pdef->name()->value() == "glow") - GetDefText(glo_name, pdef, filename); - - else if (pdef->name()->value() == "gloss") - GetDefText(gloss_name, pdef, filename); - - else if (pdef->name()->value() == "high_res") - GetDefText(hi_name, pdef, filename); - - else if (pdef->name()->value() == "high_res_west") - GetDefText(hi_name, pdef, filename); - - else if (pdef->name()->value() == "high_res_east") - GetDefText(hi_name, pdef, filename); - - else if (pdef->name()->value() == "glow_high_res") - GetDefText(glo_hi_name, pdef, filename); - - else if (pdef->name()->value() == "mass") - GetDefNumber(mass, pdef, filename); - - else if (pdef->name()->value() == "orbit") - GetDefNumber(orbit, pdef, filename); - - else if (pdef->name()->value() == "retro") - GetDefBool(retro, pdef, filename); - - else if (pdef->name()->value() == "luminous") - GetDefBool(lumin, pdef, filename); - - else if (pdef->name()->value() == "rotation") - GetDefNumber(rot, pdef, filename); - - else if (pdef->name()->value() == "radius") - GetDefNumber(radius, pdef, filename); - - else if (pdef->name()->value() == "ring") - GetDefText(img_ring, pdef, filename); - - else if (pdef->name()->value() == "minrad") - GetDefNumber(minrad, pdef, filename); - - else if (pdef->name()->value() == "maxrad") - GetDefNumber(maxrad, pdef, filename); - - else if (pdef->name()->value() == "tscale") - GetDefNumber(tscale, pdef, filename); - - else if (pdef->name()->value() == "tilt") - GetDefNumber(tilt, pdef, filename); - - else if (pdef->name()->value() == "atmosphere") { - Vec3 a; - GetDefVec(a, pdef, filename); - atmos = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z); - } - } - } - - OrbitalBody* planet = new(__FILE__,__LINE__) OrbitalBody(this, pln_name, Orbital::PLANET, mass, radius, orbit, primary_star); - planet->map_name = map_name; - planet->tex_name = img_name; - planet->tex_high_res = hi_name; - planet->tex_ring = img_ring; - planet->tex_glow = glo_name; - planet->tex_glow_high_res = glo_hi_name; - planet->tex_gloss = gloss_name; - planet->ring_min = minrad; - planet->ring_max = maxrad; - planet->tscale = tscale; - planet->tilt = tilt; - planet->retro = retro; - planet->luminous = lumin; - planet->rotation = rot * 3600; - planet->atmosphere = atmos; - - if (primary_star) - primary_star->satellites.append(planet); - else - bodies.append(planet); - - primary_planet = planet; - primary_moon = 0; - - if (orbit > StarSystem::radius) - StarSystem::radius = orbit; - - // map icon: - if (map_name[0]) { - DataLoader::GetLoader()->LoadBitmap(map_name, planet->map_icon, Bitmap::BMP_TRANSLUCENT, true); - } -} - -// +--------------------------------------------------------------------+ - -void -StarSystem::ParseMoon(TermStruct* val) -{ - char map_name[NAMELEN]; - char pln_name[NAMELEN]; - char img_name[NAMELEN]; - char hi_name[NAMELEN]; - char glo_name[NAMELEN]; - char glo_hi_name[NAMELEN]; - char gloss_name[NAMELEN]; - - double radius = 0.0; - double mass = 0.0; - double orbit = 0.0; - double rot = 0.0; - double tscale = 1.0; - double tilt = 0.0; - bool retro = false; - Color atmos = Color::Black; - - ZeroMemory(map_name, NAMELEN); - ZeroMemory(pln_name, NAMELEN); - ZeroMemory(hi_name, NAMELEN); - ZeroMemory(img_name, NAMELEN); - ZeroMemory(glo_name, NAMELEN); - ZeroMemory(glo_hi_name, NAMELEN); - ZeroMemory(gloss_name, NAMELEN); - - for (int i = 0; i < val->elements()->size(); i++) { - TermDef* pdef = val->elements()->at(i)->isDef(); - if (pdef) { - if (pdef->name()->value() == "name") - GetDefText(pln_name, pdef, filename); - - else if (pdef->name()->value() == "map" || pdef->name()->value() == "icon") - GetDefText(map_name, pdef, filename); - - else if (pdef->name()->value() == "image") - GetDefText(img_name, pdef, filename); - - else if (pdef->name()->value() == "glow") - GetDefText(glo_name, pdef, filename); - - else if (pdef->name()->value() == "high_res") - GetDefText(hi_name, pdef, filename); - - else if (pdef->name()->value() == "glow_high_res") - GetDefText(glo_hi_name, pdef, filename); - - else if (pdef->name()->value() == "gloss") - GetDefText(gloss_name, pdef, filename); - - else if (pdef->name()->value() == "mass") - GetDefNumber(mass, pdef, filename); - - else if (pdef->name()->value() == "orbit") - GetDefNumber(orbit, pdef, filename); - - else if (pdef->name()->value() == "rotation") - GetDefNumber(rot, pdef, filename); - - else if (pdef->name()->value() == "retro") - GetDefBool(retro, pdef, filename); - - else if (pdef->name()->value() == "radius") - GetDefNumber(radius, pdef, filename); - - else if (pdef->name()->value() == "tscale") - GetDefNumber(tscale, pdef, filename); - - else if (pdef->name()->value() == "inclination") - GetDefNumber(tilt, pdef, filename); - - else if (pdef->name()->value() == "atmosphere") { - Vec3 a; - GetDefVec(a, pdef, filename); - atmos = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z); - } - } - } - - OrbitalBody* moon = new(__FILE__,__LINE__) OrbitalBody(this, pln_name, Orbital::MOON, mass, radius, orbit, primary_planet); - moon->map_name = map_name; - moon->tex_name = img_name; - moon->tex_high_res = hi_name; - moon->tex_glow = glo_name; - moon->tex_glow_high_res = glo_hi_name; - moon->tex_gloss = gloss_name; - moon->tscale = tscale; - moon->retro = retro; - moon->rotation = rot * 3600; - moon->tilt = tilt; - moon->atmosphere = atmos; - - if (primary_planet) - primary_planet->satellites.append(moon); - else { - Print("WARNING: no planet for moon %s in '%s', deleted.\n", pln_name, filename); - delete moon; - moon = 0; - } - - primary_moon = moon; - - // map icon: - if (map_name[0]) { - DataLoader::GetLoader()->LoadBitmap(map_name, moon->map_icon, Bitmap::BMP_TRANSLUCENT, true); - } -} - -// +--------------------------------------------------------------------+ - -void -StarSystem::ParseRegion(TermStruct* val) -{ - char rgn_name[NAMELEN]; - char lnk_name[NAMELEN]; - double size = 1.0e6; - double orbit = 0.0; - double grid = 25000; - double inclination = 0.0; - int asteroids = 0; - - List links; - - for (int i = 0; i < val->elements()->size(); i++) { - TermDef* pdef = val->elements()->at(i)->isDef(); - if (pdef) { - if (pdef->name()->value() == "name") - GetDefText(rgn_name, pdef, filename); - - else if (pdef->name()->value() == "link") { - GetDefText(lnk_name, pdef, filename); - if (lnk_name[0]) { - links.append(new(__FILE__,__LINE__) Text(lnk_name)); - } - } - - else if (pdef->name()->value() == "orbit") - GetDefNumber(orbit, pdef, filename); - - else if (pdef->name()->value() == "size") - GetDefNumber(size, pdef, filename); - - else if (pdef->name()->value() == "radius") - GetDefNumber(size, pdef, filename); - - else if (pdef->name()->value() == "grid") - GetDefNumber(grid, pdef, filename); - - else if (pdef->name()->value() == "inclination") - GetDefNumber(inclination, pdef, filename); - - else if (pdef->name()->value() == "asteroids") - GetDefNumber(asteroids, pdef, filename); - } - } - - Orbital* primary = primary_moon; - if (!primary) primary = primary_planet; - if (!primary) primary = primary_star; - - OrbitalRegion* region = new(__FILE__,__LINE__) OrbitalRegion(this, rgn_name, 0, size, orbit, primary); - region->grid = grid; - region->inclination = inclination; - region->asteroids = asteroids; - region->links.append(links); - - if (primary) - primary->regions.append(region); - else - regions.append(region); - - all_regions.append(region); - - if (orbit > StarSystem::radius) - StarSystem::radius = orbit; -} - -// +--------------------------------------------------------------------+ - -void -StarSystem::ParseTerrain(TermStruct* val) -{ - Orbital* primary = primary_moon; - if (!primary) primary = primary_planet; - - if (!primary) { - Print("WARNING: Terrain region with no primary ignored in '%s'\n", filename); - return; - } - - TerrainRegion* region = 0; - - Text rgn_name; - Text patch_name; - Text patch_texture; - Text noise_tex0; - Text noise_tex1; - Text apron_name; - Text apron_texture; - Text water_texture; - Text env_texture_positive_x; - Text env_texture_negative_x; - Text env_texture_positive_y; - Text env_texture_negative_y; - Text env_texture_positive_z; - Text env_texture_negative_z; - Text haze_name; - Text sky_name; - Text clouds_high; - Text clouds_low; - Text shades_high; - Text shades_low; - - double size = 1.0e6; - double grid = 25000; - double inclination = 0.0; - double scale = 10e3; - double mtnscale = 1e3; - double fog_density = 0; - double fog_scale = 0; - double haze_fade = 0; - double clouds_alt_high= 0; - double clouds_alt_low= 0; - double w_period = 0; - double w_chances[Weather::NUM_STATES]; - - ZeroMemory(w_chances, sizeof(w_chances)); - - for (int i = 0; i < val->elements()->size(); i++) { - TermDef* pdef = val->elements()->at(i)->isDef(); - if (pdef) { - if (pdef->name()->value() == "name") - GetDefText(rgn_name, pdef, filename); - - else if (pdef->name()->value() == "patch") - GetDefText(patch_name, pdef, filename); - - else if (pdef->name()->value() == "patch_texture") - GetDefText(patch_texture, pdef, filename); - - else if (pdef->name()->value() == "detail_texture_0") - GetDefText(noise_tex0, pdef, filename); - - else if (pdef->name()->value() == "detail_texture_1") - GetDefText(noise_tex1, pdef, filename); - - else if (pdef->name()->value() == "apron") - GetDefText(apron_name, pdef, filename); - - else if (pdef->name()->value() == "apron_texture") - GetDefText(apron_texture, pdef, filename); - - else if (pdef->name()->value() == "water_texture") - GetDefText(water_texture, pdef, filename); - - else if (pdef->name()->value() == "env_texture_positive_x") - GetDefText(env_texture_positive_x, pdef, filename); - - else if (pdef->name()->value() == "env_texture_negative_x") - GetDefText(env_texture_negative_x, pdef, filename); - - else if (pdef->name()->value() == "env_texture_positive_y") - GetDefText(env_texture_positive_y, pdef, filename); - - else if (pdef->name()->value() == "env_texture_negative_y") - GetDefText(env_texture_negative_y, pdef, filename); - - else if (pdef->name()->value() == "env_texture_positive_z") - GetDefText(env_texture_positive_z, pdef, filename); - - else if (pdef->name()->value() == "env_texture_negative_z") - GetDefText(env_texture_negative_z, pdef, filename); - - else if (pdef->name()->value() == "clouds_high") - GetDefText(clouds_high, pdef, filename); - - else if (pdef->name()->value() == "shades_high") - GetDefText(shades_high, pdef, filename); - - else if (pdef->name()->value() == "clouds_low") - GetDefText(clouds_low, pdef, filename); - - else if (pdef->name()->value() == "shades_low") - GetDefText(shades_low, pdef, filename); - - else if (pdef->name()->value() == "haze") - GetDefText(haze_name, pdef, filename); - - else if (pdef->name()->value() == "sky_color") - GetDefText(sky_name, pdef, filename); - - else if (pdef->name()->value() == "size" || - pdef->name()->value() == "radius") - GetDefNumber(size, pdef, filename); - - else if (pdef->name()->value() == "grid") - GetDefNumber(grid, pdef, filename); - - else if (pdef->name()->value() == "inclination") - GetDefNumber(inclination, pdef, filename); - - else if (pdef->name()->value() == "scale") - GetDefNumber(scale, pdef, filename); - - else if (pdef->name()->value() == "mtnscale" || - pdef->name()->value() == "mtn_scale") - GetDefNumber(mtnscale, pdef, filename); - - else if (pdef->name()->value() == "fog_density") - GetDefNumber(fog_density, pdef, filename); - - else if (pdef->name()->value() == "fog_scale") - GetDefNumber(fog_scale, pdef, filename); - - else if (pdef->name()->value() == "haze_fade") - GetDefNumber(haze_fade, pdef, filename); - - else if (pdef->name()->value() == "clouds_alt_high") - GetDefNumber(clouds_alt_high, pdef, filename); - - else if (pdef->name()->value() == "clouds_alt_low") - GetDefNumber(clouds_alt_low, pdef, filename); - - else if (pdef->name()->value() == "weather_period") - GetDefNumber(w_period, pdef, filename); - - else if (pdef->name()->value() == "weather_clear") - GetDefNumber(w_chances[0], pdef, filename); - else if (pdef->name()->value() == "weather_high_clouds") - GetDefNumber(w_chances[1], pdef, filename); - else if (pdef->name()->value() == "weather_moderate_clouds") - GetDefNumber(w_chances[2], pdef, filename); - else if (pdef->name()->value() == "weather_overcast") - GetDefNumber(w_chances[3], pdef, filename); - else if (pdef->name()->value() == "weather_fog") - GetDefNumber(w_chances[4], pdef, filename); - else if (pdef->name()->value() == "weather_storm") - GetDefNumber(w_chances[5], pdef, filename); - - else if (pdef->name()->value() == "layer") { - if (!pdef->term() || !pdef->term()->isStruct()) { - Print("WARNING: terrain layer struct missing in '%s'\n", filename); - } - else { - - if (!region) - region = new(__FILE__,__LINE__) TerrainRegion(this, rgn_name, size, primary); - - TermStruct* val = pdef->term()->isStruct(); - ParseLayer(region, val); - } - } - } - } - - if (!region) - region = new(__FILE__,__LINE__) TerrainRegion(this, rgn_name, size, primary); - - region->grid = grid; - region->inclination = inclination; - region->patch_name = patch_name; - region->patch_texture = patch_texture; - region->noise_tex0 = noise_tex0; - region->noise_tex1 = noise_tex1; - region->apron_name = apron_name; - region->apron_texture = apron_texture; - region->water_texture = water_texture; - region->haze_name = haze_name; - region->clouds_high = clouds_high; - region->shades_high = shades_high; - region->clouds_low = clouds_low; - region->shades_low = shades_low; - region->scale = scale; - region->mtnscale = mtnscale; - region->fog_density = fog_density; - region->fog_scale = fog_scale; - region->haze_fade = haze_fade; - region->clouds_alt_high = clouds_alt_high; - region->clouds_alt_low = clouds_alt_low; - - region->env_texture_positive_x = env_texture_positive_x; - region->env_texture_negative_x = env_texture_negative_x; - region->env_texture_positive_y = env_texture_positive_y; - region->env_texture_negative_y = env_texture_negative_y; - region->env_texture_positive_z = env_texture_positive_z; - region->env_texture_negative_z = env_texture_negative_z; - - Weather& weather = region->GetWeather(); - - weather.SetPeriod(w_period); - - for (int i = 0; i < Weather::NUM_STATES; i++) - weather.SetChance(i, w_chances[i]); - - region->LoadSkyColors(sky_name); - - primary->regions.append(region); - all_regions.append(region); -} - -// +--------------------------------------------------------------------+ - -void -StarSystem::ParseLayer(TerrainRegion* rgn, TermStruct* val) -{ - Text tile_name; - Text detail_name; - double height = 0; - - - for (int i = 0; i < val->elements()->size(); i++) { - TermDef* pdef = val->elements()->at(i)->isDef(); - if (pdef) { - if (pdef->name()->value().indexOf("tile") == 0) - GetDefText(tile_name, pdef, filename); - - else if (pdef->name()->value().indexOf("detail") == 0) - GetDefText(detail_name, pdef, filename); - - else if (pdef->name()->value().contains("height") || - pdef->name()->value().contains("alt")) - GetDefNumber(height, pdef, filename); - } - } - - if (rgn) - rgn->AddLayer(height, tile_name, detail_name); -} - -// +--------------------------------------------------------------------+ - -void -StarSystem::Create() -{ - if (Game::Server()) - return; - - if (!instantiated) { - Print("Creating Star System %s\n", (const char*) name); - - DataLoader* loader = DataLoader::GetLoader(); - loader->SetDataPath(datapath); - - // poly star shell: - if (sky_poly_stars.length()) { - poly_stars = new(__FILE__,__LINE__) Solid; - poly_stars->Load(sky_poly_stars, 120); - poly_stars->SetLuminous(true); - poly_stars->SetInfinite(true); - - Print("Celestial Sphere '%s' loaded\n", (const char*) sky_poly_stars); - Print(" radius: %f\n", poly_stars->Radius()); - } - - if (sky_stars) { - Print("Point Stars: %d\n", sky_stars); - point_stars = new(__FILE__,__LINE__) Stars(sky_stars); - } - - loader->SetDataPath(datapath); - - // nebula: - if (sky_nebula.length()) { - nebula = new(__FILE__,__LINE__) Solid; - nebula->Load(sky_nebula, 100); - nebula->SetLuminous(true); - nebula->SetInfinite(true); - - Print("Nebular Sky '%s' loaded\n", (const char*) sky_nebula); - Print(" radius: %f\n", nebula->Radius()); - } - - // atmospheric haze: - if (sky_haze.length()) { - loader->SetDataPath(datapath); - haze = new(__FILE__,__LINE__) TerrainHaze(); - haze->Load(sky_haze, 120); - - haze->SetInfinite(true); - - Print("Atmospheric Haze '%s' loaded\n", (const char*) sky_haze); - Print(" radius: %f\n", haze->Radius()); - - haze->Hide(); - } - - loader->SetDataPath(0); - - ListIter star = bodies; - while (++star) { - CreateBody(*star); - - ListIter planet = star->Satellites(); - while (++planet) { - CreateBody(*planet); - - ListIter moon = planet->Satellites(); - while (++moon) { - CreateBody(*moon); - } - } - } - } - - instantiated = true; -} - -// +--------------------------------------------------------------------+ - -void -StarSystem::CreateBody(OrbitalBody& body) -{ - DataLoader* loader = DataLoader::GetLoader(); - loader->SetDataPath(datapath); - - // stars: - if (body.type == Orbital::STAR) { - Point starloc = body.loc; - starloc = starloc.OtherHand(); - - PlanetRep* rep = new(__FILE__,__LINE__) PlanetRep(body.tex_name, - 0, - body.radius, - starloc, - body.tscale); - - rep->SetLuminous(true); - rep->MoveTo(loc); - body.rep = rep; - - sun_brightness = body.light; - sun_color = body.color; - - Light* sun_light = new(__FILE__,__LINE__) Light(1.1f); - sun_light->SetColor(sun_color); - sun_light->SetShadow(true); - sun_light->MoveTo(body.loc); - sun_light->SetType(Light::LIGHT_DIRECTIONAL); - - sun_lights.append(sun_light); - body.light_rep = sun_light; - - if (body.back != Color::Black) { - Light* back_light = new(__FILE__,__LINE__) Light(0.6f); - back_light->SetColor(body.back); - back_light->SetShadow(false); - back_light->MoveTo(body.loc * -1); - back_light->SetType(Light::LIGHT_DIRECTIONAL); - - back_lights.append(back_light); - body.back_light = back_light; - } - } - - // planets and moons: - else { - Point planetloc = body.loc; - planetloc = planetloc.OtherHand(); - - double rmax = 0; - double rmin = 0; - - if (body.ring_max > 0) { - rmax = body.ring_max*body.radius; - rmin = body.ring_min*body.radius; - } - - Text surface = body.tex_name; - Text glow = body.tex_glow; - - if (Game::MaxTexSize() >= 512) { - if (body.tex_high_res.length()) - surface = body.tex_high_res; - - if (body.tex_glow_high_res.length()) - glow = body.tex_glow_high_res; - } - - PlanetRep* rep = new(__FILE__,__LINE__) PlanetRep(surface, - glow, - body.radius, - planetloc, - body.tscale, - body.tex_ring, - rmin, - rmax, - body.atmosphere, - body.tex_gloss); - - rep->SetStarSystem(this); - - /*** - if (body.luminous) { - rep->SetLuminous(1); - } - ***/ - - if (body.tilt != 0) { - Matrix m; - m.Pitch(body.tilt); - - rep->SetOrientation(m); - } - - body.rep = rep; - } -} - -// +--------------------------------------------------------------------+ - -void -StarSystem::Destroy() -{ - if (instantiated) { - ListIter star_iter = bodies; - while (++star_iter) { - OrbitalBody* star = star_iter.value(); - - GRAPHIC_DESTROY(star->rep); - LIGHT_DESTROY(star->light_rep); - LIGHT_DESTROY(star->back_light); - - ListIter planet = star->Satellites(); - while (++planet) { - GRAPHIC_DESTROY(planet->rep); - - ListIter moon = planet->Satellites(); - while (++moon) { - GRAPHIC_DESTROY(moon->rep); - } - } - } - - GRAPHIC_DESTROY(point_stars); - GRAPHIC_DESTROY(poly_stars); - GRAPHIC_DESTROY(nebula); - GRAPHIC_DESTROY(haze); - - sun_lights.clear(); - back_lights.clear(); - } - - instantiated = false; - sun_scale = 1; -} - -// +--------------------------------------------------------------------+ - -void -StarSystem::Activate(Scene& scene) -{ - if (!instantiated) - Create(); - - Starshatter* stars = Starshatter::GetInstance(); - - if (!stars) - return; - - if (point_stars) { - scene.AddBackground(point_stars); - point_stars->Hide(); - } - - if (poly_stars) { - scene.AddBackground(poly_stars); - } - - if (stars->Nebula() && nebula) { - scene.AddBackground(nebula); - } - - if (haze) { - scene.AddBackground(haze); - haze->Hide(); - } - - ListIter star_iter = bodies; - while (++star_iter) { - OrbitalBody* star = star_iter.value(); - scene.AddGraphic(star->rep); - scene.AddLight(star->light_rep); - if (nebula && stars && stars->Nebula()) { - star->back_light->SetColor(star->back); - } - else { - Color c = Color(60,60,65); - star->back_light->SetColor(c); - } - scene.AddLight(star->back_light); - - if (nebula && stars && stars->Nebula()) { - scene.SetAmbient(ambient); - } - else { - Color c = ambient; - int n = (c.Red() + c.Green() + c.Blue()) / 3; - - c = Color(n,n,n); - scene.SetAmbient(c); - } - - ListIter planet = star->Satellites(); - while (++planet) { - scene.AddGraphic(planet->rep); - - ListIter moon = planet->Satellites(); - while (++moon) { - scene.AddGraphic(moon->rep); - } - } - } - - ExecFrame(); -} - -// +--------------------------------------------------------------------+ - -void -StarSystem::Deactivate() -{ - if (!instantiated) - return; - - active_region = 0; - - if (point_stars && point_stars->GetScene()) - point_stars->GetScene()->DelBackground(point_stars); - - if (poly_stars && poly_stars->GetScene()) - poly_stars->GetScene()->DelBackground(poly_stars); - - if (nebula && nebula->GetScene()) - nebula->GetScene()->DelBackground(nebula); - - if (haze && haze->GetScene()) { - haze->GetScene()->DelBackground(haze); - haze->Hide(); - } - - ListIter star = bodies; - while (++star) { - if (star->rep && star->rep->GetScene()) - star->rep->GetScene()->DelGraphic(star->rep); - - if (star->light_rep && star->light_rep->GetScene()) - star->light_rep->GetScene()->DelLight(star->light_rep); - - if (star->back_light && star->back_light->GetScene()) - star->back_light->GetScene()->DelLight(star->back_light); - - ListIter planet = star->Satellites(); - while (++planet) { - if (planet->rep && planet->rep->GetScene()) - planet->rep->GetScene()->DelGraphic(planet->rep); - - ListIter moon = planet->Satellites(); - while (++moon) { - if (moon->rep && moon->rep->GetScene()) - moon->rep->GetScene()->DelGraphic(moon->rep); - } - } - } -} - -// +--------------------------------------------------------------------+ - -void -StarSystem::SetActiveRegion(OrbitalRegion* rgn) -{ - Scene* scene = 0; - - if (active_region != rgn) { - active_region = rgn; - - if (active_region) { - if (active_region->Type() != Orbital::TERRAIN) { - if (point_stars) point_stars->Hide(); - if (poly_stars) poly_stars->Show(); - if (nebula) nebula->Show(); - if (haze) haze->Hide(); - } - else { - if (point_stars) point_stars->Show(); - if (poly_stars) poly_stars->Hide(); - if (nebula) nebula->Hide(); - if (haze) haze->Show(); - } - - if (poly_stars) { - scene = poly_stars->GetScene(); - if (scene) - scene->SetAmbient(ambient); - } - else if (nebula) { - scene = nebula->GetScene(); - if (scene) - scene->SetAmbient(ambient); - } - - ListIter star = bodies; - while (++star) { - if (star->rep) - star->rep->Show(); - } - - ExecFrame(); - } - else { - if (point_stars) point_stars->Hide(); - if (poly_stars) poly_stars->Hide(); - if (nebula) nebula->Hide(); - if (haze) haze->Hide(); - - - ListIter star = bodies; - while (++star) { - if (star->rep) - star->rep->Hide(); - - if (star->light_rep) { - scene = star->light_rep->GetScene(); - if (scene) - scene->DelLight(star->light_rep); - } - - if (star->back_light) { - scene = star->back_light->GetScene(); - if (scene) - scene->DelLight(star->back_light); - } - } - } - } -} - -// +--------------------------------------------------------------------+ - -static BYTE max3(BYTE a, BYTE b, BYTE c) -{ - if (a > b) - if (a > c) return a; - else return c; - else - if (b > c) return b; - else return c; -} - -static BYTE min3(BYTE a, BYTE b, BYTE c) -{ - if (a < b) - if (a < c) return a; - else return c; - else - if (b < c) return b; - else return c; -} - -void -StarSystem::ExecFrame() -{ - CalcStardate(); - - ListIter star = bodies; - while (++star) - star->Update(); - - ListIter region = regions; - while (++region) - region->Update(); - - // update the graphic reps, relative to the active region: - if (instantiated && active_region) { - Point active_loc = active_region->Location(); - active_loc = active_loc.OtherHand(); - - Scene* scene = 0; - TerrainRegion* trgn = 0; - bool terrain = (active_region->Type() == Orbital::TERRAIN); - Matrix terrain_orientation; - Matrix terrain_transformation; - - if (terrain) { - trgn = (TerrainRegion*) active_region; - Color tmp = trgn->SkyColor(); - Game::SetScreenColor(tmp); - - tvpn = (active_region->Location() - active_region->Primary()->Location()); - tvpn.Normalize(); - tvup = Point(0,0,-1); - tvrt = tvpn.cross(tvup); - tvrt.Normalize(); - - terrain_orientation.Rotate(0, PI/2, 0); - terrain_transformation = Matrix(tvrt, tvup, tvpn); - - if (point_stars) { - point_stars->SetOrientation(terrain_transformation); - - Color sky_color = trgn->SkyColor(); - BYTE sky_red = (BYTE) sky_color.Red(); - BYTE sky_green = (BYTE) sky_color.Green(); - BYTE sky_blue = (BYTE) sky_color.Blue(); - - BYTE Max = max3(sky_red, sky_green, sky_blue); - BYTE Min = min3(sky_red, sky_green, sky_blue); - - BYTE lum = (BYTE) (240.0 * (Max + Min) / 510.0); - - if (lum > 50) { - point_stars->Hide(); - } - else { - Stars* pstars = (Stars*) point_stars; - - pstars->Illuminate(1.0 - lum / 50.0); - pstars->Show(); - } - - scene = point_stars->GetScene(); - } - - if (haze) { - ((TerrainHaze*)haze)->UseTerrainRegion(trgn); - scene = haze->GetScene(); - } - - if (scene) { - scene->SetAmbient(ambient); - } - - } - else { - Game::SetScreenColor(Color::Black); - } - - double star_alt = 0; - - ListIter star_iter = bodies; - while (++star_iter) { - OrbitalBody* star = star_iter.value(); - - if (active_region->Inclination() != 0) { - double distance = (active_region->Location() - star->Location()).length(); - star_alt = sin(active_region->Inclination()) * distance; - } - - if (terrain) { - Point sloc = TerrainTransform(star->Location()); - - if (star->rep) { - star->rep->MoveTo(sloc); - - PlanetRep* pr = (PlanetRep*) star->rep; - pr->SetDaytime(true); - } - - if (star->light_rep) { - star->light_rep->MoveTo(sloc); - star->light_rep->SetActive(sloc.y > -100); - } - - if (star->back_light) { - star->back_light->MoveTo(sloc * -1); - star->back_light->SetActive(sloc.y > -100); - } - - if (trgn && star->rep) { - if (trgn->IsEclipsed()) - star->rep->Hide(); - else - star->rep->Show(); - } - } - - else { - Point sloc = Point(star->Location() - active_region->Location()).OtherHand(); - sloc.y = star_alt; - - if (star->rep) { - star->rep->MoveTo(sloc); - - PlanetRep* pr = (PlanetRep*) star->rep; - pr->SetDaytime(false); - } - - if (star->light_rep) { - star->light_rep->MoveTo(sloc); - star->light_rep->SetActive(true); - } - - if (star->back_light) { - star->back_light->MoveTo(sloc * -1); - star->back_light->SetActive(true); - } - } - - ListIter planet_iter = star->Satellites(); - while (++planet_iter) { - OrbitalBody* planet = planet_iter.value(); - - if (planet->rep) { - PlanetRep* pr = (PlanetRep*) planet->rep; - - if (terrain) { - pr->MoveTo(TerrainTransform(planet->Location())); - pr->SetOrientation(terrain_orientation); - - if (planet == active_region->Primary()) { - pr->Hide(); - } - - else { - pr->Show(); - pr->SetDaytime(true); - } - } - else { - pr->Show(); - pr->TranslateBy(active_loc); - pr->SetDaytime(false); - } - } - - ListIter moon_iter = planet->Satellites(); - while (++moon_iter) { - OrbitalBody* moon = moon_iter.value(); - - if (moon->rep) { - PlanetRep* pr = (PlanetRep*) moon->rep; - - if (terrain) { - pr->MoveTo(TerrainTransform(moon->Location())); - pr->SetOrientation(terrain_orientation); - - if (moon == active_region->Primary()) { - pr->Hide(); - } - - else { - pr->Show(); - pr->SetDaytime(true); - } - } - else { - pr->Show(); - pr->TranslateBy(active_loc); - pr->SetDaytime(false); - } - } - } - } - } - } -} - -// +--------------------------------------------------------------------+ - -Orbital* -StarSystem::FindOrbital(const char* name) -{ - if (!name || !name[0]) - return 0; - - ListIter star = bodies; - while (++star) { - if (!_stricmp(star->Name(), name)) - return star.value(); - - ListIter star_rgn = star->Regions(); - while (++star_rgn) { - if (!_stricmp(star_rgn->Name(), name)) - return star_rgn.value(); - } - - ListIter planet = star->Satellites(); - while (++planet) { - if (!_stricmp(planet->Name(), name)) - return planet.value(); - - ListIter planet_rgn = planet->Regions(); - while (++planet_rgn) { - if (!_stricmp(planet_rgn->Name(), name)) - return planet_rgn.value(); - } - - ListIter moon = planet->Satellites(); - while (++moon) { - if (!_stricmp(moon->Name(), name)) - return moon.value(); - - ListIter moon_rgn = moon->Regions(); - while (++moon_rgn) { - if (!_stricmp(moon_rgn->Name(), name)) - return moon_rgn.value(); - } - } - } - } - - ListIter region = regions; - while (++region) { - if (!_stricmp(region->Name(), name)) - return region.value(); - } - - return 0; -} - -// +--------------------------------------------------------------------+ - -OrbitalRegion* -StarSystem::FindRegion(const char* name) -{ - if (!name || !name[0]) - return 0; - - ListIter region = all_regions; - while (++region) { - if (!_stricmp(region->Name(), name)) - return region.value(); - } - - return 0; -} - -// +--------------------------------------------------------------------+ - -bool -StarSystem::HasLinkTo(StarSystem* s) const -{ - ListIter iter = ((StarSystem*) this)->all_regions; - while (++iter) { - OrbitalRegion* rgn = iter.value(); - - ListIter lnk_iter = rgn->Links(); - while (++lnk_iter) { - Text* t = lnk_iter.value(); - - if (s->FindRegion(*t)) - return true; - } - } - - return false; -} - -// +--------------------------------------------------------------------+ - -Point -StarSystem::TerrainTransform(const Point& loc) -{ - Point result; - - Point tmp = loc - active_region->Location(); - - result.x = tmp * tvrt; - result.z = tmp * tvup; - result.y = tmp * tvpn; - - return result; -} - -Color -StarSystem::Ambient() const -{ - Color result = ambient; - bool terrain = (active_region && active_region->Type() == Orbital::TERRAIN); - - if (terrain) { - TerrainRegion* trgn = (TerrainRegion*) active_region; - result = trgn->Ambient(); - - if (trgn->IsEclipsed()) - result = result * 0.3; - } - - return result; -} - -void -StarSystem::SetSunlight(Color color, double brightness) -{ - sun_color = color; - sun_scale = brightness; - - ListIter sun_iter = sun_lights; - while (++sun_iter) { - Light* sun_light = sun_iter.value(); - sun_light->SetColor(color); - sun_light->SetIntensity((float) (1.1 * sun_scale)); - } - - ListIter back_iter = back_lights; - while (++back_iter) { - Light* back_light = back_iter.value(); - back_light->SetIntensity((float) (0.5 * sun_scale)); - } -} - -void -StarSystem::SetBacklight(Color color, double brightness) -{ - ListIter back_iter = back_lights; - while (++back_iter) { - Light* back_light = back_iter.value(); - back_light->SetColor(color); - back_light->SetIntensity((float) (0.5 * brightness)); - } -} - -void -StarSystem::RestoreTrueSunColor() -{ - ListIter iter = bodies; - while (++iter) { - OrbitalBody* star = iter.value(); - - if (star) { - if (star->light_rep) { - star->light_rep->SetColor(star->LightColor()); - star->light_rep->SetIntensity(1.1f); - } - - if (star->back_light) { - star->back_light->SetColor(star->back); - star->back_light->SetIntensity(0.5f); - } - } - } -} - -// +====================================================================+ - -Color -Star::GetColor() const -{ - return GetColor(seq); -} - -int -Star::GetSize() const -{ - return GetSize(seq); -} - -Color -Star::GetColor(int s) -{ - switch (s) { - case O: return Color(128,128,255); break; - case B: return Color(192,192,255); break; - case A: return Color(220,220,255); break; - case F: return Color(255,255,255); break; - case G: return Color(255,255,128); break; - case K: return Color(255,192,100); break; - case M: return Color(255,100,100); break; - - case RED_GIANT: return Color(255, 80, 80); break; - case WHITE_DWARF: return Color(255,255,255); break; - case BLACK_HOLE: return Color( 0, 0, 0); break; - } - - return Color::White; -} - -int -Star::GetSize(int s) -{ - switch (s) { - case O: return 4; break; - case B: return 4; break; - case A: return 3; break; - case F: return 3; break; - case G: return 2; break; - case K: return 2; break; - case M: return 1; break; - - case RED_GIANT: return 4; break; - case WHITE_DWARF: return 1; break; - case BLACK_HOLE: return 3; break; - } - - return 3; -} - -// +====================================================================+ - -Orbital::Orbital(StarSystem* s, const char* n, OrbitalType t, double m, double r, double o, Orbital* p) -: name(n), type(t), subtype(0), radius(r), mass(m), orbit(o), -phase(0), period(0), rotation(0), retro(false), -system(s), primary(p), loc(0, 0, 0), rep(0), velocity(0) -{ - if (system && primary && orbit > 0) { - velocity = sqrt(GRAV * primary->Mass() / orbit); - period = 2 * PI * orbit / velocity; - } - - Update(); -} - -// +--------------------------------------------------------------------+ - -Orbital::~Orbital() -{ - delete rep; - regions.destroy(); -} - -// +--------------------------------------------------------------------+ - -void -Orbital::Update() -{ - if (system && primary && orbit > 0) { - double grade = (retro) ? -1 : 1; - - // orbits are counter clockwise: - phase = -2 * PI * grade * StarSystem::Stardate() / period; - - loc = primary->Location() + Point((double) (orbit * cos(phase)), - (double) (orbit * sin(phase)), - 0); - } - - ListIter region = regions; - while (++region) - region->Update(); - - if (rep) - rep->MoveTo(loc.OtherHand()); -} - -// +--------------------------------------------------------------------+ - -Point -Orbital::PredictLocation(double delta_t) -{ - Point predicted_loc = Location(); - - if (system && primary && orbit > 0) { - predicted_loc = primary->PredictLocation(delta_t); - - double grade = (retro) ? -1 : 1; - - // orbits are(?) counter clockwise: - double predicted_phase = (double) (-2 * PI * grade * (StarSystem::Stardate()+delta_t) / period); - - predicted_loc += Point((double) (orbit * cos(predicted_phase)), - (double) (orbit * sin(predicted_phase)), - 0); - } - - return predicted_loc; -} - -void -Orbital::SetMapIcon(const Bitmap& img) -{ - if (img.Width() >=64 && img.Height() >= 64) { - map_icon.CopyBitmap(img); - map_icon.AutoMask(); - map_icon.MakeTexture(); - } -} - -// +====================================================================+ - -OrbitalBody::OrbitalBody(StarSystem* s, const char* n, OrbitalType t, double m, double r, double o, Orbital* p) -: Orbital(s, n, t, m, r, o, p), light(0), light_rep(0), back_light(0), -ring_min(0), ring_max(0), tilt(0), luminous(false) -{ - Update(); -} - -// +--------------------------------------------------------------------+ - -OrbitalBody::~OrbitalBody() -{ - satellites.destroy(); -} - -// +--------------------------------------------------------------------+ - -void -OrbitalBody::Update() -{ - Orbital::Update(); - - theta = 0; - - if (rotation > 0) - theta = -2 * PI * StarSystem::Stardate() / rotation; - - ListIter body = satellites; - while (++body) - body->Update(); - - if (rep && theta != 0) { - Matrix m; - m.Pitch(tilt); - m.Roll(tilt/2); - m.Yaw(theta); - rep->SetOrientation(m); - } - - if (light_rep) { - Point bodyloc = loc; - bodyloc = bodyloc.OtherHand(); - light_rep->MoveTo(bodyloc); - } -} - -// +====================================================================+ - -OrbitalRegion::OrbitalRegion(StarSystem* s, const char* n, double m, double r, double o, Orbital* p) -: Orbital(s, n, REGION, m, r, o, p), grid(25.0e3f), inclination(0) -{ -} - -// +--------------------------------------------------------------------+ - -OrbitalRegion::~OrbitalRegion() -{ - links.destroy(); -} - +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Stars.exe + FILE: StarSystem.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Various Heavenly Bodies +*/ + +#include "MemDebug.h" +#include "StarSystem.h" +#include "Galaxy.h" +#include "Sky.h" +#include "Starshatter.h" +#include "TerrainRegion.h" +#include "TerrainHaze.h" +#include "Weather.h" + +#include "Game.h" +#include "Sound.h" +#include "Solid.h" +#include "Light.h" +#include "Bitmap.h" +#include "DataLoader.h" +#include "Scene.h" +#include "ParseUtil.h" + +const double epoch = 0.5e9; +double StarSystem::stardate = 0; + +// +====================================================================+ + +static double base_time = 0; +static WORD oldcw = 0; +static WORD fpcw = 0; + +void FPU2Extended() +{ + _asm { fstcw oldcw } + fpcw = oldcw | 0x0300; // set 80-bit precision mode + _asm { fldcw fpcw } +} + +void FPURestore() +{ + // well, I don't actually WANT single-precision mode + // so I think I'll just ignore this... + + //_asm { fldcw oldcw } +} + +void StarSystem::SetBaseTime(double t, bool absolute) +{ + FPU2Extended(); + + if (absolute) { + base_time = t; + CalcStardate(); + } + + else if (t > 0) { + if (t > epoch) t -= epoch; + base_time = t; + CalcStardate(); + } +} + +double StarSystem::GetBaseTime() +{ + return base_time; +} + +void StarSystem::CalcStardate() +{ + if (base_time < 1) { + time_t clock_seconds; + time(&clock_seconds); + + base_time = clock_seconds; + + while (base_time < 0) + base_time += epoch; + } + + FPU2Extended(); + + double gtime = (double) Game::GameTime() / 1000.0; + double sdate = gtime + base_time + epoch; + + stardate = sdate; + + FPURestore(); +} + +static const double GRAV = 6.673e-11; +static const int NAMELEN = 64; + +// +====================================================================+ + +StarSystem::StarSystem(const char* sys_name, Point l, int iff, int s) +: name(sys_name), affiliation(iff), sky_stars(0), sky_dust(0), loc(l), seq(s), +active_region(0), instantiated(false), ambient(0,0,0), +sun_color(255,255,255), sun_scale(1), point_stars(0), poly_stars(0), +nebula(0), haze(0) +{ + center = new(__FILE__,__LINE__) Orbital(this, "CG", Orbital::NOTHING, 1.0e35f, 0.0f, 0.0f, 0); + radius = 0.0f; +} + +// +--------------------------------------------------------------------+ + +StarSystem::~StarSystem() +{ + Print(" Destroying Star System %s\n", (const char*) name); + + if (instantiated) { + Deactivate(); + Destroy(); + } + + bodies.destroy(); + regions.destroy(); + all_regions.clear(); // do not destroy these! + + delete center; +} + +// +--------------------------------------------------------------------+ + +static OrbitalBody* primary_star = 0; +static OrbitalBody* primary_planet = 0; +static OrbitalBody* primary_moon = 0; + +void +StarSystem::Load() +{ + CalcStardate(); + active_region = 0; + + BYTE* block = 0; + DataLoader* loader = DataLoader::GetLoader(); + datapath = loader->GetDataPath(); + + sprintf_s(filename, "%s/%s.def", (const char*) name, (const char*) name); + + Print("Loading StarSystem: %s\n", filename); + loader->LoadBuffer(filename, block, true); + + if (!block) { + Print("ERROR: invalid star system file '%s'\n", filename); + exit(-2); + return; + } + + Parser parser(new(__FILE__,__LINE__) BlockReader((const char*) block)); + + Term* term = parser.ParseTerm(); + + if (!term) { + Print("ERROR: could not parse '%s'\n", filename); + exit(-3); + return; + } + else { + TermText* file_type = term->isText(); + if (!file_type || file_type->value() != "STARSYSTEM") { + Print("ERROR: invalid star system file '%s'\n", filename); + term->print(10); + exit(-4); + return; + } + } + + // parse the system: + do { + delete term; + term = parser.ParseTerm(); + + if (term) { + TermDef* def = term->isDef(); + if (def) { + if (def->name()->value() == "name") { + char namebuf[NAMELEN]; + namebuf[0] = 0; + GetDefText(namebuf, def, filename); + + if (namebuf[0]) + name = namebuf; + } + + else if (def->name()->value() == "sky") { + if (!def->term() || !def->term()->isStruct()) { + Print("WARNING: sky struct missing in '%s'\n", filename); + } + else { + TermStruct* val = def->term()->isStruct(); + + char imgname[NAMELEN]; + char magname[NAMELEN]; + char hazname[NAMELEN]; + + imgname[0] = 0; + magname[0] = 0; + hazname[0] = 0; + + for (int i = 0; i < val->elements()->size(); i++) { + TermDef* pdef = val->elements()->at(i)->isDef(); + if (pdef) { + if (pdef->name()->value() == "poly_stars") + GetDefText(imgname, pdef, filename); + + else if (pdef->name()->value() == "nebula") + GetDefText(magname, pdef, filename); + + else if (pdef->name()->value() == "haze") + GetDefText(hazname, pdef, filename); + } + } + + if (imgname[0]) + sky_poly_stars = imgname; + + if (magname[0]) + sky_nebula = magname; + + if (hazname[0]) + sky_haze = hazname; + } + } + + else if (def->name()->value() == "stars") { + GetDefNumber(sky_stars, def, filename); + } + + else if (def->name()->value() == "ambient") { + Vec3 a; + GetDefVec(a, def, filename); + + ambient = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z) * 2.5; + } + + else if (def->name()->value() == "dust") { + GetDefNumber(sky_dust, def, filename); + } + + else if (def->name()->value() == "star") { + if (!def->term() || !def->term()->isStruct()) { + Print("WARNING: star struct missing in '%s'\n", filename); + } + else { + TermStruct* val = def->term()->isStruct(); + ParseStar(val); + } + } + + else if (def->name()->value() == "planet") { + if (!def->term() || !def->term()->isStruct()) { + Print("WARNING: planet struct missing in '%s'\n", filename); + } + else { + TermStruct* val = def->term()->isStruct(); + ParsePlanet(val); + } + } + + else if (def->name()->value() == "moon") { + if (!def->term() || !def->term()->isStruct()) { + Print("WARNING: moon struct missing in '%s'\n", filename); + } + else { + TermStruct* val = def->term()->isStruct(); + ParseMoon(val); + } + } + + else if (def->name()->value() == "region") { + if (!def->term() || !def->term()->isStruct()) { + Print("WARNING: region struct missing in '%s'\n", filename); + } + else { + TermStruct* val = def->term()->isStruct(); + ParseRegion(val); + } + } + + else if (def->name()->value() == "terrain") { + if (!def->term() || !def->term()->isStruct()) { + Print("WARNING: terrain struct missing in '%s'\n", filename); + } + else { + TermStruct* val = def->term()->isStruct(); + ParseTerrain(val); + } + } + + } + } + } + while (term); + + loader->ReleaseBuffer(block); +} + +// +--------------------------------------------------------------------+ + +void +StarSystem::ParseStar(TermStruct* val) +{ + char star_name[NAMELEN]; + char img_name[NAMELEN]; + char map_name[NAMELEN]; + double light = 0.0; + double radius = 0.0; + double rot = 0.0; + double mass = 0.0; + double orbit = 0.0; + double tscale = 1.0; + bool retro = false; + Color color; + Color back; + + for (int i = 0; i < val->elements()->size(); i++) { + TermDef* pdef = val->elements()->at(i)->isDef(); + if (pdef) { + if (pdef->name()->value() == "name") + GetDefText(star_name, pdef, filename); + + else if (pdef->name()->value() == "map" || pdef->name()->value() == "icon") + GetDefText(map_name, pdef, filename); + + else if (pdef->name()->value() == "image") + GetDefText(img_name, pdef, filename); + + else if (pdef->name()->value() == "mass") + GetDefNumber(mass, pdef, filename); + + else if (pdef->name()->value() == "orbit") + GetDefNumber(orbit, pdef, filename); + + else if (pdef->name()->value() == "radius") + GetDefNumber(radius, pdef, filename); + + else if (pdef->name()->value() == "rotation") + GetDefNumber(rot, pdef, filename); + + else if (pdef->name()->value() == "tscale") + GetDefNumber(tscale, pdef, filename); + + else if (pdef->name()->value() == "light") + GetDefNumber(light, pdef, filename); + + else if (pdef->name()->value() == "retro") + GetDefBool(retro, pdef, filename); + + else if (pdef->name()->value() == "color") { + Vec3 a; + GetDefVec(a, pdef, filename); + color = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z); + } + + else if (pdef->name()->value() == "back" || pdef->name()->value() == "back_color") { + Vec3 a; + GetDefVec(a, pdef, filename); + back = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z); + } + } + } + + OrbitalBody* star = new(__FILE__,__LINE__) OrbitalBody(this, star_name, Orbital::STAR, mass, radius, orbit, center); + star->map_name = map_name; + star->tex_name = img_name; + star->light = light; + star->tscale = tscale; + star->subtype = Star::G; + star->retro = retro; + star->rotation = rot * 3600; + star->color = color; + star->back = back; + + // map icon: + if (*map_name) { + DataLoader::GetLoader()->LoadBitmap(map_name, star->map_icon, Bitmap::BMP_TRANSLUCENT, true); + } + + bodies.append(star); + primary_star = star; + primary_planet = 0; + primary_moon = 0; + + if (orbit > StarSystem::radius) + StarSystem::radius = orbit; +} + +// +--------------------------------------------------------------------+ + +void +StarSystem::ParsePlanet(TermStruct* val) +{ + char pln_name[NAMELEN]; + char img_name[NAMELEN]; + char map_name[NAMELEN]; + char hi_name[NAMELEN]; + char img_ring[NAMELEN]; + char glo_name[NAMELEN]; + char glo_hi_name[NAMELEN]; + char gloss_name[NAMELEN]; + + double radius = 0.0; + double mass = 0.0; + double orbit = 0.0; + double rot = 0.0; + double minrad = 0.0; + double maxrad = 0.0; + double tscale = 1.0; + double tilt = 0.0; + bool retro = false; + bool lumin = false; + Color atmos = Color::Black; + + ZeroMemory(pln_name, NAMELEN); + ZeroMemory(hi_name, NAMELEN); + ZeroMemory(img_ring, NAMELEN); + ZeroMemory(glo_name, NAMELEN); + ZeroMemory(glo_hi_name, NAMELEN); + ZeroMemory(gloss_name, NAMELEN); + ZeroMemory(map_name, NAMELEN); + + for (int i = 0; i < val->elements()->size(); i++) { + TermDef* pdef = val->elements()->at(i)->isDef(); + if (pdef) { + if (pdef->name()->value() == "name") + GetDefText(pln_name, pdef, filename); + + else if (pdef->name()->value() == "map" || pdef->name()->value() == "icon") + GetDefText(map_name, pdef, filename); + + else if (pdef->name()->value() == "image") + GetDefText(img_name, pdef, filename); + + else if (pdef->name()->value() == "image_west") + GetDefText(img_name, pdef, filename); + + else if (pdef->name()->value() == "image_east") + GetDefText(img_name, pdef, filename); + + else if (pdef->name()->value() == "glow") + GetDefText(glo_name, pdef, filename); + + else if (pdef->name()->value() == "gloss") + GetDefText(gloss_name, pdef, filename); + + else if (pdef->name()->value() == "high_res") + GetDefText(hi_name, pdef, filename); + + else if (pdef->name()->value() == "high_res_west") + GetDefText(hi_name, pdef, filename); + + else if (pdef->name()->value() == "high_res_east") + GetDefText(hi_name, pdef, filename); + + else if (pdef->name()->value() == "glow_high_res") + GetDefText(glo_hi_name, pdef, filename); + + else if (pdef->name()->value() == "mass") + GetDefNumber(mass, pdef, filename); + + else if (pdef->name()->value() == "orbit") + GetDefNumber(orbit, pdef, filename); + + else if (pdef->name()->value() == "retro") + GetDefBool(retro, pdef, filename); + + else if (pdef->name()->value() == "luminous") + GetDefBool(lumin, pdef, filename); + + else if (pdef->name()->value() == "rotation") + GetDefNumber(rot, pdef, filename); + + else if (pdef->name()->value() == "radius") + GetDefNumber(radius, pdef, filename); + + else if (pdef->name()->value() == "ring") + GetDefText(img_ring, pdef, filename); + + else if (pdef->name()->value() == "minrad") + GetDefNumber(minrad, pdef, filename); + + else if (pdef->name()->value() == "maxrad") + GetDefNumber(maxrad, pdef, filename); + + else if (pdef->name()->value() == "tscale") + GetDefNumber(tscale, pdef, filename); + + else if (pdef->name()->value() == "tilt") + GetDefNumber(tilt, pdef, filename); + + else if (pdef->name()->value() == "atmosphere") { + Vec3 a; + GetDefVec(a, pdef, filename); + atmos = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z); + } + } + } + + OrbitalBody* planet = new(__FILE__,__LINE__) OrbitalBody(this, pln_name, Orbital::PLANET, mass, radius, orbit, primary_star); + planet->map_name = map_name; + planet->tex_name = img_name; + planet->tex_high_res = hi_name; + planet->tex_ring = img_ring; + planet->tex_glow = glo_name; + planet->tex_glow_high_res = glo_hi_name; + planet->tex_gloss = gloss_name; + planet->ring_min = minrad; + planet->ring_max = maxrad; + planet->tscale = tscale; + planet->tilt = tilt; + planet->retro = retro; + planet->luminous = lumin; + planet->rotation = rot * 3600; + planet->atmosphere = atmos; + + if (primary_star) + primary_star->satellites.append(planet); + else + bodies.append(planet); + + primary_planet = planet; + primary_moon = 0; + + if (orbit > StarSystem::radius) + StarSystem::radius = orbit; + + // map icon: + if (map_name[0]) { + DataLoader::GetLoader()->LoadBitmap(map_name, planet->map_icon, Bitmap::BMP_TRANSLUCENT, true); + } +} + +// +--------------------------------------------------------------------+ + +void +StarSystem::ParseMoon(TermStruct* val) +{ + char map_name[NAMELEN]; + char pln_name[NAMELEN]; + char img_name[NAMELEN]; + char hi_name[NAMELEN]; + char glo_name[NAMELEN]; + char glo_hi_name[NAMELEN]; + char gloss_name[NAMELEN]; + + double radius = 0.0; + double mass = 0.0; + double orbit = 0.0; + double rot = 0.0; + double tscale = 1.0; + double tilt = 0.0; + bool retro = false; + Color atmos = Color::Black; + + ZeroMemory(map_name, NAMELEN); + ZeroMemory(pln_name, NAMELEN); + ZeroMemory(hi_name, NAMELEN); + ZeroMemory(img_name, NAMELEN); + ZeroMemory(glo_name, NAMELEN); + ZeroMemory(glo_hi_name, NAMELEN); + ZeroMemory(gloss_name, NAMELEN); + + for (int i = 0; i < val->elements()->size(); i++) { + TermDef* pdef = val->elements()->at(i)->isDef(); + if (pdef) { + if (pdef->name()->value() == "name") + GetDefText(pln_name, pdef, filename); + + else if (pdef->name()->value() == "map" || pdef->name()->value() == "icon") + GetDefText(map_name, pdef, filename); + + else if (pdef->name()->value() == "image") + GetDefText(img_name, pdef, filename); + + else if (pdef->name()->value() == "glow") + GetDefText(glo_name, pdef, filename); + + else if (pdef->name()->value() == "high_res") + GetDefText(hi_name, pdef, filename); + + else if (pdef->name()->value() == "glow_high_res") + GetDefText(glo_hi_name, pdef, filename); + + else if (pdef->name()->value() == "gloss") + GetDefText(gloss_name, pdef, filename); + + else if (pdef->name()->value() == "mass") + GetDefNumber(mass, pdef, filename); + + else if (pdef->name()->value() == "orbit") + GetDefNumber(orbit, pdef, filename); + + else if (pdef->name()->value() == "rotation") + GetDefNumber(rot, pdef, filename); + + else if (pdef->name()->value() == "retro") + GetDefBool(retro, pdef, filename); + + else if (pdef->name()->value() == "radius") + GetDefNumber(radius, pdef, filename); + + else if (pdef->name()->value() == "tscale") + GetDefNumber(tscale, pdef, filename); + + else if (pdef->name()->value() == "inclination") + GetDefNumber(tilt, pdef, filename); + + else if (pdef->name()->value() == "atmosphere") { + Vec3 a; + GetDefVec(a, pdef, filename); + atmos = Color((BYTE) a.x, (BYTE) a.y, (BYTE) a.z); + } + } + } + + OrbitalBody* moon = new(__FILE__,__LINE__) OrbitalBody(this, pln_name, Orbital::MOON, mass, radius, orbit, primary_planet); + moon->map_name = map_name; + moon->tex_name = img_name; + moon->tex_high_res = hi_name; + moon->tex_glow = glo_name; + moon->tex_glow_high_res = glo_hi_name; + moon->tex_gloss = gloss_name; + moon->tscale = tscale; + moon->retro = retro; + moon->rotation = rot * 3600; + moon->tilt = tilt; + moon->atmosphere = atmos; + + if (primary_planet) + primary_planet->satellites.append(moon); + else { + Print("WARNING: no planet for moon %s in '%s', deleted.\n", pln_name, filename); + delete moon; + moon = 0; + } + + primary_moon = moon; + + // map icon: + if (map_name[0]) { + DataLoader::GetLoader()->LoadBitmap(map_name, moon->map_icon, Bitmap::BMP_TRANSLUCENT, true); + } +} + +// +--------------------------------------------------------------------+ + +void +StarSystem::ParseRegion(TermStruct* val) +{ + char rgn_name[NAMELEN]; + char lnk_name[NAMELEN]; + double size = 1.0e6; + double orbit = 0.0; + double grid = 25000; + double inclination = 0.0; + int asteroids = 0; + + List links; + + for (int i = 0; i < val->elements()->size(); i++) { + TermDef* pdef = val->elements()->at(i)->isDef(); + if (pdef) { + if (pdef->name()->value() == "name") + GetDefText(rgn_name, pdef, filename); + + else if (pdef->name()->value() == "link") { + GetDefText(lnk_name, pdef, filename); + if (lnk_name[0]) { + links.append(new(__FILE__,__LINE__) Text(lnk_name)); + } + } + + else if (pdef->name()->value() == "orbit") + GetDefNumber(orbit, pdef, filename); + + else if (pdef->name()->value() == "size") + GetDefNumber(size, pdef, filename); + + else if (pdef->name()->value() == "radius") + GetDefNumber(size, pdef, filename); + + else if (pdef->name()->value() == "grid") + GetDefNumber(grid, pdef, filename); + + else if (pdef->name()->value() == "inclination") + GetDefNumber(inclination, pdef, filename); + + else if (pdef->name()->value() == "asteroids") + GetDefNumber(asteroids, pdef, filename); + } + } + + Orbital* primary = primary_moon; + if (!primary) primary = primary_planet; + if (!primary) primary = primary_star; + + OrbitalRegion* region = new(__FILE__,__LINE__) OrbitalRegion(this, rgn_name, 0, size, orbit, primary); + region->grid = grid; + region->inclination = inclination; + region->asteroids = asteroids; + region->links.append(links); + + if (primary) + primary->regions.append(region); + else + regions.append(region); + + all_regions.append(region); + + if (orbit > StarSystem::radius) + StarSystem::radius = orbit; +} + +// +--------------------------------------------------------------------+ + +void +StarSystem::ParseTerrain(TermStruct* val) +{ + Orbital* primary = primary_moon; + if (!primary) primary = primary_planet; + + if (!primary) { + Print("WARNING: Terrain region with no primary ignored in '%s'\n", filename); + return; + } + + TerrainRegion* region = 0; + + Text rgn_name; + Text patch_name; + Text patch_texture; + Text noise_tex0; + Text noise_tex1; + Text apron_name; + Text apron_texture; + Text water_texture; + Text env_texture_positive_x; + Text env_texture_negative_x; + Text env_texture_positive_y; + Text env_texture_negative_y; + Text env_texture_positive_z; + Text env_texture_negative_z; + Text haze_name; + Text sky_name; + Text clouds_high; + Text clouds_low; + Text shades_high; + Text shades_low; + + double size = 1.0e6; + double grid = 25000; + double inclination = 0.0; + double scale = 10e3; + double mtnscale = 1e3; + double fog_density = 0; + double fog_scale = 0; + double haze_fade = 0; + double clouds_alt_high= 0; + double clouds_alt_low= 0; + double w_period = 0; + double w_chances[Weather::NUM_STATES]; + + ZeroMemory(w_chances, sizeof(w_chances)); + + for (int i = 0; i < val->elements()->size(); i++) { + TermDef* pdef = val->elements()->at(i)->isDef(); + if (pdef) { + if (pdef->name()->value() == "name") + GetDefText(rgn_name, pdef, filename); + + else if (pdef->name()->value() == "patch") + GetDefText(patch_name, pdef, filename); + + else if (pdef->name()->value() == "patch_texture") + GetDefText(patch_texture, pdef, filename); + + else if (pdef->name()->value() == "detail_texture_0") + GetDefText(noise_tex0, pdef, filename); + + else if (pdef->name()->value() == "detail_texture_1") + GetDefText(noise_tex1, pdef, filename); + + else if (pdef->name()->value() == "apron") + GetDefText(apron_name, pdef, filename); + + else if (pdef->name()->value() == "apron_texture") + GetDefText(apron_texture, pdef, filename); + + else if (pdef->name()->value() == "water_texture") + GetDefText(water_texture, pdef, filename); + + else if (pdef->name()->value() == "env_texture_positive_x") + GetDefText(env_texture_positive_x, pdef, filename); + + else if (pdef->name()->value() == "env_texture_negative_x") + GetDefText(env_texture_negative_x, pdef, filename); + + else if (pdef->name()->value() == "env_texture_positive_y") + GetDefText(env_texture_positive_y, pdef, filename); + + else if (pdef->name()->value() == "env_texture_negative_y") + GetDefText(env_texture_negative_y, pdef, filename); + + else if (pdef->name()->value() == "env_texture_positive_z") + GetDefText(env_texture_positive_z, pdef, filename); + + else if (pdef->name()->value() == "env_texture_negative_z") + GetDefText(env_texture_negative_z, pdef, filename); + + else if (pdef->name()->value() == "clouds_high") + GetDefText(clouds_high, pdef, filename); + + else if (pdef->name()->value() == "shades_high") + GetDefText(shades_high, pdef, filename); + + else if (pdef->name()->value() == "clouds_low") + GetDefText(clouds_low, pdef, filename); + + else if (pdef->name()->value() == "shades_low") + GetDefText(shades_low, pdef, filename); + + else if (pdef->name()->value() == "haze") + GetDefText(haze_name, pdef, filename); + + else if (pdef->name()->value() == "sky_color") + GetDefText(sky_name, pdef, filename); + + else if (pdef->name()->value() == "size" || + pdef->name()->value() == "radius") + GetDefNumber(size, pdef, filename); + + else if (pdef->name()->value() == "grid") + GetDefNumber(grid, pdef, filename); + + else if (pdef->name()->value() == "inclination") + GetDefNumber(inclination, pdef, filename); + + else if (pdef->name()->value() == "scale") + GetDefNumber(scale, pdef, filename); + + else if (pdef->name()->value() == "mtnscale" || + pdef->name()->value() == "mtn_scale") + GetDefNumber(mtnscale, pdef, filename); + + else if (pdef->name()->value() == "fog_density") + GetDefNumber(fog_density, pdef, filename); + + else if (pdef->name()->value() == "fog_scale") + GetDefNumber(fog_scale, pdef, filename); + + else if (pdef->name()->value() == "haze_fade") + GetDefNumber(haze_fade, pdef, filename); + + else if (pdef->name()->value() == "clouds_alt_high") + GetDefNumber(clouds_alt_high, pdef, filename); + + else if (pdef->name()->value() == "clouds_alt_low") + GetDefNumber(clouds_alt_low, pdef, filename); + + else if (pdef->name()->value() == "weather_period") + GetDefNumber(w_period, pdef, filename); + + else if (pdef->name()->value() == "weather_clear") + GetDefNumber(w_chances[0], pdef, filename); + else if (pdef->name()->value() == "weather_high_clouds") + GetDefNumber(w_chances[1], pdef, filename); + else if (pdef->name()->value() == "weather_moderate_clouds") + GetDefNumber(w_chances[2], pdef, filename); + else if (pdef->name()->value() == "weather_overcast") + GetDefNumber(w_chances[3], pdef, filename); + else if (pdef->name()->value() == "weather_fog") + GetDefNumber(w_chances[4], pdef, filename); + else if (pdef->name()->value() == "weather_storm") + GetDefNumber(w_chances[5], pdef, filename); + + else if (pdef->name()->value() == "layer") { + if (!pdef->term() || !pdef->term()->isStruct()) { + Print("WARNING: terrain layer struct missing in '%s'\n", filename); + } + else { + + if (!region) + region = new(__FILE__,__LINE__) TerrainRegion(this, rgn_name, size, primary); + + TermStruct* val = pdef->term()->isStruct(); + ParseLayer(region, val); + } + } + } + } + + if (!region) + region = new(__FILE__,__LINE__) TerrainRegion(this, rgn_name, size, primary); + + region->grid = grid; + region->inclination = inclination; + region->patch_name = patch_name; + region->patch_texture = patch_texture; + region->noise_tex0 = noise_tex0; + region->noise_tex1 = noise_tex1; + region->apron_name = apron_name; + region->apron_texture = apron_texture; + region->water_texture = water_texture; + region->haze_name = haze_name; + region->clouds_high = clouds_high; + region->shades_high = shades_high; + region->clouds_low = clouds_low; + region->shades_low = shades_low; + region->scale = scale; + region->mtnscale = mtnscale; + region->fog_density = fog_density; + region->fog_scale = fog_scale; + region->haze_fade = haze_fade; + region->clouds_alt_high = clouds_alt_high; + region->clouds_alt_low = clouds_alt_low; + + region->env_texture_positive_x = env_texture_positive_x; + region->env_texture_negative_x = env_texture_negative_x; + region->env_texture_positive_y = env_texture_positive_y; + region->env_texture_negative_y = env_texture_negative_y; + region->env_texture_positive_z = env_texture_positive_z; + region->env_texture_negative_z = env_texture_negative_z; + + Weather& weather = region->GetWeather(); + + weather.SetPeriod(w_period); + + for (int i = 0; i < Weather::NUM_STATES; i++) + weather.SetChance(i, w_chances[i]); + + region->LoadSkyColors(sky_name); + + primary->regions.append(region); + all_regions.append(region); +} + +// +--------------------------------------------------------------------+ + +void +StarSystem::ParseLayer(TerrainRegion* rgn, TermStruct* val) +{ + Text tile_name; + Text detail_name; + double height = 0; + + + for (int i = 0; i < val->elements()->size(); i++) { + TermDef* pdef = val->elements()->at(i)->isDef(); + if (pdef) { + if (pdef->name()->value().indexOf("tile") == 0) + GetDefText(tile_name, pdef, filename); + + else if (pdef->name()->value().indexOf("detail") == 0) + GetDefText(detail_name, pdef, filename); + + else if (pdef->name()->value().contains("height") || + pdef->name()->value().contains("alt")) + GetDefNumber(height, pdef, filename); + } + } + + if (rgn) + rgn->AddLayer(height, tile_name, detail_name); +} + +// +--------------------------------------------------------------------+ + +void +StarSystem::Create() +{ + if (Game::Server()) + return; + + if (!instantiated) { + Print("Creating Star System %s\n", (const char*) name); + + DataLoader* loader = DataLoader::GetLoader(); + loader->SetDataPath(datapath); + + // poly star shell: + if (sky_poly_stars.length()) { + poly_stars = new(__FILE__,__LINE__) Solid; + poly_stars->Load(sky_poly_stars, 120); + poly_stars->SetLuminous(true); + poly_stars->SetInfinite(true); + + Print("Celestial Sphere '%s' loaded\n", (const char*) sky_poly_stars); + Print(" radius: %f\n", poly_stars->Radius()); + } + + if (sky_stars) { + Print("Point Stars: %d\n", sky_stars); + point_stars = new(__FILE__,__LINE__) Stars(sky_stars); + } + + loader->SetDataPath(datapath); + + // nebula: + if (sky_nebula.length()) { + nebula = new(__FILE__,__LINE__) Solid; + nebula->Load(sky_nebula, 100); + nebula->SetLuminous(true); + nebula->SetInfinite(true); + + Print("Nebular Sky '%s' loaded\n", (const char*) sky_nebula); + Print(" radius: %f\n", nebula->Radius()); + } + + // atmospheric haze: + if (sky_haze.length()) { + loader->SetDataPath(datapath); + haze = new(__FILE__,__LINE__) TerrainHaze(); + haze->Load(sky_haze, 120); + + haze->SetInfinite(true); + + Print("Atmospheric Haze '%s' loaded\n", (const char*) sky_haze); + Print(" radius: %f\n", haze->Radius()); + + haze->Hide(); + } + + loader->SetDataPath(0); + + ListIter star = bodies; + while (++star) { + CreateBody(*star); + + ListIter planet = star->Satellites(); + while (++planet) { + CreateBody(*planet); + + ListIter moon = planet->Satellites(); + while (++moon) { + CreateBody(*moon); + } + } + } + } + + instantiated = true; +} + +// +--------------------------------------------------------------------+ + +void +StarSystem::CreateBody(OrbitalBody& body) +{ + DataLoader* loader = DataLoader::GetLoader(); + loader->SetDataPath(datapath); + + // stars: + if (body.type == Orbital::STAR) { + Point starloc = body.loc; + starloc = starloc.OtherHand(); + + PlanetRep* rep = new(__FILE__,__LINE__) PlanetRep(body.tex_name, + 0, + body.radius, + starloc, + body.tscale); + + rep->SetLuminous(true); + rep->MoveTo(loc); + body.rep = rep; + + sun_brightness = body.light; + sun_color = body.color; + + Light* sun_light = new(__FILE__,__LINE__) Light(1.1f); + sun_light->SetColor(sun_color); + sun_light->SetShadow(true); + sun_light->MoveTo(body.loc); + sun_light->SetType(Light::LIGHT_DIRECTIONAL); + + sun_lights.append(sun_light); + body.light_rep = sun_light; + + if (body.back != Color::Black) { + Light* back_light = new(__FILE__,__LINE__) Light(0.6f); + back_light->SetColor(body.back); + back_light->SetShadow(false); + back_light->MoveTo(body.loc * -1); + back_light->SetType(Light::LIGHT_DIRECTIONAL); + + back_lights.append(back_light); + body.back_light = back_light; + } + } + + // planets and moons: + else { + Point planetloc = body.loc; + planetloc = planetloc.OtherHand(); + + double rmax = 0; + double rmin = 0; + + if (body.ring_max > 0) { + rmax = body.ring_max*body.radius; + rmin = body.ring_min*body.radius; + } + + Text surface = body.tex_name; + Text glow = body.tex_glow; + + if (Game::MaxTexSize() >= 512) { + if (body.tex_high_res.length()) + surface = body.tex_high_res; + + if (body.tex_glow_high_res.length()) + glow = body.tex_glow_high_res; + } + + PlanetRep* rep = new(__FILE__,__LINE__) PlanetRep(surface, + glow, + body.radius, + planetloc, + body.tscale, + body.tex_ring, + rmin, + rmax, + body.atmosphere, + body.tex_gloss); + + rep->SetStarSystem(this); + + /*** + if (body.luminous) { + rep->SetLuminous(1); + } + ***/ + + if (body.tilt != 0) { + Matrix m; + m.Pitch(body.tilt); + + rep->SetOrientation(m); + } + + body.rep = rep; + } +} + +// +--------------------------------------------------------------------+ + +void +StarSystem::Destroy() +{ + if (instantiated) { + ListIter star_iter = bodies; + while (++star_iter) { + OrbitalBody* star = star_iter.value(); + + GRAPHIC_DESTROY(star->rep); + LIGHT_DESTROY(star->light_rep); + LIGHT_DESTROY(star->back_light); + + ListIter planet = star->Satellites(); + while (++planet) { + GRAPHIC_DESTROY(planet->rep); + + ListIter moon = planet->Satellites(); + while (++moon) { + GRAPHIC_DESTROY(moon->rep); + } + } + } + + GRAPHIC_DESTROY(point_stars); + GRAPHIC_DESTROY(poly_stars); + GRAPHIC_DESTROY(nebula); + GRAPHIC_DESTROY(haze); + + sun_lights.clear(); + back_lights.clear(); + } + + instantiated = false; + sun_scale = 1; +} + +// +--------------------------------------------------------------------+ + +void +StarSystem::Activate(Scene& scene) +{ + if (!instantiated) + Create(); + + Starshatter* stars = Starshatter::GetInstance(); + + if (!stars) + return; + + if (point_stars) { + scene.AddBackground(point_stars); + point_stars->Hide(); + } + + if (poly_stars) { + scene.AddBackground(poly_stars); + } + + if (stars->Nebula() && nebula) { + scene.AddBackground(nebula); + } + + if (haze) { + scene.AddBackground(haze); + haze->Hide(); + } + + ListIter star_iter = bodies; + while (++star_iter) { + OrbitalBody* star = star_iter.value(); + scene.AddGraphic(star->rep); + scene.AddLight(star->light_rep); + if (nebula && stars && stars->Nebula()) { + star->back_light->SetColor(star->back); + } + else { + Color c = Color(60,60,65); + star->back_light->SetColor(c); + } + scene.AddLight(star->back_light); + + if (nebula && stars && stars->Nebula()) { + scene.SetAmbient(ambient); + } + else { + Color c = ambient; + int n = (c.Red() + c.Green() + c.Blue()) / 3; + + c = Color(n,n,n); + scene.SetAmbient(c); + } + + ListIter planet = star->Satellites(); + while (++planet) { + scene.AddGraphic(planet->rep); + + ListIter moon = planet->Satellites(); + while (++moon) { + scene.AddGraphic(moon->rep); + } + } + } + + ExecFrame(); +} + +// +--------------------------------------------------------------------+ + +void +StarSystem::Deactivate() +{ + if (!instantiated) + return; + + active_region = 0; + + if (point_stars && point_stars->GetScene()) + point_stars->GetScene()->DelBackground(point_stars); + + if (poly_stars && poly_stars->GetScene()) + poly_stars->GetScene()->DelBackground(poly_stars); + + if (nebula && nebula->GetScene()) + nebula->GetScene()->DelBackground(nebula); + + if (haze && haze->GetScene()) { + haze->GetScene()->DelBackground(haze); + haze->Hide(); + } + + ListIter star = bodies; + while (++star) { + if (star->rep && star->rep->GetScene()) + star->rep->GetScene()->DelGraphic(star->rep); + + if (star->light_rep && star->light_rep->GetScene()) + star->light_rep->GetScene()->DelLight(star->light_rep); + + if (star->back_light && star->back_light->GetScene()) + star->back_light->GetScene()->DelLight(star->back_light); + + ListIter planet = star->Satellites(); + while (++planet) { + if (planet->rep && planet->rep->GetScene()) + planet->rep->GetScene()->DelGraphic(planet->rep); + + ListIter moon = planet->Satellites(); + while (++moon) { + if (moon->rep && moon->rep->GetScene()) + moon->rep->GetScene()->DelGraphic(moon->rep); + } + } + } +} + +// +--------------------------------------------------------------------+ + +void +StarSystem::SetActiveRegion(OrbitalRegion* rgn) +{ + Scene* scene = 0; + + if (active_region != rgn) { + active_region = rgn; + + if (active_region) { + if (active_region->Type() != Orbital::TERRAIN) { + if (point_stars) point_stars->Hide(); + if (poly_stars) poly_stars->Show(); + if (nebula) nebula->Show(); + if (haze) haze->Hide(); + } + else { + if (point_stars) point_stars->Show(); + if (poly_stars) poly_stars->Hide(); + if (nebula) nebula->Hide(); + if (haze) haze->Show(); + } + + if (poly_stars) { + scene = poly_stars->GetScene(); + if (scene) + scene->SetAmbient(ambient); + } + else if (nebula) { + scene = nebula->GetScene(); + if (scene) + scene->SetAmbient(ambient); + } + + ListIter star = bodies; + while (++star) { + if (star->rep) + star->rep->Show(); + } + + ExecFrame(); + } + else { + if (point_stars) point_stars->Hide(); + if (poly_stars) poly_stars->Hide(); + if (nebula) nebula->Hide(); + if (haze) haze->Hide(); + + + ListIter star = bodies; + while (++star) { + if (star->rep) + star->rep->Hide(); + + if (star->light_rep) { + scene = star->light_rep->GetScene(); + if (scene) + scene->DelLight(star->light_rep); + } + + if (star->back_light) { + scene = star->back_light->GetScene(); + if (scene) + scene->DelLight(star->back_light); + } + } + } + } +} + +// +--------------------------------------------------------------------+ + +static BYTE max3(BYTE a, BYTE b, BYTE c) +{ + if (a > b) + if (a > c) return a; + else return c; + else + if (b > c) return b; + else return c; +} + +static BYTE min3(BYTE a, BYTE b, BYTE c) +{ + if (a < b) + if (a < c) return a; + else return c; + else + if (b < c) return b; + else return c; +} + +void +StarSystem::ExecFrame() +{ + CalcStardate(); + + ListIter star = bodies; + while (++star) + star->Update(); + + ListIter region = regions; + while (++region) + region->Update(); + + // update the graphic reps, relative to the active region: + if (instantiated && active_region) { + Point active_loc = active_region->Location(); + active_loc = active_loc.OtherHand(); + + Scene* scene = 0; + TerrainRegion* trgn = 0; + bool terrain = (active_region->Type() == Orbital::TERRAIN); + Matrix terrain_orientation; + Matrix terrain_transformation; + + if (terrain) { + trgn = (TerrainRegion*) active_region; + Color tmp = trgn->SkyColor(); + Game::SetScreenColor(tmp); + + tvpn = (active_region->Location() - active_region->Primary()->Location()); + tvpn.Normalize(); + tvup = Point(0,0,-1); + tvrt = tvpn.cross(tvup); + tvrt.Normalize(); + + terrain_orientation.Rotate(0, PI/2, 0); + terrain_transformation = Matrix(tvrt, tvup, tvpn); + + if (point_stars) { + point_stars->SetOrientation(terrain_transformation); + + Color sky_color = trgn->SkyColor(); + BYTE sky_red = (BYTE) sky_color.Red(); + BYTE sky_green = (BYTE) sky_color.Green(); + BYTE sky_blue = (BYTE) sky_color.Blue(); + + BYTE Max = max3(sky_red, sky_green, sky_blue); + BYTE Min = min3(sky_red, sky_green, sky_blue); + + BYTE lum = (BYTE) (240.0 * (Max + Min) / 510.0); + + if (lum > 50) { + point_stars->Hide(); + } + else { + Stars* pstars = (Stars*) point_stars; + + pstars->Illuminate(1.0 - lum / 50.0); + pstars->Show(); + } + + scene = point_stars->GetScene(); + } + + if (haze) { + ((TerrainHaze*)haze)->UseTerrainRegion(trgn); + scene = haze->GetScene(); + } + + if (scene) { + scene->SetAmbient(ambient); + } + + } + else { + Game::SetScreenColor(Color::Black); + } + + double star_alt = 0; + + ListIter star_iter = bodies; + while (++star_iter) { + OrbitalBody* star = star_iter.value(); + + if (active_region->Inclination() != 0) { + double distance = (active_region->Location() - star->Location()).length(); + star_alt = sin(active_region->Inclination()) * distance; + } + + if (terrain) { + Point sloc = TerrainTransform(star->Location()); + + if (star->rep) { + star->rep->MoveTo(sloc); + + PlanetRep* pr = (PlanetRep*) star->rep; + pr->SetDaytime(true); + } + + if (star->light_rep) { + star->light_rep->MoveTo(sloc); + star->light_rep->SetActive(sloc.y > -100); + } + + if (star->back_light) { + star->back_light->MoveTo(sloc * -1); + star->back_light->SetActive(sloc.y > -100); + } + + if (trgn && star->rep) { + if (trgn->IsEclipsed()) + star->rep->Hide(); + else + star->rep->Show(); + } + } + + else { + Point sloc = Point(star->Location() - active_region->Location()).OtherHand(); + sloc.y = star_alt; + + if (star->rep) { + star->rep->MoveTo(sloc); + + PlanetRep* pr = (PlanetRep*) star->rep; + pr->SetDaytime(false); + } + + if (star->light_rep) { + star->light_rep->MoveTo(sloc); + star->light_rep->SetActive(true); + } + + if (star->back_light) { + star->back_light->MoveTo(sloc * -1); + star->back_light->SetActive(true); + } + } + + ListIter planet_iter = star->Satellites(); + while (++planet_iter) { + OrbitalBody* planet = planet_iter.value(); + + if (planet->rep) { + PlanetRep* pr = (PlanetRep*) planet->rep; + + if (terrain) { + pr->MoveTo(TerrainTransform(planet->Location())); + pr->SetOrientation(terrain_orientation); + + if (planet == active_region->Primary()) { + pr->Hide(); + } + + else { + pr->Show(); + pr->SetDaytime(true); + } + } + else { + pr->Show(); + pr->TranslateBy(active_loc); + pr->SetDaytime(false); + } + } + + ListIter moon_iter = planet->Satellites(); + while (++moon_iter) { + OrbitalBody* moon = moon_iter.value(); + + if (moon->rep) { + PlanetRep* pr = (PlanetRep*) moon->rep; + + if (terrain) { + pr->MoveTo(TerrainTransform(moon->Location())); + pr->SetOrientation(terrain_orientation); + + if (moon == active_region->Primary()) { + pr->Hide(); + } + + else { + pr->Show(); + pr->SetDaytime(true); + } + } + else { + pr->Show(); + pr->TranslateBy(active_loc); + pr->SetDaytime(false); + } + } + } + } + } + } +} + +// +--------------------------------------------------------------------+ + +Orbital* +StarSystem::FindOrbital(const char* name) +{ + if (!name || !name[0]) + return 0; + + ListIter star = bodies; + while (++star) { + if (!_stricmp(star->Name(), name)) + return star.value(); + + ListIter star_rgn = star->Regions(); + while (++star_rgn) { + if (!_stricmp(star_rgn->Name(), name)) + return star_rgn.value(); + } + + ListIter planet = star->Satellites(); + while (++planet) { + if (!_stricmp(planet->Name(), name)) + return planet.value(); + + ListIter planet_rgn = planet->Regions(); + while (++planet_rgn) { + if (!_stricmp(planet_rgn->Name(), name)) + return planet_rgn.value(); + } + + ListIter moon = planet->Satellites(); + while (++moon) { + if (!_stricmp(moon->Name(), name)) + return moon.value(); + + ListIter moon_rgn = moon->Regions(); + while (++moon_rgn) { + if (!_stricmp(moon_rgn->Name(), name)) + return moon_rgn.value(); + } + } + } + } + + ListIter region = regions; + while (++region) { + if (!_stricmp(region->Name(), name)) + return region.value(); + } + + return 0; +} + +// +--------------------------------------------------------------------+ + +OrbitalRegion* +StarSystem::FindRegion(const char* name) +{ + if (!name || !name[0]) + return 0; + + ListIter region = all_regions; + while (++region) { + if (!_stricmp(region->Name(), name)) + return region.value(); + } + + return 0; +} + +// +--------------------------------------------------------------------+ + +bool +StarSystem::HasLinkTo(StarSystem* s) const +{ + ListIter iter = ((StarSystem*) this)->all_regions; + while (++iter) { + OrbitalRegion* rgn = iter.value(); + + ListIter lnk_iter = rgn->Links(); + while (++lnk_iter) { + Text* t = lnk_iter.value(); + + if (s->FindRegion(*t)) + return true; + } + } + + return false; +} + +// +--------------------------------------------------------------------+ + +Point +StarSystem::TerrainTransform(const Point& loc) +{ + Point result; + + Point tmp = loc - active_region->Location(); + + result.x = tmp * tvrt; + result.z = tmp * tvup; + result.y = tmp * tvpn; + + return result; +} + +Color +StarSystem::Ambient() const +{ + Color result = ambient; + bool terrain = (active_region && active_region->Type() == Orbital::TERRAIN); + + if (terrain) { + TerrainRegion* trgn = (TerrainRegion*) active_region; + result = trgn->Ambient(); + + if (trgn->IsEclipsed()) + result = result * 0.3; + } + + return result; +} + +void +StarSystem::SetSunlight(Color color, double brightness) +{ + sun_color = color; + sun_scale = brightness; + + ListIter sun_iter = sun_lights; + while (++sun_iter) { + Light* sun_light = sun_iter.value(); + sun_light->SetColor(color); + sun_light->SetIntensity((float) (1.1 * sun_scale)); + } + + ListIter back_iter = back_lights; + while (++back_iter) { + Light* back_light = back_iter.value(); + back_light->SetIntensity((float) (0.5 * sun_scale)); + } +} + +void +StarSystem::SetBacklight(Color color, double brightness) +{ + ListIter back_iter = back_lights; + while (++back_iter) { + Light* back_light = back_iter.value(); + back_light->SetColor(color); + back_light->SetIntensity((float) (0.5 * brightness)); + } +} + +void +StarSystem::RestoreTrueSunColor() +{ + ListIter iter = bodies; + while (++iter) { + OrbitalBody* star = iter.value(); + + if (star) { + if (star->light_rep) { + star->light_rep->SetColor(star->LightColor()); + star->light_rep->SetIntensity(1.1f); + } + + if (star->back_light) { + star->back_light->SetColor(star->back); + star->back_light->SetIntensity(0.5f); + } + } + } +} + +// +====================================================================+ + +Color +Star::GetColor() const +{ + return GetColor(seq); +} + +int +Star::GetSize() const +{ + return GetSize(seq); +} + +Color +Star::GetColor(int s) +{ + switch (s) { + case O: return Color(128,128,255); break; + case B: return Color(192,192,255); break; + case A: return Color(220,220,255); break; + case F: return Color(255,255,255); break; + case G: return Color(255,255,128); break; + case K: return Color(255,192,100); break; + case M: return Color(255,100,100); break; + + case RED_GIANT: return Color(255, 80, 80); break; + case WHITE_DWARF: return Color(255,255,255); break; + case BLACK_HOLE: return Color( 0, 0, 0); break; + } + + return Color::White; +} + +int +Star::GetSize(int s) +{ + switch (s) { + case O: return 4; break; + case B: return 4; break; + case A: return 3; break; + case F: return 3; break; + case G: return 2; break; + case K: return 2; break; + case M: return 1; break; + + case RED_GIANT: return 4; break; + case WHITE_DWARF: return 1; break; + case BLACK_HOLE: return 3; break; + } + + return 3; +} + +// +====================================================================+ + +Orbital::Orbital(StarSystem* s, const char* n, OrbitalType t, double m, double r, double o, Orbital* p) +: name(n), type(t), subtype(0), radius(r), mass(m), orbit(o), +phase(0), period(0), rotation(0), retro(false), +system(s), primary(p), loc(0, 0, 0), rep(0), velocity(0) +{ + if (system && primary && orbit > 0) { + velocity = sqrt(GRAV * primary->Mass() / orbit); + period = 2 * PI * orbit / velocity; + } + + Update(); +} + +// +--------------------------------------------------------------------+ + +Orbital::~Orbital() +{ + delete rep; + regions.destroy(); +} + +// +--------------------------------------------------------------------+ + +void +Orbital::Update() +{ + if (system && primary && orbit > 0) { + double grade = (retro) ? -1 : 1; + + // orbits are counter clockwise: + phase = -2 * PI * grade * StarSystem::Stardate() / period; + + loc = primary->Location() + Point((double) (orbit * cos(phase)), + (double) (orbit * sin(phase)), + 0); + } + + ListIter region = regions; + while (++region) + region->Update(); + + if (rep) + rep->MoveTo(loc.OtherHand()); +} + +// +--------------------------------------------------------------------+ + +Point +Orbital::PredictLocation(double delta_t) +{ + Point predicted_loc = Location(); + + if (system && primary && orbit > 0) { + predicted_loc = primary->PredictLocation(delta_t); + + double grade = (retro) ? -1 : 1; + + // orbits are(?) counter clockwise: + double predicted_phase = (double) (-2 * PI * grade * (StarSystem::Stardate()+delta_t) / period); + + predicted_loc += Point((double) (orbit * cos(predicted_phase)), + (double) (orbit * sin(predicted_phase)), + 0); + } + + return predicted_loc; +} + +void +Orbital::SetMapIcon(const Bitmap& img) +{ + if (img.Width() >=64 && img.Height() >= 64) { + map_icon.CopyBitmap(img); + map_icon.AutoMask(); + map_icon.MakeTexture(); + } +} + +// +====================================================================+ + +OrbitalBody::OrbitalBody(StarSystem* s, const char* n, OrbitalType t, double m, double r, double o, Orbital* p) +: Orbital(s, n, t, m, r, o, p), light(0), light_rep(0), back_light(0), +ring_min(0), ring_max(0), tilt(0), luminous(false) +{ + Update(); +} + +// +--------------------------------------------------------------------+ + +OrbitalBody::~OrbitalBody() +{ + satellites.destroy(); +} + +// +--------------------------------------------------------------------+ + +void +OrbitalBody::Update() +{ + Orbital::Update(); + + theta = 0; + + if (rotation > 0) + theta = -2 * PI * StarSystem::Stardate() / rotation; + + ListIter body = satellites; + while (++body) + body->Update(); + + if (rep && theta != 0) { + Matrix m; + m.Pitch(tilt); + m.Roll(tilt/2); + m.Yaw(theta); + rep->SetOrientation(m); + } + + if (light_rep) { + Point bodyloc = loc; + bodyloc = bodyloc.OtherHand(); + light_rep->MoveTo(bodyloc); + } +} + +// +====================================================================+ + +OrbitalRegion::OrbitalRegion(StarSystem* s, const char* n, double m, double r, double o, Orbital* p) +: Orbital(s, n, REGION, m, r, o, p), grid(25.0e3f), inclination(0) +{ +} + +// +--------------------------------------------------------------------+ + +OrbitalRegion::~OrbitalRegion() +{ + links.destroy(); +} + -- cgit v1.1