diff --git a/src/body.h b/src/body.h
index c8ac8e6..126b5ca 100644
--- a/src/body.h
+++ b/src/body.h
@@ -31,7 +31,7 @@ public:
   const vector3d& GetProjectedPos() const;
   bool IsOnscreen() const { return m_onscreen; }
   void SetOnscreen(const bool onscreen) { m_onscreen = onscreen; }
-
+  virtual void TimeStepUpdate(const float timeStep) {}
   enum { FLAG_CAN_MOVE_FRAME = 1 };
 
 protected:
diff --git a/src/l3d.h b/src/l3d.h
index bd81df3..0ef1e5a 100644
--- a/src/l3d.h
+++ b/src/l3d.h
@@ -41,8 +41,9 @@ public:
   static void   Quit(void);
   static float  GetFrameTime(void)            { return frameTime; }
   static double GetGameTime(void)             { return gameTime; }
-  static void   SetTimeStep(float s)          { timeStep = s; }
-  static float  GetTimeStep(void)             { return timeStep; }
+  static void   SetTimeAccel(float s)         { timeAccel = s; }
+  static float  GetTimeAccel(void)            { return timeAccel; }
+  static float  GetTimeStep(void)             { return timeAccel*frameTime; }
   static int    GetScrWidth(void)             { return scrWidth; }
   static int    GetScrHeight(void)            { return scrHeight; }
   static int    GetScrAspect(void)            { return scrAspect; }
@@ -91,7 +92,7 @@ private:
   static StarSystem*  selected_system;
   static enum CamType cam_type;
   static enum MapView map_view;
-  static float        timeStep;
+  static float        timeAccel;
   static float        frameTime;
   static int          scrWidth, scrHeight;
   static float        scrAspect;
diff --git a/src/main.cpp b/src/main.cpp
index 44af530..ca85ebd 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -18,7 +18,7 @@
 #include "space_station_view.h"
 #include "info_view.h"
 
-float             L3D::timeStep = 1.0f;
+float             L3D::timeAccel = 1.0f;
 int               L3D::scrWidth;
 int               L3D::scrHeight;
 float             L3D::scrAspect;
@@ -199,7 +199,7 @@ void L3D::MainLoop(void) {
     snprintf(buf, sizeof(buf), "X%c-0%02d", "A"+i, i);
     body->SetLabel(buf);
     body->SetFrame(earth_frame);
-    body->SetPosition(vector3d(i*200, 0, -200));
+    body->SetPosition(vector3d(i*2000, 0, -400));
     Space::AddBody(body);
   }
 
@@ -207,7 +207,7 @@ void L3D::MainLoop(void) {
     SpaceStation* body = new SpaceStation();
     body->SetLabel("Some Back Country Joint");
     body->SetFrame(earth_frame);
-    body->SetPosition(vector3d(0, 0, 6000));
+    body->SetPosition(vector3d(0, 0, 600));
     Space::AddBody(body);
   }
 
