protected Matrix4 straightMissileSpawnTxfm(ISSpaceMissileTarget target, Vector3 launcherPos, Vector3 launcherVel, int id, int clusterSize) { const float sideDispersal = 2f; float angle = (float)Math.PI * 2f / (float)clusterSize * id; Vector3 toTarget = (target.position - launcherPos); float length = toTarget.Length; if (length < 0.0001f) { toTarget = -Vector3.UnitZ; } else { // normalize toTarget /= length; } Quaternion orientQuat = OpenTKHelper.neededRotation(Vector3.UnitZ, toTarget); Matrix4 orientMat = Matrix4.CreateFromQuaternion(orientQuat); Matrix4 disperalMat = Matrix4.CreateTranslation(sideDispersal * (float)Math.Cos(angle), sideDispersal * (float)Math.Sin(angle), 0f); return(disperalMat * orientMat * Matrix4.CreateTranslation(launcherPos) * Matrix4.CreateTranslation(toTarget * 7f)); }
public override void updateExecution(float timeElapsed) { base.updateExecution(timeElapsed); if (timeElapsed <= 0f) { return; } var mParams = missile.parameters as SSpaceMissileVisualParameters; var target = missile.target; // make visual direction "lean into" velocity Vector3 axis; float angle; OpenTKHelper.neededRotation(missile.visualDirection, missile.velocity.Normalized(), out axis, out angle); float abs = Math.Abs(angle); if (abs > mParams.pursuitVisualRotationRate && abs > 0f) { angle = angle / abs * mParams.pursuitVisualRotationRate; } Quaternion quat = Quaternion.FromAxisAngle(axis, angle); missile.visualDirection = Vector3.Transform(missile.visualDirection, quat); missile.visualSmokeAmmount = missile.velocity.LengthFast / mParams.pursuitMaxVelocity; }
protected void moveShips(float timeElapsed) { if (timeElapsed <= 0f) { return; } // make the target drone move from side to side localTime += timeElapsed; Vector3 pos = targetDrone.Pos; pos.Z = 30f * (float)Math.Sin(localTime); targetDrone.Pos = pos; // make the vandal ship orbit missile target Vector3 desiredPos; Vector3 desiredDir; float angle = localTime * 0.5f; float desiredXOffset = 100f * (float)Math.Cos(angle); float desiredYOffset = 20f * (float)Math.Sin(angle * 0.77f); float desiredZOffset = 80f * (float)Math.Sin(angle * 0.88f); Vector3 desiredOffset = new Vector3(desiredXOffset, desiredYOffset, desiredZOffset); var target = getTargetObject(); if (missileLauncher != MissileLaunchers.VandalShip || target == null || target == vandalShip) { desiredPos = new Vector3(100f, 0f, 0f); desiredDir = -Vector3.UnitX; } else if (target == main3dScene.ActiveCamera) { desiredPos = main3dScene.ActiveCamera.Pos + -main3dScene.ActiveCamera.Dir * 300f; Quaternion cameraOrient = OpenTKHelper.neededRotation(Vector3.UnitZ, -main3dScene.ActiveCamera.Up); desiredPos += Vector3.Transform(desiredOffset * 0.1f, cameraOrient); desiredDir = (target.Pos - vandalShip.Pos).Normalized(); } else { //float desiredZOffset = 5f * (float)Math.Sin(angle + 0.2f); desiredPos = target.Pos + desiredOffset; desiredDir = (target.Pos - vandalShip.Pos).Normalized(); } Vector3 desiredMotion = desiredPos - vandalShip.Pos; const float vel = 100f; float displacement = vel * timeElapsed; Vector3 vandalNewPos; if (displacement > desiredMotion.LengthFast) { vandalNewPos = desiredPos; } else { vandalNewPos = vandalShip.Pos + desiredMotion.Normalized() * displacement; } vandalVelocity = (vandalNewPos - vandalShip.Pos) / timeElapsed; vandalShip.Pos = vandalNewPos; Quaternion vandalOrient = OpenTKHelper.neededRotation(Vector3.UnitZ, desiredDir); vandalShip.Orient(desiredDir, Vector3.Transform(Vector3.UnitY, vandalOrient)); }
public void updateExecution(float timeElapsed) { if (timeElapsed <= 0f) { return; } var mParams = _missile.cluster.parameters; var target = _missile.cluster.target; // basic proportional navigation. see wikipedia Vector3 Vr = target.velocity - _missile.velocity; Vector3 R = target.position - _missile.position; Vector3 omega = Vector3.Cross(R, Vr) / R.LengthSquared; Vector3 latax = mParams.pursuitNavigationGain * Vector3.Cross(Vr, omega); if (mParams.pursuitAugmentedPN == true) { // this code is not tested as there are currently no targets with well defined accelerations Vector3 losDir = R.Normalized(); float targetAccLos = Vector3.Dot(target.acceleration, losDir); Vector3 targetLatAx = target.acceleration - targetAccLos * losDir; latax += mParams.pursuitNavigationGain * targetLatAx / 2f; } _missile._lataxDebug = latax; // apply latax var oldVelMag = _missile.velocity.LengthFast; _missile.velocity += latax * timeElapsed; float tempVelMag = _missile.velocity.LengthFast; if (oldVelMag != 0f) { float r = tempVelMag / oldVelMag; if (r > 1f) { _missile.velocity /= r; } } if (mParams.pursuitHitTimeCorrection) { // apply pursuit hit time correction float dist = R.LengthFast; if (dist != 0f) { Vector3 targetDir = R / dist; float v0 = -Vector3.Dot(Vr, targetDir); float t = _missile.cluster.timeToHit; float correctionAccMag = 2f * (dist - v0 * t) / t / t; Vector3 corrAcc = correctionAccMag * targetDir; _missile.velocity += corrAcc * timeElapsed; _missile._hitTimeCorrAccDebug = corrAcc; } } else { // hit time correction inactive. allow accelerating to achieve optimal velocity or forever oldVelMag = _missile.velocity.LengthFast; float velDelta = mParams.pursuitMaxAcc * timeElapsed; float newVelMag = Math.Min(oldVelMag + velDelta, mParams.pursuitMaxVelocity); if (oldVelMag != 0f) { _missile.velocity *= (newVelMag / oldVelMag); } } // make visual direction "lean into" velocity Vector3 axis; float angle; OpenTKHelper.neededRotation(_missile.visualDirection, _missile.velocity.Normalized(), out axis, out angle); float abs = Math.Abs(angle); if (abs > mParams.pursuitVisualRotationRate && abs > 0f) { angle = angle / abs * mParams.pursuitVisualRotationRate; } Quaternion quat = Quaternion.FromAxisAngle(axis, angle); _missile.visualDirection = Vector3.Transform(_missile.visualDirection, quat); }