diff --git a/src/frame.cpp b/src/frame.cpp index 4416f58..84ccc7d 100644 --- a/src/frame.cpp +++ b/src/frame.cpp @@ -18,6 +18,7 @@ void Frame::RemoveChild(Frame* f) { } void Frame::Init(Frame* parent, const char* label, unsigned int flags) { + sBody = 0; m_parent = parent; m_flags = flags; m_radius = 0; diff --git a/src/frame.h b/src/frame.h index 555e65e..917890f 100644 --- a/src/frame.h +++ b/src/frame.h @@ -2,6 +2,7 @@ #include #include #include "libs.h" +#include "star_system.h" /* Frame of reference. */ class Frame { @@ -33,6 +34,7 @@ public: /* If parent is null then frame position is absolute. */ Frame* m_parent; std::list m_children; + StarSystem::SBody* sBody; /* Points to SBodies in L3D::current_system. */ enum { TEMP_VIEWING=1 }; diff --git a/src/l3d.h b/src/l3d.h index 16da893..08acfc0 100644 --- a/src/l3d.h +++ b/src/l3d.h @@ -82,6 +82,7 @@ public: static InfoView* infoView; static ShipCpanel* cpan; static GLUquadric* gluQuadric; + static StarSystem* current_system; private: static void InitOpenGL(void); diff --git a/src/main.cpp b/src/main.cpp index 15fd495..050c9ed 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -44,6 +44,7 @@ SystemView* L3D::system_view; SystemInfoView* L3D::system_info_view; ShipCpanel* L3D::cpan; StarSystem* L3D::selected_system; +StarSystem* L3D::current_system; MTRand L3D::rng; double L3D::gameTime; float L3D::frameTime; @@ -309,8 +310,14 @@ StarSystem* L3D::GetSelectedSystem(void) { } void L3D::HyperspaceTo(StarSystem* dest) { + int sec_x, sec_y, sys_idx; + dest->GetPos(&sec_x, &sec_y, &sys_idx); + + if(current_system) delete current_system; + current_system = new StarSystem(sec_x, sec_y, sys_idx); + Space::Clear(); - Space::BuildSystem(dest); + Space::BuildSystem(); float ang = rng.Double(M_PI); L3D::player->SetPosition(vector3d(sin(ang)*8*AU, cos(ang)*8*AU, 0)); dest->GetPos(&L3D::playerLoc); diff --git a/src/player.cpp b/src/player.cpp index 34c1d76..e222bd5 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -245,11 +245,11 @@ void Player::DrawHUD(const Frame* cam_frame) { vector3d abs_pos = GetPositionRelTo(Space::GetRootFrame()); const char* rel_to = (GetFrame() ? GetFrame()->GetLabel() : "System"); snprintf(buf, sizeof(buf), "Pos: %.1f,%.1f,%.1f\n" - "AbsPos: %.1f,%.1f,%.1f\n" - "Rel-to: %s", + "AbsPos: %.1f,%.1f,%.1f (%.3f AU)\n" + "Rel-to: %s (%.0f km)", pos.x, pos.y, pos.z, - abs_pos.x, abs_pos.y, abs_pos.z, - rel_to); + abs_pos.x, abs_pos.y, abs_pos.z, abs_pos.Length()/AU, + rel_to, pos.Length()/1000); Gui::Screen::RenderString(buf); glPopMatrix(); } diff --git a/src/space.cpp b/src/space.cpp index 7eb219f..7ef4ff7 100644 --- a/src/space.cpp +++ b/src/space.cpp @@ -41,8 +41,22 @@ void Space::Clear(void) { L3D::player->SetFrame(rootFrame); } -void Space::GenBody(StarSystem* system, StarSystem::SBody* sbody, Frame* f) { +void Space::MoveFramesOfReference(Frame* f) { + if(f->sBody) { + vector3d pos = f->sBody->orbit.CartesianPosAtTime(L3D::GetGameTime()); + f->SetPosition(pos); + } + + for(std::list::iterator i = f->m_children.begin(); i != f->m_children.end(); ++i) { + MoveFramesOfReference(*i); + } +} + +void Space::GenBody(StarSystem::SBody* sbody, Frame* f) { Body* b; + + if(sbody->type == StarSystem::TYPE_GRAVPOINT) goto just_make_child; + if(sbody->GetSuperType() == StarSystem::SUPERTYPE_STAR) { Star* star = new Star(sbody); b = star; @@ -59,24 +73,27 @@ void Space::GenBody(StarSystem* system, StarSystem::SBody* sbody, Frame* f) { vector3d pos = sbody->orbit.CartesianPosAtTime(0); myframe->SetPosition(pos); myframe->SetRadius(10*sbody->GetRadius()); + myframe->sBody = sbody; b->SetFrame(myframe); } else { b->SetFrame(f); myframe = f; } + f = myframe; b->SetPosition(vector3d(0, 0, 0)); AddBody(b); +just_make_child: for(std::vector::iterator i = sbody->children.begin(); i != sbody->children.end(); ++i) { - GenBody(system, *i, myframe); + GenBody(*i, f); } } -void Space::BuildSystem(StarSystem* system) { - GenBody(system, system->rootBody, rootFrame); +void Space::BuildSystem(void) { + GenBody(L3D::current_system->rootBody, rootFrame); } void Space::AddBody(Body* b) { @@ -223,6 +240,7 @@ void Space::TimeStep(float step) { /* TODO: Does not need to be done this often. */ UpdateFramesOfReference(); + MoveFramesOfReference(rootFrame); for(bodiesIter_t i = bodies.begin(); i != bodies.end(); ++i) { (*i)->TimeStepUpdate(step); diff --git a/src/space.h b/src/space.h index 725d592..08366e5 100644 --- a/src/space.h +++ b/src/space.h @@ -11,8 +11,8 @@ class Space { public: static void Init(void); static void Clear(void); - static void BuildSystem(StarSystem* s); - static void GenBody(StarSystem* s, StarSystem::SBody* b, Frame* f); + static void BuildSystem(void); + static void GenBody(StarSystem::SBody* b, Frame* f); static void TimeStep(float step); static void AddBody(Body*); static void KillBody(Body*); @@ -24,6 +24,7 @@ public: typedef std::list::iterator bodiesIter_t; static Frame* rootFrame; private: + static void MoveFramesOfReference(Frame* f); static void UpdateFramesOfReference(void); static void CollideFrame(Frame* f); static void PruneCorpses(void); diff --git a/src/star_system.cpp b/src/star_system.cpp index be087fb..c814a40 100644 --- a/src/star_system.cpp +++ b/src/star_system.cpp @@ -6,7 +6,8 @@ #define DEBUG_DUMP /* Indexed by enum type. */ -float StarSystem::starColors[7][3] = { +float StarSystem::starColors[][3] = { + { 0, 0, 0 }, /* Gravpoint. / { 1.0, 0.2, 0.0 }, /* M */ { 1.0, 0.6, 0.1 }, /* K */ { 1.0, 1.0, 0.4 }, /* G */ @@ -24,6 +25,9 @@ static const struct SBodySubTypeInfo { const char *icon; int tempMin, tempMax; } bodyTypeInfo[StarSystem::TYPE_MAX] = { + { + StarSystem::SUPERTYPE_NONE, 0, 0, "You can't see me!", + }, { StarSystem::SUPERTYPE_STAR, 40, 50, "Type 'M' red star", @@ -387,14 +391,84 @@ StarSystem::StarSystem(int sector_x, int sector_y, int system_idx) { /* Primary. */ SBody* primary = new SBody; - StarSystem::BodyType type = s.m_systems[system_idx].primaryStarClass; - primary->type = type; - primary->parent = NULL; - primary->radius = fixed(bodyTypeInfo[type].radius, 100); - primary->mass = fixed(bodyTypeInfo[type].mass, 100); - primary->averageTemp = rand.Int32(bodyTypeInfo[type].tempMin, - bodyTypeInfo[type].tempMax); - rootBody = primary; + int isBinary = rand.Int32(2); + if(!isBinary) { + StarSystem::BodyType type = s.m_systems[system_idx].primaryStarClass; + primary->type = type; + primary->parent = NULL; + primary->radius = fixed(bodyTypeInfo[type].radius, 100); + primary->mass = fixed(bodyTypeInfo[type].mass, 100); + primary->averageTemp = rand.Int32(bodyTypeInfo[type].tempMin, + bodyTypeInfo[type].tempMax); + primary->name = s.m_systems[system_idx].name; + rootBody = primary; + } else { + SBody* centGrav = new SBody; + centGrav->type = TYPE_GRAVPOINT; + centGrav->parent = NULL; + centGrav->name = s.m_systems[system_idx].name; + rootBody = centGrav; + + fixed ecc = rand.NFixed(3); + StarSystem::BodyType type = s.m_systems[system_idx].primaryStarClass; + SBody* star[2]; + star[0] = new SBody; + star[0]->type = type; + star[0]->name = s.m_systems[system_idx].name+" A"; + star[0]->parent = centGrav; + star[0]->radius = fixed(bodyTypeInfo[type].radius, 100); + star[0]->mass = fixed(bodyTypeInfo[type].mass, 100); + star[0]->averageTemp = rand.Int32(bodyTypeInfo[type].tempMin, + bodyTypeInfo[type].tempMax); + + /* + * Usually, star types are chosen by spectral class distribution in + * our galactic neighbourhood. In binary systems, we instead just choose + * random companion types up to spectral class of primary. + */ + StarSystem::BodyType type2 = (BodyType)rand.Int32(TYPE_STAR_M, type); + star[1] = new SBody; + star[1]->type = type2; + star[1]->name = s.m_systems[system_idx].name+" B"; + star[1]->parent = centGrav; + star[1]->radius = fixed(bodyTypeInfo[type2].radius, 100); + star[1]->mass = fixed(bodyTypeInfo[type2].mass, 100); + star[1]->averageTemp = rand.Int32(bodyTypeInfo[type2].tempMin, + bodyTypeInfo[type2].tempMax); + fixed m = star[0]->mass + star[1]->mass; + fixed a0 = star[1]->mass / m; + fixed a1 = star[0]->mass / m; + fixed semiMajorAxis; + + switch(rand.Int32(3)) { + case 2: semiMajorAxis = fixed(rand.Int32(100, 10000), 100); break; + case 1: semiMajorAxis = fixed(rand.Int32(10, 1000), 100); break; + default: + case 0: semiMajorAxis = fixed(rand.Int32(1, 100), 100); break; + } + printf("Binary seperation: %.2fAU\n", semiMajorAxis.ToDouble()); + + star[0]->orbit.eccentricity = ecc.ToDouble(); + star[0]->orbit.semiMajorAxis = AU * (semiMajorAxis*a0).ToDouble(); + star[0]->orbit.period = 60*60*24*365*semiMajorAxis.ToDouble()*sqrt(semiMajorAxis.ToDouble() / m.ToDouble()); + star[0]->orbit.rotMatrix = matrix4x4d::RotateZMatrix(M_PI); + + star[1]->orbit.eccentricity = ecc.ToDouble(); + star[1]->orbit.semiMajorAxis = AU * (semiMajorAxis*a1).ToDouble(); + star[1]->orbit.period = star[0]->orbit.period; + star[1]->orbit.rotMatrix = matrix4x4d::Identity(); + + fixed radMin = semiMajorAxis - ecc*semiMajorAxis; + fixed radMax = 2*semiMajorAxis - radMin; + star[0]->radMin = radMin; + star[1]->radMin = radMin; + star[0]->radMax = radMax; + star[1]->radMax = radMax; + + centGrav->children.push_back(star[0]); + centGrav->children.push_back(star[1]); + return; + } /* FIXME: Not good if the enum is tampered with... */ int disc_size = rand.Int32(6, 100) + rand.Int32(60,140)*primary->type*primary->type; diff --git a/src/star_system.h b/src/star_system.h index f5c513d..2ac4cad 100644 --- a/src/star_system.h +++ b/src/star_system.h @@ -22,6 +22,7 @@ struct CustomSBody; /* Doubles: All masses are in Kg, all lengths in meters. */ class StarSystem { public: + StarSystem(void) { rootBody = 0; } StarSystem(int sector_x, int sector_y, int system_idx); ~StarSystem(void); bool IsSystem(int sector_x, int sector_y, int system_idx); @@ -30,7 +31,7 @@ public: *sec_x = loc.secX; *sec_y = loc.secY, *sys_idx = loc.sysIdx; } - static float starColors[7][3]; + static float starColors[][3]; struct Orbit { void KeplerPosAtTime(double t, double* dist, double* ang); @@ -42,6 +43,7 @@ public: }; enum BodyType { + TYPE_GRAVPOINT, TYPE_STAR_M, TYPE_STAR_K, TYPE_STAR_G, diff --git a/src/system_info_view.cpp b/src/system_info_view.cpp index 74a9806..5fd514a 100644 --- a/src/system_info_view.cpp +++ b/src/system_info_view.cpp @@ -53,23 +53,48 @@ void SystemInfoView::OnBodySelected(StarSystem::SBody* b) { void SystemInfoView::SystemChanged(StarSystem* s) { DeleteAllChildren(); float csize[2]; + int majorBodies = 0; GetSize(csize); float xpos = 0; float size[2]; - Gui::ImageButton* ib = new Gui::ImageButton(s->rootBody->GetIcon()); - ib->GetSize(size); - ib->onClick.connect(sigc::bind(sigc::mem_fun(this, &SystemInfoView::OnBodySelected), s->rootBody)); - Add(ib, 0, csize[1] - size[1]); - xpos += size[0]; - float ycent = csize[1] - size[1]*0.5; + float ycent; + std::vector::iterator i = s->rootBody->children.begin(); - for(std::vector::iterator i = s->rootBody->children.begin(); - i != s->rootBody->children.end(); ++i) { + if(s->rootBody->type == StarSystem::TYPE_GRAVPOINT) { + /* Binary system. */ + Gui::ImageButton* ib = new Gui::ImageButton((*i)->GetIcon()); + ib->GetSize(size); + ib->onClick.connect(sigc::bind(sigc::mem_fun(this, &SystemInfoView::OnBodySelected), *i)); + Add(ib, 0, csize[1] - size[1]); + float yoffset = size[1]; + float xoffset = size[0]; + ++i; majorBodies++; + + ib = new Gui::ImageButton((*i)->GetIcon()); + ib->GetSize(size); + ib->onClick.connect(sigc::bind(sigc::mem_fun(this, &SystemInfoView::OnBodySelected), *i)); + Add(ib, 0, csize[1] - size[1] - yoffset); + ++i; majorBodies++; + + xpos += xoffset; + ycent = csize[1] - yoffset*0.5; + } else { + Gui::ImageButton* ib = new Gui::ImageButton(s->rootBody->GetIcon()); + ib->GetSize(size); + ib->onClick.connect(sigc::bind(sigc::mem_fun(this, &SystemInfoView::OnBodySelected), s->rootBody)); + Add(ib, 0, csize[1] - size[1]); + xpos += size[0]; + ycent = csize[1] - size[1]*0.5; + majorBodies++; + } + + for(; i != s->rootBody->children.end(); ++i) { Gui::ImageButton* ib = new Gui::ImageButton((*i)->GetIcon()); ib->GetSize(size); ib->onClick.connect(sigc::bind(sigc::mem_fun(this, &SystemInfoView::OnBodySelected), *i)); Add(ib, xpos, ycent - 0.5*size[1]); + majorBodies++; float moon_ypos = ycent - size[1] - 5; if((*i)->children.size()) @@ -86,7 +111,7 @@ void SystemInfoView::SystemChanged(StarSystem* s) { } char buf[512]; - snprintf(buf, sizeof(buf), "Stable system with %d major bodies.", 1+s->rootBody->children.size()); + snprintf(buf, sizeof(buf), "Stable system with %d major bodies", majorBodies); m_infoText = new Gui::Label(buf); m_infoText->SetColor(1, 1, 0); Add(m_infoText, 50, 200); diff --git a/src/system_view.cpp b/src/system_view.cpp index 6f28d2b..df59038 100644 --- a/src/system_view.cpp +++ b/src/system_view.cpp @@ -116,13 +116,15 @@ void SystemView::PutLabel(StarSystem::SBody* b) { #define ROUGH_SIZE_OF_THING 10.0 void SystemView::PutBody(StarSystem::SBody* b) { - glPointSize(5); - glColor3f(1,1,1); - glBegin(GL_POINTS); - glVertex3f(0,0,0); - glEnd(); - - PutLabel(b); + if(b->type != StarSystem::TYPE_GRAVPOINT) { + glPointSize(5); + glColor3f(1,1,1); + glBegin(GL_POINTS); + glVertex3f(0,0,0); + glEnd(); + + PutLabel(b); + } if(b->children.size()) for(std::vector::iterator kid = b->children.begin(); diff --git a/src/world_view.cpp b/src/world_view.cpp index 052d464..209aa8d 100644 --- a/src/world_view.cpp +++ b/src/world_view.cpp @@ -115,7 +115,7 @@ void WorldView::Draw3D(void) { } void WorldView::Update(void) { - if(L3D::GetSelectedSystem() /* && isn't current system */) { + if(L3D::GetSelectedSystem() && !L3D::player->GetDockedWith()/* && isn't current system */) { m_hyperspaceButton->Show(); } else { m_hyperspaceButton->Hide();