Example #1
0
        public override bool Attach(MyMotorRotor rotor, bool updateSync = false, bool updateGroup = true)
        {
            if (CubeGrid.Physics == null || SafeConstraint != null)
            {
                return(false);
            }

            Debug.Assert(SafeConstraint == null);

            if (CubeGrid.Physics.Enabled && rotor != null)
            {
                m_rotorBlock   = rotor;
                m_rotorBlockId = rotor.EntityId;

                if (updateSync)
                {
                    SyncObject.AttachRotor(m_rotorBlock);
                }

                m_rotorGrid = m_rotorBlock.CubeGrid;
                if (m_rotorGrid.Physics == null)
                {
                    return(false);
                }
                var rotorBody = m_rotorGrid.Physics.RigidBody;
                var data      = new HkLimitedHingeConstraintData();
                m_motor = new HkVelocityConstraintMotor(1.0f, 1000000f);

                data.SetSolvingMethod(HkSolvingMethod.MethodStabilized);
                data.Motor = m_motor;
                data.DisableLimits();

                var posA      = DummyPosition;
                var posB      = rotor.Position * rotor.CubeGrid.GridSize;
                var axisA     = PositionComp.LocalMatrix.Up;
                var axisAPerp = PositionComp.LocalMatrix.Forward;
                var axisB     = rotor.PositionComp.LocalMatrix.Up;
                var axisBPerp = rotor.PositionComp.LocalMatrix.Forward;
                data.SetInBodySpace(ref posA, ref posB, ref axisA, ref axisB, ref axisAPerp, ref axisBPerp);
                m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, rotorBody, data);

                m_constraint.WantRuntime = true;
                CubeGrid.Physics.AddConstraint(m_constraint);
                m_constraint.Enabled = true;

                SetAngleToPhysics();

                m_rotorBlock.Attach(this);

                if (updateGroup)
                {
                    OnConstraintAdded(GridLinkTypeEnum.Physical, m_rotorGrid);
                    OnConstraintAdded(GridLinkTypeEnum.Logical, m_rotorGrid);
                }
                m_isAttached = true;
                return(true);
            }

            return(false);
        }
Example #2
0
 void SetAngleToPhysics()
 {
     if (SafeConstraint != null)
     {
         HkLimitedHingeConstraintData.SetCurrentAngle(SafeConstraint, m_currentAngle);
     }
 }
Example #3
0
        private void SetConstraintPosition(MyAttachableTopBlockBase rotor, HkLimitedHingeConstraintData data)
        {
            var posA      = DummyPosition;
            var posB      = rotor.Position * rotor.CubeGrid.GridSize;
            var axisA     = PositionComp.LocalMatrix.Up;
            var axisAPerp = PositionComp.LocalMatrix.Forward;
            var axisB     = rotor.PositionComp.LocalMatrix.Up;
            var axisBPerp = rotor.PositionComp.LocalMatrix.Forward;

            data.SetInBodySpace(posA, posB, axisA, axisB, axisAPerp, axisBPerp, CubeGrid.Physics, TopGrid.Physics);
        }
        void SetSafeAngles(bool lowerIsFixed, float lowerLimit, float upperLimit)
        {
            // When out of limits get to limits
            if (m_currentAngle < lowerLimit)
            {
                ScaleUp();
            }

            if (m_currentAngle > upperLimit)
            {
                ScaleDown();
            }

            // Min must be smaller than max
            if (upperLimit < lowerLimit)
            {
                if (lowerIsFixed)
                {
                    upperLimit = lowerLimit;
                }
                else
                {
                    lowerLimit = upperLimit;
                }
            }

            if (lowerLimit < MIN_LOWER_LIMIT)
            {
                lowerLimit = float.NegativeInfinity;
            }

            if (upperLimit > MAX_UPPER_LIMIT)
            {
                upperLimit = float.PositiveInfinity;
            }

            m_minAngle.Value = lowerLimit;
            m_maxAngle.Value = upperLimit;

            m_limitsActive = false;
            TryActivateLimits();
            if (SafeConstraint != null)
            {
                m_currentAngle = HkLimitedHingeConstraintData.GetCurrentAngle(SafeConstraint);
            }
            UpdateText();

            RaisePropertiesChanged();
        }
