#include "ship.h" #include "frame.h" #include "l3d.h" #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 }, { 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) : DynamicBody() { m_wheelTransition = 0; 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); for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) { m_tempLaserGeom[i] = 0; m_gunState[i] = 0; } memset(m_thrusters, 0, sizeof(m_thrusters)); const ShipType& stype = GetShipType(); SetModel(stype.sbreModel); SetMassDistributionFromCollMesh(GetModelSBRECollMesh(stype.sbreModel)); GeomsSetBody(m_body); UpdateMass(); } void Ship::UpdateMass(void) { shipstats_t s; CalcStats(&s); dMassAdjust(&m_mass, s.total_mass*1000); dBodySetMass(m_body, &m_mass); } vector3d Ship::CalcRotDamping(void) { /* Rotation damping. */ const dReal* _av = dBodyGetAngularVel(m_body); vector3d angVel(_av[0], _av[1], _av[2]); matrix4x4d rot; GetRotMatrix(rot); angVel = rot.InverseOf() * angVel; return angVel * 0.6; } void Ship::SetThrusterState(enum ShipType::Thruster t, float level) { m_thrusters[t] = level; } void Ship::ClearThrusterState(void) { SetAngThrusterState(0, 0.0f); SetAngThrusterState(1, 0.0f); SetAngThrusterState(2, 0.0f); for(int i = 0; i < ShipType::THRUSTER_MAX; i++) m_thrusters[i] = 0; } /* Hyperspace range is: * (200 * hyperspace_class^2) / total_mass (in tonnes) */ void Ship::CalcStats(shipstats_t* stats) { const ShipType& stype = GetShipType(); stats->max_capacity = stype.capacity; stats->used_capacity = 0; for(int i = 0; i < Equip::SLOT_MAX; i++) { for(int j = 0; j < stype.equipSlotCapacity[i]; j++) { Equip::Type t = m_equipment.Get((Equip::Slot)i, j); if(t) stats->used_capacity += EquipType::types[t].mass; } } stats->free_capacity = stats->max_capacity - stats->used_capacity; stats->total_mass = stats->used_capacity + stype.hullMass; Equip::Type t = m_equipment.Get(Equip::SLOT_ENGINE); float hyperclass = EquipType::types[t].pval; stats->hyperspace_range = 200 * hyperclass * hyperclass / stats->total_mass; } void Ship::TimeStepUpdate(const float timeStep) { dockingTimer = (dockingTimer-timeStep > 0 ? dockingTimer-timeStep : 0); /* ODE tri mesh likes to know our old position. */ TriMeshUpdateLastPos(); const ShipType& stype = GetShipType(); for(int i = 0; i < ShipType::THRUSTER_MAX; i++) { float force = timeStep * stype.linThrust[i] * m_thrusters[i]; switch(i) { case ShipType::THRUSTER_REAR: case ShipType::THRUSTER_FRONT: dBodyAddRelForce(m_body, 0, 0, force); break; case ShipType::THRUSTER_TOP: case ShipType::THRUSTER_BOTTOM: dBodyAddRelForce(m_body, 0, force, 0); break; case ShipType::THRUSTER_LEFT: case ShipType::THRUSTER_RIGHT: dBodyAddRelForce(m_body, force, 0, 0); break; } } dBodyAddRelTorque(m_body, stype.angThrust*m_angThrusters[0], stype.angThrust*m_angThrusters[1], stype.angThrust*m_angThrusters[2]); /* LASERZ!! */ for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) { /* Free old temp laser geoms. */ if(m_tempLaserGeom[i]) dGeomDestroy(m_tempLaserGeom[i]); m_tempLaserGeom[i] = 0; if(!m_gunState[i]) continue; dGeomID ray = dCreateRay(GetFrame()->GetSpaceID(), 10000); const vector3d pos = GetPosition(); const vector3f _dir = stype.gunMount[i].dir; vector3d dir = vector3d(_dir.x, _dir.y, _dir.z); matrix4x4d m; GetRotMatrix(m); dir = m.ApplyRotationOnly(dir); dGeomRaySet(ray, pos.x, pos.y, pos.z, dir.x, dir.y, dir.z); dGeomSetData(ray, static_cast(&m_laserCollisionObj)); m_tempLaserGeom[i] = ray; } if(m_wheelTransition != 0.0f) { m_wheelState += m_wheelTransition*timeStep; m_wheelState = CLAMP(m_wheelState, 0, 1); if((m_wheelState == 0) || (m_wheelState == 1)) m_wheelTransition = 0; } } void Ship::NotifyDeath(const Body* const dyingBody) { if(GetNavTarget() == dyingBody) SetNavTarget(0); if(GetCombatTarget() == dyingBody) SetCombatTarget(0); } const ShipType& Ship::GetShipType(void) { return ShipType::types[m_shipType]; } void Ship::SetDockedWith(SpaceStation* s) { if(m_dockedWith && !s) { /* * 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); 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; dockingTimer = 0.0f; SetVelocity(vector3d(0, 0, 0)); SetAngVelocity(vector3d(0, 0, 0)); Disable(); } } void Ship::SetGunState(int idx, int state) { m_gunState[idx] = state; } void Ship::SetWheelState(bool down) { if(down) m_wheelTransition = 1; else m_wheelTransition = -1; } void Ship::SetNavTarget(Body* const target) { m_navTarget = target; L3D::world_view->UpdateCommsOptions(); } void Ship::SetCombatTarget(Body* const target) { m_combatTarget = target; L3D::world_view->UpdateCommsOptions(); } /* Assumed to be at model coords. */ void Ship::RenderLaserfire(void) { const ShipType& stype = GetShipType(); glDisable(GL_LIGHTING); for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) { if(!m_gunState[i]) continue; glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT); glColor3f(1, 0, 0); glLineWidth(2.0f); glBegin(GL_LINES); vector3f pos = stype.gunMount[i].pos; glVertex3f(pos.x, pos.y, pos.z); glVertex3fv(&((10000)*stype.gunMount[i].dir)[0]); glEnd(); glPopAttrib(); } glEnable(GL_LIGHTING); } 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(); glColor3f(1,1,1); glDepthRange(0, 1.0f-0.0002f); for(int i = 0; i < m->ni; i += 3) { glBegin(GL_LINE_LOOP); glVertex3fv(&m->pVertex[3*m->pIndex[i]]); glVertex3fv(&m->pVertex[3*m->pIndex[i+1]]); glVertex3fv(&m->pVertex[3*m->pIndex[i+2]]); glEnd(); } glDepthRange(0.0, 1.0); glEnable(GL_LIGHTING); } void Ship::Render(const Frame* camFrame) { if(!dBodyIsEnabled(m_body)) return; const ShipType& stype = GetShipType(); params.angthrust[0] = m_angThrusters[0]; params.angthrust[1] = m_angThrusters[1]; params.angthrust[2] = m_angThrusters[2]; params.linthrust[0] = m_thrusters[ShipType::THRUSTER_RIGHT] - m_thrusters[ShipType::THRUSTER_LEFT]; params.linthrust[1] = m_thrusters[ShipType::THRUSTER_TOP] - m_thrusters[ShipType::THRUSTER_BOTTOM]; params.linthrust[2] = m_thrusters[ShipType::THRUSTER_REAR] - m_thrusters[ShipType::THRUSTER_FRONT]; params.pAnim[ASRC_SECFRAC] = L3D::GetGameTime(); params.pAnim[ASRC_MINFRAC] = L3D::GetGameTime() / 60; params.pAnim[ASRC_HOURFRAC] = L3D::GetGameTime() / 3600.0f; params.pAnim[ASRC_DAYFRAC] = L3D::GetGameTime() / (24*3600.0f); params.pAnim[ASRC_GEAR] = m_wheelState; params.pFlag[AFLAG_GEAR] = m_wheelState != 0.0f; strncpy(params.pText[0], GetLabel().c_str(), sizeof(params.pText)); RenderSbreModel(camFrame, stype.sbreModel, ¶ms); glPushMatrix(); TransformToModelCoords(camFrame); //render_coll_mesh(sbreCollMesh); RenderLaserfire(); glPopMatrix(); }