234 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			234 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "ship.h"
 | |
| #include "objimport.h"
 | |
| #include "frame.h"
 | |
| #include "l3d.h"
 | |
| #include "world_view.h"
 | |
| #include "space.h"
 | |
| #include "model_coll_mesh_data.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;
 | |
|   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();
 | |
|   SetGeomFromSBREModel(stype.sbreModel, ¶ms);
 | |
|   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);
 | |
| }
 | |
| 
 | |
| void Ship::SetThrusterState(enum ShipType::Thruster t, float level) {
 | |
|   m_thrusters[t] = level;
 | |
| }
 | |
| 
 | |
| void Ship::ClearThrusterState(void) {
 | |
|   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) {
 | |
|   /* 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<Object*>(&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) {
 | |
|     /* Launching. */
 | |
|     printf("Buhbai!\n");
 | |
|     m_dockedWith = 0;
 | |
|     vector3d pos = GetPosition();
 | |
|     pos.x += 5000;
 | |
|     SetPosition(pos);
 | |
|   } else {
 | |
|     m_dockedWith = s;
 | |
|     SetVelocity(vector3d(0, 0, 0));
 | |
|     SetAngVelocity(vector3d(0, 0, 0));
 | |
|   }
 | |
| }
 | |
| 
 | |
| 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;
 | |
| }
 | |
| 
 | |
| /* 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) {
 | |
|   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();
 | |
| }
 | |
| 
 | 
