public override void ExclusiveUpdate() { if (Helicopter.HeloPilot == null) { return; // Don't fly when there's nobody driving this! } // Collect the helicopter's relative "up" vector BEPUutilities.Vector3 up = BEPUutilities.Quaternion.Transform(BEPUutilities.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.HeloPilot.SprintOrWalk; } else { uspeed += (Helicopter.LiftStrength - uspeed) * Helicopter.HeloPilot.SprintOrWalk; } BEPUutilities.Vector3 upvel = up * uspeed * Delta; Entity.ApplyLinearImpulse(ref upvel); // Rotate slightly to move in a direction. // At the same time, fight against existing rotation. BEPUutilities.Vector3 VecUp = new BEPUutilities.Vector3(Helicopter.HeloPilot.XMove * 0.2f * Helicopter.HeloTiltMod, Helicopter.HeloPilot.YMove * -0.2f * Helicopter.HeloTiltMod, 1); // TODO: Simplify yawrel calculation. float tyaw = (float)(Utilities.MatrixToAngles(Matrix.CreateFromQuaternion(Entity.Orientation)).Z * Utilities.PI180); BEPUutilities.Quaternion yawrel = BEPUutilities.Quaternion.CreateFromAxisAngle(BEPUutilities.Vector3.UnitZ, tyaw); VecUp = BEPUutilities.Quaternion.Transform(VecUp, yawrel); VecUp.Normalize(); VecUp.Y = -VecUp.Y; BEPUutilities.Vector3 axis = BEPUutilities.Vector3.Cross(VecUp, up); double len = axis.Length(); if (len > 0) { axis /= len; float angle = (float)Math.Asin(len); if (!float.IsNaN(angle)) { double avel = BEPUutilities.Vector3.Dot(Entity.AngularVelocity, axis); BEPUutilities.Vector3 torque = axis * ((-angle) - 0.3f * avel); torque *= Entity.Mass * Delta * 30; Entity.ApplyAngularImpulse(ref torque); } } // Spin in place float rotation = (Helicopter.HeloPilot.ItemRight ? -1f : 0f) + (Helicopter.HeloPilot.ItemLeft ? 1f : 0f); if (rotation * rotation > 0f) { BEPUutilities.Vector3 rot = new BEPUutilities.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(); }
private void OnInputEvent(ReadOnlyCollection <SInputButtonEvent> buttonevents, string textinput) { foreach (var buttonEvent in buttonevents) { if (buttonEvent.button == EInputButton.MouseMiddleButton && buttonEvent.buttonEvent == EButtonEvent.Pressed) { CViewManager viewManager = m_gameWorld.ViewManager; int mouseAbsX = System.Windows.Forms.Cursor.Position.X - (int)viewManager.ScreenLeft; int mouseAbsY = System.Windows.Forms.Cursor.Position.Y - (int)viewManager.ScreenTop; if (mouseAbsX < 0 || mouseAbsY < 0) { return; } viewManager.GetViewInfo(out SSceneViewInfo viewInfo); Ray pickRay = Ray.GetPickRay(mouseAbsX, mouseAbsY, new ViewportF(0, 0, viewManager.ScreenWidth, viewManager.ScreenHeight), viewInfo.ViewMatrix * viewInfo.ProjectionMatrix); if (m_physicSpace.RayCast(pickRay.ToBepu(), 9999.0f, out RayCastResult result)) { float fieldRadius = 5.0f; float impulseStrength = 20.0f; List <BroadPhaseEntry> queryResults = new List <BroadPhaseEntry>(); BoundingSphere bs = new BoundingSphere(result.HitData.Location, fieldRadius); m_physicSpace.BroadPhase.QueryAccelerator.GetEntries(bs, queryResults); foreach (var entry in queryResults) { var entityCollision = entry as EntityCollidable; if (entityCollision != null) { var e = entityCollision.Entity; if (e.IsDynamic) { Vector3 toEntity = e.Position - result.HitData.Location; float length = toEntity.Length(); float strength = impulseStrength / length; toEntity.Y = 1.0f; toEntity.Normalize(); e.ApplyImpulse(e.Position, toEntity * strength); } } } } } } }