diff --git a/src/dynamic_body.cpp b/src/dynamic_body.cpp index 97f299e..f1c12a9 100644 --- a/src/dynamic_body.cpp +++ b/src/dynamic_body.cpp @@ -22,12 +22,16 @@ void DynamicBody::Disable(void) { dBodyDisable(m_body); } -void DynamicBody::SetRotation(const matrix4x4d &r) { +void DynamicBody::SetRotMatrix(const matrix4x4d& r) { dMatrix3 _m; r.SaveToOdeMatrix(_m); dBodySetRotation(m_body, _m); } +void DynamicBody::GetRotMatrix(matrix4x4d& m) { + m.LoadFromOdeMatrix(dBodyGetRotation(m_body)); +} + void DynamicBody::SetMassDistributionFromCollMesh(const CollMesh* m) { /* * XXX: This is silly. the radius of mass distribution should be diff --git a/src/dynamic_body.h b/src/dynamic_body.h index f4c910f..804b313 100644 --- a/src/dynamic_body.h +++ b/src/dynamic_body.h @@ -10,7 +10,8 @@ class DynamicBody : public ModelBody { public: DynamicBody(void); virtual ~DynamicBody(void); - virtual void SetRotation(const matrix4x4d& r); + virtual void SetRotMatrix(const matrix4x4d& r); + virtual void GetRotMatrix(matrix4x4d& m); virtual void SetVelocity(vector3d v); virtual vector3d GetVelocity(void); void SetAngVelocity(vector3d v); diff --git a/src/main.cpp b/src/main.cpp index 1bcc509..eb4d31d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -98,6 +98,8 @@ void L3D::Init(IniConfig& config) { L3D::scrHeight = height; L3D::scrAspect = width / (float)height; + L3D::rng.seed(time(NULL)); + InitOpenGL(); dInitODE(); @@ -229,8 +231,14 @@ void L3D::MainLoop(void) { station->SetPosition(vector3d(0,0,0)); Space::AddBody(station); - player->SetFrame(stationFrame); - player->SetPosition(vector3d(0,0,2000)); + //player->SetFrame(stationFrame); + //player->SetPosition(vector3d(0,0,2000)); + player->SetFrame(pframe); + float ang1 = L3D::rng.Double(0,M_PI); + float ang2 = L3D::rng.Double(0,M_PI); + double r = EARTH_RADIUS*1.0001; + player->SetPosition(vector3d(r*cos(ang1)*cos(ang2), r*sin(ang1)*cos(ang2), r*sin(ang2))); + //player->SetPosition(vector3d(r, 0, 0); Gui::Init(scrWidth, scrHeight, 640, 480); @@ -246,7 +254,7 @@ void L3D::MainLoop(void) { infoView = new InfoView(); SetView(worldView); - player->SetDockedWith(station); + //player->SetDockedWith(station); Uint32 last_stats = SDL_GetTicks(); int frame_stat = 0; diff --git a/src/object.h b/src/object.h index 925393e..a6e4403 100644 --- a/src/object.h +++ b/src/object.h @@ -2,7 +2,7 @@ class Object { public: - enum Type { NONE, BODY, SHIP, SPACESTATION, LASER, GEOM }; + enum Type { NONE, BODY, SHIP, SPACESTATION, LASER, GEOM, PLANET }; virtual Type GetType(void) = 0; }; diff --git a/src/planet.h b/src/planet.h index 2259bc9..40a428f 100644 --- a/src/planet.h +++ b/src/planet.h @@ -15,6 +15,7 @@ public: virtual void SetFrame(Frame* f); virtual bool OnCollision(Body* b, Uint32 flags) { return true; } virtual double GetMass(void) const { return m_mass; } + virtual Object::Type GetType(void) { return Object::PLANET; } private: void DrawRockyPlanet(void); void DrawGasGiant(void); diff --git a/src/player.cpp b/src/player.cpp index 591a5d9..b08b1dc 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -88,6 +88,9 @@ void Player::PollControls(void) { if(L3D::KeyState(SDLK_EQUALS)) m_external_view_dist -= 10; if(L3D::KeyState(SDLK_MINUS)) m_external_view_dist += 10; m_external_view_dist = MAX(50, m_external_view_dist); + + /* When landed don't let external view look from below. */ + if(m_isLanded) m_external_view_rotx = CLAMP(m_external_view_rotx, -170.0, -10); } if((time_accel == 0) || GetDockedWith()) { @@ -265,6 +268,7 @@ void Player::DrawHUD(const Frame* cam_frame) { if(GetFrame()->m_astroBody) { double radius = GetFrame()->m_astroBody->GetRadius(); double altitude = GetPosition().Length() - radius; + if(altitude < 0) altitude = 0; char buf[128]; snprintf(buf, sizeof(buf), "Altitude: %.0f m", altitude); glPushMatrix(); diff --git a/src/ship.cpp b/src/ship.cpp index b3e942a..11dc6a4 100644 --- a/src/ship.cpp +++ b/src/ship.cpp @@ -23,13 +23,15 @@ static ObjParams params = { }; Ship::Ship(ShipType::Type shipType) : DynamicBody() { + m_isLanded = false; + m_testLanded = false; m_wheelTransition = 0; - m_wheelState = 0; - m_dockedWith = 0; - dockingTimer = 0; - m_navTarget = 0; - m_combatTarget = 0; - m_shipType = shipType; + m_wheelState = 0; + m_dockedWith = 0; + dockingTimer = 0; + m_navTarget = 0; + m_combatTarget = 0; + m_shipType = shipType; m_angThrusters[0] = m_angThrusters[1] = m_angThrusters[2] = 0; m_laserCollisionObj.owner = this; m_equipment = EquipSet(shipType); @@ -52,6 +54,14 @@ void Ship::UpdateMass(void) { dBodySetMass(m_body, &m_mass); } +bool Ship::OnCollision(Body* b, Uint32 flags) { + if(b->GetType() == Object::PLANET) { + if(m_isLanded) return false; + else m_testLanded = true; + } + return true; +} + vector3d Ship::CalcRotDamping(void) { /* Rotation damping. */ const dReal* _av = dBodyGetAngularVel(m_body); @@ -97,6 +107,43 @@ void Ship::CalcStats(shipstats_t* stats) { stats->hyperspace_range = 200 * hyperclass * hyperclass / stats->total_mass; } +void Ship::TestLanded(void) { + if(GetFrame()->m_astroBody) { + const dReal* vel = dBodyGetLinearVel(m_body); + double speed = vector3d(vel[0], vel[1], vel[2]).Length(); + const double planetRadius = GetFrame()->m_astroBody->GetRadius(); + + if(speed < 15) { + printf("Landed!\n"); + + /* Orient the damn thing right! */ + matrix4x4d rot; + GetRotMatrix(rot); + + vector3d up = vector3d::Normalize(GetPosition()); + + /* Position at zero altitude. */ + SetPosition(up * planetRadius); + + vector3d forward = rot * vector3d(0, 0, 1); + vector3d other = vector3d::Normalize(vector3d::Cross(up, forward)); + + rot = matrix4x4d::MakeRotMatrix(other, up, forward); + rot = rot.InverseOf(); + SetRotMatrix(rot); + + /* + * We don'tuse DynamicBody::Disable because that also disables the geom + * and that must still get collisions. + */ + dBodyDisable(m_body); + ClearThrusterState(); + m_isLanded = true; + m_testLanded = false; + } + } +} + void Ship::TimeStepUpdate(const float timeStep) { dockingTimer = (dockingTimer-timeStep > 0 ? dockingTimer-timeStep : 0); /* ODE tri mesh likes to know our old position. */ @@ -143,6 +190,8 @@ void Ship::TimeStepUpdate(const float timeStep) { m_wheelState = CLAMP(m_wheelState, 0, 1); if((m_wheelState == 0) || (m_wheelState == 1)) m_wheelTransition = 0; } + + if(m_testLanded) TestLanded(); } void Ship::NotifyDeath(const Body* const dyingBody) { @@ -169,7 +218,7 @@ void Ship::SetDockedWith(SpaceStation* s) { matrix4x4d rot = stationRot * matrix4x4d::MakeRotMatrix(m_dockedWith->port.horiz, port_y, m_dockedWith->port.normal); vector3d pos = m_dockedWith->GetPosition() + stationRot*m_dockedWith->port.center; SetPosition(pos); - SetRotation(rot); + SetRotMatrix(rot); SetVelocity(vector3d(0, 0, 0)); SetAngVelocity(vector3d(0, 0, 0)); Enable(); @@ -253,7 +302,7 @@ static void render_coll_mesh(const CollMesh* m) { } void Ship::Render(const Frame* camFrame) { - if(!dBodyIsEnabled(m_body)) return; + if((!dBodyIsEnabled(m_body)) && !m_isLanded) return; const ShipType& stype = GetShipType(); params.angthrust[0] = m_angThrusters[0]; params.angthrust[1] = m_angThrusters[1]; diff --git a/src/ship.h b/src/ship.h index 322da74..ea32331 100644 --- a/src/ship.h +++ b/src/ship.h @@ -38,6 +38,7 @@ public: void SetDockingTimer(float t) { dockingTimer = t; } virtual void TimeStepUpdate(const float timeStep); virtual void NotifyDeath(const Body* const dyingBody); + virtual bool OnCollision(Body* b, Uint32 flags); class LaserObj : public Object { public: @@ -50,11 +51,14 @@ protected: void RenderLaserfire(void); SpaceStation* m_dockedWith; + bool m_isLanded; enum ShipType::Type m_shipType; Uint32 m_gunState[ShipType::GUNMOUNT_MAX]; private: bool IsFiringLasers(void); + void TestLanded(void); + bool m_testLanded; float m_wheelState; float m_wheelTransition; diff --git a/src/space.cpp b/src/space.cpp index 6e9b0be..4bee721 100644 --- a/src/space.cpp +++ b/src/space.cpp @@ -254,7 +254,7 @@ static void nearCallback(void* data, dGeomID oO, dGeomID o1) { for(int i = 0; i < MAX_CONTACTS; i++) { contact[i].surface.mode = dContactBounce; - contact[i].surface.mu = 0; + contact[i].surface.mu = 0.8; contact[i].surface.mu2 = 0; contact[i].surface.bounce = 0.1; contact[i].surface.bounce_vel = 0.1;