Example #5
0
        protected override bool Attach(MyAttachableTopBlockBase rotor, bool updateGroup = true)
        {
            if (rotor is MyMotorRotor && base.Attach(rotor, updateGroup))
            {
                Debug.Assert(rotor != null, "Rotor cannot be null!");
                Debug.Assert(m_constraint == null, "Already attached, call detach first!");
                Debug.Assert(m_connectionState.Value.TopBlockId == 0 || m_connectionState.Value.TopBlockId == rotor.EntityId, "m_rotorBlockId must be set prior calling Attach");


                var rotorBody = m_topGrid.Physics.RigidBody;
                var data      = new HkLimitedHingeConstraintData();
                m_motor = new HkVelocityConstraintMotor(1.0f, 1000000f);

                data.SetSolvingMethod(HkSolvingMethod.MethodStabilized);
                data.Motor = m_motor;
                data.DisableLimits();

                var posA      = DummyPosition;
                var posB      = rotor.Position * rotor.CubeGrid.GridSize;
                var axisA     = PositionComp.LocalMatrix.Up;
                var axisAPerp = PositionComp.LocalMatrix.Forward;
                var axisB     = rotor.PositionComp.LocalMatrix.Up;
                var axisBPerp = rotor.PositionComp.LocalMatrix.Forward;
                data.SetInBodySpace(posA, posB, axisA, axisB, axisAPerp, axisBPerp, CubeGrid.Physics, m_topGrid.Physics);
                m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, rotorBody, data);

                m_constraint.WantRuntime = true;
                CubeGrid.Physics.AddConstraint(m_constraint);
                if (!m_constraint.InWorld)
                {
                    CubeGrid.Physics.RemoveConstraint(m_constraint);
                    m_constraint.Dispose();
                    m_constraint = null;
                    return(false);
                }

                m_constraint.Enabled = true;

                SetAngleToPhysics();

                m_topBlock.Attach(this);

                m_isAttached = true;
                UpdateText();
                return(true);
            }
            return(false);
        }
        public static void SetInBodySpace(this HkLimitedHingeConstraintData data, Vector3 posA, Vector3 posB, Vector3 axisA, Vector3 axisB, Vector3 axisAPerp, Vector3 axisBPerp, MyPhysicsBody bodyA, MyPhysicsBody bodyB)
        {
            if (bodyA.IsWelded)
            {
                posA      = Vector3.Transform(posA, bodyA.WeldInfo.Transform);
                axisA     = Vector3.TransformNormal(axisA, bodyA.WeldInfo.Transform);
                axisAPerp = Vector3.TransformNormal(axisAPerp, bodyA.WeldInfo.Transform);
            }
            if (bodyB.IsWelded)
            {
                posB      = Vector3.Transform(posB, bodyB.WeldInfo.Transform);
                axisB     = Vector3.TransformNormal(axisB, bodyB.WeldInfo.Transform);
                axisBPerp = Vector3.TransformNormal(axisBPerp, bodyB.WeldInfo.Transform);
            }

            data.SetInBodySpaceInternal(ref posA, ref posB, ref axisA, ref axisB, ref axisAPerp, ref axisBPerp);
        }
Example #7
0
        protected override bool CreateConstraint(MyAttachableTopBlockBase rotor)
        {
            if (!base.CreateConstraint(rotor))
            {
                return(false);
            }
            Debug.Assert(rotor != null, "Rotor cannot be null!");
            Debug.Assert(m_constraint == null, "Already attached, call detach first!");
            Debug.Assert(
                m_connectionState.Value.TopBlockId == 0 || m_connectionState.Value.TopBlockId == rotor.EntityId,
                "m_rotorBlockId must be set prior calling Attach");


            var rotorBody = TopGrid.Physics.RigidBody;
            var data      = new HkLimitedHingeConstraintData();

            m_motor = new HkVelocityConstraintMotor(1.0f, 1000000f);

            data.SetSolvingMethod(HkSolvingMethod.MethodStabilized);
            data.Motor = m_motor;
            data.DisableLimits();

            SetConstraintPosition(rotor, data);
            m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, rotorBody, data);

            m_constraint.WantRuntime = true;
            CubeGrid.Physics.AddConstraint(m_constraint);
            if (!m_constraint.InWorld)
            {
                CubeGrid.Physics.RemoveConstraint(m_constraint);
                m_constraint.Dispose();
                m_constraint = null;
                return(false);
            }

            m_constraint.Enabled = true;

            SetAngleToPhysics();
            return(true);
        }
