[Fix] Position ships correctly when sat on ground so they don't sink in.

This commit is contained in:
Allanis 2018-01-21 14:00:00 +00:00
parent 6091e4f534
commit 5afece9c00
17 changed files with 129 additions and 62 deletions

View File

@ -9,7 +9,8 @@ include_HEADERS = body.h frame.h generic_system_view.h glfreetype.h gui_button.h
gui_radio_group.h gui_screen.h gui_toggle_button.h gui_widget.h libs.h matrix4x4.h mtrand.h l3d.h \
planet.h player.h dynamic_body.h sector.h sector_view.h ship_cpanel.h ship.h space.h star.h star_system.h system_info_view.h \
system_view.h vector3.h view.h world_view.h date.h space_station.h space_station_view.h model_body.h gui_iselectable.h \
ship_type.h object.h info_view.h model_coll_mesh_data.h object_viewer_view.h fixed.h custom_starsystems.h gameconsts.h
ship_type.h object.h info_view.h model_coll_mesh_data.h object_viewer_view.h fixed.h custom_starsystems.h gameconsts.h \
aabb.h
libgui_a_SOURCES = gui_button.cpp gui.cpp gui_fixed.cpp gui_screen.cpp gui_label.cpp gui_toggle_button.cpp gui_radio_button.cpp \
gui_radio_group.cpp gui_image_button.cpp gui_image.cpp gui_image_radio_button.cpp gui_multi_state_image_button.cpp gui_widget.cpp \

8
src/aabb.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include "vector3.h"
struct Aabb {
vector3d max, min;
};

View File

@ -17,6 +17,7 @@
#include "fixed.h"
#include "vector3.h"
#include "aabb.h"
#include "matrix4x4.h"
#include "mtrand.h"

View File

