[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.
This commit is contained in:
Rtch90 2017-12-24 14:30:29 +00:00
parent e67e7f12f2
commit 4d475bdf9b
12 changed files with 171 additions and 38 deletions

View File

@ -18,6 +18,7 @@ void Frame::RemoveChild(Frame* f) {
} }
void Frame::Init(Frame* parent, const char* label, unsigned int flags) { void Frame::Init(Frame* parent, const char* label, unsigned int flags) {
sBody = 0;
m_parent = parent; m_parent = parent;
m_flags = flags; m_flags = flags;
m_radius = 0; m_radius = 0;

View File

@ -2,6 +2,7 @@
#include <string> #include <string>
#include <list> #include <list>
#include "libs.h" #include "libs.h"
#include "star_system.h"
/* Frame of reference. */ /* Frame of reference. */
class Frame { class Frame {
@ -33,6 +34,7 @@ public:
/* If parent is null then frame position is absolute. */ /* If parent is null then frame position is absolute. */
Frame* m_parent; Frame* m_parent;
std::list<Frame*> m_children; std::list<Frame*> m_children;
StarSystem::SBody* sBody; /* Points to SBodies in L3D::current_system. */
enum { TEMP_VIEWING=1 }; enum { TEMP_VIEWING=1 };

View File

@ -82,6 +82,7 @@ public:
static InfoView* infoView; static InfoView* infoView;
static ShipCpanel* cpan; static ShipCpanel* cpan;
static GLUquadric* gluQuadric; static GLUquadric* gluQuadric;
static StarSystem* current_system;
private: private:
static void InitOpenGL(void); static void InitOpenGL(void);

View File

@ -44,6 +44,7 @@ SystemView* L3D::system_view;
SystemInfoView* L3D::system_info_view; SystemInfoView* L3D::system_info_view;
ShipCpanel* L3D::cpan; ShipCpanel* L3D::cpan;
StarSystem* L3D::selected_system; StarSystem* L3D::selected_system;
StarSystem* L3D::current_system;
MTRand L3D::rng; MTRand L3D::rng;
double L3D::gameTime; double L3D::gameTime;
float L3D::frameTime; float L3D::frameTime;
@ -309,8 +310,14 @@ StarSystem* L3D::GetSelectedSystem(void) {
} }
void L3D::HyperspaceTo(StarSystem* dest) { 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::Clear();
Space::BuildSystem(dest); Space::BuildSystem();
float ang = rng.Double(M_PI); float ang = rng.Double(M_PI);
L3D::player->SetPosition(vector3d(sin(ang)*8*AU, cos(ang)*8*AU, 0)); L3D::player->SetPosition(vector3d(sin(ang)*8*AU, cos(ang)*8*AU, 0));
dest->GetPos(&L3D::playerLoc); dest->GetPos(&L3D::playerLoc);

View File

@ -245,11 +245,11 @@ void Player::DrawHUD(const Frame* cam_frame) {
vector3d abs_pos = GetPositionRelTo(Space::GetRootFrame()); vector3d abs_pos = GetPositionRelTo(Space::GetRootFrame());
const char* rel_to = (GetFrame() ? GetFrame()->GetLabel() : "System"); const char* rel_to = (GetFrame() ? GetFrame()->GetLabel() : "System");
snprintf(buf, sizeof(buf), "Pos: %.1f,%.1f,%.1f\n" snprintf(buf, sizeof(buf), "Pos: %.1f,%.1f,%.1f\n"
"AbsPos: %.1f,%.1f,%.1f\n" "AbsPos: %.1f,%.1f,%.1f (%.3f AU)\n"
"Rel-to: %s", "Rel-to: %s (%.0f km)",
pos.x, pos.y, pos.z, pos.x, pos.y, pos.z,
abs_pos.x, abs_pos.y, abs_pos.z, abs_pos.x, abs_pos.y, abs_pos.z, abs_pos.Length()/AU,
rel_to); rel_to, pos.Length()/1000);
Gui::Screen::RenderString(buf); Gui::Screen::RenderString(buf);
glPopMatrix(); glPopMatrix();
} }

View File

@ -41,8 +41,22 @@ void Space::Clear(void) {
L3D::player->SetFrame(rootFrame); 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<Frame*>::iterator i = f->m_children.begin(); i != f->m_children.end(); ++i) {
MoveFramesOfReference(*i);
}
}
void Space::GenBody(StarSystem::SBody* sbody, Frame* f) {
Body* b; Body* b;
if(sbody->type == StarSystem::TYPE_GRAVPOINT) goto just_make_child;
if(sbody->GetSuperType() == StarSystem::SUPERTYPE_STAR) { if(sbody->GetSuperType() == StarSystem::SUPERTYPE_STAR) {
Star* star = new Star(sbody); Star* star = new Star(sbody);
b = star; b = star;
@ -59,24 +73,27 @@ void Space::GenBody(StarSystem* system, StarSystem::SBody* sbody, Frame* f) {
vector3d pos = sbody->orbit.CartesianPosAtTime(0); vector3d pos = sbody->orbit.CartesianPosAtTime(0);
myframe->SetPosition(pos); myframe->SetPosition(pos);
myframe->SetRadius(10*sbody->GetRadius()); myframe->SetRadius(10*sbody->GetRadius());
myframe->sBody = sbody;
b->SetFrame(myframe); b->SetFrame(myframe);
} else { } else {
b->SetFrame(f); b->SetFrame(f);
myframe = f; myframe = f;
} }
f = myframe;
b->SetPosition(vector3d(0, 0, 0)); b->SetPosition(vector3d(0, 0, 0));
AddBody(b); AddBody(b);
just_make_child:
for(std::vector<StarSystem::SBody*>::iterator i = sbody->children.begin(); for(std::vector<StarSystem::SBody*>::iterator i = sbody->children.begin();
i != sbody->children.end(); ++i) { i != sbody->children.end(); ++i) {
GenBody(system, *i, myframe); GenBody(*i, f);
} }
} }
void Space::BuildSystem(StarSystem* system) { void Space::BuildSystem(void) {
GenBody(system, system->rootBody, rootFrame); GenBody(L3D::current_system->rootBody, rootFrame);
} }
void Space::AddBody(Body* b) { void Space::AddBody(Body* b) {
@ -223,6 +240,7 @@ void Space::TimeStep(float step) {
/* TODO: Does not need to be done this often. */ /* TODO: Does not need to be done this often. */
UpdateFramesOfReference(); UpdateFramesOfReference();
MoveFramesOfReference(rootFrame);
for(bodiesIter_t i = bodies.begin(); i != bodies.end(); ++i) { for(bodiesIter_t i = bodies.begin(); i != bodies.end(); ++i) {
(*i)->TimeStepUpdate(step); (*i)->TimeStepUpdate(step);

View File

@ -11,8 +11,8 @@ class Space {
public: public:
static void Init(void); static void Init(void);
static void Clear(void); static void Clear(void);
static void BuildSystem(StarSystem* s); static void BuildSystem(void);
static void GenBody(StarSystem* s, StarSystem::SBody* b, Frame* f); static void GenBody(StarSystem::SBody* b, Frame* f);
static void TimeStep(float step); static void TimeStep(float step);
static void AddBody(Body*); static void AddBody(Body*);
static void KillBody(Body*); static void KillBody(Body*);
@ -24,6 +24,7 @@ public:
typedef std::list<Body*>::iterator bodiesIter_t; typedef std::list<Body*>::iterator bodiesIter_t;
static Frame* rootFrame; static Frame* rootFrame;
private: private:
static void MoveFramesOfReference(Frame* f);
static void UpdateFramesOfReference(void); static void UpdateFramesOfReference(void);
static void CollideFrame(Frame* f); static void CollideFrame(Frame* f);
static void PruneCorpses(void); static void PruneCorpses(void);

View File

@ -6,7 +6,8 @@
#define DEBUG_DUMP #define DEBUG_DUMP
/* Indexed by enum type. */ /* 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.2, 0.0 }, /* M */
{ 1.0, 0.6, 0.1 }, /* K */ { 1.0, 0.6, 0.1 }, /* K */
{ 1.0, 1.0, 0.4 }, /* G */ { 1.0, 1.0, 0.4 }, /* G */
@ -24,6 +25,9 @@ static const struct SBodySubTypeInfo {
const char *icon; const char *icon;
int tempMin, tempMax; int tempMin, tempMax;
} bodyTypeInfo[StarSystem::TYPE_MAX] = { } bodyTypeInfo[StarSystem::TYPE_MAX] = {
{
StarSystem::SUPERTYPE_NONE, 0, 0, "You can't see me!",
},
{ {
StarSystem::SUPERTYPE_STAR, StarSystem::SUPERTYPE_STAR,
40, 50, "Type 'M' red star", 40, 50, "Type 'M' red star",
@ -387,14 +391,84 @@ StarSystem::StarSystem(int sector_x, int sector_y, int system_idx) {
/* Primary. */ /* Primary. */
SBody* primary = new SBody; SBody* primary = new SBody;
StarSystem::BodyType type = s.m_systems[system_idx].primaryStarClass; int isBinary = rand.Int32(2);
primary->type = type; if(!isBinary) {
primary->parent = NULL; StarSystem::BodyType type = s.m_systems[system_idx].primaryStarClass;
primary->radius = fixed(bodyTypeInfo[type].radius, 100); primary->type = type;
primary->mass = fixed(bodyTypeInfo[type].mass, 100); primary->parent = NULL;
primary->averageTemp = rand.Int32(bodyTypeInfo[type].tempMin, primary->radius = fixed(bodyTypeInfo[type].radius, 100);
bodyTypeInfo[type].tempMax); primary->mass = fixed(bodyTypeInfo[type].mass, 100);
rootBody = primary; 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... */ /* FIXME: Not good if the enum is tampered with... */
int disc_size = rand.Int32(6, 100) + rand.Int32(60,140)*primary->type*primary->type; int disc_size = rand.Int32(6, 100) + rand.Int32(60,140)*primary->type*primary->type;

View File

@ -22,6 +22,7 @@ struct CustomSBody;
/* Doubles: All masses are in Kg, all lengths in meters. */ /* Doubles: All masses are in Kg, all lengths in meters. */
class StarSystem { class StarSystem {
public: public:
StarSystem(void) { rootBody = 0; }
StarSystem(int sector_x, int sector_y, int system_idx); StarSystem(int sector_x, int sector_y, int system_idx);
~StarSystem(void); ~StarSystem(void);
bool IsSystem(int sector_x, int sector_y, int system_idx); 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; *sec_x = loc.secX; *sec_y = loc.secY, *sys_idx = loc.sysIdx;
} }
static float starColors[7][3]; static float starColors[][3];
struct Orbit { struct Orbit {
void KeplerPosAtTime(double t, double* dist, double* ang); void KeplerPosAtTime(double t, double* dist, double* ang);
@ -42,6 +43,7 @@ public:
}; };
enum BodyType { enum BodyType {
TYPE_GRAVPOINT,
TYPE_STAR_M, TYPE_STAR_M,
TYPE_STAR_K, TYPE_STAR_K,
TYPE_STAR_G, TYPE_STAR_G,

View File

@ -53,23 +53,48 @@ void SystemInfoView::OnBodySelected(StarSystem::SBody* b) {
void SystemInfoView::SystemChanged(StarSystem* s) { void SystemInfoView::SystemChanged(StarSystem* s) {
DeleteAllChildren(); DeleteAllChildren();
float csize[2]; float csize[2];
int majorBodies = 0;
GetSize(csize); GetSize(csize);
float xpos = 0; float xpos = 0;
float size[2]; float size[2];
Gui::ImageButton* ib = new Gui::ImageButton(s->rootBody->GetIcon()); float ycent;
ib->GetSize(size); std::vector<StarSystem::SBody*>::iterator i = s->rootBody->children.begin();
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;
for(std::vector<StarSystem::SBody*>::iterator i = s->rootBody->children.begin(); if(s->rootBody->type == StarSystem::TYPE_GRAVPOINT) {
i != s->rootBody->children.end(); ++i) { /* 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()); Gui::ImageButton* ib = new Gui::ImageButton((*i)->GetIcon());
ib->GetSize(size); ib->GetSize(size);
ib->onClick.connect(sigc::bind(sigc::mem_fun(this, &SystemInfoView::OnBodySelected), *i)); ib->onClick.connect(sigc::bind(sigc::mem_fun(this, &SystemInfoView::OnBodySelected), *i));
Add(ib, xpos, ycent - 0.5*size[1]); Add(ib, xpos, ycent - 0.5*size[1]);
majorBodies++;
float moon_ypos = ycent - size[1] - 5; float moon_ypos = ycent - size[1] - 5;
if((*i)->children.size()) if((*i)->children.size())
@ -86,7 +111,7 @@ void SystemInfoView::SystemChanged(StarSystem* s) {
} }
char buf[512]; 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 = new Gui::Label(buf);
m_infoText->SetColor(1, 1, 0); m_infoText->SetColor(1, 1, 0);
Add(m_infoText, 50, 200); Add(m_infoText, 50, 200);

View File

@ -116,13 +116,15 @@ void SystemView::PutLabel(StarSystem::SBody* b) {
#define ROUGH_SIZE_OF_THING 10.0 #define ROUGH_SIZE_OF_THING 10.0
void SystemView::PutBody(StarSystem::SBody* b) { void SystemView::PutBody(StarSystem::SBody* b) {
glPointSize(5); if(b->type != StarSystem::TYPE_GRAVPOINT) {
glColor3f(1,1,1); glPointSize(5);
glBegin(GL_POINTS); glColor3f(1,1,1);
glVertex3f(0,0,0); glBegin(GL_POINTS);
glEnd(); glVertex3f(0,0,0);
glEnd();
PutLabel(b); PutLabel(b);
}
if(b->children.size()) if(b->children.size())
for(std::vector<StarSystem::SBody*>::iterator kid = b->children.begin(); for(std::vector<StarSystem::SBody*>::iterator kid = b->children.begin();

View File

@ -115,7 +115,7 @@ void WorldView::Draw3D(void) {
} }
void WorldView::Update(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(); m_hyperspaceButton->Show();
} else { } else {
m_hyperspaceButton->Hide(); m_hyperspaceButton->Hide();