From f96e519b931ebf89da134212491b5caf03de126c Mon Sep 17 00:00:00 2001 From: Allanis Date: Sun, 24 Dec 2017 14:30:29 +0000 Subject: [PATCH] [Add] Initial work on binary star systems. Right now they are generated without planets and with no more than two stars. Orbits around center of mass should be correct. World view objects now move along their orbit rails. --- src/frame.cpp | 1 + src/frame.h | 2 + src/l3d.h | 1 + src/main.cpp | 9 +++- src/player.cpp | 8 ++-- src/space.cpp | 26 ++++++++++-- src/space.h | 5 ++- src/star_system.cpp | 92 ++++++++++++++++++++++++++++++++++++---- src/star_system.h | 4 +- src/system_info_view.cpp | 43 +++++++++++++++---- src/system_view.cpp | 16 ++++--- src/world_view.cpp | 2 +- 12 files changed, 171 insertions(+), 38 deletions(-) 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();