initial work on binary star systems. currently they are generated without planets and with no more than 2 stars. orbits around centre of mass should be correct. world view objects now move along their orbit rails

git-svn-id: https://pioneer.svn.sourceforge.net/svnroot/pioneer/trunk@87 e632f14b-6550-0410-b89e-a82653faca30
master
tompox 2008-08-12 16:38:23 +00:00
parent c675e1952b
commit 5ab5761dca
12 changed files with 169 additions and 36 deletions

View File

@ -23,6 +23,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

@ -4,6 +4,7 @@
#include "libs.h"
#include <string>
#include <list>
#include "StarSystem.h"
/*
* Frame of reference.
@ -36,6 +37,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 Pi::current_system
enum { TEMP_VIEWING=1 };
private:

View File

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

View File

@ -253,11 +253,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

@ -42,9 +42,25 @@ void Space::Clear()
Pi::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(Pi::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;
// yay goto
if (sbody->type == StarSystem::TYPE_GRAVPOINT) goto just_make_kids;
if (sbody->GetSuperType() == StarSystem::SUPERTYPE_STAR) {
Star *star = new Star(sbody);
b = star;
@ -60,24 +76,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_kids:
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)
void Space::BuildSystem()
{
GenBody(system, system->rootBody, rootFrame);
GenBody(Pi::current_system->rootBody, rootFrame);
}
void Space::AddBody(Body *b)
@ -228,6 +247,7 @@ void Space::TimeStep(float step)
dJointGroupEmpty(_contactgroup);
// XXX 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

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

View File

@ -6,7 +6,8 @@
#define DEBUG_DUMP
// indexed by enum type turd
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
@ -25,6 +26,8 @@ static const struct SBodySubTypeInfo {
int tempMin, tempMax;
} bodyTypeInfo[StarSystem::TYPE_MAX] = {
{
StarSystem::SUPERTYPE_NONE, 0, 0, "Shouldn't see this!",
}, {
StarSystem::SUPERTYPE_STAR,
40, 50, "Type 'M' red star",
"icons/object_star_m.png",
@ -394,14 +397,82 @@ 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);
// normally star types are picked by spectral class distribution in
// our galactic neighbourhood. in binary systems instead just pick
// 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 separation: %.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;
}
// XXX bad if the enum is fiddled with........
int disc_size = rand.Int32(6,100) + rand.Int32(60,140)*primary->type*primary->type;

View File

@ -26,6 +26,7 @@ struct CustomSBody;
class StarSystem {
public:
StarSystem() { rootBody = 0; }
StarSystem(int sector_x, int sector_y, int system_idx);
~StarSystem();
bool IsSystem(int sector_x, int sector_y, int system_idx);
@ -34,7 +35,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);
@ -46,6 +47,7 @@ public:
};
enum BodyType {
TYPE_GRAVPOINT,
TYPE_STAR_M,
TYPE_STAR_K,
TYPE_STAR_G,

View File

@ -57,22 +57,48 @@ 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<StarSystem::SBody*>::iterator i = s->rootBody->children.begin();
for (std::vector<StarSystem::SBody*>::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()) for(std::vector<StarSystem::SBody*>::iterator moon = (*i)->children.begin(); moon != (*i)->children.end(); ++moon) {
@ -87,7 +113,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

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

View File

@ -120,7 +120,7 @@ void WorldView::Draw3D()
void WorldView::Update()
{
if (Pi::GetSelectedSystem() /* && isn't current system */ ) {
if (Pi::GetSelectedSystem() && !Pi::player->GetDockedWith()/* && isn't current system */ ) {
m_hyperspaceButton->Show();
} else {
m_hyperspaceButton->Hide();

View File

@ -44,6 +44,7 @@ SystemView *Pi::system_view;
SystemInfoView *Pi::system_info_view;
ShipCpanel *Pi::cpan;
StarSystem *Pi::selected_system;
StarSystem *Pi::current_system;
MTRand Pi::rng;
double Pi::gameTime;
float Pi::frameTime;
@ -317,8 +318,14 @@ StarSystem *Pi::GetSelectedSystem()
void Pi::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);
Pi::player->SetPosition(vector3d(sin(ang)*8*AU,cos(ang)*8*AU,0));
dest->GetPos(&Pi::playerLoc);