[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) {
sBody = 0;
m_parent = parent;
m_flags = flags;
m_radius = 0;

View File

@ -2,6 +2,7 @@
#include <string>
#include <list>
#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<Frame*> m_children;
StarSystem::SBody* sBody; /* Points to SBodies in L3D::current_system. */
enum { TEMP_VIEWING=1 };

View File

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

View File

@ -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);

View File

@ -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();
}

View File

@ -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<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;
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<StarSystem::SBody*>::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);

View File

@ -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<Body*>::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);

View File

@ -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,6 +391,8 @@ StarSystem::StarSystem(int sector_x, int sector_y, int system_idx) {
/* Primary. */
SBody* primary = new SBody;
int isBinary = rand.Int32(2);
if(!isBinary) {
StarSystem::BodyType type = s.m_systems[system_idx].primaryStarClass;
primary->type = type;
primary->parent = NULL;
@ -394,7 +400,75 @@ StarSystem::StarSystem(int sector_x, int sector_y, int system_idx) {
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;

View File

@ -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,

View File

@ -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];
float ycent;
std::vector<StarSystem::SBody*>::iterator i = s->rootBody->children.begin();
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];
float ycent = csize[1] - size[1]*0.5;
ycent = csize[1] - size[1]*0.5;
majorBodies++;
}
for(std::vector<StarSystem::SBody*>::iterator i = s->rootBody->children.begin();
i != s->rootBody->children.end(); ++i) {
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);

View File

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

View File

@ -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();