#include <cassert>#include <cstdio>#include <config.h>#include <celutil/debug.h>#include <celmath/mathlib.h>#include <celutil/util.h>#include "astro.h"#include "parser.h"#include "texmanager.h"#include "meshmanager.h"#include "universe.h"#include "multitexture.h"#include "parseobject.h"Include dependency graph for solarsys.cpp:

Go to the source code of this file.
Enumerations | |
| enum | Disposition { AddObject, ReplaceObject, ModifyObject } |
Functions | |
| static Location * | CreateLocation (Hash *locationData, Body *body) |
| static Body * | CreatePlanet (PlanetarySystem *system, Body *existingBody, Hash *planetData, const string &path, Disposition disposition, bool usePlanetUnits=true) |
| static void | errorMessagePrelude (const Tokenizer &tok) |
| static void | FillinSurface (Hash *surfaceData, Surface *surface, const std::string &path) |
| bool | LoadSolarSystemObjects (istream &in, Universe &universe, const std::string &directory) |
| static void | sscError (const Tokenizer &tok, const string &msg) |
|
|
Definition at line 37 of file solarsys.cpp. 00038 {
00039 AddObject,
00040 ReplaceObject,
00041 ModifyObject,
00042 };
|
|
||||||||||||
|
Definition at line 91 of file solarsys.cpp. References Location::setFeatureType(), Location::setImportance(), Location::setPosition(), Location::setSize(), Vector3< T >::x, Vector3< T >::y, and Vector3< T >::z. Referenced by LoadSolarSystemObjects(). 00093 {
00094 Location* location = new Location();
00095
00096 Vec3d longlat(0.0, 0.0, 0.0);
00097 locationData->getVector("LongLat", longlat);
00098
00099 Vec3f position = body->planetocentricToCartesian((float) longlat.x,
00100 (float) longlat.y,
00101 (float) longlat.z);
00102 location->setPosition(position);
00103
00104 double size = 1.0;
00105 locationData->getNumber("Size", size);
00106 location->setSize((float) size);
00107
00108 double importance = -1.0;
00109 locationData->getNumber("Importance", importance);
00110 location->setImportance((float) importance);
00111
00112 string featureTypeName;
00113 if (locationData->getString("Type", featureTypeName))
00114 location->setFeatureType(Location::parseFeatureType(featureTypeName));
00115
00116 return location;
00117 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 209 of file solarsys.cpp. References Atmosphere::cloudHeight, Atmosphere::cloudSpeed, Atmosphere::cloudTexture, RingSystem::color, Surface::color, compareIgnoringCase(), CreateOrbit(), degToRad(), DPRINTF, FillinRotationElements(), FillinSurface(), Body::getAtmosphere(), Body::getClassification(), AssociativeArray::getColor(), ResourceManager< T >::getHandle(), Value::getHash(), Body::getLifespan(), GetModelManager(), Body::getName(), AssociativeArray::getNumber(), Body::getOrbit(), Orbit::getPeriod(), Body::getRadius(), Body::getRings(), Body::getRotationElements(), AssociativeArray::getString(), Body::getSurface(), Value::getType(), Surface::hazeColor, Atmosphere::height, RingSystem::innerRadius, Atmosphere::lowerColor, ModifyObject, RingSystem::outerRadius, ParseDate(), RotationElements::period, Body::setAlbedo(), Body::setAtmosphere(), Body::setClassification(), Body::setInfoURL(), Body::setLifespan(), Body::setMass(), Body::setModel(), Body::setOblateness(), Body::setOrbit(), Body::setOrientation(), Body::setRadius(), Body::setRings(), Body::setRotationElements(), Body::setSurface(), MultiResTexture::setTexture(), Atmosphere::skyColor, Atmosphere::sunsetColor, RingSystem::texture, and Atmosphere::upperColor. Referenced by LoadSolarSystemObjects(). 00215 {
00216 Body* body = NULL;
00217
00218 if (disposition == ModifyObject)
00219 {
00220 body = existingBody;
00221 }
00222
00223 if (body == NULL)
00224 {
00225 body = new Body(system);
00226 }
00227
00228 Orbit* orbit = CreateOrbit(system, planetData, path, usePlanetUnits);
00229
00230 if (orbit != NULL)
00231 {
00232 body->setOrbit(orbit);
00233 }
00234
00235 if (body->getOrbit() == NULL)
00236 {
00237 DPRINTF(0, "No valid orbit specified for object '%s'; skipping . . .\n",
00238 body->getName().c_str());
00239 delete body;
00240 return NULL;
00241 }
00242
00243 double radius = (double)body->getRadius();
00244 planetData->getNumber("Radius", radius);
00245 body->setRadius((float) radius);
00246
00247 int classification = body->getClassification();
00248 string classificationName;
00249 if (planetData->getString("Class", classificationName))
00250 {
00251 if (compareIgnoringCase(classificationName, "planet") == 0)
00252 classification = Body::Planet;
00253 else if (compareIgnoringCase(classificationName, "moon") == 0)
00254 classification = Body::Moon;
00255 else if (compareIgnoringCase(classificationName, "comet") == 0)
00256 classification = Body::Comet;
00257 else if (compareIgnoringCase(classificationName, "asteroid") == 0)
00258 classification = Body::Asteroid;
00259 else if (compareIgnoringCase(classificationName, "spacecraft") == 0)
00260 classification = Body::Spacecraft;
00261 else if (compareIgnoringCase(classificationName, "invisible") == 0)
00262 classification = Body::Invisible;
00263 }
00264
00265 if (classification == Body::Unknown)
00266 {
00267 //Try to guess the type
00268 if (system->getPrimaryBody() != NULL)
00269 {
00270 if(radius > 0.1)
00271 classification = Body::Moon;
00272 else
00273 classification = Body::Spacecraft;
00274 }
00275 else
00276 {
00277 if(radius < 1000.0)
00278 classification = Body::Asteroid;
00279 else
00280 classification = Body::Planet;
00281 }
00282 }
00283 body->setClassification(classification);
00284
00285 // g++ is missing limits header, so we can use this
00286 // double beginning = -numeric_limits<double>::infinity();
00287 // double ending = numeric_limits<double>::infinity();
00288 double beginning = -1.0e+50;
00289 double ending = 1.0e+50;
00290 body->getLifespan(beginning, ending);
00291 ParseDate(planetData, "Beginning", beginning);
00292 ParseDate(planetData, "Ending", ending);
00293 body->setLifespan(beginning, ending);
00294
00295 string infoURL;
00296 if (planetData->getString("InfoURL", infoURL))
00297 body->setInfoURL(infoURL);
00298
00299 double albedo = 0.5;
00300 if (planetData->getNumber("Albedo", albedo))
00301 body->setAlbedo((float) albedo);
00302
00303 double oblateness = 0.0;
00304 if (planetData->getNumber("Oblateness", oblateness))
00305 body->setOblateness((float) oblateness);
00306
00307 double mass = 0.0;
00308 if (planetData->getNumber("Mass", mass))
00309 body->setMass((float) mass);
00310
00311 Quatf orientation;
00312 if (planetData->getRotation("Orientation", orientation))
00313 body->setOrientation(orientation);
00314
00315 RotationElements re = body->getRotationElements();
00316 if (disposition != ModifyObject)
00317 re.period = (float) body->getOrbit()->getPeriod();
00318 FillinRotationElements(planetData, re);
00319 body->setRotationElements(re);
00320
00321 Surface surface;
00322 if (disposition == ModifyObject)
00323 {
00324 surface = body->getSurface();
00325 }
00326 else
00327 {
00328 surface.color = Color(1.0f, 1.0f, 1.0f);
00329 surface.hazeColor = Color(0.0f, 0.0f, 0.0f, 0.0f);
00330 }
00331 FillinSurface(planetData, &surface, path);
00332 body->setSurface(surface);
00333
00334 {
00335 string model("");
00336 if (planetData->getString("Mesh", model))
00337 {
00338 Vec3f modelCenter(0.0f, 0.0f, 0.0f);
00339 if (planetData->getVector("MeshCenter", modelCenter))
00340 {
00341 // TODO: Adjust bounding radius if model center isn't
00342 // (0.0f, 0.0f, 0.0f)
00343 }
00344
00345 ResourceHandle modelHandle = GetModelManager()->getHandle(ModelInfo(model, path, modelCenter));
00346 body->setModel(modelHandle);
00347
00348 }
00349 }
00350
00351 // Read the atmosphere
00352 {
00353 Value* atmosDataValue = planetData->getValue("Atmosphere");
00354 if (atmosDataValue != NULL)
00355 {
00356 if (atmosDataValue->getType() != Value::HashType)
00357 {
00358 cout << "ReadSolarSystem: Atmosphere must be an assoc array.\n";
00359 }
00360 else
00361 {
00362 Hash* atmosData = atmosDataValue->getHash();
00363 assert(atmosData != NULL);
00364
00365 Atmosphere* atmosphere = NULL;
00366 if (disposition == ModifyObject)
00367 {
00368 atmosphere = body->getAtmosphere();
00369 if (atmosphere == NULL)
00370 {
00371 Atmosphere atm;
00372 body->setAtmosphere(atm);
00373 atmosphere = body->getAtmosphere();
00374 }
00375 }
00376 else
00377 {
00378 atmosphere = new Atmosphere();
00379 }
00380 atmosData->getNumber("Height", atmosphere->height);
00381 atmosData->getColor("Lower", atmosphere->lowerColor);
00382 atmosData->getColor("Upper", atmosphere->upperColor);
00383 atmosData->getColor("Sky", atmosphere->skyColor);
00384 atmosData->getColor("Sunset", atmosphere->sunsetColor);
00385 atmosData->getNumber("CloudHeight", atmosphere->cloudHeight);
00386 if (atmosData->getNumber("CloudSpeed", atmosphere->cloudSpeed))
00387 atmosphere->cloudSpeed = degToRad(atmosphere->cloudSpeed);
00388
00389 string cloudTexture;
00390 if (atmosData->getString("CloudMap", cloudTexture))
00391 {
00392 atmosphere->cloudTexture.setTexture(cloudTexture,
00393 path,
00394 TextureInfo::WrapTexture);
00395 }
00396
00397 body->setAtmosphere(*atmosphere);
00398 if (disposition != ModifyObject)
00399 delete atmosphere;
00400 }
00401
00402 delete atmosDataValue;
00403 }
00404 }
00405
00406 // Read the ring system
00407 {
00408 Value* ringsDataValue = planetData->getValue("Rings");
00409 if (ringsDataValue != NULL)
00410 {
00411 if (ringsDataValue->getType() != Value::HashType)
00412 {
00413 cout << "ReadSolarSystem: Rings must be an assoc array.\n";
00414 }
00415 else
00416 {
00417 Hash* ringsData = ringsDataValue->getHash();
00418 // ASSERT(ringsData != NULL);
00419
00420 RingSystem rings(0.0f, 0.0f);
00421 if (body->getRings() != NULL)
00422 rings = *body->getRings();
00423
00424 double inner = 0.0, outer = 0.0;
00425 if (ringsData->getNumber("Inner", inner))
00426 rings.innerRadius = (float) inner;
00427 if (ringsData->getNumber("Outer", outer))
00428 rings.outerRadius = (float) outer;
00429
00430 Color color(1.0f, 1.0f, 1.0f);
00431 if (ringsData->getColor("Color", color))
00432 rings.color = color;
00433
00434 string textureName;
00435 if (ringsData->getString("Texture", textureName))
00436 rings.texture = MultiResTexture(textureName, path);
00437
00438 body->setRings(rings);
00439 }
00440
00441 delete ringsDataValue;
00442 }
00443 }
00444
00445 return body;
00446 }
|
|
|
Solar system catalog (.ssc) files contain items of three different types: bodies, locations, and alternate surfaces. Bodies planets, moons, asteroids, comets, and spacecraft. Locations are points on the surfaces of bodies which may be labelled but aren't rendered. Alternate surfaces are additional surface definitions for bodies. An ssc file contains zero or more definitions of this form:
[disposition] [item type] "name" "parent name" { ...object info fields... } The disposition of the object determines what happens if an item with the same parent and same name already exists. It may be one of the following:
All dispositions are equivalent to add if no item of the same name already exists. The item type is one of Body, Location, or AltSurface, defaulting to Body when no type is given. The name and parent name are both mandatory. Definition at line 78 of file solarsys.cpp. References _. Referenced by LoadSolarSystemObjects(), sscError(), and stcError(). 00079 {
00080 cerr << _("Error in .ssc file (line ") << tok.getLineNumber() << "): ";
00081 }
|
|
||||||||||||||||
|
Definition at line 120 of file solarsys.cpp. References Color::alpha(), Color::blue(), Color::green(), and Color::red(). Referenced by CreatePlanet(), and LoadSolarSystemObjects(). 00123 {
00124 surfaceData->getColor("Color", surface->color);
00125
00126 Color hazeColor = surface->hazeColor;
00127 float hazeDensity = hazeColor.alpha();
00128 if (surfaceData->getColor("HazeColor", hazeColor) | surfaceData->getNumber("HazeDensity", hazeDensity))
00129 {
00130 surface->hazeColor = Color(hazeColor.red(), hazeColor.green(),
00131 hazeColor.blue(), hazeDensity);
00132 }
00133
00134 surfaceData->getColor("SpecularColor", surface->specularColor);
00135 surfaceData->getNumber("SpecularPower", surface->specularPower);
00136
00137 string baseTexture;
00138 string bumpTexture;
00139 string nightTexture;
00140 string specularTexture;
00141 string normalTexture;
00142 string overlayTexture;
00143 bool applyBaseTexture = surfaceData->getString("Texture", baseTexture);
00144 bool applyBumpMap = surfaceData->getString("BumpMap", bumpTexture);
00145 bool applyNightMap = surfaceData->getString("NightTexture", nightTexture);
00146 bool separateSpecular = surfaceData->getString("SpecularTexture",
00147 specularTexture);
00148 bool applyNormalMap = surfaceData->getString("NormalMap", normalTexture);
00149 bool applyOverlay = surfaceData->getString("OverlayTexture",
00150 overlayTexture);
00151
00152 unsigned int baseFlags = TextureInfo::WrapTexture | TextureInfo::AllowSplitting;
00153 unsigned int bumpFlags = TextureInfo::WrapTexture | TextureInfo::AllowSplitting;
00154 unsigned int nightFlags = TextureInfo::WrapTexture | TextureInfo::AllowSplitting;
00155 unsigned int specularFlags = TextureInfo::WrapTexture | TextureInfo::AllowSplitting;
00156
00157 float bumpHeight = 2.5f;
00158 surfaceData->getNumber("BumpHeight", bumpHeight);
00159
00160 bool blendTexture = false;
00161 surfaceData->getBoolean("BlendTexture", blendTexture);
00162
00163 bool emissive = false;
00164 surfaceData->getBoolean("Emissive", emissive);
00165
00166 bool compressTexture = false;
00167 surfaceData->getBoolean("CompressTexture", compressTexture);
00168 if (compressTexture)
00169 baseFlags |= TextureInfo::CompressTexture;
00170
00171 if (blendTexture)
00172 surface->appearanceFlags |= Surface::BlendTexture;
00173 if (emissive)
00174 surface->appearanceFlags |= Surface::Emissive;
00175 if (applyBaseTexture)
00176 surface->appearanceFlags |= Surface::ApplyBaseTexture;
00177 if (applyBumpMap || applyNormalMap)
00178 surface->appearanceFlags |= Surface::ApplyBumpMap;
00179 if (applyNightMap)
00180 surface->appearanceFlags |= Surface::ApplyNightMap;
00181 if (separateSpecular)
00182 surface->appearanceFlags |= Surface::SeparateSpecularMap;
00183 if (applyOverlay)
00184 surface->appearanceFlags |= Surface::ApplyOverlay;
00185 if (surface->specularColor != Color(0.0f, 0.0f, 0.0f))
00186 surface->appearanceFlags |= Surface::SpecularReflection;
00187
00188 if (applyBaseTexture)
00189 surface->baseTexture.setTexture(baseTexture, path, baseFlags);
00190 if (applyNightMap)
00191 surface->nightTexture.setTexture(nightTexture, path, nightFlags);
00192 if (separateSpecular)
00193 surface->specularTexture.setTexture(specularTexture, path, specularFlags);
00194
00195 // If both are present, NormalMap overrides BumpMap
00196 if (applyNormalMap)
00197 surface->bumpTexture.setTexture(normalTexture, path, bumpFlags);
00198 else if (applyBumpMap)
00199 surface->bumpTexture.setTexture(bumpTexture, path, bumpHeight, bumpFlags);
00200
00201 if (applyOverlay)
00202 surface->overlayTexture.setTexture(overlayTexture, path, baseFlags);
00203 }
|
|
||||||||||||||||
|
Definition at line 449 of file solarsys.cpp. References _, Body::addAlternateSurface(), PlanetarySystem::addBody(), Body::addLocation(), AddObject, Selection::body(), Surface::color, CreateLocation(), CreatePlanet(), errorMessagePrelude(), FillinSurface(), PlanetarySystem::find(), Value::getHash(), Tokenizer::getNameValue(), SolarSystem::getPlanets(), Body::getSatellites(), Tokenizer::getStringValue(), Tokenizer::getTokenType(), Value::getType(), Surface::hazeColor, ModifyObject, Tokenizer::nextToken(), Parser::readValue(), PlanetarySystem::replaceBody(), ReplaceObject, Location::setName(), Body::setName(), Body::setSatellites(), sscError(), and Selection::star(). Referenced by CelestiaCore::initSimulation(), and SolarSystemLoader::process(). 00452 {
00453 Tokenizer tokenizer(&in);
00454 Parser parser(&tokenizer);
00455
00456 while (tokenizer.nextToken() != Tokenizer::TokenEnd)
00457 {
00458 // Read the disposition; if none is specified, the default is Add.
00459 Disposition disposition = AddObject;
00460 if (tokenizer.getTokenType() == Tokenizer::TokenName)
00461 {
00462 if (tokenizer.getNameValue() == "Add")
00463 {
00464 disposition = AddObject;
00465 tokenizer.nextToken();
00466 }
00467 else if (tokenizer.getNameValue() == "Replace")
00468 {
00469 disposition = ReplaceObject;
00470 tokenizer.nextToken();
00471 }
00472 else if (tokenizer.getNameValue() == "Modify")
00473 {
00474 disposition = ModifyObject;
00475 tokenizer.nextToken();
00476 }
00477 }
00478
00479 // Read the item type; if none is specified the default is Body
00480 string itemType("Body");
00481 if (tokenizer.getTokenType() == Tokenizer::TokenName)
00482 {
00483 itemType = tokenizer.getNameValue();
00484 tokenizer.nextToken();
00485 }
00486
00487 if (tokenizer.getTokenType() != Tokenizer::TokenString)
00488 {
00489 sscError(tokenizer, "object name expected");
00490 return false;
00491 }
00492 string name = tokenizer.getStringValue().c_str();
00493
00494 if (tokenizer.nextToken() != Tokenizer::TokenString)
00495 {
00496 sscError(tokenizer, "bad parent object name");
00497 return false;
00498 }
00499 string parentName = tokenizer.getStringValue().c_str();
00500
00501 Value* objectDataValue = parser.readValue();
00502 if (objectDataValue == NULL)
00503 {
00504 sscError(tokenizer, "bad object definition");
00505 return false;
00506 }
00507
00508 if (objectDataValue->getType() != Value::HashType)
00509 {
00510 sscError(tokenizer, "{ expected");
00511 return false;
00512 }
00513 Hash* objectData = objectDataValue->getHash();
00514
00515 Selection parent = universe.findPath(parentName, NULL, 0);
00516 PlanetarySystem* parentSystem = NULL;
00517
00518 if (itemType == "Body")
00519 {
00520 bool orbitsPlanet = false;
00521 if (parent.star() != NULL)
00522 {
00523 SolarSystem* solarSystem = universe.getSolarSystem(parent.star());
00524 if (solarSystem == NULL)
00525 {
00526 // No solar system defined for this star yet, so we need
00527 // to create it.
00528 solarSystem = universe.createSolarSystem(parent.star());
00529 }
00530 parentSystem = solarSystem->getPlanets();
00531 }
00532 else if (parent.body() != NULL)
00533 {
00534 // Parent is a planet or moon
00535 parentSystem = parent.body()->getSatellites();
00536 if (parentSystem == NULL)
00537 {
00538 // If the planet doesn't already have any satellites, we
00539 // have to create a new planetary system for it.
00540 parentSystem = new PlanetarySystem(parent.body());
00541 parent.body()->setSatellites(parentSystem);
00542 }
00543 orbitsPlanet = true;
00544 }
00545 else
00546 {
00547 errorMessagePrelude(tokenizer);
00548 cerr << _("parent body '") << parentName << _("' of '") << name << _("' not found.\n");
00549 }
00550
00551 if (parentSystem != NULL)
00552 {
00553 Body* existingBody = parentSystem->find(name);
00554 if (existingBody && disposition == AddObject)
00555 {
00556 errorMessagePrelude(tokenizer);
00557 cerr << _("warning duplicate definition of ") <<
00558 parentName << " " << name << '\n';
00559 }
00560
00561 Body* body = CreatePlanet(parentSystem, existingBody, objectData, directory, disposition, !orbitsPlanet);
00562 if (body != NULL)
00563 {
00564 body->setName(name);
00565 if (disposition == ReplaceObject)
00566 {
00567 parentSystem->replaceBody(existingBody, body);
00568 delete existingBody;
00569 }
00570 else if (disposition == AddObject)
00571 {
00572 parentSystem->addBody(body);
00573 }
00574 }
00575 }
00576 }
00577 else if (itemType == "AltSurface")
00578 {
00579 Surface* surface = new Surface();
00580 surface->color = Color(1.0f, 1.0f, 1.0f);
00581 surface->hazeColor = Color(0.0f, 0.0f, 0.0f, 0.0f);
00582 FillinSurface(objectData, surface, directory);
00583 if (surface != NULL && parent.body() != NULL)
00584 parent.body()->addAlternateSurface(name, surface);
00585 else
00586 sscError(tokenizer, _("bad alternate surface"));
00587 }
00588 else if (itemType == "Location")
00589 {
00590 if (parent.body() != NULL)
00591 {
00592 Location* location = CreateLocation(objectData, parent.body());
00593 if (location != NULL)
00594 {
00595 location->setName(name);
00596 parent.body()->addLocation(location);
00597 }
00598 else
00599 {
00600 sscError(tokenizer, _("bad location"));
00601 }
00602 }
00603 else
00604 {
00605 errorMessagePrelude(tokenizer);
00606 cerr << _("parent body '") << parentName << _("' of '") << name << _("' not found.\n");
00607 }
00608 }
00609 }
00610
00611 // TODO: Return some notification if there's an error parsing the file
00612 return true;
00613 }
|
|
||||||||||||
|
Definition at line 83 of file solarsys.cpp. References errorMessagePrelude(). Referenced by LoadSolarSystemObjects(). 00085 {
00086 errorMessagePrelude(tok);
00087 cerr << msg << '\n';
00088 }
|
1.4.1