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<Frame*>::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> 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<T> 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<Frame*>::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<Frame*>::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;