From 1b35d387b90fa13631658a2183bf9485d5c6b520 Mon Sep 17 00:00:00 2001
From: Rtch90 <ritchie.cunningham@protonmail.com>
Date: Mon, 20 Nov 2017 22:15:23 +0000
Subject: [PATCH] [Change] Position player in docking bay on undocking. Need to
 do request docking clearance, because at the minute repeat docking is not
 possible. D:

---
 src/main.cpp                 |  4 +--
 src/matrix4x4.h              |  8 +++++
 src/model_body.cpp           |  4 +--
 src/model_body.h             |  3 +-
 src/model_coll_mesh_data.cpp | 12 ++++----
 src/model_coll_mesh_data.h   |  8 ++++-
 src/sbre/models.cpp          |  2 +-
 src/ship.cpp                 | 25 ++++++++++++----
 src/space.cpp                |  1 -
 src/space_station.cpp        | 58 ++++++++++++++++++++++++++++++++++--
 src/space_station.h          | 12 +++++++-
 src/vector3.h                | 28 +++++++++--------
 12 files changed, 130 insertions(+), 35 deletions(-)

diff --git a/src/main.cpp b/src/main.cpp
index 19e5b57..3a7432a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -205,9 +205,9 @@ void L3D::MainLoop(void) {
 
   {
     SpaceStation* body = new SpaceStation();
-    body->SetLabel("Some Back Country Joint");
+    body->SetLabel("Poemi-chan's Folly");
     body->SetFrame(earth_frame);
-    body->SetPosition(vector3d(0, 0, 7999400));
+    body->SetPosition(vector3d(0, 0, 7998000));
     Space::AddBody(body);
   }
 
diff --git a/src/matrix4x4.h b/src/matrix4x4.h
index f9cec86..d981668 100644
--- a/src/matrix4x4.h
+++ b/src/matrix4x4.h
@@ -60,6 +60,14 @@ public:
     return m;
   }
 
+  static matrix4x4 MakeRotMatrix(vector3<T> rx, vector3<T> ry, vector3<T> rz) {
+    matrix4x4 m;
+    m[0] = rx.x; m[4] = rx.y; m[ 8] = rx.z; m[12] = 0;
+    m[1] = ry.x; m[5] = ry.y; m[ 9] = ry.z; m[13] = 0;
+    m[2] = rz.x; m[6] = rz.y; m[10] = rz.z; m[14] = 0;
+    m[3] = 0; m[7] = 0; m[11] = 0; m[15] = 1;
+  }
+
   void RotateZ(T radians) { *this = (*this) * RotateZMatrix(radians); }
   void RotateY(T radians) { *this = (*this) * RotateYMatrix(radians); }
   void rotateX(T radians) { *this = (*this) * RotateXMatrix(radians); }
diff --git a/src/model_body.cpp b/src/model_body.cpp
index 47cbcde..8519109 100644
--- a/src/model_body.cpp
+++ b/src/model_body.cpp
@@ -43,10 +43,10 @@ void ModelBody::SetModel(int sbreModel) {
   geomColl.resize(mset->numMeshParts);
   geoms.resize(mset->numMeshParts);
 
-  for(unsigned int i = 0; i < mset->numMeshParts; i++) {
+  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->meshFlags[i];
+    geomColl[i].flags = mset->meshInfo[i].flags;
     dGeomSetData(geoms[i], static_cast<Object*>(&geomColl[i]));
   }
 }
diff --git a/src/model_body.h b/src/model_body.h
index f245dec..2a05a15 100644
--- a/src/model_body.h
+++ b/src/model_body.h
@@ -36,8 +36,9 @@ public:
     Body* parent;
     int flags;
   };
-private:
+protected:
   std::vector<Geom> geomColl;
+private:
   std::vector<dGeomID> geoms;
   dReal triMeshTrans[32];
   int triMeshLastMatrixIndex;
diff --git a/src/model_coll_mesh_data.cpp b/src/model_coll_mesh_data.cpp
index 9e91084..d368d17 100644
--- a/src/model_coll_mesh_data.cpp
+++ b/src/model_coll_mesh_data.cpp
@@ -40,9 +40,9 @@ void CollMeshSet::GetMeshParts(void) {
     if(curFlag != triIndices[i].flags) numMeshParts++;
     curFlag = triIndices[i].flags;
   }
