public override void ExclusiveUpdate() { if (Plane.DriverSeat.Sitter == null) { return; // Don't fly when there's nobody driving this! } // TODO: Special case for motion on land: only push forward if W key is pressed? Or maybe apply that rule in general? // Collect the plane's relative vectors Vector3 forward = Quaternion.Transform(Vector3.UnitY, Entity.Orientation); Vector3 side = Quaternion.Transform(Vector3.UnitX, Entity.Orientation); Vector3 up = Quaternion.Transform(Vector3.UnitZ, Entity.Orientation); // Engines! if (Plane.FastOrSlow >= 0.0) { Vector3 force = forward * (Plane.RegularStrength + Plane.FastStrength) * Delta; entity.ApplyLinearImpulse(ref force); } double dotforw = Vector3.Dot(entity.LinearVelocity, forward); entity.ApplyImpulse(side * 5 + entity.Position, up * -Plane.RightLeft * entity.Mass * dotforw * 0.5 * Delta); entity.ApplyImpulse(forward * 5 + entity.Position, side * ((Plane.IRight ? 1 : 0) + (Plane.ILeft ? -1 : 0)) * entity.Mass * dotforw * 0.5 * Delta); entity.ApplyImpulse(forward * 5 + entity.Position, up * Plane.ForwBack * entity.Mass * 0.5 * Delta * dotforw); // Rotate the entity pre-emptively, and re-apply the movement velocity in this new direction! double vellen = entity.LinearVelocity.Length(); Vector3 normvel = entity.LinearVelocity / vellen; Vector3 norm_vel_transf = Quaternion.Transform(normvel, Quaternion.Inverse(entity.Orientation)); // Probably just 1,0,0 on whichever axis... can be simplified! Vector3 inc = entity.AngularVelocity * Delta * 0.5; Quaternion quat = new Quaternion(inc.X, inc.Y, inc.Z, 0); quat = quat * entity.Orientation; Quaternion orient = entity.Orientation; Quaternion.Add(ref orient, ref quat, out orient); orient.Normalize(); entity.Orientation = orient; entity.LinearVelocity = Quaternion.Transform(norm_vel_transf, orient) * vellen; entity.AngularVelocity *= 0.1; // Apply air drag Entity.ModifyLinearDamping(Plane.FastOrSlow < 0.0 ? 0.6 : 0.1); // TODO: arbitrary constant Entity.ModifyAngularDamping(0.5); // TODO: arbitrary constant // Ensure we're active if flying! Entity.ActivityInformation.Activate(); }
public override void ExclusiveUpdate() { if (Plane.Driver == null) // TODO: Engine on/off rather than driver check { return; // Don't fly when there's nobody driving this! } // TODO: Special case for motion on land: only push forward if FORWARD key is pressed? Or maybe apply that rule in general? // Collect the plane's relative vectors Vector3 forward = BEPUutilities.Quaternion.Transform(Vector3.UnitY, Entity.Orientation); Vector3 side = BEPUutilities.Quaternion.Transform(Vector3.UnitX, Entity.Orientation); Vector3 up = BEPUutilities.Quaternion.Transform(Vector3.UnitZ, Entity.Orientation); // Engines! if (Plane.FastOrSlow >= 0.0) { // TODO: Controls raise/lower engine thrust rather than continual direct control Vector3 force = forward * (Plane.RegularStrength + Plane.FastStrength * Plane.FastOrSlow) * Delta; entity.ApplyLinearImpulse(ref force); } // TODO: For very low forward velocities, turn weaker double dotforw = Vector3.Dot(entity.LinearVelocity, forward); double mval = 2.0 * (1.0 / Math.Max(1.0, entity.LinearVelocity.Length())); double rot_x = -Plane.ForwBack * Plane.StrPitch * Delta * dotforw * mval; double rot_y = Plane.RightLeft * dotforw * Plane.StrRoll * Delta * mval; double rot_z = -((Plane.IRight ? 1 : 0) + (Plane.ILeft ? -1 : 0)) * dotforw * Plane.StrYaw * Delta * mval; entity.AngularVelocity += BEPUutilities.Quaternion.Transform(new Vector3(rot_x, rot_y, rot_z), entity.Orientation); double vellen = entity.LinearVelocity.Length(); Vector3 newVel = forward * vellen; double forwVel = Vector3.Dot(entity.LinearVelocity, forward); double root = Math.Sqrt(Math.Sign(forwVel) * forwVel); entity.LinearVelocity += (newVel - entity.LinearVelocity) * MathHelper.Clamp(Delta, 0.01, 0.3) * Math.Min(2.0, root * Plane.ForwardHelper); // Apply air drag Entity.ModifyLinearDamping(Plane.FastOrSlow < 0.0 ? 0.5 : 0.1); // TODO: arbitrary constants Entity.ModifyAngularDamping(0.995); // TODO: arbitrary constant // Ensure we're active if flying! Entity.ActivityInformation.Activate(); }
public override void ExclusiveUpdate() { if (Helicopter.DriverSeat.Sitter == null) { return; // Don't fly when there's nobody driving this! } // Collect the helicopter's relative "up" vector Vector3 up = Quaternion.Transform(Vector3.UnitZ, Entity.Orientation); // Apply the amount of force necessary to counteract downward force, within a limit. // POTENTIAL: Adjust according to orientation? double uspeed = Math.Min(Helicopter.LiftStrength, -(Entity.LinearVelocity.Z + Entity.Space.ForceUpdater.Gravity.Z) * Entity.Mass); if (uspeed < 0f) { uspeed += (uspeed - Helicopter.FallStrength) * Helicopter.SprintOrWalk; } else { uspeed += (Helicopter.LiftStrength - uspeed) * Helicopter.SprintOrWalk; } Vector3 upvel = up * uspeed * Delta; Entity.ApplyLinearImpulse(ref upvel); // Rotate slightly to move in a direction. // At the same time, fight against existing rotation. Vector3 VecUp = new Vector3(Helicopter.RightLeft * 0.2f * Helicopter.TiltMod, Helicopter.ForwBack * -0.2f * Helicopter.TiltMod, 1); // TODO: Simplify yawrel calculation. double tyaw = (double)(Utilities.MatrixToAngles(Matrix.CreateFromQuaternion(Entity.Orientation)).Z *Utilities.PI180); Quaternion yawrel = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, tyaw); VecUp = Quaternion.Transform(VecUp, yawrel); VecUp.Y = -VecUp.Y; VecUp.Normalize(); Vector3 axis = Vector3.Cross(VecUp, up); double len = axis.Length(); if (len > 0) { axis /= len; double angle = (double)Math.Asin(len); if (!double.IsNaN(angle)) { double avel = Vector3.Dot(Entity.AngularVelocity, axis); Vector3 torque = axis * ((-angle) - 0.3f * avel); torque *= Entity.Mass * Delta * 30; Entity.ApplyAngularImpulse(ref torque); } } // Spin in place double rotation = (Helicopter.IRight ? -1f : 0f) + (Helicopter.ILeft ? 1f : 0f); if (rotation * rotation > 0f) { Vector3 rot = new Vector3(0, 0, rotation * 15f * Delta * Entity.Mass); Entity.ApplyAngularImpulse(ref rot); } // Apply air drag Entity.ModifyLinearDamping(0.3f); // TODO: arbitrary constant Entity.ModifyAngularDamping(0.6f); // TODO: arbitrary constant // Ensure we're active if flying! Entity.ActivityInformation.Activate(); }