diff --git a/src/body.h b/src/body.h index cb71377..6b68b6a 100644 --- a/src/body.h +++ b/src/body.h @@ -18,6 +18,7 @@ public: virtual void SetVelocity(vector3d v) { assert(0); } virtual vector3d GetVelocity(void) { assert(0); return vector3d(0.0); } virtual double GetRadius(void) const = 0 ; + virtual double GetMass(void) const { assert(0); return 0; } virtual void SetRotMatrix(const matrix4x4d& r) {}; virtual void GetRotMatrix(matrix4x4d& m) {}; virtual void Render(const Frame* camFrame) = 0; diff --git a/src/dynamic_body.h b/src/dynamic_body.h index e866c5f..f4c910f 100644 --- a/src/dynamic_body.h +++ b/src/dynamic_body.h @@ -20,6 +20,7 @@ public: void SetMassDistributionFromCollMesh(const CollMesh* m); virtual void Disable(void); virtual void Enable(void); + virtual double GetMass(void) const { return m_mass.mass; } dBodyID m_body; dMass m_mass; diff --git a/src/frame.cpp b/src/frame.cpp index 693a322..577ced8 100644 --- a/src/frame.cpp +++ b/src/frame.cpp @@ -19,6 +19,7 @@ void Frame::RemoveChild(Frame* f) { void Frame::Init(Frame* parent, const char* label, unsigned int flags) { m_sBody = 0; + m_astroBody = 0; m_parent = parent; m_flags = flags; m_radius = 0; diff --git a/src/frame.h b/src/frame.h index 15f06e1..5e0b969 100644 --- a/src/frame.h +++ b/src/frame.h @@ -4,6 +4,8 @@ #include "libs.h" #include "star_system.h" +class Body; + /* Frame of reference. */ class Frame { public: @@ -43,6 +45,7 @@ public: Frame* m_parent; std::list m_children; StarSystem::SBody* m_sBody; /* Points to SBodies in L3D::current_system. */ + Body* m_astroBody; /* If frame contains a star or planet or something.. */ enum { TEMP_VIEWING=1 }; diff --git a/src/generic_system_view.cpp b/src/generic_system_view.cpp index d32f8d4..a1c6327 100644 --- a/src/generic_system_view.cpp +++ b/src/generic_system_view.cpp @@ -48,7 +48,7 @@ void GenericSystemView::Draw3D(void) { desc = s->rootBody->GetAstroDescription(); } - m_systemName->SetText(s->rootBody->name); + m_systemName->SetText(sec.m_systems[pidx].name); m_distance->SetText(buf); m_starType->SetText(desc); m_shortDesc->SetText("Short description of system"); diff --git a/src/planet.cpp b/src/planet.cpp index 8add198..f654675 100644 --- a/src/planet.cpp +++ b/src/planet.cpp @@ -8,6 +8,7 @@ Planet::Planet(StarSystem::SBody* sbody) : Body() { pos = vector3d(0, 0, 0); geom = dCreateSphere(0, sbody->GetRadius()); dGeomSetData(geom, static_cast(this)); + m_mass = sbody->GetMass(); this->sbody = *sbody; this->sbody.children.clear(); this->sbody.parent = 0; diff --git a/src/planet.h b/src/planet.h index f718aa1..2259bc9 100644 --- a/src/planet.h +++ b/src/planet.h @@ -14,11 +14,13 @@ public: virtual void Render(const Frame* camFrame); virtual void SetFrame(Frame* f); virtual bool OnCollision(Body* b, Uint32 flags) { return true; } + virtual double GetMass(void) const { return m_mass; } private: void DrawRockyPlanet(void); void DrawGasGiant(void); void DrawAtmosphere(double rad, vector3d& pos); + double m_mass; vector3d pos; dGeomID geom; StarSystem::SBody sbody; diff --git a/src/player.cpp b/src/player.cpp index 630d74e..591a5d9 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -261,6 +261,18 @@ void Player::DrawHUD(const Frame* cam_frame) { glPopMatrix(); } + /* Altitude. */ + if(GetFrame()->m_astroBody) { + double radius = GetFrame()->m_astroBody->GetRadius(); + double altitude = GetPosition().Length() - radius; + char buf[128]; + snprintf(buf, sizeof(buf), "Altitude: %.0f m", altitude); + glPushMatrix(); + glTranslatef(400, 6, 0); + Gui::Screen::RenderString(buf); + glPopMatrix(); + } + Gui::Screen::LeaveOrtho(); } diff --git a/src/space.cpp b/src/space.cpp index d6b3244..7dc68e1 100644 --- a/src/space.cpp +++ b/src/space.cpp @@ -81,6 +81,7 @@ static Frame* MakeFrameFor(StarSystem::SBody* sbody, Body* b, Frame* f) { rotFrame = new Frame(orbFrame, sbody->name.c_str()); rotFrame->SetRadius(1.1*sbody->GetRadius()); rotFrame->SetAngVelocity(vector3d(0,2*M_PI/sbody->GetRotationPeriod(), 0)); + rotFrame->m_astroBody = b; b->SetFrame(rotFrame); return orbFrame; /* Stars want a single small non-rotating frame. */ @@ -88,6 +89,7 @@ static Frame* MakeFrameFor(StarSystem::SBody* sbody, Body* b, Frame* f) { default: orbFrame = new Frame(f, sbody->name.c_str()); orbFrame->m_sBody = sbody; + orbFrame->m_astroBody = b; orbFrame->SetRadius(1.2*sbody->GetRadius()); b->SetFrame(orbFrame); return orbFrame; @@ -288,7 +290,22 @@ void Space::CollideFrame(Frame* f) { } } +void Space::ApplyGravity(void) { + /* Just to the player and only in the most stupid way for the moment. */ + if(L3D::player->GetFrame()->m_astroBody) { + Body* other = L3D::player->GetFrame()->m_astroBody; + vector3d b1b2 = other->GetPosition() - L3D::player->GetPosition(); + const double m1m2 = L3D::player->GetMass() * other->GetMass(); + const double r = b1b2.Length(); + const double force = G*m1m2 / (r*r); + b1b2.Normalize(); + b1b2 = b1b2 * force; + dBodyAddForce(L3D::player->m_body, b1b2.x, b1b2.y, b1b2.z); + } +} + void Space::TimeStep(float step) { + ApplyGravity(); CollideFrame(rootFrame); dWorldQuickStep(world, step); dJointGroupEmpty(_contactgroup); diff --git a/src/space.h b/src/space.h index 4f04d39..907ddbd 100644 --- a/src/space.h +++ b/src/space.h @@ -28,6 +28,7 @@ private: static void UpdateFramesOfReference(void); static void CollideFrame(Frame* f); static void PruneCorpses(void); + static void ApplyGravity(void); //static std::list rootFrames; static std::list corpses; }; diff --git a/src/star_system.cpp b/src/star_system.cpp index f11a2d8..676d056 100644 --- a/src/star_system.cpp +++ b/src/star_system.cpp @@ -189,7 +189,7 @@ static double calcEnergyPerUnitAreaAtDist(double star_radius, double star_temp, } /* Bond albedo, not geometric. */ -static double calcSurfaceTemp(double star_radius, double star_temp, +static double CalcSurfaceTemp(double star_radius, double star_temp, double object_dist, double albedo, double greenhouse) { @@ -208,8 +208,17 @@ static fixed calcEnergyPerUnitAreaAtDist(fixed star_radius, int star_temp, fixed return fixed(1744665451, 100000)*(total_solar_emission / (object_dist*object_dist)); } -static int calcSurfaceTemp(fixed star_radius, int star_temp, fixed object_dist, fixed albedo, fixed greenhouse) { - const fixed energy_per_meter2 = calcEnergyPerUnitAreaAtDist(star_radius, star_temp, object_dist); +static int CalcSurfaceTemp(StarSystem::SBody* primary, fixed distToPrimary, fixed albedo, fixed greenhouse) { + fixed energy_per_meter2; + if(primary->type == StarSystem::TYPE_GRAVPOINT) { + /* Binary, take energies of both stars. */ + energy_per_meter2 = calcEnergyPerUnitAreaAtDist(primary->children[0]->radius, + primary->children[0]->averageTemp, distToPrimary); + energy_per_meter2 += calcEnergyPerUnitAreaAtDist(primary->children[1]->radius, + primary->children[1]->averageTemp, distToPrimary); + } else { + energy_per_meter2 = calcEnergyPerUnitAreaAtDist(primary->radius, primary->averageTemp, distToPrimary); + } const fixed surface_temp_pow4 = energy_per_meter2*(1-albedo)/(1-greenhouse); return isqrt(isqrt((surface_temp_pow4.v>>16)*4409673)); } @@ -474,7 +483,7 @@ StarSystem::StarSystem(int sector_x, int sector_y, int system_idx) { centGrav1 = new SBody; centGrav1->type = TYPE_GRAVPOINT; centGrav1->parent = NULL; - centGrav1->name = s.m_systems[system_idx].name; + centGrav1->name = s.m_systems[system_idx].name+" A,B"; rootBody = centGrav1; StarSystem::BodyType type = s.m_systems[system_idx].primaryStarClass; @@ -509,7 +518,7 @@ StarSystem::StarSystem(int sector_x, int sector_y, int system_idx) { } else { centGrav2 = new SBody; centGrav2->type = TYPE_GRAVPOINT; - centGrav2->name = s.m_systems[system_idx].name; + centGrav2->name = s.m_systems[system_idx].name+" C,D"; centGrav2->orbMax = 0; star[2] = new SBody; @@ -558,15 +567,14 @@ void StarSystem::MakePlanetsAround(SBody* primary) { if(primary->type == TYPE_GRAVPOINT) { SBody* star = primary->children[0]; orbMinKill = star->orbMax*10; - /* - * TODO: Need to consider triple and quadruple systems - - * the other par will obsruct also. - */ } else if((primary->GetSuperType() == SUPERTYPE_STAR) && (primary->parent)) { /* Limit planets out to 10% distance to stars binary companion. */ orbMaxKill = primary->orbMin * fixed(1,10); } - printf("Kill at %f,%f AU\n", orbMinKill.ToDouble(), orbMaxKill.ToDouble()); + + if(m_numStars >= 3) { + orbMaxKill = MIN(orbMaxKill, fixed(5, 100)*rootBody->children[0]->orbMin); + } std::vector* disc = AccreteDisc(disc_size, 10, rand.Int32(10,400), rand); for(unsigned int i = 0; i < disc->size(); i++) { @@ -636,7 +644,7 @@ void StarSystem::SBody::PickPlanetType(SBody* star, const fixed distToPrimary, M int bbody_temp; bool fiddle = false; for(int i = 0; i < 10; i++) { - bbody_temp = calcSurfaceTemp(star->radius, star->averageTemp, distToPrimary, albedo, globalwarming); + bbody_temp = CalcSurfaceTemp(star, distToPrimary, albedo, globalwarming); //printf(temp %f, albedo %f, globalwarming %f\n", bbody_temp, albedo, globalwarming); /* Extreme high temperature and low mass causes atmosphere loss. */ #define ATMOS_LOSS_MASS_CUTOFF 2 @@ -658,7 +666,7 @@ void StarSystem::SBody::PickPlanetType(SBody* star, const fixed distToPrimary, M globalwarming *= 0.2; albedo = rand.Double(0.05) + 0.9; } - bbody_temp = calcSurfaceTemp(star->radius, star->averageTemp, distToPrimary, albedo, globalwarming); + bbody_temp = CalcSurfaceTemp(star, distToPrimary, albedo, globalwarming); // printf("= temp %f, albedo %f, globalwarming %f\n", bbody_temp, albedo, globalwarming); averageTemp = bbody_temp; @@ -684,8 +692,8 @@ void StarSystem::SBody::PickPlanetType(SBody* star, const fixed distToPrimary, M } else if(mass < 3) { if((averageTemp > CELSIUS-10) && (averageTemp < CELSIUS+70)) { /* Try for life.. */ - int minTemp = calcSurfaceTemp(star->radius, star->averageTemp, orbMax, albedo, globalwarming); - int maxTemp = calcSurfaceTemp(star->radius, star->averageTemp, orbMin, albedo, globalwarming); + int minTemp = CalcSurfaceTemp(star, orbMax, albedo, globalwarming); + int maxTemp = CalcSurfaceTemp(star, orbMin, albedo, globalwarming); if((minTemp > CELSIUS-10) && (minTemp < CELSIUS+70) && (maxTemp > CELSIUS-10) && (maxTemp < CELSIUS+70)) { type = TYPE_PLANET_INDIGENOUS_LIFE;