From aa28ff95b34c9e98df5d6a8d4fabcf806e67c9a2 Mon Sep 17 00:00:00 2001
From: Allanis <allanis.saracraft.studios@gmail.com>
Date: Sat, 18 Nov 2017 18:18:31 +0000
Subject: [PATCH] [Add] Collisions using collision meshes.

---
 src/player.cpp            |  1 +
 src/rigid_body.cpp        |  2 --
 src/ship.cpp              | 57 ++++++++++++++++++++++++---------------
 src/ship.h                |  3 +--
 src/space.cpp             |  7 +++--
 src/space_station.cpp     | 41 +++++++++++++++-------------
 src/static_rigid_body.cpp | 49 ++++++++++++++++++++++++++++++---
 src/static_rigid_body.h   |  5 ++++
 8 files changed, 114 insertions(+), 51 deletions(-)

diff --git a/src/player.cpp b/src/player.cpp
index 9f2b61c..82967e7 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -157,6 +157,7 @@ void Player::DrawHUD(const Frame* cam_frame) {
 
   {
     for(std::list<Body*>::iterator i = Space::bodies.begin(); i != Space::bodies.end(); ++i) {
+      if((L3D::GetCamType() != L3D::CAM_EXTERNAL) && (*i == this)) continue;
       Body* b = *i;
       vector3d _pos = b->GetPositionRelTo(cam_frame);
       vector3d cam_coord = rot*_pos;
diff --git a/src/rigid_body.cpp b/src/rigid_body.cpp
index 00bde01..9a6cc37 100644
--- a/src/rigid_body.cpp
+++ b/src/rigid_body.cpp
@@ -11,8 +11,6 @@ RigidBody::RigidBody(void) : StaticRigidBody() {
   dMassAdjust(&m_mass, 1.0f);
 
   dBodySetMass(m_body, &m_mass);
-  dGeomSetBody(m_geom, m_body);
-  SetPosition(vector3d(0,0,0));
 }
 
 vector3d RigidBody::GetAngularMomentum(void) {
diff --git a/src/ship.cpp b/src/ship.cpp
index e9a03e1..e8ba68e 100644
--- a/src/ship.cpp
+++ b/src/ship.cpp
@@ -3,15 +3,29 @@
 #include "frame.h"
 #include "l3d.h"
 #include "world_view.h"
-#include "sbre/sbre.h"
 #include "space.h"
 
+static ObjParams params = {
+  { 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+  { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+  { 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f },
+
+  /* pColor[3] */
+  {
+    { { 1.0f, 0.0f, 1.0f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
+    { { 0.8f, 0.6f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
+    { { 0.5f, 0.5f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 }
+  },
+
+  /* pText[3][256] */
+  { "IR-L33T", "ME TOO" },
+};
+
 Ship::Ship(ShipType::Type shipType) : RigidBody() {
   m_wheelTransition = 0;
   m_wheelState = 0;
   m_dockedWith = 0;
   m_target = 0;
-  m_mesh = 0;
   m_shipType = shipType;
   m_angThrusters[0] = m_angThrusters[1] = m_angThrusters[2] = 0;
   m_laserCollisionObj.owner = this;
@@ -20,7 +34,9 @@ Ship::Ship(ShipType::Type shipType) : RigidBody() {
     m_tempLaserGeom[i] = 0;
     m_gunState[i] = 0;
   }
-  dGeomSetData(m_geom, static_cast<Body*>(this));
+  const ShipType& stype = GetShipType();
+  SetGeomFromSBREModel(stype.sbreModel, &params);
+  dGeomSetBody(m_geom, m_body);
 }
 
 void Ship::UpdateMass(void) {
@@ -61,6 +77,8 @@ void Ship::CalcStats(shipstats_t* stats) {
 }
 
 void Ship::AITurn(void) {
+  /* 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++) {
@@ -125,10 +143,6 @@ void Ship::SetDockedWith(SpaceStation* s) {
   }
 }
 
-void Ship::SetMesh(ObjMesh* m) {
-  m_mesh = m;
-}
-
 void Ship::SetGunState(int idx, int state) {
   m_gunState[idx] = state;
 }
@@ -157,20 +171,20 @@ void Ship::RenderLaserfire(void) {
   glEnable(GL_LIGHTING);
 }
 
-static ObjParams params = {
-  { 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-  { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-  { 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f },
-
-  /* pColor[3] */
-  {
-    { { 1.0f, 0.0f, 1.0f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
-    { { 0.8f, 0.6f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
-    { { 0.5f, 0.5f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 }
-  },
-  /* pText[3][256] */
-  { "IZ-L33T", "ME TOO" },
-};
+#if 0
+static void render_coll_mesh(const CollMesh* m) {
+  glDisable(GL_LIGHTING);
+  glColor3f(1, 0, 1);
+  glBegin(GL_TRIANGLES);
+  for(int i = 0; i < m->ni; i += 3) {
+    glVertex3fv(&m->pVertex[3*m->pIndex[i]]);
+    glVertex3fv(&m->pVertex[3*m->pIndex[i+1]]);
+    glVertex3fv(&m->pVertex[3*m->pIndex[i+2]]);
+  }
+  glEnd();
+  glEnable(GL_LIGHTING);
+}
+#endif
 
 void Ship::Render(const Frame* camFrame) {
   const ShipType& stype = GetShipType();
@@ -190,6 +204,7 @@ void Ship::Render(const Frame* camFrame) {
   strncpy(params.pText[0], GetLabel().c_str(), sizeof(params.pText));
 
   RenderSbreModel(camFrame, stype.sbreModel, &params);
+  
   glPushMatrix();
   TransformToModelCoords(camFrame);
   RenderLaserfire();
diff --git a/src/ship.h b/src/ship.h
index a5e54d1..6a9d400 100644
--- a/src/ship.h
+++ b/src/ship.h
@@ -2,6 +2,7 @@
 #include "libs.h"
 #include "rigid_body.h"
 #include "ship_type.h"
+#include "sbre/sbre.h"
 
 class SpaceStation;
 
@@ -23,7 +24,6 @@ public:
   void SetTarget(Body* const target) { m_target = target; }
   Body* GetTarget(void) const { return m_target; }
   virtual void Render(const Frame* camFrame);
-  void SetMesh(ObjMesh* m);
   void SetThrusterState(enum ShipType::Thruster t, float level);
   void SetAngThrusterState(int axis, float level) { m_angThrusters[axis] = CLAMP(level, -1, 1); }
   void ClearThrusterState(void);
@@ -45,7 +45,6 @@ protected:
   
   SpaceStation* m_dockedWith;
   enum ShipType::Type m_shipType;
-  ObjMesh* m_mesh;
   Uint32 m_gunState[ShipType::GUNMOUNT_MAX];
 private:
   float m_wheelState;
diff --git a/src/space.cpp b/src/space.cpp
index 7ca99e5..bd9cfa0 100644
--- a/src/space.cpp
+++ b/src/space.cpp
@@ -153,12 +153,11 @@ static void nearCallback(void* data, dGeomID oO, dGeomID o1) {
   dContact contact[MAX_CONTACTS];
 
   for(int i = 0; i < MAX_CONTACTS; i++) {
-    contact[i].surface.mode       = dContactBounce | dContactSoftCFM;
-    contact[i].surface.mu         = dInfinity;
+    contact[i].surface.mode       = dContactBounce;
+    contact[i].surface.mu         = 0;
     contact[i].surface.mu2        = 0;
-    contact[i].surface.bounce     = 0.8;
+    contact[i].surface.bounce     = 0;
     contact[i].surface.bounce_vel = 0.1;
-    contact[i].surface.soft_cfm   = 0.01;
   }
   if(int numc = dCollide(oO, o1, MAX_CONTACTS, &contact[0].geom, sizeof(dContact))) {
     Object* po1 = static_cast<Object*>(dGeomGetData(oO));
diff --git a/src/space_station.cpp b/src/space_station.cpp
index 17d0168..08c3ce0 100644
--- a/src/space_station.cpp
+++ b/src/space_station.cpp
@@ -2,9 +2,26 @@
 #include "ship.h"
 #include "objimport.h"
 
+#define STATION_SBRE_MODEL  65
+
+static ObjParams params = {
+  { 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+  { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+  { 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f },
+
+  /* pColor[3] */
+  {
+    { { 1.0f, 0.0f, 1.0f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
+    { { 0.8f, 0.6f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
+    { { 0.5f, 0.5f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 }
+  },
+
+  /* pText[3][256] */
+  { "Hello you!", "CATZ" },
+};
+
 SpaceStation::SpaceStation(void) : StaticRigidBody() {
-  dGeomSphereSetRadius(m_geom, 100.0);
-  dGeomSetData(m_geom, static_cast<Body*>(this));
+  SetGeomFromSBREModel(STATION_SBRE_MODEL, &params);
   matrix4x4d m = matrix4x4d::RotateYMatrix(M_PI);
   dMatrix3 _m;
   m.SaveToOdeMatrix(_m);
@@ -17,6 +34,8 @@ SpaceStation::~SpaceStation(void) {
 }
 
 bool SpaceStation::OnCollision(Body* b) {
+  return true;
+
   if(b->GetType() == Object::SHIP) {
     Ship* s = static_cast<Ship*>(b);
     if(!s->GetDockedWith()) {
@@ -33,23 +52,7 @@ void SpaceStation::SetMesh(ObjMesh* m) {
   m_mesh = m;
 }
 
-static ObjParams params = {
-  { 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-  { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-  { 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f },
-
-  /* pColor[3] */
-  {
-    { { 1.0f, 0.0f, 1.0f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
-    { { 0.8f, 0.6f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 },
-    { { 0.5f, 0.5f, 0.5f }, { 0, 0, 0 }, { 0, 0, 0 }, 0 }
-  },
-
-  /* pText[3][256] */
-  { "Hello old bean", "CATZ!" },
-};
-
 void SpaceStation::Render(const Frame* camFrame) {
-  RenderSbreModel(camFrame, 65, &params);
+  RenderSbreModel(camFrame, STATION_SBRE_MODEL, &params);
 }
 
diff --git a/src/static_rigid_body.cpp b/src/static_rigid_body.cpp
index d100394..3b264ba 100644
--- a/src/static_rigid_body.cpp
+++ b/src/static_rigid_body.cpp
@@ -7,15 +7,45 @@
 #include "world_view.h"
 
 StaticRigidBody::StaticRigidBody(void): Body() {
-  m_geom = dCreateSphere(0, 50.0f);
-  dGeomSetBody(m_geom, 0);
-  SetPosition(vector3d(0,0,0));
+  m_geom = 0;
+  sbreCollMesh = 0;
 }
 
 StaticRigidBody::~StaticRigidBody(void) {
+  if(sbreCollMesh) {
+    free(sbreCollMesh->pVertex);
+    free(sbreCollMesh->pIndex);
+    free(sbreCollMesh->pFlag);
+    free(sbreCollMesh);
+  }
   dGeomDestroy(m_geom);
 }
 
+void StaticRigidBody::SetGeomSphere(double radius) {
+  assert(!m_geom);
+  m_geom = dCreateSphere(0, radius);
+}
+
+void StaticRigidBody::SetGeomFromSBREModel(int sbreModel, ObjParams* params) {
+  assert(!m_geom);
+  assert(sbreCollMesh == 0);
+  sbreCollMesh = (CollMesh*)calloc(1, sizeof(CollMesh));
+  sbreGenCollMesh(sbreCollMesh, sbreModel, params);
+  /* TODO: Flip Z & X because SBRE is in magicspace. */
+  for(int i = 0; i < 3*sbreCollMesh->nv; i += 3) {
+    sbreCollMesh->pVertex[i]    = -sbreCollMesh->pVertex[i];
+    sbreCollMesh->pVertex[i+2]  = -sbreCollMesh->pVertex[i+2];
+  }
+  dTriMeshDataID triMeshDataID = dGeomTriMeshDataCreate();
+  dGeomTriMeshDataBuildSingle(triMeshDataID, (void*)sbreCollMesh->pVertex,
+          3*sizeof(float), sbreCollMesh->nv, (void*)sbreCollMesh->pIndex,
+          sbreCollMesh->ni, 3*sizeof(int));
+
+  /* TODO: Leaking StaticRigidBody m_geom. */
+  m_geom = dCreateTriMesh(0, triMeshDataID, NULL, NULL, NULL);
+  dGeomSetData(m_geom, static_cast<Body*>(this));
+}
+
 void StaticRigidBody::SetPosition(vector3d p) {
   dGeomSetPosition(m_geom, p.x, p.y, p.z);
 }
@@ -67,6 +97,19 @@ void StaticRigidBody::SetFrame(Frame* f) {
   if(f) f->AddGeom(m_geom);
 }
 
+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);
+}
+
 void StaticRigidBody::RenderSbreModel(const Frame* camFrame, int model, ObjParams* params) {
   glPushMatrix();
 
diff --git a/src/static_rigid_body.h b/src/static_rigid_body.h
index 292ce18..2fc2854 100644
--- a/src/static_rigid_body.h
+++ b/src/static_rigid_body.h
@@ -22,8 +22,13 @@ public:
   void GetRotMatrix(matrix4x4d& m);
   virtual void SetFrame(Frame* f);
 
+  void TriMeshUpdateLastPos(void);
+  void SetGeomFromSBREModel(int sbreModel, ObjParams* params);
+  void SetGeomSphere(double radius);
+
   void RenderSbreModel(const Frame* camFrame, int model, ObjParams* params);
 protected:
   dGeomID m_geom;
+  CollMesh* sbreCollMesh;
 };