Example #8
0
        public override void UpdateBeforeSimulation()
        {
            base.UpdateBeforeSimulation();

            if (MyFakes.REPORT_INVALID_ROTORS)
            {
                //Debug.Assert(m_constraint != null, "Rotor constraint is not created although it should be!");
            }
            if (CheckVelocities())
            {
                return;
            }

            if (m_rotorGrid == null || SafeConstraint == null)
            {
                return;
            }
            if (SafeConstraint.RigidBodyA == SafeConstraint.RigidBodyB) //welded
            {
                SafeConstraint.Enabled = false;
                return;
            }

            var oldAngle = m_currentAngle;

            m_currentAngle = HkLimitedHingeConstraintData.GetCurrentAngle(SafeConstraint);
            if (oldAngle != m_currentAngle)
            {
                UpdateText();
            }
            var data = (HkLimitedHingeConstraintData)m_constraint.ConstraintData;

            data.MaxFrictionTorque = BrakingTorque;

            TryActivateLimits();

            if (!m_limitsActive)
            {
                data.DisableLimits();
            }
            else if (!data.MinAngularLimit.IsEqual(m_minAngle) || !data.MaxAngularLimit.IsEqual(m_maxAngle))
            {
                data.MinAngularLimit = m_minAngle;
                data.MaxAngularLimit = m_maxAngle;

                // Activate even when motor is stopped, so it fixes it's limits
                CubeGrid.Physics.RigidBody.Activate();
                m_rotorGrid.Physics.RigidBody.Activate();
            }
            if (m_limitsActive)
            {
                var handle = LimitReached;
                if (handle != null)
                {
                    if (oldAngle > data.MinAngularLimit && m_currentAngle <= data.MinAngularLimit)
                    {
                        handle(false);
                    }
                    if (oldAngle < data.MaxAngularLimit && m_currentAngle >= data.MaxAngularLimit)
                    {
                        handle(true);
                    }
                }
            }

            m_motor.MaxForce       = Torque;
            m_motor.MinForce       = -Torque;
            m_motor.VelocityTarget = TargetVelocity * Sync.RelativeSimulationRatio;

            bool motorRunning = IsWorking;

            if (data.MotorEnabled != motorRunning)
            {
                data.SetMotorEnabled(m_constraint, motorRunning);
            }

            if (motorRunning && m_rotorGrid != null && !m_motor.VelocityTarget.IsZero())
            {
                CubeGrid.Physics.RigidBody.Activate();
                m_rotorGrid.Physics.RigidBody.Activate();
            }
        }
        public override bool Attach(MyMotorRotor rotor, bool updateGroup = true)
        {
            Debug.Assert(rotor != null, "Rotor cannot be null!");
            Debug.Assert(m_constraint == null, "Already attached, call detach first!");
            Debug.Assert(m_rotorBlockId.Value.OtherEntityId == 0 || m_rotorBlockId.Value.OtherEntityId == rotor.EntityId, "m_rotorBlockId must be set prior calling Attach");

            if (rotor == null || rotor.CubeGrid == null || MarkedForClose || Closed || CubeGrid.MarkedForClose || CubeGrid.Closed || rotor.MarkedForClose || rotor.Closed ||
                rotor.CubeGrid.MarkedForClose || rotor.CubeGrid.Closed)
            {
                return(false);
            }

            if (CubeGrid.Physics != null && CubeGrid.Physics.Enabled)
            {
                m_rotorBlock = rotor;
                m_rotorGrid  = m_rotorBlock.CubeGrid;
                if (m_rotorGrid.Physics == null)
                {
                    return(false);
                }
                if (CubeGrid.Physics.RigidBody == m_rotorGrid.Physics.RigidBody)
                {
                    if (updateGroup && m_welded)
                    {
                        OnConstraintAdded(GridLinkTypeEnum.Physical, m_rotorGrid);
                        OnConstraintAdded(GridLinkTypeEnum.Logical, m_rotorGrid);
                    }
                    m_isAttached = true;
                    return(true);
                }
                var rotorBody = m_rotorGrid.Physics.RigidBody;
                var data      = new HkLimitedHingeConstraintData();
                m_motor = new HkVelocityConstraintMotor(1.0f, 1000000f);

                data.SetSolvingMethod(HkSolvingMethod.MethodStabilized);
                data.Motor = m_motor;
                data.DisableLimits();

                var posA      = DummyPosition;
                var posB      = rotor.Position * rotor.CubeGrid.GridSize;
                var axisA     = PositionComp.LocalMatrix.Up;
                var axisAPerp = PositionComp.LocalMatrix.Forward;
                var axisB     = rotor.PositionComp.LocalMatrix.Up;
                var axisBPerp = rotor.PositionComp.LocalMatrix.Forward;
                data.SetInBodySpace(posA, posB, axisA, axisB, axisAPerp, axisBPerp, CubeGrid.Physics, m_rotorGrid.Physics);
                m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, rotorBody, data);

                m_constraint.WantRuntime = true;
                CubeGrid.Physics.AddConstraint(m_constraint);
                if (!m_constraint.InWorld)
                {
                    CubeGrid.Physics.RemoveConstraint(m_constraint);
                    m_constraint.Dispose();
                    m_constraint = null;
                    return(false);
                }
                m_constraint.Enabled = true;

                SetAngleToPhysics();

                m_rotorBlock.Attach(this);

                if (updateGroup)
                {
                    OnConstraintAdded(GridLinkTypeEnum.Physical, m_rotorGrid);
                    OnConstraintAdded(GridLinkTypeEnum.Logical, m_rotorGrid);
                    m_rotorGrid.OnPhysicsChanged += cubeGrid_OnPhysicsChanged;
                }
                m_isAttached = true;
                UpdateText();
                return(true);
            }

            return(false);
        }
        public override bool Attach(MyMotorRotor rotor, bool updateGroup = true)
        {
            Debug.Assert(rotor != null, "Rotor cannot be null!");
            Debug.Assert(m_constraint == null, "Already attached, call detach first!");
            Debug.Assert(m_rotorBlockId.Value.OtherEntityId == 0 || m_rotorBlockId.Value.OtherEntityId == rotor.EntityId, "m_rotorBlockId must be set prior calling Attach");

            if (rotor == null || MarkedForClose || Closed || rotor.MarkedForClose || rotor.Closed || CubeGrid.MarkedForClose || CubeGrid.Closed)
            {
                return false;
            }

            if (CubeGrid.Physics != null && CubeGrid.Physics.Enabled)
            {
                m_rotorBlock = rotor;
                m_rotorGrid = m_rotorBlock.CubeGrid;
                if (m_rotorGrid.Physics == null)
                    return false;
                if (CubeGrid.Physics.RigidBody == m_rotorGrid.Physics.RigidBody)
                {
                    if (updateGroup && m_welded)
                    {
                        OnConstraintAdded(GridLinkTypeEnum.Physical, m_rotorGrid);
                        OnConstraintAdded(GridLinkTypeEnum.Logical, m_rotorGrid);
                   }
                    m_isAttached = true;
                    return true;
                }
                var rotorBody = m_rotorGrid.Physics.RigidBody;
                var data = new HkLimitedHingeConstraintData();
                m_motor = new HkVelocityConstraintMotor(1.0f, 1000000f);

                data.SetSolvingMethod(HkSolvingMethod.MethodStabilized);
                data.Motor = m_motor;
                data.DisableLimits();

                var posA = DummyPosition;
                var posB = rotor.Position * rotor.CubeGrid.GridSize;
                var axisA = PositionComp.LocalMatrix.Up;
                var axisAPerp = PositionComp.LocalMatrix.Forward;
                var axisB = rotor.PositionComp.LocalMatrix.Up;
                var axisBPerp = rotor.PositionComp.LocalMatrix.Forward;
                data.SetInBodySpace(posA, posB, axisA, axisB, axisAPerp, axisBPerp, CubeGrid.Physics, m_rotorGrid.Physics);
                m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, rotorBody, data);

                m_constraint.WantRuntime = true;
                CubeGrid.Physics.AddConstraint(m_constraint);
                if(!m_constraint.InWorld)
                {
                    CubeGrid.Physics.RemoveConstraint(m_constraint);
                    m_constraint.Dispose();
                    m_constraint = null;
                    return false;
                }
                m_constraint.Enabled = true;

                SetAngleToPhysics();

                m_rotorBlock.Attach(this);

                if (updateGroup)
                {
                    OnConstraintAdded(GridLinkTypeEnum.Physical, m_rotorGrid);
                    OnConstraintAdded(GridLinkTypeEnum.Logical, m_rotorGrid);
                    m_rotorGrid.OnPhysicsChanged += cubeGrid_OnPhysicsChanged;
                }
                m_isAttached = true;
                UpdateText();
                return true;
            }

            return false;
        }
