void ObjectViewerView::Update() { if (Pi::KeyState(SDLK_EQUALS)) viewingDist *= 0.99; if (Pi::KeyState(SDLK_MINUS)) viewingDist *= 1.01; viewingDist = Clamp(viewingDist, 10.0f, 1e12f); char buf[128]; Body *body = Pi::player->GetNavTarget(); if(body && (body != lastTarget)) { // Reset view distance for new target. viewingDist = body->GetBoundingRadius() * 2.0f; lastTarget = body; if (body->IsType(Object::PLANET)) { Planet *planet = static_cast<Planet*>(body); const SBody *sbody = planet->GetSBody(); m_sbodyVolatileGas->SetText(stringf("%0{f.3}", sbody->m_volatileGas.ToFloat())); m_sbodyVolatileLiquid->SetText(stringf("%0{f.3}", sbody->m_volatileLiquid.ToFloat())); m_sbodyVolatileIces->SetText(stringf("%0{f.3}", sbody->m_volatileIces.ToFloat())); m_sbodyLife->SetText(stringf("%0{f.3}", sbody->m_life.ToFloat())); m_sbodyVolcanicity->SetText(stringf("%0{f.3}", sbody->m_volcanicity.ToFloat())); m_sbodyMetallicity->SetText(stringf("%0{f.3}", sbody->m_metallicity.ToFloat())); m_sbodySeed->SetText(stringf("%0{d}", sbody->seed)); m_sbodyMass->SetText(stringf("%0{f}", sbody->mass.ToFloat())); m_sbodyRadius->SetText(stringf("%0{f}", sbody->radius.ToFloat())); } } snprintf(buf, sizeof(buf), "View dist: %s Object: %s", format_distance(viewingDist).c_str(), (body ? body->GetLabel().c_str() : "<none>")); m_infoLabel->SetText(buf); }
static Frame *MakeFrameFor(SBody *sbody, Body *b, Frame *f) { Frame *orbFrame, *rotFrame; double frameRadius; if (!sbody->parent) { if (b) b->SetFrame(f); f->m_sbody = sbody; f->m_astroBody = b; return f; } if (sbody->type == SBody::TYPE_GRAVPOINT) { orbFrame = new Frame(f, sbody->name.c_str()); orbFrame->m_sbody = sbody; orbFrame->m_astroBody = b; orbFrame->SetRadius(sbody->GetMaxChildOrbitalDistance()*1.1); return orbFrame; } SBody::BodySuperType supertype = sbody->GetSuperType(); if ((supertype == SBody::SUPERTYPE_GAS_GIANT) || (supertype == SBody::SUPERTYPE_ROCKY_PLANET)) { // for planets we want an non-rotating frame for a few radii // and a rotating frame in the same position but with maybe 1.05*radius, // which actually contains the object. frameRadius = std::max(4.0*sbody->GetRadius(), sbody->GetMaxChildOrbitalDistance()*1.05); orbFrame = new Frame(f, sbody->name.c_str()); orbFrame->m_sbody = sbody; orbFrame->SetRadius(frameRadius); //printf("\t\t\t%s has frame size %.0fkm, body radius %.0fkm\n", sbody->name.c_str(), // (frameRadius ? frameRadius : 10*sbody->GetRadius())*0.001f, // sbody->GetRadius()*0.001f); assert(sbody->rotationPeriod != 0); rotFrame = new Frame(orbFrame, sbody->name.c_str()); // rotating frame has size of GeoSphere terrain bounding sphere rotFrame->SetRadius(b->GetBoundingRadius()); rotFrame->SetAngVelocity(vector3d(0,2*M_PI/sbody->GetRotationPeriod(),0)); rotFrame->m_astroBody = b; SetFrameOrientationFromSBodyAxialTilt(rotFrame, sbody); b->SetFrame(rotFrame); return orbFrame; } else if (supertype == SBody::SUPERTYPE_STAR) { // stars want a single small non-rotating frame orbFrame = new Frame(f, sbody->name.c_str()); orbFrame->m_sbody = sbody; orbFrame->m_astroBody = b; orbFrame->SetRadius(sbody->GetMaxChildOrbitalDistance()*1.1); b->SetFrame(orbFrame); return orbFrame; } else if (sbody->type == SBody::TYPE_STARPORT_ORBITAL) { // space stations want non-rotating frame to some distance // and a much closer rotating frame frameRadius = 1000000.0; // XXX NFI! orbFrame = new Frame(f, sbody->name.c_str()); orbFrame->m_sbody = sbody; // orbFrame->SetRadius(10*sbody->GetRadius()); orbFrame->SetRadius(frameRadius); assert(sbody->rotationPeriod != 0); rotFrame = new Frame(orbFrame, sbody->name.c_str()); rotFrame->SetRadius(1000.0); // rotFrame->SetRadius(1.1*sbody->GetRadius()); // enough for collisions? rotFrame->SetAngVelocity(vector3d(0.0,double(static_cast<SpaceStation*>(b)->GetDesiredAngVel()),0.0)); rotFrame->m_astroBody = b; // hope this doesn't break anything b->SetFrame(rotFrame); return orbFrame; } else if (sbody->type == SBody::TYPE_STARPORT_SURFACE) { // just put body into rotating frame of planet, not in its own frame // (because collisions only happen between objects in same frame, // and we want collisions on starport and on planet itself) Frame *frame = *f->m_children.begin(); b->SetFrame(frame); assert(frame->m_astroBody->IsType(Object::PLANET)); Planet *planet = static_cast<Planet*>(frame->m_astroBody); /* position on planet surface */ double height; int tries; matrix4x4d rot; vector3d pos; // first try suggested position rot = sbody->orbit.rotMatrix; pos = rot * vector3d(0,1,0); if (planet->GetTerrainHeight(pos) - planet->GetSBody()->GetRadius() <= 0.0) { MTRand r(sbody->seed); // position is under water. try some random ones for (tries=0; tries<100; tries++) { // used for orientation on planet surface double r2 = r.Double(); // function parameter evaluation order is implementation-dependent double r1 = r.Double(); // can't put two rands in the same expression rot = matrix4x4d::RotateZMatrix(2*M_PI*r1) * matrix4x4d::RotateYMatrix(2*M_PI*r2); pos = rot * vector3d(0,1,0); height = planet->GetTerrainHeight(pos) - planet->GetSBody()->GetRadius(); // don't want to be under water if (height > 0.0) break; } } b->SetPosition(pos * planet->GetTerrainHeight(pos)); b->SetRotMatrix(rot); return frame; } else { assert(0); } return NULL; }