diff --git a/src/collider/geom.cpp b/src/collider/geom.cpp
index 83c1efd..10a34da 100644
--- a/src/collider/geom.cpp
+++ b/src/collider/geom.cpp
@@ -14,6 +14,12 @@ Geom::Geom(GeomTree* geomtree) {
   m_data = 0;
 }
 
+matrix4x4d Geom::GetRotation(void) const {
+  matrix4x4d m = GetTransform();
+  m[12] = 0; m [13] = 0; m[14] = 0;
+  return m;
+}
+
 void Geom::MoveTo(const matrix4x4d& m) {
   m_orientIdx = !m_orientIdx;
   m_orient[m_orientIdx] = m;
diff --git a/src/collider/geom.h b/src/collider/geom.h
index c6d8ebd..c4893ef 100644
--- a/src/collider/geom.h
+++ b/src/collider/geom.h
@@ -12,8 +12,9 @@ public:
   Geom(GeomTree*);
   void MoveTo(const matrix4x4d& m);
   void MoveTo(const matrix4x4d& m, const vector3d pos);
-  const matrix4x4d& GetInvTransform(void) { return m_invOrient; }
-  const matrix4x4d& GetTransform(void) { return m_orient[m_orientIdx]; }
+  const matrix4x4d& GetInvTransform(void) const { return m_invOrient; }
+  const matrix4x4d& GetTransform(void) const { return m_orient[m_orientIdx]; }
+  matrix4x4d GetRotation(void) const;
   vector3d GetPosition(void) const;
   void Enable(void) { m_active = true; }
   void Disable(void) {m_active = false; }
diff --git a/src/dynamic_body.cpp b/src/dynamic_body.cpp
index 8245cfc..736b06b 100644
--- a/src/dynamic_body.cpp
+++ b/src/dynamic_body.cpp
@@ -27,6 +27,22 @@ void DynamicBody::Load(void) {
   SetVelocity(rd_vector3d());
 }
 
+void DynamicBody::SetPosition(vector3d p) {
+  dBodySetPosition(m_body, p.x, p.y, p.z);
+  ModelBody::SetPosition(p);
+}
+
+void DynamicBody::TimeStepUpdate(const float timeStep) {
+  matrix4x4d t;
+  GetRotMatrix(t);
+  const dReal* v = dBodyGetPosition(m_body);
+  t[12] = v[0];
+  t[13] = v[1];
+  t[14] = v[2];
+
+  TriMeshUpdateLastPos(t);
+}
+
 void DynamicBody::Enable(void) {
   ModelBody::Enable();
   dBodyEnable(m_body);
diff --git a/src/dynamic_body.h b/src/dynamic_body.h
index 769151b..60dd210 100644
--- a/src/dynamic_body.h
+++ b/src/dynamic_body.h
@@ -14,6 +14,7 @@ public:
   virtual void SetRotMatrix(const matrix4x4d& r);
   virtual void GetRotMatrix(matrix4x4d& m);
   virtual void SetVelocity(vector3d v);
+  virtual void SetPosition(vector3d p);
   virtual vector3d GetVelocity(void);
   vector3d GetAngVelocity(void);
   void SetAngVelocity(vector3d v);
@@ -24,6 +25,7 @@ public:
   virtual void Disable(void);
   virtual void Enable(void);
   virtual double GetMass(void) const { return m_mass.mass; }
+  virtual void TimeStepUpdate(const float timeStep);
 
   dBodyID m_body;
   dMass   m_mass;
diff --git a/src/model_body.cpp b/src/model_body.cpp
index 75f01af..5d3bc69 100644
--- a/src/model_body.cpp
+++ b/src/model_body.cpp
@@ -10,16 +10,13 @@
 #include "collider/collider.h"
 
 ModelBody::ModelBody(void): Body() {
-  m_triMeshLastMatrixIndex = 0;
   m_collMeshSet = 0;
   m_geom = 0;
 }
 
 ModelBody::~ModelBody(void) {
   SetFrame(0); /* Will remove geom from frame if necessary. */
-  for(unsigned int i = 0; i < geoms.size(); i++) {
-    dGeomDestroy(geoms[i]);
-  }
+  delete m_geom;
 }
 
 void ModelBody::Save(void) {
@@ -33,21 +30,14 @@ void ModelBody::Load(void) {
 }
 
 void ModelBody::Disable(void) {
-  for(unsigned int i = 0; i < geoms.size(); i++) {
-    dGeomDisable(geoms[i]);
-  }
+  m_geom->Disable();
 }
 
 void ModelBody::Enable(void) {
-  for(unsigned int i = 0; i < geoms.size(); i++) {
-    dGeomEnable(geoms[i]);
-  }
+  m_geom->Enable();
 }
 
 void ModelBody::GeomsSetBody(dBodyID body) {
-  for(unsigned int i = 0; i < geoms.size(); i++) {
-    dGeomSetBody(geoms[i], body);
-  }
 }
 
 void ModelBody::GetAabb(Aabb& aabb) {
@@ -55,22 +45,12 @@ void ModelBody::GetAabb(Aabb& aabb) {
 }
 
 void ModelBody::SetModel(int sbreModel) {
-  assert(geoms.size() == 0);
   assert(m_geom == 0);
   CollMeshSet* mset = GetModelCollMeshSet(sbreModel);
 
   m_geom = new Geom(mset->m_geomTree);
   m_geom->SetUserData((void*)this);
 
-  geomColl.resize(mset->numMeshParts);
-  geoms.resize(mset->numMeshParts);
-
-  for(int i = 0; i < mset->numMeshParts; i++) {
-    geoms[i] = dCreateTriMesh(0, mset->meshParts[i], NULL, NULL, NULL);
-    geomColl[i].parent = this;
-    geomColl[i].flags = mset->meshInfo[i].flags;
-    dGeomSetData(geoms[i], static_cast<Object*>(&geomColl[i]));
-  }
   m_collMeshSet = mset;
 }
 
@@ -79,109 +59,50 @@ void ModelBody::SetPosition(vector3d p) {
   GetRotMatrix(m);
   m_geom->MoveTo(m, p);
   m_geom->MoveTo(m, p);
-
-  for(unsigned int i = 0; i < geoms.size(); i++) {
-    dGeomSetPosition(geoms[i], p.x, p.y, p.z);
-  }
 }
 
 vector3d ModelBody::GetPosition(void) const {
-  const dReal* pos = dGeomGetPosition(geoms[0]);
-  return vector3d(pos[0], pos[1], pos[2]);
+  return m_geom->GetPosition();
 }
 
 double ModelBody::GetRadius(void) const {
-  /* Calculate single AABB containing all geoms. */
-  dReal aabbAll[6] = {
-    std::numeric_limits<double>::max(),
-    std::numeric_limits<double>::min(),
-    std::numeric_limits<double>::max(),
-    std::numeric_limits<double>::min(),
-    std::numeric_limits<double>::max(),
-    std::numeric_limits<double>::min()
-  };
-
-  for(size_t i = 0; i < geoms.size(); ++i) {
-    dReal aabbGeom[6];
-    dGeomGetAABB(geoms[i], aabbGeom);
-    aabbAll[0] = std::min(aabbAll[0], aabbGeom[0]);
-    aabbAll[1] = std::max(aabbAll[1], aabbGeom[1]);
-    aabbAll[2] = std::min(aabbAll[2], aabbGeom[2]);
-    aabbAll[3] = std::max(aabbAll[3], aabbGeom[3]);
-    aabbAll[4] = std::min(aabbAll[4], aabbGeom[4]);
-    aabbAll[5] = std::max(aabbAll[5], aabbGeom[5]);
-  }
+  Aabb aabb = m_geom->GetGeomTree()->GetAabb();
 
   /* Return size of largest dimension. */
-  return std::max(aabbAll[1] - aabbAll[0], std::max(aabbAll[3] - aabbAll[2], aabbAll[5] - aabbAll[4]));
+  return std::max(aabb.max.x - aabb.min.x, std::max(aabb.max.y, aabb.max.z - aabb.min.z));
 }
 
 void ModelBody::SetRotMatrix(const matrix4x4d& r) {
-  dMatrix3 _m;
-  r.SaveToOdeMatrix(_m);
-  for(unsigned int i = 0; i < geoms.size(); i++) {
-    dGeomSetRotation(geoms[i], _m);
-  }
   vector3d pos = m_geom->GetPosition();
   m_geom->MoveTo(r, pos);
   m_geom->MoveTo(r, pos);
 }
 
 void ModelBody::GetRotMatrix(matrix4x4d& m) const {
-  m.LoadFromOdeMatrix(dGeomGetRotation(geoms[0]));
+  m = m_geom->GetRotation();
 }
 
 void ModelBody::TransformToModelCoords(const Frame* camFrame) {
-  const vector3d pos = GetPosition();
-  const dReal* r = dGeomGetRotation(geoms[0]);
-  matrix4x4d m, m2;
-
+  matrix4x4d m = m_geom->GetTransform();
+  matrix4x4d m2;
   Frame::GetFrameTransform(GetFrame(), camFrame, m2);
 
-  m[ 0] = r[ 0]; m[ 1] = r[ 4]; m[ 2] = r[ 8]; m[ 3] = 0;
-  m[ 4] = r[ 1]; m[ 5] = r[ 5]; m[ 6] = r[ 9]; m[ 7] = 0;
-  m[ 8] = r[ 2]; m[ 9] = r[ 6]; m[10] = r[10]; m[11] = 0;
-  m[12] = pos.x; m[13] = pos.y; m[14] = pos.z; m[15] = 1;
-
   m = m2 * m;
   glMultMatrixd(&m[0]);
 }
 
 void ModelBody::SetFrame(Frame* f) {
   if(GetFrame()) {
-    for(unsigned int i = 0; i < geoms.size(); i++) {
-      GetFrame()->_RemoveGeom(geoms[i]);
-    }
     GetFrame()->RemoveGeom(m_geom);
   }
   Body::SetFrame(f);
   if(f) {
-    for(unsigned int i = 0; i < geoms.size(); i++) {
-      f->_AddGeom(geoms[i]);
-    }
     f->AddGeom(m_geom);
   }
 }
 
-void ModelBody::TriMeshUpdateLastPos(void) {
-  /* ODE tri mesh likes to know our old position. */
-  const dReal* r = dGeomGetRotation(geoms[0]);
-  vector3d pos = GetPosition();
-  dReal* t = m_triMeshTrans + 16*m_triMeshLastMatrixIndex;
-  t[ 0] = r[0]; t[1] = r[1]; t[ 2] = r[ 2]; t[ 3] = 0;
-  t[ 4] = r[4]; t[5] = r[5]; t[ 6] = r[ 6]; t[ 7] = 0;
-  t[ 8] = r[8]; t[9] = r[9]; t[10] = r[10]; t[11] = 0;
-  t[12] = pos.x; t[13] = pos.y; t[14] = pos.z; t[15] = 1;
-
-  /* REESTED! */
-  matrix4x4d wtf;
-  memcpy(&wtf[0], t, 16*sizeof(double));
-  m_geom->MoveTo(wtf);
-
-  m_triMeshLastMatrixIndex = !m_triMeshLastMatrixIndex;
-  for(unsigned int i = 0; i < geoms.size(); i++) {
-    dGeomTriMeshSetLastTransform(geoms[i], *(dMatrix4*)(m_triMeshTrans + 16*m_triMeshLastMatrixIndex));
-  }
+void ModelBody::TriMeshUpdateLastPos(matrix4x4d currentTransform) {
+  m_geom->MoveTo(currentTransform);
 }
 
 void ModelBody::RenderSbreModel(const Frame* camFrame, int model, ObjParams* params) {
@@ -211,7 +132,7 @@ void ModelBody::RenderSbreModel(const Frame* camFrame, int model, ObjParams* par
   pos = frameTrans * pos;
   Vector p; p.x = pos.x; p.y = pos.y; p.z = -pos.z;
   matrix4x4d rot;
-  rot.LoadFromOdeMatrix(dGeomGetRotation(geoms[0]));
+  GetRotMatrix(rot);
   frameTrans.ClearToRotOnly();
   rot = frameTrans * rot;
   Matrix m;
diff --git a/src/model_body.h b/src/model_body.h
index 45de130..6b6ed4e 100644
--- a/src/model_body.h
+++ b/src/model_body.h
@@ -28,7 +28,7 @@ public:
   virtual void Enable(void);
   void GetAabb(Aabb& aabb);
 
-  void TriMeshUpdateLastPos(void);
+  void TriMeshUpdateLastPos(matrix4x4d currentTransform);
   void SetModel(int sbreModel);
 
   void RenderSbreModel(const Frame* camFrame, int model, ObjParams* params);
@@ -42,12 +42,8 @@ public:
 protected:
   virtual void Save(void);
   virtual void Load(void);
-  std::vector<GeomBit> geomColl;
 private:
   CollMeshSet* m_collMeshSet;
-  std::vector<dGeomID> geoms;
   Geom* m_geom;
-  dReal m_triMeshTrans[32];
-  int m_triMeshLastMatrixIndex;
 };
 
diff --git a/src/ship.cpp b/src/ship.cpp
index 4f7f142..27a1d9d 100644
--- a/src/ship.cpp
+++ b/src/ship.cpp
@@ -252,9 +252,9 @@ void Ship::TestLanded(void) {
 }
 
 void Ship::TimeStepUpdate(const float timeStep) {
+  DynamicBody::TimeStepUpdate(timeStep);
+
   m_dockingTimer = (m_dockingTimer-timeStep > 0 ? m_dockingTimer-timeStep : 0);
-  /* ODE tri mesh likes to know our old position. */
-  TriMeshUpdateLastPos();
 
   m_launchLockTimeout -= timeStep;
   if(m_launchLockTimeout < 0) m_launchLockTimeout = 0;
diff --git a/src/space_station.cpp b/src/space_station.cpp
index 8bd707b..308fa90 100644
--- a/src/space_station.cpp
+++ b/src/space_station.cpp
@@ -52,7 +52,6 @@ void SpaceStation::GetDockingSurface(CollMeshSet* mset, int midx) {
 
   assert(m_numPorts <= MAX_DOCKING_PORTS);
   assert((minfo->flags & 0xf) < MAX_DOCKING_PORTS);
-  assert(minfo->flags & 0x10);
   assert(minfo->numTris);
   
   dport->center = vector3d(0.0);
@@ -97,11 +96,8 @@ void SpaceStation::Init(void) {
   SetModel(sbreModel);
 
   CollMeshSet* mset = GetModelCollMeshSet(sbreModel);
-  for(unsigned int i = 0; i < geomColl.size(); i++) {
-    if(geomColl[i].flags & 0x10) {
-      /* Docking surface. */
-      GetDockingSurface(mset, i);
-    }
+  for(int i = 0; i < mset->numMeshParts; i++) {
+    if(mset->meshInfo[i].flags & 0x10) GetDockingSurface(mset, i);
   }
 }