コード例 #1
0
        public static long AddRopeData(MyRopeData publicData, long ropeId)
        {
            if (ropeId == 0)
                ropeId = MyEntityIdentifier.AllocateId();

            // Avoid referencing external objects during addition. They might not have been created yet.
            var ropeData = new InternalRopeData
            {
                Public = publicData,
                RopeId = ropeId,
            };

            Debug.Assert(!m_hookIdToRopeId.ContainsKey(ropeData.Public.HookEntityIdA), "Hook already has rope attached!");
            Debug.Assert(!m_hookIdToRopeId.ContainsKey(ropeData.Public.HookEntityIdB), "Hook already has rope attached!");
            Debug.Assert(!m_ropeIdToRope.ContainsKey(ropeData.RopeId), "Rope with given ID already exists!");
            m_ropeIdToRope[ropeData.RopeId] = ropeData;
            m_hookIdToRopeId[ropeData.Public.HookEntityIdA] = ropeId;
            m_hookIdToRopeId[ropeData.Public.HookEntityIdB] = ropeId;

            if (ropeData.Public.Definition.EnableRayCastRelease && Sync.IsServer)
            {
                m_ropeIdToRayCastRelease.Add(ropeId, ropeData);
            }

            m_ropeIdToInit.Add(ropeId);

            return ropeId;
        }
コード例 #2
0
        private static Vector3 ComputeTorqueFromRopeImpulse(WindingData windingData, InternalRopeData ropeData, Vector3 ropeDirectionVector, Vector3 centerDelta)
        {
            /*
             * /R   = rope direction vector (unit length, world space)
             * /A   = drum axis (unit length, world space)
             * /r   = displacement vector for torque application (world space) from center of mass
             * /tau = torque applied
             * /C_d = center delta (center of winding (world space) - center of mass (world space))
             * /F   = force
             * r    = drum radius
             * I    = impulse applied
             * 
             * /r = |/R x /A| * r + C_d
             * /F = /R * -I
             * /tau = /r x /F
             */

            Vector3 A, r, F, tau;
            Vector3.Normalize(ref ropeDirectionVector, out ropeDirectionVector);
            A = windingData.CurrentDummyWorld.Backward;
            Vector3.Cross(ref ropeDirectionVector, ref A, out r);
            r = r * windingData.Radius + centerDelta;
            F = ropeDirectionVector * ropeData.ImpulseApplied;
            Vector3.Cross(ref r, ref F, out tau);
            return tau;
        }
コード例 #3
0
        private static void ApplyRopeLimits(InternalRopeData ropeData, RopeDrumLimits limits = null)
        {
            if (limits == null) m_hookIdToRopeLimits.TryGetValue(ropeData.Public.HookEntityIdA, out limits);
            if (limits == null) m_hookIdToRopeLimits.TryGetValue(ropeData.Public.HookEntityIdB, out limits);

            if (limits != null)
            {
                Debug.Assert(
                    m_hookIdToRopeLimits.ContainsKey(ropeData.Public.HookEntityIdA) ^
                    m_hookIdToRopeLimits.ContainsKey(ropeData.Public.HookEntityIdB),
                    "Rope should only be connected to one drum with rope limits.");
                ropeData.Public.MinRopeLength = limits.MinLength;
                ropeData.Public.MaxRopeLength = limits.MaxLength;
                WindingData winding;
                float newLength;
                if (m_hookIdToWinding.TryGetValue(ropeData.Public.HookEntityIdA, out winding) && winding.IsUnlocked)
                    newLength = limits.MaxLength;
                else if (m_hookIdToWinding.TryGetValue(ropeData.Public.HookEntityIdB, out winding) && winding.IsUnlocked)
                    newLength = limits.MaxLength;
                else
                    newLength = MathHelper.Clamp(ropeData.Public.CurrentRopeLength, limits.MinLength, limits.MaxLength);

                ropeData.Public.CurrentRopeLength = newLength;
                if (ropeData.ConstraintData != null)
                {
                    // Would be nice if I could leave this up to the normal update by changing only target rope length.
                    // But target rope length is limited to only certain delta in actual length per update.
                    ropeData.ConstraintData.LinearLimit = newLength;
                    ropeData.Constraint.RigidBodyA.Activate();
                    ropeData.Constraint.RigidBodyB.Activate();
                }
            }

            ropeData.TargetRopeLength = ropeData.Public.CurrentRopeLength;
        }