Example #11
0
        protected override bool CreateConstraint(MyAttachableTopBlockBase rotor)
        {
            if (!base.CreateConstraint(rotor))
                return false;
            Debug.Assert(rotor != null, "Rotor cannot be null!");
            Debug.Assert(m_constraint == null, "Already attached, call detach first!");
            Debug.Assert(
                m_connectionState.Value.TopBlockId == 0 || m_connectionState.Value.TopBlockId == rotor.EntityId,
                "m_rotorBlockId must be set prior calling Attach");


            var rotorBody = TopGrid.Physics.RigidBody;
            var data = new HkLimitedHingeConstraintData();
            m_motor = new HkVelocityConstraintMotor(1.0f, 1000000f);

            data.SetSolvingMethod(HkSolvingMethod.MethodStabilized);
            data.Motor = m_motor;
            data.DisableLimits();

            SetConstraintPosition(rotor, data);
            m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, rotorBody, data);

            m_constraint.WantRuntime = true;
            CubeGrid.Physics.AddConstraint(m_constraint);
            if (!m_constraint.InWorld)
            {
                CubeGrid.Physics.RemoveConstraint(m_constraint);
                m_constraint.Dispose();
                m_constraint = null;
                return false;
            }

            m_constraint.Enabled = true;

            SetAngleToPhysics();
            return true;
        }
