223 lines
6.5 KiB
C++
223 lines
6.5 KiB
C++
#include "space_station.h"
|
|
#include "ship.h"
|
|
#include "model_coll_mesh_data.h"
|
|
#include "gameconsts.h"
|
|
#include "star_system.h"
|
|
#include "serializer.h"
|
|
|
|
struct SpaceStationType {
|
|
Uint32 sbreModel;
|
|
enum { ORBITAL, SURFACE } dockMethod;
|
|
};
|
|
|
|
struct SpaceStationType stationTypes[SpaceStation::TYPE_MAX] = {
|
|
{ 65, SpaceStationType::ORBITAL },
|
|
{ 90, SpaceStationType::SURFACE },
|
|
};
|
|
|
|
void SpaceStation::Save(void) {
|
|
using namespace Serializer::Write;
|
|
ModelBody::Save();
|
|
wr_int((int)m_type);
|
|
}
|
|
|
|
void SpaceStation::Load(void) {
|
|
using namespace Serializer::Read;
|
|
ModelBody::Load();
|
|
m_type = (TYPE)rd_int();
|
|
m_numPorts = 0;
|
|
Init();
|
|
}
|
|
|
|
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" },
|
|
};
|
|
|
|
void SpaceStation::GetDockingSurface(CollMeshSet* mset, int midx) {
|
|
meshinfo_t* const minfo = &mset->meshInfo[midx];
|
|
dockingport_t* const dport = &port[minfo->flags & 0xf];
|
|
m_numPorts++;
|
|
|
|
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);
|
|
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) {
|
|
dport->normal = vector3d::Cross(v2-v1, v2-v3);
|
|
dport->normal.Normalize();
|
|
dport->horiz = vector3d::Normalize(v1-v2);
|
|
}
|
|
dport->center += v1+v2+v3;
|
|
}
|
|
dport->center *= 1.0/(3.0*minfo->numTris);
|
|
/*printf("Docking port center %f,%f,%f, normal %f,%f,%f, horiz %f,%f,%f\n",
|
|
dport->center.x,
|
|
dport->center.y,
|
|
dport->center.z,
|
|
dport->normal.x,
|
|
dport->normal.y,
|
|
dport->normal.z,
|
|
dport->horiz.x,
|
|
dport->horiz.y,
|
|
dport->horiz.z); */
|
|
}
|
|
|
|
SpaceStation::SpaceStation(TYPE type) : ModelBody() {
|
|
m_type = type;
|
|
m_numPorts = 0;
|
|
Init();
|
|
}
|
|
|
|
void SpaceStation::Init(void) {
|
|
const Uint32 sbreModel = stationTypes[m_type].sbreModel;
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
SpaceStation::~SpaceStation(void) {
|
|
|
|
}
|
|
|
|
bool SpaceStation::IsGroundStation(void) const {
|
|
return (stationTypes[m_type].dockMethod == SpaceStationType::SURFACE);
|
|
}
|
|
|
|
void SpaceStation::OrientDockedShip(Ship* ship, int port) const {
|
|
const dockingport_t* dport = &this->port[port];
|
|
const int dockMethod = stationTypes[m_type].dockMethod;
|
|
if(dockMethod == SpaceStationType::SURFACE) {
|
|
matrix4x4d stationRot;
|
|
GetRotMatrix(stationRot);
|
|
vector3d port_y = vector3d::Cross(-dport->horiz, dport->normal);
|
|
matrix4x4d rot = stationRot * matrix4x4d::MakeRotMatrix(-dport->horiz, -dport->normal, -port_y);
|
|
vector3d pos = GetPosition() + stationRot*dport->center;
|
|
|
|
/* Position with wheels perfectly on ground. :D */
|
|
Aabb aabb;
|
|
ship->GetAabb(aabb);
|
|
pos += stationRot*vector3d(0, -aabb.min.y, 0);
|
|
|
|
ship->SetPosition(pos);
|
|
ship->SetRotMatrix(rot);
|
|
}
|
|
}
|
|
|
|
void SpaceStation::OrientLaunchingShip(Ship* ship, int port) const {
|
|
const dockingport_t* dport = &this->port[port];
|
|
const int dockMethod = stationTypes[m_type].dockMethod;
|
|
if(dockMethod == SpaceStationType::ORBITAL) {
|
|
/*
|
|
* Position ship in middle of docking bay, pointing out of it.
|
|
* TODO: Need to do forced thrusting thing.
|
|
* TODO: ang vel not zeroed for some reason..
|
|
*/
|
|
matrix4x4d stationRot;
|
|
GetRotMatrix(stationRot);
|
|
vector3d port_y = vector3d::Cross(-dport->horiz, dport->normal);
|
|
matrix4x4d rot = stationRot * matrix4x4d::MakeRotMatrix(dport->horiz, port_y, dport->normal);
|
|
vector3d pos = GetPosition() + stationRot*dport->center;
|
|
ship->SetPosition(pos);
|
|
ship->SetRotMatrix(rot);
|
|
ship->SetVelocity(vector3d(0,0,0));
|
|
ship->SetAngVelocity(vector3d(0,0,0));
|
|
}
|
|
else if(dockMethod == SpaceStationType::SURFACE) {
|
|
ship->Blastoff();
|
|
|
|
/*
|
|
* Not necessary, since for the time being 'SURFACE' starports are on planets
|
|
* so the positioning Blastoff does is fine.
|
|
*/
|
|
#if 0
|
|
matrix4x4d stationRot;
|
|
GetRotMatrix(stationRot);
|
|
vector3d port_y = vector3d::Cross(-dport->horiz, dport->normal);
|
|
matrix4x4d rot = stationRot * matrix4x4d::MakeRotMatrix(-dport->horiz, -dport->normal, -port_y);
|
|
vector3d pos = GetPosition() + stationRot*dport->center;
|
|
ship->SetPosition(pos - stationRot*(10*dport->normal));
|
|
ship->SetRotMatrix(rot);
|
|
ship->SetVelocity(vector3d(0,0,0));
|
|
ship->SetAngVelocity(vector3d(0,0,0));
|
|
#endif
|
|
} else {
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
bool SpaceStation::GetDockingClearance(Ship* s) {
|
|
s->SetDockingTimer(68*10);
|
|
return true;
|
|
}
|
|
|
|
bool SpaceStation::OnCollision(Body* b, Uint32 flags) {
|
|
if(flags & 0x10) {
|
|
dockingport_t* dport = &port[flags & 0xf];
|
|
/* Hitting docking area of a station. */
|
|
if(b->IsType(Object::SHIP)) {
|
|
Ship* s = static_cast<Ship*>(b);
|
|
const dReal* vel = dBodyGetLinearVel(s->m_body);
|
|
double speed = vector3d(vel[0], vel[1], vel[2]).Length();
|
|
|
|
/* Must be oriented sensibly and have wheels down. */
|
|
if(IsGroundStation()) {
|
|
matrix4x4d rot;
|
|
s->GetRotMatrix(rot);
|
|
matrix4x4d invRot = rot.InverseOf();
|
|
|
|
matrix4x4d stationRot;
|
|
GetRotMatrix(stationRot);
|
|
vector3d dockingNormal = stationRot*dport->normal;
|
|
|
|
/* Check player is sort of sensibly oriented for landing. */
|
|
const double dot = vector3d::Dot(vector3d(-invRot[1], -invRot[5], -invRot[9]), dockingNormal);
|
|
if((dot < 0.99) || (s->GetWheelState() != 1.0)) return false;
|
|
}
|
|
|
|
if((speed < MAX_LANDING_SPEED) &&
|
|
(!s->GetDockedWith()) &&
|
|
(s->GetDockingTimer() != 0.0f)) {
|
|
s->SetDockedWith(this, flags & 0xf);
|
|
}
|
|
}
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void SpaceStation::Render(const Frame* camFrame) {
|
|
RenderSbreModel(camFrame, stationTypes[m_type].sbreModel, ¶ms);
|
|
}
|
|
|