@ -259,7 +259,7 @@ void L3D::MainLoop(void) {
infoView = new InfoView();
SetView(worldView);
player->SetDockedWith(station2);
player->SetDockedWith(station2, 0);
Uint32 last_stats = SDL_GetTicks();
int frame_stat = 0;

View File

@ -8,7 +8,8 @@
#include "model_coll_mesh_data.h"
ModelBody::ModelBody(void): Body() {
triMeshLastMatrixIndex = 0;
m_triMeshLastMatrixIndex = 0;
m_collMeshSet = 0;
}
ModelBody::~ModelBody(void) {
@ -36,6 +37,10 @@ void ModelBody::GeomsSetBody(dBodyID body) {
}
}
void ModelBody::GetAabb(Aabb& aabb) {
aabb = m_collMeshSet->aabb;
}
void ModelBody::SetModel(int sbreModel) {
assert(geoms.size() == 0);
CollMeshSet* mset = GetModelCollMeshSet(sbreModel);
@ -49,6 +54,7 @@ void ModelBody::SetModel(int sbreModel) {
geomColl[i].flags = mset->meshInfo[i].flags;
dGeomSetData(geoms[i], static_cast<Object*>(&geomColl[i]));
}
m_collMeshSet = mset;
}
void ModelBody::SetPosition(vector3d p) {
@ -134,14 +140,14 @@ void ModelBody::TriMeshUpdateLastPos(void) {
/* ODE tri mesh likes to know our old position. */
const dReal* r = dGeomGetRotation(geoms[0]);
vector3d pos = GetPosition();
dReal* t = triMeshTrans + 16*triMeshLastMatrixIndex;
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;
triMeshLastMatrixIndex = !triMeshLastMatrixIndex;
m_triMeshLastMatrixIndex = !m_triMeshLastMatrixIndex;
for(unsigned int i = 0; i < geoms.size(); i++) {
dGeomTriMeshSetLastTransform(geoms[i], *(dMatrix4*)(triMeshTrans + 16*triMeshLastMatrixIndex));
dGeomTriMeshSetLastTransform(geoms[i], *(dMatrix4*)(m_triMeshTrans + 16*m_triMeshLastMatrixIndex));
}
}

View File

@ -6,6 +6,7 @@
#include "sbre/sbre.h"
class ObjMesh;
class CollMeshSet;
class ModelBody: public Body {
public:
@ -23,6 +24,7 @@ public:
/* To remove from simulation for a period. */
virtual void Disable(void);
virtual void Enable(void);
void GetAabb(Aabb& aabb);
void TriMeshUpdateLastPos(void);
void SetModel(int sbreModel);
@ -38,8 +40,9 @@ public:
protected:
std::vector<Geom> geomColl;
private:
CollMeshSet* m_collMeshSet;
std::vector<dGeomID> geoms;
dReal triMeshTrans[32];
int triMeshLastMatrixIndex;
dReal m_triMeshTrans[32];
int m_triMeshLastMatrixIndex;
};

View File

@ -15,7 +15,7 @@ struct coltri_compare : public std::binary_function<coltri_t, coltri_t, bool> {
};
static ObjParams params = {
{ 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0.f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f },
@ -65,12 +65,21 @@ void CollMeshSet::GetMeshParts(void) {
}
CollMeshSet::CollMeshSet(int sbreModel) {
aabb.min = vector3d(FLT_MAX, FLT_MAX, FLT_MAX);
aabb.max = vector3d(-FLT_MIN, -FLT_MIN, -FLT_MIN);
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];
/* Make axis aligned bounding box. */
for(int a = 0; a < 3; a++) {
if(sbreCollMesh->pVertex[i+a] < aabb.min[a])
aabb.min[a] = sbreCollMesh->pVertex[i+a];
if(sbreCollMesh->pVertex[i+a] < aabb.max[a])
aabb.max[a] = sbreCollMesh->pVertex[i+a];
}
}
triIndices = new coltri_t[sbreCollMesh->ni/3];

View File

@ -19,6 +19,7 @@ public:
dTriMeshDataID* meshParts;
meshinfo_t* meshInfo;
int numMeshParts;
Aabb aabb;
CollMeshSet(int sbreModel);
private:

View File

@ -30,8 +30,8 @@ void Player::Render(const Frame* camFrame) {
}
}
void Player::SetDockedWith(SpaceStation* s) {
Ship::SetDockedWith(s);
void Player::SetDockedWith(SpaceStation* s, int port) {
Ship::SetDockedWith(s, port);
if(s) {
L3D::SetView(L3D::spaceStationView);
}

View File

@ -9,7 +9,7 @@ public:
void PollControls(void);
virtual void Render(const Frame* camFrame);
void DrawHUD(const Frame* cam_frame);
virtual void SetDockedWith(SpaceStation*);
virtual void SetDockedWith(SpaceStation*, int port);
vector3d GetExternalViewTranslation(void);
void ApplyExternalViewRotation(matrix4x4d &m);
void TimeStepUpdate(const float timeStep);

View File

@ -776,7 +776,7 @@ static uint16 station1data[] = {
PTYPE_TUBE | RFLAG_XREF, 0, 38, 34, 35, 1, 11500, 10000,
PTYPE_SETCFLAG, 1,
PTYPE_SETCFLAG, 0x10,
PTYPE_QUADFLAT | RFLAG_INVISIBLE, 39, 38, 37, 36,
PTYPE_SETCFLAG, 0,
// PTYPE_QUADFLAT | RFLAG_XREF,
@ -1287,6 +1287,11 @@ static PlainVertex starport1vtx1[] = {
{ VTYPE_PLAIN, { 0, 0, 2 } },
{ VTYPE_PLAIN, { 0.5, 0, 0 } },
{ VTYPE_PLAIN, { -0.5, 0, 0 } },
{ VTYPE_PLAIN, { 0, 0, 2 } },
{ VTYPE_PLAIN, { 0.5, 0, 2 } },
{ VTYPE_PLAIN, { -0.5, 0, 2 } },
{ VTYPE_PLAIN, { -0.1, .01, 2-0.1 } },
};
#if 0
@ -1310,22 +1315,27 @@ uint16 PFUNC_COMPSMOOTH
static uint16 starport1data[] = {
PTYPE_MATFIXED, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0,
PTYPE_SETCFLAG, 1,
PTYPE_SETCFLAG, 0x10,
PTYPE_COMPFLAT, 0x8000, 20, 6, 1, 11, 1,
COMP_HERMITE, 12, 1, 9, 10,
COMP_HERMITE, 11, 1, 10, 9,
COMP_END,
//PTYPE_CYLINDER, 0x8000, 8, 6, 7, 0, 50,
PTYPE_SETCFLAG, 0x11,
PTYPE_COMPFLAT, 0x8000, 20, 13, 1, 14, 1,
COMP_HERMITE, 15, 1, 9, 10,
COMP_HERMITE, 14, 1, 10, 9,
COMP_END,
PTYPE_SETCFLAG, 0,
PTYPE_MATFIXED, 100, 100, 100, 0, 0, 0, 0, 0, 0, 0,
PTYPE_ZBIAS, 6, 1, 0,
PTYPE_TEXT, 0, 10, 8, 1, 0, 0, 0, 20,
PTYPE_TEXT, 0, 11, 16, 1, 0, 0, 0, 20,
PTYPE_ZBIAS, 0x8000, 0, 0,
PTYPE_SUBOBJECT, 0x8000, 100, 0, 1, 2, 100,
PTYPE_SUBOBJECT, 0x8000, 100, 3, 1, 2, 100,
PTYPE_END,
};
Model starport1model = { 100.0f, 55.0f, 13, starport1vtx1, 13, 0, dummyvtx2, 1,
Model starport1model = { 100.0f, 55.0f, 17, starport1vtx1, 17, 0, dummyvtx2, 1,
{ { 0, starport1data, 0, 0, 0 } } };

View File

@ -175,7 +175,7 @@ const int pCompSize[] = { 1, 3, 5, 3, 3, 2 };
const char pModelString[][256] = {
"IZRILGOOD", "Rawr", "", "", "", "", "", "", "", "",
/* 10 - Landing pad messages. */
"1"
"1", "2", "3","4",
};
void RenderThrusters(RState* pState, int numThrusters, Thruster* pThrusters);

View File

@ -29,6 +29,7 @@ Ship::Ship(ShipType::Type shipType) : DynamicBody() {
m_wheelTransition = 0;
m_wheelState = 0;
m_dockedWith = 0;
m_dockedWithPort = 0;
m_dockingTimer = 0;
m_navTarget = 0;
m_combatTarget = 0;
@ -121,14 +122,17 @@ void Ship::Blastoff(void) {
m_launchLockTimeout = 1.0; /* One second of applying thrusters. */
Enable();
const double planetRadius = GetFrame()->m_astroBody->GetRadius();
const double planetRadius = 0.1 + GetFrame()->m_astroBody->GetRadius();
vector3d up = vector3d::Normalize(GetPosition());
dBodySetLinearVel(m_body, 0, 0, 0);
dBodySetAngularVel(m_body, 0, 0, 0);
dBodySetForce(m_body, 0, 0, 0);
dBodySetTorque(m_body, 0, 0, 0);
Aabb aabb;
GetAabb(aabb);
/* TODO: We need to be able to get sbre aabb. */
SetPosition(up*planetRadius+10.0*up);
SetPosition(up*planetRadius - aabb.min.y*up);
SetThrusterState(ShipType::THRUSTER_TOP, 1.0f);
}
@ -153,8 +157,11 @@ void Ship::TestLanded(void) {
/* Check player is sortof sensibly oriented for landing. */
const double dot = vector3d::Dot(vector3d::Normalize(vector3d(invRot[1], invRot[5], invRot[9])), up);
if(dot > 0.99) {
Aabb aabb;
GetAabb(aabb);
/* Position at zero altitude. */
SetPosition(up * planetRadius);
SetPosition(up * (planetRadius - aabb.min.y));
vector3d forward = rot * vector3d(0,0,1);
vector3d other = vector3d::Normalize(vector3d::Cross(up, forward));
@ -195,7 +202,7 @@ void Ship::TimeStepUpdate(const float timeStep) {
* and can't be positioned. Instead we do it every freaking
* update which is stupid.
*/
if(m_dockedWith) m_dockedWith->OrientDockedShip(this);
if(m_dockedWith) m_dockedWith->OrientDockedShip(this, m_dockedWithPort);
const ShipType& stype = GetShipType();
for(int i = 0; i < ShipType::THRUSTER_MAX; i++) {
@ -254,14 +261,15 @@ const ShipType& Ship::GetShipType(void) {
return ShipType::types[m_shipType];
}
void Ship::SetDockedWith(SpaceStation* s) {
void Ship::SetDockedWith(SpaceStation* s, int port) {
if(m_dockedWith && !s) {
m_dockedWith->OrientLaunchingShip(this);
m_dockedWith->OrientLaunchingShip(this, port);
Enable();
m_dockedWith = 0;
} else {
m_dockedWith = s;
m_dockedWithPort = port;
m_dockingTimer = 0.0f;
if(s->IsGroundStation()) m_flightState = LANDED;
SetVelocity(vector3d(0, 0, 0));

View File

@ -18,7 +18,7 @@ class Ship : public DynamicBody {
public:
Ship(ShipType::Type shipType);
virtual Object::Type GetType(void) { return Object::SHIP; }
virtual void SetDockedWith(SpaceStation*);
virtual void SetDockedWith(SpaceStation*, int port);
SpaceStation* GetDockedWith(void) { return m_dockedWith; }
void SetNavTarget(Body* const target);
Body* GetNavTarget(void) const { return m_navTarget; }
@ -55,6 +55,7 @@ protected:
void RenderLaserfire(void);
SpaceStation* m_dockedWith;
int m_dockedWithPort;
enum ShipType::Type m_shipType;
Uint32 m_gunState[ShipType::GUNMOUNT_MAX];
private:

View File

@ -30,10 +30,16 @@ static ObjParams params = {
};
void SpaceStation::GetDockingSurface(CollMeshSet* mset, int midx) {
meshinfo_t* minfo = &mset->meshInfo[midx];
assert(minfo->flags == 0x1);
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);
port.center = vector3d(0.0);
dport->center = vector3d(0.0);
const int t = minfo->triStart;
float* const vts = mset->sbreCollMesh->pVertex;
for(int pos = 0; pos < minfo->numTris; pos++) {
@ -45,33 +51,34 @@ void SpaceStation::GetDockingSurface(CollMeshSet* mset, int midx) {
* docking port).
*/
if(pos == 0) {
port.normal = vector3d::Cross(v2-v1, v2-v3);
port.normal.Normalize();
port.horiz = vector3d::Normalize(v1-v2);
dport->normal = vector3d::Cross(v2-v1, v2-v3);
dport->normal.Normalize();
dport->horiz = vector3d::Normalize(v1-v2);
}
port.center += v1+v2+v3;
dport->center += v1+v2+v3;
}
port.center *= 1.0/(3.0*minfo->numTris);
dport->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); */
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() {
const Uint32 sbreModel = stationTypes[type].sbreModel;
m_type = type;
m_numPorts = 0;
SetModel(sbreModel);
CollMeshSet* mset = GetModelCollMeshSet(sbreModel);
for(unsigned int i = 0; i < geomColl.size(); i++) {
if(geomColl[i].flags == 0x1) {
if(geomColl[i].flags & 0x10) {
/* Docking surface. */
GetDockingSurface(mset, i);
//mset->meshInfo[i];
@ -94,20 +101,28 @@ bool SpaceStation::IsGroundStation(void) const {
return (stationTypes[m_type].dockMethod == SpaceStationType::SURFACE);
}
void SpaceStation::OrientDockedShip(Ship* ship) const {
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(-port.horiz, port.normal);
matrix4x4d rot = stationRot * matrix4x4d::MakeRotMatrix(-port.horiz, -port.normal, -port_y);
vector3d pos = GetPosition() + stationRot*port.center;
ship->SetPosition(pos - stationRot*port.normal);
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) const {
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) {
/*
@ -117,9 +132,9 @@ void SpaceStation::OrientLaunchingShip(Ship* ship) const {
*/
matrix4x4d stationRot;
GetRotMatrix(stationRot);
vector3d port_y = vector3d::Cross(-port.horiz, port.normal);
matrix4x4d rot = stationRot * matrix4x4d::MakeRotMatrix(port.horiz, port_y, port.normal);
vector3d pos = GetPosition() + stationRot*port.center;
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));
@ -135,10 +150,10 @@ void SpaceStation::OrientLaunchingShip(Ship* ship) const {
#if 0
matrix4x4d stationRot;
GetRotMatrix(stationRot);
vector3d port_y = vector3d::Cross(-port.horiz, port.normal);
matrix4x4d rot = stationRot * matrix4x4d::MakeRotMatrix(-port.horiz, -port.normal, -port_y);
vector3d pos = GetPosition() + stationRot*port.center;
ship->SetPosition(pos - stationRot*(10*port.normal));
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));
@ -154,7 +169,8 @@ bool SpaceStation::GetDockingClearance(Ship* s) {
}
bool SpaceStation::OnCollision(Body* b, Uint32 flags) {
if(flags == 1) {
if(flags & 0x10) {
dockingport_t* dport = &port[flags & 0xf];
/* Hitting docking area of a station. */
if(b->GetType() == Object::SHIP) {
Ship* s = static_cast<Ship*>(b);
@ -169,7 +185,7 @@ bool SpaceStation::OnCollision(Body* b, Uint32 flags) {
matrix4x4d stationRot;
GetRotMatrix(stationRot);
vector3d dockingNormal = stationRot*port.normal;
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);
@ -179,7 +195,7 @@ bool SpaceStation::OnCollision(Body* b, Uint32 flags) {
if((speed < MAX_LANDING_SPEED) &&
(!s->GetDockedWith()) &&
(s->GetDockingTimer() != 0.0f)) {
s->SetDockedWith(this);
s->SetDockedWith(this, flags & 0xf);
}
}
return false;

View File

@ -2,6 +2,8 @@
#include "libs.h"
#include "model_body.h"
#define MAX_DOCKING_PORTS 4
class CollMeshSet;
class Ship;
@ -13,8 +15,8 @@ public:
virtual bool OnCollision(Body* b, Uint32 flags);
virtual Object::Type GetType(void) { return Object::SPACESTATION; }
virtual void Render(const Frame* camFrame);
void OrientLaunchingShip(Ship* ship) const;
void OrientDockedShip(Ship* ship) const;
void OrientLaunchingShip(Ship* ship, int port) const;
void OrientDockedShip(Ship* ship, int port) const;
void GetDockingSurface(CollMeshSet* mset, int midx);
bool GetDockingClearance(Ship* s);
bool IsGroundStation(void) const;
@ -22,9 +24,10 @@ public:
vector3d center;
vector3d normal;
vector3d horiz;
} port;
} port[MAX_DOCKING_PORTS];
private:
TYPE m_type;
int m_numPorts;
};

View File

@ -32,7 +32,7 @@ SpaceStationView::SpaceStationView(void) : View() {
}
void SpaceStationView::OnClickRequestLaunch(void) {
L3D::player->SetDockedWith(0);
L3D::player->SetDockedWith(0,0);
L3D::SetView(L3D::worldView);
}