@@ -290,7 +290,7 @@ void L3D::MainLoop(void) {
     //if(glGetError()) printf("GL: %s\n", gluErrorString(glGetError()));
 
     L3D::frameTime = 0.001*(SDL_GetTicks() - time_before_frame);
-    float step = L3D::timeStep * L3D::frameTime;
+    float step = L3D::timeAccel * L3D::frameTime;
 
     time_before_frame = SDL_GetTicks();
     /* Game state update stuff. */
diff --git a/src/player.cpp b/src/player.cpp
index 82967e7..7577e6a 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -53,24 +53,25 @@ void Player::ApplyExternalViewRotation(void) {
 }
 
 #define MOUSE_CTRL_AREA   10.0f
-#define MOUSE_RESTITUTION 0.9f
+#define MOUSE_RESTITUTION 0.01f
 
-void Player::AITurn(void) {
+void Player::PollControls(void) {
   int mouseMotion[2];
-  float time_step = L3D::GetTimeStep();
-  float ts2 = time_step*time_step;
-  
+  float time_accel = L3D::GetTimeAccel();
+  float ta2 = time_accel*time_accel;
+
   SetAngThrusterState(0, 0.0f);
   SetAngThrusterState(1, 0.0f);
   SetAngThrusterState(2, 0.0f);
 
-  if(time_step == 0)  return;
-  if(GetDockedWith()) return;
+  if((time_accel == 0) || GetDockedWith()) {
+    return;
+  }
 
   vector3f angThrust(0.0f);
 
   if(L3D::MouseButtonState(3)) {
-    float restitution = powf(MOUSE_RESTITUTION, time_step);
+    float restitution = powf(MOUSE_RESTITUTION, L3D::GetTimeStep());
     L3D::GetMouseMotion(mouseMotion);
     m_mouseCMov[0] += mouseMotion[0];
     m_mouseCMov[1] += mouseMotion[1];
@@ -93,7 +94,7 @@ void Player::AITurn(void) {
   else SetGunState(0,0);
 
   /* No torques at huge time accels -- ODE hates it. */
-  if(time_step <= 10) {
+  if(time_accel <= 10) {
     if(L3D::GetCamType() != L3D::CAM_EXTERNAL) {
       if(L3D::KeyState(SDLK_LEFT))  angThrust.y +=  1;
       if(L3D::KeyState(SDLK_RIGHT)) angThrust.y += -1;
@@ -107,7 +108,7 @@ void Player::AITurn(void) {
     GetRotMatrix(rot);
     angVel = rot.InverseOf() * angVel;
 
-    angVel *= 0.4;
+    angVel *= 0.6;
     angThrust.x -= angVel.x;
     angThrust.y -= angVel.y;
     angThrust.z -= angVel.z;
@@ -116,12 +117,12 @@ void Player::AITurn(void) {
      * Divided by time step so controls don't go totally insane when
      * used at 10x accel.
      */
-    angThrust *= 1.0f/ts2;
+    angThrust *= 1.0f/ta2;
     SetAngThrusterState(0, angThrust.x);
     SetAngThrusterState(1, angThrust.y);
     SetAngThrusterState(2, angThrust.z);
   }
-  if(time_step > 10) {
+  if(time_accel > 10) {
     dBodySetAngularVel(m_body, 0, 0, 0);
   }
   if(L3D::GetCamType() == L3D::CAM_EXTERNAL) {
@@ -133,7 +134,6 @@ void Player::AITurn(void) {
     if(L3D::KeyState(SDLK_MINUS))  m_external_view_dist += 10;
     m_external_view_dist = MAX(50, m_external_view_dist);
   }
-  Ship::AITurn();
 }
 
 #define HUD_CROSSHAIR_SIZE  24.0f
diff --git a/src/player.h b/src/player.h
index 37c010d..a45e161 100644
--- a/src/player.h
+++ b/src/player.h
@@ -5,7 +5,7 @@
 class Player : public Ship {
 public:
   Player(ShipType::Type shipType);
-  virtual void AITurn();
+  void PollControls(void);
   virtual void Render(const Frame* camFrame);
   void DrawHUD(const Frame* cam_frame);
   virtual void SetDockedWith(SpaceStation*);
diff --git a/src/rigid_body.cpp b/src/rigid_body.cpp
index 9a6cc37..71f7adf 100644
--- a/src/rigid_body.cpp
+++ b/src/rigid_body.cpp
@@ -13,6 +13,21 @@ RigidBody::RigidBody(void) : StaticRigidBody() {
   dBodySetMass(m_body, &m_mass);
 }
 
+void RigidBody::SetMassDistributionFromCollMesh(const CollMesh* m) {
+  vector3d min = vector3d(FLT_MAX);
+  vector3d max = vector3d(-FLT_MAX);
+  for(int i = 0; i < 3*m->nv; i += 3) {
+    min.x = MIN(m->pVertex[i],    min.x);
+    min.y = MIN(m->pVertex[i+1],  min.y);
+    min.z = MIN(m->pVertex[i+2],  min.z);
+    max.x = MAX(m->pVertex[i],    max.x);
+    max.y = MAX(m->pVertex[i+1],  max.y);
+    max.z = MAX(m->pVertex[i+2],  max.z);
+  }
+  dMassSetBox(&m_mass, 1, max.x-min.x, max.y-min.y, max.z-min.z);
+  dBodySetMass(m_body, &m_mass);
+}
+
 vector3d RigidBody::GetAngularMomentum(void) {
   matrix4x4d I;
   I.LoadFromOdeMatrix(m_mass.I);
diff --git a/src/rigid_body.h b/src/rigid_body.h
index 6aae5ac..4a3c8a4 100644
--- a/src/rigid_body.h
+++ b/src/rigid_body.h
@@ -15,6 +15,7 @@ public:
   void SetMesh(ObjMesh* m);
   virtual bool OnCollision(Body* b) { return true; }
   vector3d GetAngularMomentum(void);
+  void SetMassDistributionFromCollMesh(const CollMesh* m);
 
   dBodyID m_body;
   dMass   m_mass;
diff --git a/src/sbre/brender.cpp b/src/sbre/brender.cpp
index 7203614..71c34a1 100644
--- a/src/sbre/brender.cpp
+++ b/src/sbre/brender.cpp
@@ -88,7 +88,7 @@ static void ResolveVertices(Model* pMod, Vector* pRes, ObjParams* pObjParam) {
 
 static float g_dn, g_df, g_sd;
 static int g_wireframe = 0;
-float SBRE_ZBIAS = 0;
+float SBRE_ZBIAS = 0.00002f;
 
 void sbreSetZBias(float zbias) {
   SBRE_ZBIAS = zbias;
diff --git a/src/ship.cpp b/src/ship.cpp
index f2bc78a..cb56faa 100644
--- a/src/ship.cpp
+++ b/src/ship.cpp
@@ -37,7 +37,9 @@ Ship::Ship(ShipType::Type shipType) : RigidBody() {
   memset(m_thrusters, 0, sizeof(m_thrusters)); 
   const ShipType& stype = GetShipType();
   SetGeomFromSBREModel(stype.sbreModel, &params);
+  SetMassDistributionFromCollMesh(sbreCollMesh);
   dGeomSetBody(m_geom, m_body);
+  UpdateMass();
 }
 
 void Ship::UpdateMass(void) {
@@ -77,11 +79,10 @@ void Ship::CalcStats(shipstats_t* stats) {
   stats->hyperspace_range = 200 * hyperclass * hyperclass / stats->total_mass;
 }
 
-void Ship::AITurn(void) {
+void Ship::TimeStepUpdate(const float timeStep) {
   /* ODE tri mesh likes to know our old position. */
   TriMeshUpdateLastPos();
   const ShipType& stype = GetShipType();
-  float timeStep = L3D::GetTimeStep();
   for(int i = 0; i < ShipType::THRUSTER_MAX; i++) {
     float force = timeStep * stype.linThrust[i] * m_thrusters[i];
     switch(i) {
@@ -172,7 +173,6 @@ void Ship::RenderLaserfire(void) {
   glEnable(GL_LIGHTING);
 }
 
-#if 0
 static void render_coll_mesh(const CollMesh* m) {
   glDisable(GL_LIGHTING);
   glColor3f(1, 0, 1);
@@ -183,9 +183,18 @@ static void render_coll_mesh(const CollMesh* m) {
     glVertex3fv(&m->pVertex[3*m->pIndex[i+2]]);
   }
   glEnd();
+  glColor3f(1,1,1);
+  glDepthRange(0, 1.0f-0.0002f);
+  for(int i = 0; i < m->ni; i += 3) {
+    glBegin(GL_LINE_LOOP);
+      glVertex3fv(&m->pVertex[3*m->pIndex[i]]);
+      glVertex3fv(&m->pVertex[3*m->pIndex[i+1]]);
+      glVertex3fv(&m->pVertex[3*m->pIndex[i+2]]);
+    glEnd();
+  }
+  glDepthRange(0.0, 1.0);
   glEnable(GL_LIGHTING);
 }
-#endif
 
 void Ship::Render(const Frame* camFrame) {
   const ShipType& stype = GetShipType();
@@ -208,6 +217,7 @@ void Ship::Render(const Frame* camFrame) {
   
   glPushMatrix();
   TransformToModelCoords(camFrame);
+  //render_coll_mesh(sbreCollMesh);
   RenderLaserfire();
   glPopMatrix();
 }
diff --git a/src/ship.h b/src/ship.h
index 6a9d400..f9c92e7 100644
--- a/src/ship.h
+++ b/src/ship.h
@@ -17,7 +17,6 @@ struct shipstats_t {
 class Ship : public RigidBody {
 public:
   Ship(ShipType::Type shipType);
-  virtual void AITurn(void);
   virtual Object::Type GetType(void) { return Object::SHIP; }
   virtual void SetDockedWith(SpaceStation*);
   SpaceStation* GetDockedWith(void) { return m_dockedWith; }
@@ -32,6 +31,7 @@ public:
   void CalcStats(shipstats_t* stats);
   void UpdateMass(void);
   void SetWheelState(bool down);
+  virtual void TimeStepUpdate(const float timeStep);
 
   class LaserObj : public Object {
   public:
diff --git a/src/ship_cpanel.cpp b/src/ship_cpanel.cpp
index 154add6..ee06ec5 100644
--- a/src/ship_cpanel.cpp
+++ b/src/ship_cpanel.cpp
@@ -107,7 +107,7 @@ void ShipCpanel::OnChangeMapView(Gui::MultiStateImageButton* b) {
 }
 
 void ShipCpanel::OnClickTimeaccel(Gui::ISelectable* i, double step) {
-  L3D::SetTimeStep(step);
+  L3D::SetTimeAccel(step);
 }
 
 void ShipCpanel::OnClickComms(void) {
diff --git a/src/ship_type.cpp b/src/ship_type.cpp
index fc30184..f2870b3 100644
--- a/src/ship_type.cpp
+++ b/src/ship_type.cpp
@@ -7,7 +7,7 @@ const ShipType ShipType::types[] = {
      * Sirius corporation make a range of lovely ships!
      */
     "Sirius Interdictor", 61,
-    { 1e7, -1e7, 1e6, -1e6, -1e6, 1e6 },
+    { 1e8, -1e8, 1e7, -1e6, -1e7, 1e7 },
     1e7,
     {
       { vector3f(0, -0.5, 0), vector3f(0, 0, -1) },
diff --git a/src/space.cpp b/src/space.cpp
index bd9cfa0..6d3d290 100644
--- a/src/space.cpp
+++ b/src/space.cpp
@@ -156,7 +156,7 @@ static void nearCallback(void* data, dGeomID oO, dGeomID o1) {
     contact[i].surface.mode       = dContactBounce;
     contact[i].surface.mu         = 0;
     contact[i].surface.mu2        = 0;
-    contact[i].surface.bounce     = 0;
+    contact[i].surface.bounce     = 0.5;
     contact[i].surface.bounce_vel = 0.1;
   }
   if(int numc = dCollide(oO, o1, MAX_CONTACTS, &contact[0].geom, sizeof(dContact))) {
@@ -178,6 +178,16 @@ static void nearCallback(void* data, dGeomID oO, dGeomID o1) {
        * finally create the temp contact joint between the two geom bodies.
        */
       dJointID c = dJointCreateContact(Space::world, _contactgroup, contact + i);
+      printf("Depth: %f\n", contact[i].geom.depth);
+#if 0
+      struct dContactGeom {
+        dVector3  pos;    /* Constact position. */
+        dVector3  normal; /* Normal vector. */
+        dReal     depth;  /* Penetration depth. */
+        dGeomId g1, g2;   /* The colliding geoms. */
+      };
+#endif
+
       dJointAttach(c, b1, b2);
     }
   }
@@ -192,12 +202,15 @@ void Space::CollideFrame(Frame* f) {
 
 void Space::TimeStep(float step) {
   CollideFrame(rootFrame);
-  //CollideFrame(L3D::player->GetFrame());
   dWorldQuickStep(world, step);
   dJointGroupEmpty(_contactgroup);
 
   /* TODO: Does not need to be done this often. */
   UpdateFramesOfReference();
+
+  for(bodiesIter_t i = bodies.begin(); i != bodies.end(); ++i) {
+    (*i)->TimeStepUpdate(step);
+  }
 }
 
 struct body_zsort_t {
diff --git a/src/space.h b/src/space.h
index cd3a4c7..8195557 100644
--- a/src/space.h
+++ b/src/space.h
@@ -20,6 +20,7 @@ public:
 
   static dWorldID world;
   static std::list<Body*> bodies;
+  typedef std::list<Body*>::iterator bodiesIter_t;
 private:
   static void UpdateFramesOfReference(void);
   static void CollideFrame(Frame* f);
diff --git a/src/space_station.cpp b/src/space_station.cpp
index 08c3ce0..a6a1683 100644
--- a/src/space_station.cpp
+++ b/src/space_station.cpp
@@ -22,15 +22,15 @@ static ObjParams params = {
 
 SpaceStation::SpaceStation(void) : StaticRigidBody() {
   SetGeomFromSBREModel(STATION_SBRE_MODEL, &params);
-  matrix4x4d m = matrix4x4d::RotateYMatrix(M_PI);
+  matrix4x4d m = matrix4x4d::RotateYMatrix(-M_PI/4);
   dMatrix3 _m;
   m.SaveToOdeMatrix(_m);
   dGeomSetRotation(m_geom, _m);
-  m_mesh = 0;
+  dGeomSetBody(m_geom, 0);
 }
 
 SpaceStation::~SpaceStation(void) {
-  //dGeomDestroy(m_geom);
+  dGeomDestroy(m_geom);
 }
 
 bool SpaceStation::OnCollision(Body* b) {
@@ -48,10 +48,6 @@ bool SpaceStation::OnCollision(Body* b) {
   }
 }
 
-void SpaceStation::SetMesh(ObjMesh* m) {
-  m_mesh = m;
-}
-
 void SpaceStation::Render(const Frame* camFrame) {
   RenderSbreModel(camFrame, STATION_SBRE_MODEL, &params);
 }
diff --git a/src/space_station.h b/src/space_station.h
index fb66114..6949654 100644
--- a/src/space_station.h
+++ b/src/space_station.h
@@ -9,8 +9,6 @@ public:
   virtual bool OnCollision(Body* b);
   virtual Object::Type GetType(void) { return Object::SPACESTATION; }
   virtual void Render(const Frame* camFrame);
-  void SetMesh(ObjMesh* m);
 protected:
-  ObjMesh* m_mesh;
 };
 
diff --git a/src/static_rigid_body.cpp b/src/static_rigid_body.cpp
index 3b264ba..33dcd78 100644
--- a/src/static_rigid_body.cpp
+++ b/src/static_rigid_body.cpp
@@ -9,6 +9,7 @@
 StaticRigidBody::StaticRigidBody(void): Body() {
   m_geom = 0;
   sbreCollMesh = 0;
+  triMeshLastMatrixIndex = 0;
 }
 
 StaticRigidBody::~StaticRigidBody(void) {
@@ -36,10 +37,26 @@ void StaticRigidBody::SetGeomFromSBREModel(int sbreModel, ObjParams* params) {
     sbreCollMesh->pVertex[i]    = -sbreCollMesh->pVertex[i];
     sbreCollMesh->pVertex[i+2]  = -sbreCollMesh->pVertex[i+2];
   }
+  /* Make normals. */
+  meshNormals = new float[sbreCollMesh->ni];
+  for(int i = 0; i < sbreCollMesh->ni; i += 3) {
+    float* vtx1 = sbreCollMesh->pVertex + 3*sbreCollMesh->pIndex[i];
+    float* vtx2 = sbreCollMesh->pVertex + 3*sbreCollMesh->pIndex[i+1];
+    float* vtx3 = sbreCollMesh->pVertex + 3*sbreCollMesh->pIndex[i+2];
+    vector3f v1(vtx1[0], vtx1[1], vtx1[2]);
+    vector3f v2(vtx2[0], vtx2[1], vtx2[2]);
+    vector3f v3(vtx3[0], vtx3[1], vtx3[2]);
+    vector3f n = vector3f::Cross(v1-v2, v1-v3);
+    n.Normalize();
+    meshNormals[i]    = n.x;
+    meshNormals[i+1]  = n.y;
+    meshNormals[i+2]  = n.z;
+
+  }
   dTriMeshDataID triMeshDataID = dGeomTriMeshDataCreate();
-  dGeomTriMeshDataBuildSingle(triMeshDataID, (void*)sbreCollMesh->pVertex,
+  dGeomTriMeshDataBuildSingle1(triMeshDataID, (void*)sbreCollMesh->pVertex,
           3*sizeof(float), sbreCollMesh->nv, (void*)sbreCollMesh->pIndex,
-          sbreCollMesh->ni, 3*sizeof(int));
+          sbreCollMesh->ni, 3*sizeof(int), NULL/*meshNormals*/);
 
   /* TODO: Leaking StaticRigidBody m_geom. */
   m_geom = dCreateTriMesh(0, triMeshDataID, NULL, NULL, NULL);
@@ -101,13 +118,13 @@ void StaticRigidBody::TriMeshUpdateLastPos(void) {
   /* ODE tri mesh likes to know our old position. */
   const dReal* r = dGeomGetRotation(m_geom);
   vector3d pos = GetPosition();
-  dMatrix4 t;
-  /* Row-major. */
-  t[0] = r[0]; t[1] = r[1]; t[ 2] = r[ 2]; t[ 3] = pos.x;
-  t[4] = r[4]; t[5] = r[5]; t[ 6] = r[ 6]; t[ 7] = pos.y;
-  t[8] = r[8]; t[9] = r[9]; t[10] = r[10]; t[11] = pos.z;
-  t[12] = t[13] = t[15] = 0;
-  dGeomTriMeshSetLastTransform(m_geom, t);
+  dReal* t = triMeshTrans + 16*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;
+  triMeshLastMatrixIndex = !triMeshLastMatrixIndex;
+  dGeomTriMeshSetLastTransform(m_geom, *(dMatrix4*)(triMeshTrans + 16*triMeshLastMatrixIndex));
 }
 
 void StaticRigidBody::RenderSbreModel(const Frame* camFrame, int model, ObjParams* params) {
diff --git a/src/static_rigid_body.h b/src/static_rigid_body.h
index 2fc2854..3e16343 100644
--- a/src/static_rigid_body.h
+++ b/src/static_rigid_body.h
@@ -30,5 +30,8 @@ public:
 protected:
   dGeomID m_geom;
   CollMesh* sbreCollMesh;
+  float* meshNormals;
+  dReal triMeshTrans[32];
+  int triMeshLastMatrixIndex;
 };
 
diff --git a/src/world_view.cpp b/src/world_view.cpp
index 896ffd7..c749955 100644
--- a/src/world_view.cpp
+++ b/src/world_view.cpp
@@ -110,7 +110,7 @@ void WorldView::Update(void) {
     m_hyperspaceButton->Hide();
   }
   /* Player control inputs. */
-  L3D::player->AITurn();
+  L3D::player->PollControls();
 }
 
 void WorldView::OnMouseDown(Gui::MouseButtonEvent* e) {