コード例 #4
0
        private static void RemoveConstraint(InternalRopeData ropeData)
        {
            if (ropeData.Constraint == null)
                return;

            if (ropeData.Constraint.RigidBodyA != null)
                ropeData.Constraint.RigidBodyA.Activate();

            if (ropeData.Constraint.RigidBodyB != null)
                ropeData.Constraint.RigidBodyB.Activate();

            var physics = ropeData.GridA.Physics;
            if (physics != null)
                physics.RemoveConstraint(ropeData.Constraint);

            if (!ropeData.Constraint.IsDisposed)
                ropeData.Constraint.Dispose();
            ropeData.Constraint = null;
            // HkConstraint deletes constraint data as well. Is this correct? (prevents sharing
            // constraint data, as each instance reduces reference count on data by 2 on dispose!)
            ropeData.ConstraintData = null;

            MyCubeGrid.BreakGridGroupLink(GridLinkTypeEnum.Physical, ropeData.RopeId, ropeData.GridA, ropeData.GridB);
        }
コード例 #5
0
        private static void CreateConstraint(InternalRopeData ropeData, HookData hookA, HookData hookB, MyCubeBlock blockA, MyCubeBlock blockB)
        {
            if (ropeData.GridA == ropeData.GridB)
                return;

            var physicsA = blockA.CubeGrid.Physics;
            var physicsB = blockB.CubeGrid.Physics;
            if (physicsA == null || physicsB == null || !physicsA.RigidBody.IsAddedToWorld || !physicsB.RigidBody.IsAddedToWorld)
                return;

            Vector3D posA, posB;
            ComputeLocalPosition(blockA, hookA, out posA);
            ComputeLocalPosition(blockB, hookB, out posB);

            ropeData.ConstraintData = new HkRopeConstraintData();
            {
                Vector3 posAf = (Vector3)posA;
                Vector3 posBf = (Vector3)posB;
                ropeData.ConstraintData.SetInBodySpace( posAf,  posBf, physicsA, physicsB);
            }
            posA = Vector3D.Transform(posA, physicsA.GetWorldMatrix());
            posB = Vector3D.Transform(posB, physicsB.GetWorldMatrix());
            ropeData.ConstraintData.LinearLimit = ropeData.Public.CurrentRopeLength;
            ropeData.ConstraintData.Strength = 0.6f;
            ropeData.Constraint = new HkConstraint(physicsA.RigidBody, physicsB.RigidBody, ropeData.ConstraintData);
            physicsA.AddConstraint(ropeData.Constraint);
            ropeData.Constraint.Enabled = true;
            ropeData.ConstraintData.Update(ropeData.Constraint);

            MyCubeGrid.CreateGridGroupLink(GridLinkTypeEnum.Physical, ropeData.RopeId, blockA.CubeGrid, blockB.CubeGrid);

            physicsA.RigidBody.Activate();
            physicsB.RigidBody.Activate();
        }
コード例 #6
0
 private static void CreateConstraint(InternalRopeData ropeData)
 {
     CreateConstraint(ropeData,
         m_hookIdToHook[ropeData.Public.HookEntityIdA],
         m_hookIdToHook[ropeData.Public.HookEntityIdB],
         (MyCubeBlock)MyEntities.GetEntityById(ropeData.Public.HookEntityIdA),
         (MyCubeBlock)MyEntities.GetEntityById(ropeData.Public.HookEntityIdB));
 }