Example #12
0
 private void SetConstraintPosition(MyAttachableTopBlockBase rotor, HkLimitedHingeConstraintData data)
 {
     var posA = DummyPosition;
     var posB = rotor.Position * rotor.CubeGrid.GridSize;
     var axisA = PositionComp.LocalMatrix.Up;
     var axisAPerp = PositionComp.LocalMatrix.Forward;
     var axisB = rotor.PositionComp.LocalMatrix.Up;
     var axisBPerp = rotor.PositionComp.LocalMatrix.Forward;
     data.SetInBodySpace(posA, posB, axisA, axisB, axisAPerp, axisBPerp, CubeGrid.Physics, TopGrid.Physics);
 }
Example #13
0
        protected override bool Attach(MyAttachableTopBlockBase rotor, bool updateGroup = true)
        {
            if (rotor is MyMotorRotor && base.Attach(rotor, updateGroup))
            {
                Debug.Assert(rotor != null, "Rotor cannot be null!");
                Debug.Assert(m_constraint == null, "Already attached, call detach first!");
                Debug.Assert(m_connectionState.Value.TopBlockId == 0 || m_connectionState.Value.TopBlockId == rotor.EntityId, "m_rotorBlockId must be set prior calling Attach");


                var rotorBody = m_topGrid.Physics.RigidBody;
                var data = new HkLimitedHingeConstraintData();
                m_motor = new HkVelocityConstraintMotor(1.0f, 1000000f);

                data.SetSolvingMethod(HkSolvingMethod.MethodStabilized);
                data.Motor = m_motor;
                data.DisableLimits();

                var posA = DummyPosition;
                var posB = rotor.Position * rotor.CubeGrid.GridSize;
                var axisA = PositionComp.LocalMatrix.Up;
                var axisAPerp = PositionComp.LocalMatrix.Forward;
                var axisB = rotor.PositionComp.LocalMatrix.Up;
                var axisBPerp = rotor.PositionComp.LocalMatrix.Forward;
                data.SetInBodySpace(posA, posB, axisA, axisB, axisAPerp, axisBPerp, CubeGrid.Physics, m_topGrid.Physics);
                m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, rotorBody, data);

                m_constraint.WantRuntime = true;
                CubeGrid.Physics.AddConstraint(m_constraint);
                if (!m_constraint.InWorld)
                {
                    CubeGrid.Physics.RemoveConstraint(m_constraint);
                    m_constraint.Dispose();
                    m_constraint = null;
                    return false;
                }

                m_constraint.Enabled = true;

                SetAngleToPhysics();

                m_topBlock.Attach(this);

                m_isAttached = true;
                UpdateText();
                return true;
            }
            return false;
        }
