void Ship::AIAccelToModelRelativeVelocity(const vector3d v) { vector3d difVel = v - GetVelocity() * GetOrient(); // required change in velocity vector3d maxThrust = GetMaxThrust(difVel); vector3d maxFrameAccel = maxThrust * (Pi::game->GetTimeStep() / GetMass()); SetThrusterState(0, difVel.x / maxFrameAccel.x); SetThrusterState(1, difVel.y / maxFrameAccel.y); SetThrusterState(2, difVel.z / maxFrameAccel.z); // use clamping }
// position in ship's frame vector3d Ship::AIGetNextFramePos() { vector3d thrusters = GetThrusterState(); vector3d maxThrust = GetMaxThrust(thrusters); vector3d thrust = vector3d(maxThrust.x*thrusters.x, maxThrust.y*thrusters.y, maxThrust.z*thrusters.z); matrix4x4d rot; GetRotMatrix(rot); vector3d vel = GetVelocity() + rot * thrust * Pi::GetTimeStep() / GetMass(); vector3d pos = GetPosition() + vel * Pi::GetTimeStep(); return pos; }
void Ship::TimeStepUpdate(const float timeStep) { // XXX why not just f*****g do this rather than track down the // reason that ship geoms are being collision tested during launch if (m_flightState == FLYING) Enable(); else Disable(); vector3d maxThrust = GetMaxThrust(m_thrusters); AddRelForce(vector3d(maxThrust.x*m_thrusters.x, maxThrust.y*m_thrusters.y, maxThrust.z*m_thrusters.z)); AddRelTorque(GetShipType().angThrust * m_angThrusters); DynamicBody::TimeStepUpdate(timeStep); }
// diffvel is required change in velocity in object space // returns true if this can be done in a single timestep bool Ship::AIChangeVelBy(const vector3d &diffvel) { // counter external forces vector3d extf = GetExternalForce() * (Pi::game->GetTimeStep() / GetMass()); vector3d diffvel2 = diffvel - extf * GetOrient(); vector3d maxThrust = GetMaxThrust(diffvel2); vector3d maxFrameAccel = maxThrust * (Pi::game->GetTimeStep() / GetMass()); vector3d thrust(diffvel2.x / maxFrameAccel.x, diffvel2.y / maxFrameAccel.y, diffvel2.z / maxFrameAccel.z); SetThrusterState(thrust); // use clamping if (thrust.x*thrust.x > 1.0 || thrust.y*thrust.y > 1.0 || thrust.z*thrust.z > 1.0) return false; return true; }
// Change object-space velocity in direction of param vector3d Ship::AIChangeVelDir(const vector3d &reqdiffvel) { // get max thrust in desired direction after external force compensation vector3d maxthrust = GetMaxThrust(reqdiffvel); maxthrust += GetExternalForce() * GetOrient(); vector3d maxFA = maxthrust * (Pi::game->GetTimeStep() / GetMass()); maxFA.x = fabs(maxFA.x); maxFA.y = fabs(maxFA.y); maxFA.z = fabs(maxFA.z); // crunch diffvel by relative thruster power to get acceleration in right direction vector3d diffvel = reqdiffvel; if (fabs(diffvel.x) > maxFA.x) diffvel *= maxFA.x / fabs(diffvel.x); if (fabs(diffvel.y) > maxFA.y) diffvel *= maxFA.y / fabs(diffvel.y); if (fabs(diffvel.z) > maxFA.z) diffvel *= maxFA.z / fabs(diffvel.z); AIChangeVelBy(diffvel); // should always return true because it's already capped? return GetOrient() * (reqdiffvel - diffvel); // should be remaining diffvel to correct }
// diffvel is required change in velocity in object space // returns true if this can be done in a single timestep bool Ship::AIChangeVelBy(const vector3d &diffvel) { // counter external forces unless we're in an orbital station rotating frame matrix4x4d rot; GetRotMatrix(rot); vector3d diffvel2 = GetExternalForce() * Pi::GetTimeStep() / GetMass(); if (GetFrame()->IsStationRotFrame()) diffvel2 = diffvel; else diffvel2 = diffvel - diffvel2 * rot; vector3d maxThrust = GetMaxThrust(diffvel2); vector3d maxFrameAccel = maxThrust * Pi::GetTimeStep() / GetMass(); vector3d thrust(diffvel2.x / maxFrameAccel.x, diffvel2.y / maxFrameAccel.y, diffvel2.z / maxFrameAccel.z); SetThrusterState(thrust); // use clamping if (thrust.x*thrust.x > 1.0 || thrust.y*thrust.y > 1.0 || thrust.z*thrust.z > 1.0) return false; return true; }
void Ship::TimeStepUpdate(const float timeStep) { // If docked, station is responsible for updating position/orient of ship // but we call this crap anyway and hope it doesn't do anything bad vector3d maxThrust = GetMaxThrust(m_thrusters); vector3d thrust = vector3d(maxThrust.x*m_thrusters.x, maxThrust.y*m_thrusters.y, maxThrust.z*m_thrusters.z); AddRelForce(thrust); AddRelTorque(GetShipType().angThrust * m_angThrusters); DynamicBody::TimeStepUpdate(timeStep); // fuel use decreases mass, so do this as the last thing in the frame UpdateFuel(timeStep, thrust); if (m_landingGearAnimation) static_cast<SceneGraph::Model*>(GetModel())->UpdateAnimations(); }
void Ship::AIAccelToModelRelativeVelocity(const vector3d v) { // OK. For rotating frames linked to space stations we want to set // speed relative to non-rotating frame (so we apply Frame::GetStasisVelocityAtPosition. // For rotating frames linked to planets we want to set velocity relative to // surface, so we do not apply Frame::GetStasisVelocityAtPosition vector3d relVel = GetVelocity(); if (GetFrame()->IsStationRotFrame()) { relVel -= GetFrame()->GetStasisVelocityAtPosition(GetPosition()); } matrix4x4d m; GetRotMatrix(m); vector3d difVel = v - (relVel * m); // required change in velocity vector3d maxThrust = GetMaxThrust(difVel); vector3d maxFrameAccel = maxThrust * Pi::GetTimeStep() / GetMass(); SetThrusterState(0, difVel.x / maxFrameAccel.x); SetThrusterState(1, difVel.y / maxFrameAccel.y); SetThrusterState(2, difVel.z / maxFrameAccel.z); // use clamping }
// reldir*targdist and relvel are pos and vel of ship relative to target in ship's frame // endspeed is in direction of motion, must be positive // maxdecel is maximum deceleration thrust bool Ship::AIMatchPosVel2(const vector3d &reldir, double targdist, const vector3d &relvel, double endspeed, double maxdecel) { matrix4x4d rot; GetRotMatrix(rot); double parspeed = relvel.Dot(reldir); double ivel = calc_ivel(targdist, endspeed, maxdecel); double diffspeed = ivel - parspeed; vector3d diffvel = diffspeed * reldir * rot; bool rval = false; // crunch diffvel by relative thruster power to get acceleration in right direction if (diffspeed > 0.0) { vector3d maxFA = GetMaxThrust(diffvel) * Pi::game->GetTimeStep() / GetMass(); if (abs(diffvel.x) > maxFA.x) diffvel *= maxFA.x / abs(diffvel.x); if (abs(diffvel.y) > maxFA.y) diffvel *= maxFA.y / abs(diffvel.y); // if (abs(diffvel.z) > maxFA.z) diffvel *= maxFA.z / abs(diffvel.z); if (maxFA.z < diffspeed) rval = true; } // add perpendicular velocity vector3d perpvel = relvel - parspeed*reldir; diffvel -= perpvel * rot; AIChangeVelBy(diffvel); return rval; // true if acceleration was capped }