public Vector3 GetAngularVelocity(Vector3 control) { /*if (m_grid.GridControllers.IsControlledByLocalPlayer || (!m_grid.GridControllers.IsControlledByAnyPlayer && Sync.IsServer) || (false && Sync.IsServer)) {*/ // Not checking whether engines are running, since ControlTorque should be 0 when // engines are stopped (set by cockpit). if (ResourceSink.SuppliedRatio > 0f && m_grid.Physics != null && m_grid.Physics.Enabled && !m_grid.Physics.RigidBody.IsFixed) { Matrix invWorldRot = m_grid.PositionComp.WorldMatrixInvScaled.GetOrientation(); Matrix worldRot = m_grid.WorldMatrix.GetOrientation(); Vector3 localAngularVelocity = Vector3.Transform(m_grid.Physics.AngularVelocity, ref invWorldRot); // CH: CAUTION: Don't try to use InertiaTensor, although it might be more intuitive in some cases. // I tried it and it's not an inverse of the InverseInertiaTensor! Only the InverseInertiaTensor seems to be correct! var invTensor = m_grid.Physics.RigidBody.InverseInertiaTensor; Vector3 invTensorVector = new Vector3(invTensor.M11, invTensor.M22, invTensor.M33); var minInvTensor = invTensorVector.Min(); // Max rotation limiter float divider = Math.Max(1, minInvTensor * INV_TENSOR_MAX_LIMIT); // Calculate the velocity correction torque Vector3 correctionTorque = Vector3.Zero; Vector3 desiredAcceleration = desiredAcceleration = (m_overrideTargetVelocity - localAngularVelocity) * MyEngineConstants.UPDATE_STEPS_PER_SECOND; // The correction is done by overridden gyros and by the remaining power of the controlled gyros // This is not entirely physically correct, but it feels good float correctionForce = m_maxOverrideForce + m_maxGyroForce * (1.0f - control.Length()); // This is to ensure that the correction is done uniformly in all axes desiredAcceleration = desiredAcceleration * Vector3.Normalize(invTensorVector); Vector3 desiredTorque = desiredAcceleration / invTensorVector; float framesToDesiredVelocity = desiredTorque.Length() / correctionForce; // If we are very close to the target velocity, just set it without applying the torque const float minimalBypassVelocity = 0.005f * 0.005f; if (framesToDesiredVelocity < 0.5f && m_overrideTargetVelocity.LengthSquared() < minimalBypassVelocity) { return m_overrideTargetVelocity; } if (!Vector3.IsZero(desiredAcceleration, 0.0001f)) { // The smoothing coefficient is here to avoid the slowdown stopping the ship abruptly, which doesn't look good float smoothingCoeff = 1.0f - 0.8f / (float)Math.Exp(0.5f * framesToDesiredVelocity); correctionTorque = Vector3.ClampToSphere(desiredTorque, correctionForce) * 0.95f * smoothingCoeff + desiredTorque * 0.05f * (1.0f - smoothingCoeff); // A little black magic to make slowdown on large ships bigger if (m_grid.GridSizeEnum == MyCubeSize.Large) correctionTorque *= 2.0f; } Torque = (control * m_maxGyroForce + correctionTorque) / divider; Torque *= ResourceSink.SuppliedRatio; if (Torque.LengthSquared() > 0.0001f) { // Manually apply torque and use minimal component of inverted inertia tensor to make rotate same in all axes var delta = Torque * new Vector3(minInvTensor) * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; var newAngularVelocity = localAngularVelocity + delta; return Vector3.Transform(newAngularVelocity, ref worldRot); } const float stoppingVelocitySq = 0.0003f * 0.0003f; if (control == Vector3.Zero && m_overrideTargetVelocity == Vector3.Zero && m_grid.Physics.AngularVelocity != Vector3.Zero && m_grid.Physics.AngularVelocity.LengthSquared() < stoppingVelocitySq && m_grid.Physics.RigidBody.IsActive) { return Vector3.Zero; } } //} if (m_grid.Physics != null) { return m_grid.Physics.AngularVelocity; } else { return Vector3.Zero; } }
public void RenderObject(MDL0ObjectNode p, TKContext ctx, ModelPanel mainWindow, float maxDrawPriority) { if (p._render) { if (_dontRenderOffscreen) { Vector3 min = new Vector3(float.MaxValue); Vector3 max = new Vector3(float.MinValue); if (p._manager != null) foreach (Vertex3 vertex in p._manager._vertices) { Vector3 v = mainWindow.Project(vertex.WeightedPosition); min.Min(v); max.Max(v); } if (max._x < 0 || min._x > mainWindow.Size.Width || max._y < 0 || min._y > mainWindow.Size.Height) return; } if (_renderPolygons) { float polyOffset = 0.0f; //polyOffset -= p.DrawPriority; //polyOffset += maxDrawPriority; if (_renderWireframe) polyOffset += 1.0f; if (polyOffset != 0) { GL.Enable(EnableCap.PolygonOffsetFill); GL.PolygonOffset(1.0f, polyOffset); } else GL.Disable(EnableCap.PolygonOffsetFill); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); p.Render(ctx, false, mainWindow); } if (_renderWireframe) { GL.Disable(EnableCap.PolygonOffsetFill); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); GL.LineWidth(0.5f); p.Render(ctx, true, mainWindow); } } }
private void UpdateOverriddenGyros() { // Not checking whether engines are running, since ControlTorque should be 0 when // engines are stopped (set by cockpit). if (ResourceSink.SuppliedRatio > 0f && m_grid.Physics.Enabled && !m_grid.Physics.RigidBody.IsFixed) { Matrix invWorldRot = m_grid.PositionComp.WorldMatrixInvScaled.GetOrientation(); Matrix worldRot = m_grid.WorldMatrix.GetOrientation(); Vector3 localAngularVelocity = Vector3.Transform(m_grid.Physics.AngularVelocity, ref invWorldRot); Vector3 desiredAcceleration = (m_overrideTargetVelocity - localAngularVelocity) * MyEngineConstants.UPDATE_STEPS_PER_SECOND; // CH: CAUTION: Don't try to use InertiaTensor, although it might be more intuitive in some cases. // I tried it and it's not an inverse of the InverseInertiaTensor! Only the InverseInertiaTensor seems to be correct! var invTensor = m_grid.Physics.RigidBody.InverseInertiaTensor; Vector3 invTensorVector = new Vector3(invTensor.M11, invTensor.M22, invTensor.M33); var minInvTensor = invTensorVector.Min(); // This is to ensure that the correction is done uniformly in all axes desiredAcceleration = desiredAcceleration * Vector3.Normalize(invTensorVector); // Calculate the desired velocity correction torque Vector3 desiredTorque = desiredAcceleration / invTensorVector; // Apply rotation limiters float divider = Math.Max(1, minInvTensor * INV_TENSOR_MAX_LIMIT); Torque = (ControlTorque * m_maxGyroForce + desiredTorque) / divider; Torque *= ResourceSink.SuppliedRatio; // Damp the torque dynamically so stopping the ship abruptly looks good Torque *= m_framesFromLastOverride / MyEngineConstants.UPDATE_STEPS_PER_SECOND; if (m_framesFromLastOverride < MyEngineConstants.UPDATE_STEPS_PER_SECOND) m_framesFromLastOverride++; if (Torque.LengthSquared() > 0.0001f) m_grid.Physics.AddForce(MyPhysicsForceType.ADD_BODY_FORCE_AND_BODY_TORQUE, null, null, Torque); } }
public static Vector3 Min(Vector3 val1, Vector3 val2) => Vector3.Min(val1, val2);
public void ExpandVolume(Vector3 value) { _min.Min(value); _max.Max(value); }
public void GetBox(out Vector3 min, out Vector3 max) { min = new Vector3(float.MaxValue); max = new Vector3(float.MinValue); if (_manager != null && _manager._vertices != null) foreach (Vertex3 vertex in _manager._vertices) { Vector3 v = vertex.WeightedPosition; min.Min(v); max.Max(v); } }