-  printf("%d parts\n", numMeshParts);
+  //printf("%d parts\n", numMeshParts);
   meshParts = new dTriMeshDataID[numMeshParts];
-  meshFlags = new int[numMeshParts];
+  meshInfo  = new meshinfo_t[numMeshParts];
 
   int tidx = 0;
   int midx = 0;
@@ -50,14 +50,16 @@ void CollMeshSet::GetMeshParts(void) {
     int len = 0;
     int flag = triIndices[tidx].flags;
     while((len < sbreCollMesh->ni/3) && (triIndices[tidx+len].flags == flag)) len++;
-    printf("%d: len %d\n", tidx, len);
+    //printf("%d: len %d\n", tidx, len);
 
     dTriMeshDataID triMeshDataID = dGeomTriMeshDataCreate();
     dGeomTriMeshDataBuildSingle(triMeshDataID, (void*)sbreCollMesh->pVertex,
                                 3*sizeof(float), sbreCollMesh->nv, (void*)&triIndices[tidx],
                                 3*len, 4*sizeof(int));
-    meshFlags[midx] = flag;
-    meshParts[midx++] = triMeshDataID;
+    meshInfo[midx].flags      = flag;
+    meshInfo[midx].triStart   = tidx;
+    meshInfo[midx].numTris    = len;
+    meshParts[midx++]         = triMeshDataID;
     tidx += len;
   } while(tidx < sbreCollMesh->ni/3);
 }
diff --git a/src/model_coll_mesh_data.h b/src/model_coll_mesh_data.h
index 889a909..8cbca35 100644
--- a/src/model_coll_mesh_data.h
+++ b/src/model_coll_mesh_data.h
@@ -6,12 +6,18 @@ struct coltri_t {
   int v1, v2, v3, flags;
 };
 
