diff --git a/src/body.cpp b/src/body.cpp
index ded37d4..7149f1d 100644
--- a/src/body.cpp
+++ b/src/body.cpp
@@ -17,7 +17,9 @@ Body::~Body(void) {
/* f == NULL, then absolute position within system. */
vector3d Body::GetPositionRelTo(const Frame* relTo) {
- return m_frame->GetPosRelativeToOtherFrame(relTo) + GetPosition();
+ matrix4x4d m;
+ Frame::GetFrameTransform(m_frame, relTo, m);
+ return m * GetPosition();
}
const vector3d& Body::GetProjectedPos(void) const {
diff --git a/src/body.h b/src/body.h
index d05e56a..cb71377 100644
--- a/src/body.h
+++ b/src/body.h
@@ -18,6 +18,8 @@ public:
virtual void SetVelocity(vector3d v) { assert(0); }
virtual vector3d GetVelocity(void) { assert(0); return vector3d(0.0); }
virtual double GetRadius(void) const = 0 ;
+ virtual void SetRotMatrix(const matrix4x4d& r) {};
+ virtual void GetRotMatrix(matrix4x4d& m) {};
virtual void Render(const Frame* camFrame) = 0;
virtual void SetFrame(Frame* f) { m_frame = f; }
/* return true if to we do collision response and apply damage. */
diff --git a/src/frame.cpp b/src/frame.cpp
index 97aaf3c..bd93003 100644
--- a/src/frame.cpp
+++ b/src/frame.cpp
@@ -24,6 +24,8 @@ void Frame::Init(Frame* parent, const char* label, unsigned int flags) {
m_radius = 0;
m_pos = vector3d(0.0f);
m_vel = vector3d(0.0);
+ m_angVel = vector3d(0.0);
+ m_orient = matrix4x4d::Identity();
m_dSpaceID = dHashSpaceCreate(0);
if(m_parent) {
m_parent->m_children.push_back(this);
@@ -36,23 +38,40 @@ Frame::~Frame(void) {
for(std::list::iterator i = m_children.begin(); i != m_children.end(); ++i) delete *i;
}
-vector3d Frame::GetFramePosRelativeToOther(const Frame* frame, const Frame* relTo) {
- vector3d pos = vector3d(0,0,0);
+void Frame::ApplyLeavingTransform(matrix4x4d& m) const {
+ m = matrix4x4d::Translation(m_pos) * m_orient * m;
+}
- const Frame* f = frame;
+void Frame::ApplyEnteringTransform(matrix4x4d& m) const {
+ m = m * m_orient.InverseOf() * matrix4x4d::Translation(-m_pos);
+}
+
+void Frame::GetFrameTransform(const Frame* fFrom, const Frame* fTo, matrix4x4d& m) {
+ matrix4x4d m2 = matrix4x4d::Identity();
+ m = matrix4x4d::Identity();
+
+ const Frame* f = fFrom;
const Frame* root = Space::GetRootFrame();
- while((f!=root) && (relTo !=f)) {
- pos += f->m_pos;
+ while((f != root) && (fTo != f)) {
+ f->ApplyLeavingTransform(m);
f = f->m_parent;
}
- /* Now pos is relative to root, or to desired frame. */
- while(relTo != f) {
- pos -= relTo->m_pos;
- relTo = relTo->m_parent;
+ while(fTo != f) {
+ fTo->ApplyEnteringTransform(m2);
+ fTo = fTo->m_parent;
}
- return pos;
+ m = m2 * m;
+}
+
+void Frame::RotateInTimestep(double step) {
+ double ang = m_angVel.Length() * step;
+ if(ang == 0) return;
+ vector3d rotAxis = vector3d::Normalize(m_angVel);
+ matrix4x4d rotMatrix = matrix4x4d::RotateMatrix(ang, rotAxis.x, rotAxis.y, rotAxis.z);
+
+ m_orient = m_orient * rotMatrix;
}
diff --git a/src/frame.h b/src/frame.h
index 6799dc3..294d285 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -12,23 +12,28 @@ public:
Frame(Frame* parent, const char* label, unsigned int flags);
~Frame(void);
- const char* GetLabel(void) { return m_label.c_str(); }
- void SetLabel(const char* label) { m_label = label; }
- void SetPosition(const vector3d &pos) { m_pos = pos; }
- vector3d GetPosition(void) { return m_pos; }
- void SetVelocity(const vector3d& vel) { m_vel = vel; }
- vector3d GetVelocity(void) { return m_vel; }
- void SetRadius(double radius) { m_radius = radius; }
+ const char* GetLabel(void) const { return m_label.c_str(); }
+ void SetLabel(const char* label) { m_label = label; }
+ void SetPosition(const vector3d &pos) { m_pos = pos; }
+ vector3d GetPosition(void) const { return m_pos; }
+ void SetVelocity(const vector3d& vel) { m_vel = vel; }
+ vector3d GetVelocity(void) const { return m_vel; }
+ void SetAngVelocity(const vector3d& angvel) { m_angVel = angvel; }
+ vector3d GetAngVelocity(void) const { return m_angVel; }
+ const matrix4x4d& GetOrientation(void) const { return m_orient; }
+ void SetOrientation(const matrix4x4d& m) { m_orient = m; }
+ void SetRadius(double radius) { m_radius = radius; }
void RemoveChild(Frame* f);
- void AddGeom(dGeomID g) { dSpaceAdd(m_dSpaceID, g); }
- void RemoveGeom(dGeomID g) { dSpaceRemove(m_dSpaceID, g); }
- dSpaceID GetSpaceID(void) { return m_dSpaceID; }
+ void AddGeom(dGeomID g) { dSpaceAdd(m_dSpaceID, g); }
+ void RemoveGeom(dGeomID g) { dSpaceRemove(m_dSpaceID, g); }
+ dSpaceID GetSpaceID(void) const { return m_dSpaceID; }
+ void RotateInTimestep(double step);
- static vector3d GetFramePosRelativeToOther(const Frame* frame, const Frame* relTo);
- vector3d GetPosRelativeToOtherFrame(const Frame* relTo) const {
- return GetFramePosRelativeToOther(this, relTo);
- }
+ void ApplyLeavingTransform(matrix4x4d& m) const;
+ void ApplyEnteringTransform(matrix4x4d& m) const;
+
+ static void GetFrameTransform(const Frame* fFrom, const Frame* fTo, matrix4x4d& m);
bool IsLocalPosInFrame(const vector3d& pos) {
return (pos.Length() < m_radius);
@@ -46,6 +51,8 @@ private:
vector3d m_pos;
/* We don't use this to move frame, rather, orbital rails determine velocity. */
vector3d m_vel;
+ vector3d m_angVel; /* This however *is* directly applied (for rotating frames). */
+ matrix4x4d m_orient;
std::string m_label;
double m_radius;
int m_flags;
diff --git a/src/l3d.h b/src/l3d.h
index 08acfc0..6c6ec6d 100644
--- a/src/l3d.h
+++ b/src/l3d.h
@@ -34,6 +34,8 @@ public:
}
};
+class Frame;
+
/* Implementation is done in main.cpp, just to confuse you. :D */
class L3D {
public:
diff --git a/src/main.cpp b/src/main.cpp
index 19691fc..d972e74 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -194,8 +194,6 @@ void L3D::MainLoop(void) {
const float zpos = EARTH_RADIUS * 1;
Frame* pframe = *(Space::rootFrame->m_children.begin());
- player->SetFrame(pframe);
- player->SetPosition(vector3d(0, zpos*0.1, zpos));
for(int i = 0; i < 4; i++) {
Ship* body = new Ship(ShipType::SLEEK/*LADYBIRD*/);
@@ -207,12 +205,21 @@ void L3D::MainLoop(void) {
Space::AddBody(body);
}
+ Frame* stationFrame = new Frame(pframe, "Station frame...");
+ stationFrame->SetRadius(5000);
+ stationFrame->sBody = 0;
+ stationFrame->SetPosition(vector3d(0,0,zpos));
+ stationFrame->SetAngVelocity(vector3d(0,0,0.5));
+
SpaceStation* station = new SpaceStation();
station->SetLabel("Poemi-chan's Folly");
- station->SetFrame(pframe);
- station->SetPosition(vector3d(5000, zpos*0.1, zpos-10000));
+ station->SetFrame(stationFrame);
+ station->SetPosition(vector3d(0,0,0));
Space::AddBody(station);
+ player->SetFrame(stationFrame);
+ player->SetPosition(vector3d(0,0,2000));
+
Gui::Init(scrWidth, scrHeight, 640, 480);
cpan = new ShipCpanel();
@@ -227,7 +234,7 @@ void L3D::MainLoop(void) {
infoView = new InfoView();
SetView(world_view);
- player->SetDockedWith(station);
+ //player->SetDockedWith(station);
Uint32 last_stats = SDL_GetTicks();
int frame_stat = 0;
diff --git a/src/matrix4x4.h b/src/matrix4x4.h
index 22d8f35..f90b054 100644
--- a/src/matrix4x4.h
+++ b/src/matrix4x4.h
@@ -174,6 +174,12 @@ public:
return m;
}
+ void ClearToRotOnly(void) {
+ cell[12] = 0;
+ cell[13] = 0;
+ cell[14] = 0;
+ }
+
T& operator[] (const int i) { return cell[i]; }
friend matrix4x4 operator+(const matrix4x4& a, const matrix4x4& b) {
matrix4x4 m;
@@ -223,12 +229,28 @@ public:
return out;
}
- void Translatef(T x, T y, T z) {
+ void Translate(vector3 t) {
+ Translate(t.x, t.y, t.z);
+ }
+
+ void Translate(T x, T y, T z) {
matrix4x4 m = Identity();
m[12] = x;
m[13] = y;
m[14] = z;
- *this = (*this) * m;
+ *this = m * (*this);
+ }
+
+ static matrix4x4 Translation(vector3 v) {
+ return Translation(v.x, v.y, v.z);
+ }
+
+ static matrix4x4 Translation(T x, T y, T z) {
+ matrix4x4 m = Identity();
+ m[12] = x;
+ m[13] = y;
+ m[14] = z;
+ return m;
}
matrix4x4 InverseOf(void) const {
diff --git a/src/model_body.cpp b/src/model_body.cpp
index 4a40e5f..35d0475 100644
--- a/src/model_body.cpp
+++ b/src/model_body.cpp
@@ -88,7 +88,7 @@ double ModelBody::GetRadius(void) const {
return std::max(aabbAll[1] - aabbAll[0], std::max(aabbAll[3] - aabbAll[2], aabbAll[5] - aabbAll[4]));
}
-void ModelBody::SetRotation(const matrix4x4d& r) {
+void ModelBody::SetRotMatrix(const matrix4x4d& r) {
dMatrix3 _m;
r.SaveToOdeMatrix(_m);
for(unsigned int i = 0; i < geoms.size(); i++) {
@@ -168,12 +168,15 @@ void ModelBody::RenderSbreModel(const Frame* camFrame, int model, ObjParams* par
sbreSetViewport(L3D::GetScrWidth(), L3D::GetScrHeight(), L3D::GetScrWidth()
*0.5, 5.0f, 100000.0f, 0.0f, 1.0f);
- vector3d pos = GetPositionRelTo(camFrame);
- pos = L3D::world_view->viewingRotation*pos;
+ matrix4x4d frameTrans;
+ Frame::GetFrameTransform(GetFrame(), camFrame, frameTrans);
+
+ vector3d pos = GetPosition();
+ pos = L3D::world_view->viewingRotation * frameTrans * pos;
Vector p; p.x = pos.x; p.y = pos.y; p.z = -pos.z;
matrix4x4d rot;
rot.LoadFromOdeMatrix(dGeomGetRotation(geoms[0]));
- rot = L3D::world_view->viewingRotation * rot;
+ rot = L3D::world_view->viewingRotation * frameTrans * rot;
Matrix m;
m.x1 = rot[0]; m.x2 = rot[4]; m.x3 = -rot[8];
m.y1 = rot[1]; m.y2 = rot[5]; m.y3 = -rot[9];
diff --git a/src/model_body.h b/src/model_body.h
index d772ba6..78d6088 100644
--- a/src/model_body.h
+++ b/src/model_body.h
@@ -12,7 +12,7 @@ public:
ModelBody(void);
virtual ~ModelBody(void);
void SetPosition(vector3d p);
- virtual void SetRotation(const matrix4x4d& r);
+ virtual void SetRotMatrix(const matrix4x4d& r);
/* Not valid to SetVelocity on these. If you want them to move, use a DynamicBody. */
vector3d GetPosition(void);
virtual double GetRadius(void) const;
diff --git a/src/space.cpp b/src/space.cpp
index d9062dc..a4ef3f1 100644
--- a/src/space.cpp
+++ b/src/space.cpp
@@ -50,6 +50,7 @@ void Space::MoveOrbitingObjectFrames(Frame* f) {
f->SetPosition(pos);
f->SetVelocity(vel);
}
+ f->RotateInTimestep(L3D::GetTimeStep());
for(std::list::iterator i = f->m_children.begin(); i != f->m_children.end(); ++i) {
MoveOrbitingObjectFrames(*i);
@@ -117,13 +118,27 @@ void Space::UpdateFramesOfReference(void) {
if(!b->GetFrame()->IsLocalPosInFrame(b->GetPosition())) {
printf("%s leaves frame %s\n", b->GetLabel().c_str(), b->GetFrame()->GetLabel());
- b->SetVelocity(b->GetVelocity() + b->GetFrame()->GetVelocity());
+ vector3d oldFrameVel = b->GetFrame()->GetVelocity();
Frame* new_frame = b->GetFrame()->m_parent;
if(new_frame) { /* Don't fall out of root frame. */
- vector3d new_pos = b->GetPositionRelTo(new_frame);
+ matrix4x4d m = matrix4x4d::Identity();
+ b->GetFrame()->ApplyLeavingTransform(m);
+
+ vector3d new_pos = m * b->GetPosition();
+
+ matrix4x4d rot;
+ b->GetRotMatrix(rot);
+ b->SetRotMatrix(m * rot);
+
b->SetFrame(new_frame);
b->SetPosition(new_pos);
+
+ /* Get rid of transforms. */
+ m.ClearToRotOnly();
+ b->SetVelocity(m*b->GetVelocity() + oldFrameVel);
+ } else {
+ b->SetVelocity(b->GetVelocity() + oldFrameVel);
}
}
@@ -131,12 +146,21 @@ void Space::UpdateFramesOfReference(void) {
for(std::list::iterator j = b->GetFrame()->m_children.begin();
j != b->GetFrame()->m_children.end(); ++j) {
Frame* child = *j;
- vector3d pos = b->GetFrame()->GetPosRelativeToOtherFrame(child) + b->GetPosition();
+ matrix4x4d m;
+ Frame::GetFrameTransform(b->GetFrame(), child, m);
+ vector3d pos = m * b->GetPosition();
if(child->IsLocalPosInFrame(pos)) {
printf("%s enters frame %s\n", b->GetLabel().c_str(), child->GetLabel());
b->SetPosition(pos);
b->SetFrame(child);
- b->SetVelocity(b->GetVelocity() - child->GetVelocity());
+
+ matrix4x4d rot;
+ b->GetRotMatrix(rot);
+ b->SetRotMatrix(m * rot);
+
+ /* Get rid of transforms. */
+ m.ClearToRotOnly();
+ b->SetVelocity(m*b->GetVelocity()-child->GetVelocity());
break;
}
}
diff --git a/src/space_station.cpp b/src/space_station.cpp
index 60a0c04..4db8b58 100644
--- a/src/space_station.cpp
+++ b/src/space_station.cpp
@@ -57,8 +57,6 @@ void SpaceStation::GetDockingSurface(CollMeshSet* mset, int midx) {
SpaceStation::SpaceStation(void) : ModelBody() {
SetModel(STATION_SBRE_MODEL);
- matrix4x4d m = matrix4x4d::RotateYMatrix(M_PI-M_PI/6);
- SetRotation(m);
CollMeshSet* mset = GetModelCollMeshSet(STATION_SBRE_MODEL);
for(unsigned int i = 0; i < geomColl.size(); i++) {
diff --git a/src/world_view.cpp b/src/world_view.cpp
index d261847..a5df94e 100644
--- a/src/world_view.cpp
+++ b/src/world_view.cpp
@@ -109,7 +109,9 @@ void WorldView::Draw3D(void) {
glCallList(m_bgstarsDlist);
/* Position light at sol. */
- vector3d lpos = vector3d::Normalize(Frame::GetFramePosRelativeToOther(Space::GetRootFrame(), &cam_frame));
+ matrix4x4d m;
+ Frame::GetFrameTransform(Space::GetRootFrame(), &cam_frame, m);
+ vector3d lpos = vector3d::Normalize(m*vector3d(0,0,0));
float lightPos[4];
lightPos[0] = lpos.x;
lightPos[1] = lpos.y;