Example #14
0
        public override void UpdateBeforeSimulation()
        {
            base.UpdateBeforeSimulation();

            if (m_welded)
            {
                return;
            }

            if (TopGrid == null || SafeConstraint == null)
            {
                return;
            }

            if (SafeConstraint.RigidBodyA == SafeConstraint.RigidBodyB) //welded
            {
                SafeConstraint.Enabled = false;
                return;
            }

            var oldAngle = m_currentAngle;

            m_currentAngle = HkLimitedHingeConstraintData.GetCurrentAngle(SafeConstraint);
            if (oldAngle != m_currentAngle)
            {
                UpdateText();
            }
            var data = (HkLimitedHingeConstraintData)m_constraint.ConstraintData;

            data.MaxFrictionTorque = BrakingTorque;

            TryActivateLimits();

            if (!m_limitsActive)
            {
                data.DisableLimits();
            }
            else if (!data.MinAngularLimit.IsEqual(m_minAngle) || !data.MaxAngularLimit.IsEqual(m_maxAngle))
            {
                data.MinAngularLimit = m_minAngle;
                data.MaxAngularLimit = m_maxAngle;

                // Activate even when motor is stopped, so it fixes it's limits
                CubeGrid.Physics.RigidBody.Activate();
                TopGrid.Physics.RigidBody.Activate();
            }
            if (m_limitsActive)
            {
                var handle = LimitReached;
                if (handle != null)
                {
                    if (oldAngle > data.MinAngularLimit && m_currentAngle <= data.MinAngularLimit)
                    {
                        handle(false);
                    }
                    if (oldAngle < data.MaxAngularLimit && m_currentAngle >= data.MaxAngularLimit)
                    {
                        handle(true);
                    }
                }
                if (m_currentAngle > MathHelper.TwoPi)
                {
                    ScaleDown();
                }
                if (m_currentAngle < -MathHelper.TwoPi)
                {
                    ScaleUp();
                }
            }

            var effectiveTorque = Math.Min(Torque, TopGrid.Physics.Mass * TopGrid.Physics.Mass) * Sync.RelativeSimulationRatio;

            m_motor.MaxForce       = effectiveTorque;
            m_motor.MinForce       = -effectiveTorque;
            m_motor.VelocityTarget = TargetVelocity * Sync.RelativeSimulationRatio;

            bool motorRunning = IsWorking;

            if (data.MotorEnabled != motorRunning)
            {
                data.SetMotorEnabled(m_constraint, motorRunning);
            }

            if (motorRunning && TopGrid != null && !m_motor.VelocityTarget.IsZero())
            {
                CubeGrid.Physics.RigidBody.Activate();
                TopGrid.Physics.RigidBody.Activate();
            }
        }
        public override bool Attach(MyMotorRotor rotor, bool updateSync = false, bool updateGroup = true)
        {
            if (CubeGrid.Physics == null || SafeConstraint != null)
                return false;

            Debug.Assert(SafeConstraint == null);

            if (CubeGrid.Physics.Enabled && rotor != null)
            {
                m_rotorBlock = rotor;
                m_rotorBlockId = rotor.EntityId;

                if (updateSync)
                    SyncObject.AttachRotor(m_rotorBlock);

                m_rotorGrid = m_rotorBlock.CubeGrid;
                if (m_rotorGrid.Physics == null)
                    return false;
                var rotorBody = m_rotorGrid.Physics.RigidBody;
                var data = new HkLimitedHingeConstraintData();
                m_motor = new HkVelocityConstraintMotor(1.0f, 1000000f);

                data.SetSolvingMethod(HkSolvingMethod.MethodStabilized);
                data.Motor = m_motor;
                data.DisableLimits();

                var posA = DummyPosition;
                var posB = rotor.Position * rotor.CubeGrid.GridSize;
                var axisA = PositionComp.LocalMatrix.Up;
                var axisAPerp = PositionComp.LocalMatrix.Forward;
                var axisB = rotor.PositionComp.LocalMatrix.Up;
                var axisBPerp = rotor.PositionComp.LocalMatrix.Forward;
                data.SetInBodySpace(ref posA, ref posB, ref axisA, ref axisB, ref axisAPerp, ref axisBPerp);
                m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, rotorBody, data);

                m_constraint.WantRuntime = true;
                CubeGrid.Physics.AddConstraint(m_constraint);
                m_constraint.Enabled = true;

                SetAngleToPhysics();

                m_rotorBlock.Attach(this);

                if (updateGroup)
                {
                    OnConstraintAdded(GridLinkTypeEnum.Physical, m_rotorGrid);
                    OnConstraintAdded(GridLinkTypeEnum.Logical, m_rotorGrid);
                }
                m_isAttached = true;
                return true;
            }

            return false;
        }