+struct meshinfo_t {
+  int flags;
+  int triStart; /* Into triIndices. */
+  int numTris;
+};
+
 class CollMeshSet {
 public:
   CollMesh* sbreCollMesh;
   coltri_t* triIndices;
   dTriMeshDataID* meshParts;
-  int* meshFlags;
+  meshinfo_t* meshInfo;
   int numMeshParts;
 
   CollMeshSet(int sbreModel);
diff --git a/src/sbre/models.cpp b/src/sbre/models.cpp
index 24a9d21..0bb71a3 100644
--- a/src/sbre/models.cpp
+++ b/src/sbre/models.cpp
@@ -781,7 +781,7 @@ static uint16 station1data[] = {
   PTYPE_END,
 };
 
-Model station1model = { 4.0f, 120.0f, 40, station1vtx1, 100, 0, station1vtx2, 1,
+Model station1model = { 10.0f, 120.0f, 40, station1vtx1, 100, 0, station1vtx2, 1,
                       { { 0, station1data, 0, 0, 0 } } };
 
 static PlainVertex ship3vtx1[] = {
diff --git a/src/ship.cpp b/src/ship.cpp
index 6115de2..cc7a654 100644
--- a/src/ship.cpp
+++ b/src/ship.cpp
@@ -5,6 +5,7 @@
 #include "world_view.h"
 #include "space.h"
 #include "model_coll_mesh_data.h"
+#include "space_station.h"
 
 static ObjParams params = {
   { 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
@@ -141,13 +142,25 @@ const ShipType& Ship::GetShipType(void) {
 
 void Ship::SetDockedWith(SpaceStation* s) {
   if(m_dockedWith && !s) {
-    /* Launching. */
-    printf("Buhbai!\n");
-    m_dockedWith = 0;
-    Enable();
-    vector3d pos = GetPosition();
-    pos.x += 5000;
+    /*
+     * Position player in middle of docking bay, pointing out of it.
+     * TODO Need to do forced thrusting thingy.
+     * TODO ang vel not zeroed for some reason..
+     */
+    matrix4x4d stationRot;
+    m_dockedWith->GetRotMatrix(stationRot);
+    vector3d port_y = vector3d::Cross(-m_dockedWith->port.horiz, m_dockedWith->port.normal);
+    matrix4x4d rot = stationRot * matrix4x4d::MakeRotMatrix(m_dockedWith->port.horiz, port_y, m_dockedWith->port.normal);
+    rot.Print();
+    vector3d pos = m_dockedWith->GetPosition() + stationRot*m_dockedWith->port.center;
     SetPosition(pos);
+    SetRotation(rot);
+    SetVelocity(vector3d(0, 0, 0));
+    SetAngVelocity(vector3d(0, 0, 0));
+    Enable();
+
+    m_dockedWith = 0;
+
   } else {
     m_dockedWith = s;
     SetVelocity(vector3d(0, 0, 0));
diff --git a/src/space.cpp b/src/space.cpp
index 7abdc25..172025b 100644
--- a/src/space.cpp
+++ b/src/space.cpp
@@ -180,7 +180,6 @@ static void nearCallback(void* data, dGeomID oO, dGeomID o1) {
     contact[i].surface.bounce_vel = 0.1;
   }
   if(int numc = dCollide(oO, o1, MAX_CONTACTS, &contact[0].geom, sizeof(dContact))) {
-    printf("%d contacts\n", numc);
     Object* po1 = static_cast<Object*>(dGeomGetData(oO));
     Object* po2 = static_cast<Object*>(dGeomGetData(o1));
     if(!_OnCollision(oO, o1, po1, po2, numc, contact)) return;
diff --git a/src/space_station.cpp b/src/space_station.cpp
index 1140c5f..5b5bb79 100644
--- a/src/space_station.cpp
+++ b/src/space_station.cpp
@@ -1,6 +1,7 @@
 #include "space_station.h"
 #include "ship.h"
 #include "objimport.h"
+#include "model_coll_mesh_data.h"
 
 #define STATION_SBRE_MODEL  65
 
@@ -20,10 +21,62 @@ static ObjParams params = {
   { "Hello you!", "CATZ" },
 };
 
+void SpaceStation::GetDockingSurface(CollMeshSet* mset, int midx) {
+  meshinfo_t* minfo = &mset->meshInfo[midx];
+  assert(minfo->flags == 0x1);
+  assert(minfo->numTris);
+  port.center = vector3d(0.0);
+  const int t = minfo->triStart;
+  float* const vts = mset->sbreCollMesh->pVertex;
+  for(int pos = 0; pos < minfo->numTris; pos++) {
+    vector3d v1(vts + 3*mset->triIndices[t+pos].v1);
+    vector3d v2(vts + 3*mset->triIndices[t+pos].v2);
+    vector3d v3(vts + 3*mset->triIndices[t+pos].v3);
+    /* 
+     * Use first tri to get docking port normal (which points out of the
+     * docking port).
+     */
+    if(pos == 0) {
+      port.normal = vector3d::Cross(v2-v1, v2-v3);
+      port.normal.Normalize();
+      port.horiz = vector3d::Normalize(v1-v2);
+    }
+    port.center += v1+v2+v3;
+  }
+  port.center *= 1.0/(3.0*minfo->numTris);
+  /*printf("Docking port center %f,%f,%f, normal %f,%f,%f, horiz %f,%f,%f\n",
+          port.center.x,
+          port.center.y,
+          port.center.z,
+          port.normal.x,
+          port.normal.y,
+          port.normal.z,
+          port.horiz.x,
+          port.horiz.y,
+          port.horiz.z); */
+}
+
 SpaceStation::SpaceStation(void) : ModelBody() {
+  allowDocking = true;
   SetModel(STATION_SBRE_MODEL);
-  matrix4x4d m = matrix4x4d::RotateYMatrix(M_PI);
+  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++) {
+    if(geomColl[i].flags == 0x1) {
+      /* Docking surface. */
+      GetDockingSurface(mset, i);
+      //mset->meshInfo[i];
+#if 0
+      struct meshinfo_t {
+        int flags;
+        int triStart; /* Into triIndices. */
+        int numTris;
+      };
+#endif
+    }
+  }
 }
 
 SpaceStation::~SpaceStation(void) {
@@ -35,7 +88,8 @@ bool SpaceStation::OnCollision(Body* b, Uint32 flags) {
     /* Hitting docking area of a station. */
     if(b->GetType() == Object::SHIP) {
       Ship* s = static_cast<Ship*>(b);
-      if(!s->GetDockedWith()) {
+      if(!s->GetDockedWith() && allowDocking) {
+        allowDocking = false;
         s->Disable();
         s->SetDockedWith(this);
         printf("Docking!\n");
diff --git a/src/space_station.h b/src/space_station.h
index 848dc7c..d839ede 100644
--- a/src/space_station.h
+++ b/src/space_station.h
@@ -2,6 +2,8 @@
 #include "libs.h"
 #include "model_body.h"
 
+class CollMeshSet;
+
 class SpaceStation : public ModelBody {
 public:
   SpaceStation(void);
@@ -9,6 +11,14 @@ public:
   virtual bool OnCollision(Body* b, Uint32 flags);
   virtual Object::Type GetType(void) { return Object::SPACESTATION; }
   virtual void Render(const Frame* camFrame);
-protected:
+  void GetDockingSurface(CollMeshSet* mset, int midx);
+  struct dockingport_t {
+    vector3d center;
+    vector3d normal;
+    vector3d horiz;
+  } port;
+
+private:
+  bool allowDocking;
 };
 
diff --git a/src/vector3.h b/src/vector3.h
index 2a1d76f..c7146b9 100644
--- a/src/vector3.h
+++ b/src/vector3.h
@@ -6,20 +6,22 @@ class vector3 {
 public:
   T x,y,z;
 
-  vector3(void)                                                 { }
-  vector3(T val): x(val), y(val), z(val)                        { }
-  vector3(T _x, T _y, T _z): x(_x), y(_y), z(_z)                { }
-  vector3(const T vals[3]): x(vals[0]), y(vals[1]), z(vals[2])  { }
+  vector3(void)                                                       { }
+  vector3(T val): x(val), y(val), z(val)                              { }
+  vector3(T _x, T _y, T _z): x(_x), y(_y), z(_z)                      { }
+  vector3(const double vals[3]): x(vals[0]), y(vals[1]), z(vals[2])   { }
+  vector3(const float vals[3]) : x(vals[0]), y(vals[1]), z(vals[2])   { }
+
+  T&        operator[]        (const int i) { return ((T*)this)[i]; }
+  vector3   operator+         (const vector3 a) const { return vector3 (a.x+x, a.y+y, a.z+z); }
+  vector3&  operator+=        (const vector3 a) { x+=a.x; y+=a.y; z+=a.z; return *this; }
+  vector3&  operator-=        (const vector3 a) { x-=a.x; y-=a.y; z-=a.z; return *this; }
+  vector3&  operator*=        (const T a) { x*=a; y*=a; z*=a; return *this; }
+  vector3   operator-         (const vector3 a) const { return vector3 (x-a.x, y-a.y, z-a.z); }
+  vector3   operator-(void)   const { return vector3 (-x, -y, -z); }
+  bool      operator==(const vector3 a) const { return ((a.x==x)&&(a.y==y)&&(a.z==z)); }
+  bool      operator!=(const vector3 a) const { return ((a.x!=x)||(a.y!=y)||(a.z!=z)); }
 
-  T& operator[]           (const int i) { return ((T*)this)[i]; }
-  vector3 operator+       (const vector3 a) const { return vector3 (a.x+x, a.y+y, a.z+z); }
-  vector3& operator+=     (const vector3 a) { x+=a.x; y+=a.y; z+=a.z; return *this; }
-  vector3& operator-=     (const vector3 a) { x-=a.x; y-=a.y; z-=a.z; return *this; }
-  vector3& operator*=     (const T a) { x*=a; y*=a; z*=a; return *this; }
-  vector3 operator-       (const vector3 a) const { return vector3 (x-a.x, y-a.y, z-a.z); }
-  vector3 operator-(void) const { return vector3 (-x, -y, -z); }
-  bool operator==(const vector3 a) const { return ((a.x==x)&&(a.y==y)&&(a.z==z)); }
-  bool operator!=(const vector3 a) const { return ((a.x!=x)||(a.y!=y)||(a.z!=z)); }
   friend vector3 operator*(const vector3 a, const vector3 b) { 
     return vector3 (a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x); }
   friend vector3 operator*(const vector3 a, const T scalar) {