예제 #1
0
        /// <summary>
        /// parses all active rigids, updates the aabbs and checks for possible collisions using the DAABB
        /// </summary>
        public override void DoWork()
        {
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("ClearInteractions");
            ClearInteractions();
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();

            MyRBInteractionModule module       = MyPhysics.physicsSystem.GetRBInteractionModule();
            HashSet <MyRigidBody> activeRigids = MyPhysics.physicsSystem.GetRigidBodyModule().GetActiveRigids();
            float       dt = MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep;
            BoundingBox aabb;

            //Dictionary<string, int> typeStats = new Dictionary<string, int>();

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("MoveProxy");

            // A.B. this might be expensive, maybe update separate or move somewhere else like in the solve -> update positions !!
            foreach (MyRigidBody rbo in activeRigids)
            {
                /*
                 * string ts = ((MinerWars.AppCode.Game.Physics.MyPhysicsBody)rbo.m_UserData).Entity.GetType().Name.ToString();
                 * if (!typeStats.ContainsKey(ts))
                 * typeStats.Add(ts, 0);
                 * typeStats[ts]++;
                 */

                for (int j = 0; j < rbo.GetRBElementList().Count; j++)
                {
                    MyRBElement el = rbo.GetRBElementList()[j];
                    el.UpdateAABB();
                    aabb = el.GetWorldSpaceAABB();
                    m_DAABBTree.MoveProxy(el.ProxyData, ref aabb, el.GetRigidBody().LinearVelocity *dt);
                }
            }
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("make the AABB test");
            // make the AABB test
            MyRBElementInteraction interaction = null;

#if RENDER_PROFILING && !MEMORY_PROFILING
            int[] heights = new int[activeRigids.Count];
            int[] tests   = new int[activeRigids.Count];
#endif

            int i = 0;
            foreach (MyRigidBody rbo in activeRigids)
            {
                for (int j = 0; j < rbo.GetRBElementList().Count; j++)
                {
                    MyRBElement el             = rbo.GetRBElementList()[j];
                    Vector3     globalPosition = Vector3.Transform(el.LocalPosition, rbo.Matrix);
                    Vector3     deltaVelocity  = rbo.LinearVelocity * dt;
                    aabb = el.GetWorldSpaceAABB();

                    if (rbo.ReadFlag(RigidBodyFlag.RBF_COLDET_THROUGH_VOXEL_TRIANGLES) || el is MyRBSphereElement) //because sphere is interpolated for whole path
                    {
                        Vector3 v = globalPosition + rbo.LinearVelocity * dt;
                        //Vector3 v = aabb.GetCenter()+rbo.LinearVelocity * dt;
                        aabb = aabb.Include(ref v);
                    }
                    else
                    {
                        aabb.Max += deltaVelocity;
                        aabb.Min += deltaVelocity;
                    }

                    //if (el is MyRBSphereElement)
                    //{
                    //MyDebugDraw.AddDrawSphereWireframe(new BoundingSphere(aabb.GetCenter(), (aabb.GetCorners()[0] - aabb.GetCenter()).Length()));
                    // MyDebugDraw.AddDrawSphereWireframe(new BoundingSphere(aabb.GetCenter()+rbo.LinearVelocity * dt, (aabb.GetCorners()[0] - aabb.GetCenter()).Length()));
                    //}

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("m_DAABBTree.OverlapAllBoundingBox");
#if RENDER_PROFILING && !MEMORY_PROFILING
                    m_DAABBTree.OverlapAllBoundingBox(ref aabb, m_overlapElementList, 0);
#else
                    m_DAABBTree.OverlapAllBoundingBox(ref aabb, m_overlapElementList, 0);
#endif

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Interactions");

                    foreach (var lEl in m_overlapElementList)
                    {
                        if (el == lEl)//optimization?
                        {
                            continue;
                        }
                        if ((lEl.Flags & MyElementFlag.EF_SENSOR_ELEMENT) > 0)
                        {
                            MySensorElement sensorElement = lEl as MySensorElement;
                            MyRBElement     rbElement     = el as MyRBElement;
                            MyPhysics.physicsSystem.GetSensorInteractionModule().AddSensorInteraction(sensorElement, rbElement);
                            continue;
                        }

                        if ((lEl.Flags & MyElementFlag.EF_RB_ELEMENT) > 0)
                        {
                            MyRBElement testEl = (MyRBElement)lEl;

                            if (el.GetRigidBody().IsStatic() && testEl.GetRigidBody().IsStatic())
                            {
                                continue;
                            }

                            if (el.GetRigidBody().IsKinematic() && testEl.GetRigidBody().IsKinematic())
                            {
                                continue;
                            }

                            if (el.GetRigidBody().IsKinematic() && testEl.GetRigidBody().IsStatic())
                            {
                                continue;
                            }

                            if (el.GetRigidBody().IsStatic() && testEl.GetRigidBody().IsKinematic())
                            {
                                continue;
                            }

                            if (el.GetRigidBody() == testEl.GetRigidBody())
                            {
                                continue;
                            }

                            if (!MyFiltering.AcceptCollision(el, testEl))
                            {
                                continue;
                            }

                            interaction = module.FindRBElementInteraction(el, testEl);
                            if (interaction == null)
                            {
                                interaction = module.AddRBElementInteraction(el, testEl);
                            }

                            if (interaction != null)
                            {
                                bool iinserted = false;
                                for (int t = 0; t < m_InteractionList.Count; t++)
                                {
                                    if (m_InteractionList[t] == interaction)
                                    {
                                        iinserted = true;
                                        break;
                                    }
                                }
                                if (!iinserted)
                                {
                                    m_InteractionList.Add(interaction);
                                }
                            }
                        }
                    }

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
                }

                i++;
            }

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().ProfileCustomValue("Active rigids", activeRigids.Count);

#if RENDER_PROFILING && !MEMORY_PROFILING
            float averageHeight = 0;
            float averageTest   = 0;
            int   maxHeight     = 0;
            int   maxTest       = 0;
            for (int j = 0; j < activeRigids.Count; j++)
            {
                averageHeight += heights[j];
                averageTest   += tests[j];
                if (maxHeight < heights[j])
                {
                    maxHeight = heights[j];
                }
                if (maxTest < tests[j])
                {
                    maxTest = tests[j];
                }
            }

            averageHeight /= activeRigids.Count;
            averageTest   /= activeRigids.Count;

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().ProfileCustomValue("Average height", averageHeight);
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().ProfileCustomValue("Average test", averageTest);
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().ProfileCustomValue("Max height", maxHeight);
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().ProfileCustomValue("Max test", maxTest);
#endif

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("handle active sensors");
            List <MySensor> activeSensors = MyPhysics.physicsSystem.GetSensorModule().ActiveSensors;
            if (activeSensors.Count > 0)
            {
                if (m_activeSensorIndex >= activeSensors.Count)
                {
                    m_activeSensorIndex = 0;
                }

                MySensor activeSensor = activeSensors[m_activeSensorIndex];
                activeSensor.PrepareSensorInteractions();
                MySensorElement sensorElement = activeSensor.GetElement();
                BoundingBox     sensorElAABB  = sensorElement.GetWorldSpaceAABB();
                m_sensorInteractonList.Clear();
                m_DAABBTree.OverlapAllBoundingBox(ref sensorElAABB, m_sensorInteractonList, (uint)MyElementFlag.EF_RB_ELEMENT);
                foreach (MyRBElement rbElement in m_sensorInteractonList)
                {
                    MyPhysics.physicsSystem.GetSensorInteractionModule().AddSensorInteraction(sensorElement, rbElement);
                }
                activeSensor.Active = false;
                m_activeSensorIndex++;
            }
            //List<MySensor> activeSensors = MyPhysics.physicsSystem.GetSensorModule().ActiveSensors;
            //for (int i = activeSensors.Count - 1; i >= 0; i--)
            //{
            //    MySensorElement sensorElement = activeSensors[i].GetElement();
            //    BoundingBox sensorElAABB = sensorElement.GetWorldSpaceAABB();
            //    m_sensorInteractonList.Clear();
            //    m_DAABBTree.OverlapRBAllBoundingBox(ref sensorElAABB, m_sensorInteractonList);
            //    foreach (MyRBElement rbElement in m_sensorInteractonList)
            //    {
            //        MyPhysics.physicsSystem.GetSensorInteractionModule().AddSensorInteraction(sensorElement, rbElement);
            //    }
            //    activeSensors[i].IsActive = false;
            //    activeSensors.RemoveAt(i);
            //}

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
        }
예제 #2
0
        public override void DoWork()
        {
            // brute force
            MyRBInteractionModule module       = MyPhysics.physicsSystem.GetRBInteractionModule();
            List <MyRigidBody>    activeRigids = MyPhysics.physicsSystem.GetRigidBodyModule().GetActiveRigids();

            m_ActiveElements.Clear();

            for (int i = 0; i < activeRigids.Count; i++)
            {
                MyRigidBody rbo = activeRigids[i];
                for (int j = 0; j < rbo.GetRBElementList().Count; j++)
                {
                    MyRBElement el = rbo.GetRBElementList()[j];
                    el.UpdateAABB();
                    m_ActiveElements.Add(el);
                }
            }

            // parse the elements
            BoundingBox            bbox;
            MyRBElementInteraction interaction = null;

            m_InteractionList.Clear();
            for (int i = 0; i < m_ActiveElements.Count; i++)
            {
                MyRBElement testEl   = m_ActiveElements[i];
                BoundingBox testAABB = testEl.GetWorldSpaceAABB();
                for (int j = 0; j < m_Elements.Count; j++)
                {
                    MyRBElement el = m_Elements[j];
                    interaction = null;
                    if (el != testEl)
                    {
                        if (el.GetRigidBody().IsStatic() && testEl.GetRigidBody().IsStatic())
                        {
                            continue;
                        }

                        if (el.GetRigidBody().IsKinematic() && testEl.GetRigidBody().IsKinematic())
                        {
                            continue;
                        }

                        if (el.GetRigidBody() == testEl.GetRigidBody())
                        {
                            continue;
                        }

                        bbox = el.GetWorldSpaceAABB();
                        if (bbox.Intersects(testAABB))
                        {
                            interaction = module.FindRBElementInteraction(el, testEl);
                            if (interaction == null)
                            {
                                interaction = module.AddRBElementInteraction(el, testEl);
                            }
                        }
                        else
                        {
                            interaction = module.FindRBElementInteraction(el, testEl);
                            if (interaction != null)
                            {
                                interaction = null;
                                module.RemoveRBElementInteraction(el, testEl);
                            }
                        }

                        if (interaction != null)
                        {
                            bool iinserted = false;
                            for (int t = 0; t < m_InteractionList.Count; t++)
                            {
                                if (m_InteractionList[t] == interaction)
                                {
                                    iinserted = true;
                                    break;
                                }
                            }
                            if (!iinserted)
                            {
                                m_InteractionList.Add(interaction);
                            }
                        }
                    }
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Computes the inertia tensor of a rigid body using box inertia definition
        /// </summary>
        public static void ComputeIntertiaTensor(MyRigidBody rbo)
        {
            MyCommonDebugUtils.AssertDebug(rbo != null);
            MyCommonDebugUtils.AssertDebug(rbo.GetRBElementList().Count > 0);
            MyCommonDebugUtils.AssertDebug(rbo.GetMass() > 0);

            float mass = rbo.GetMass();

            BoundingBox box;

            box.Min = new Vector3(FLT_MAX);
            box.Max = new Vector3(FLT_MIN);
            BoundingBox aabb;

            Matrix infTensor = new Matrix();

            infTensor.M11 = FLT_MAX;
            infTensor.M22 = FLT_MAX;
            infTensor.M33 = FLT_MAX;
            infTensor.M44 = 1.0f;
            if (rbo.IsStatic())
            {
                rbo.InertiaTensor = infTensor;
                return;
            }

            if (rbo.GetRBElementList().Count > 1)
            {
                for (int e = 0; e < rbo.GetRBElementList().Count; e++)
                {
                    MyRBElement el = rbo.GetRBElementList()[e];
                    switch (el.GetElementType())
                    {
                    case MyRBElementType.ET_TRIANGLEMESH:
                    {
                        rbo.InertiaTensor = infTensor;
                        return;
                    }
                    break;

                    case MyRBElementType.ET_VOXEL:
                    {
                        rbo.InertiaTensor = infTensor;
                        return;
                    }
                    break;

                    default:
                    {
                        aabb = el.GetWorldSpaceAABB();
                        box  = BoundingBox.CreateMerged(box, aabb);
                    }
                    break;
                    }
                }

                Vector3 size = box.Max - box.Min;

                infTensor.M11 = mass * (size.Y * size.Y + size.Z * size.Z) / 12.0f;
                infTensor.M22 = mass * (size.X * size.X + size.Z * size.Z) / 12.0f;
                infTensor.M33 = mass * (size.X * size.X + size.Y * size.Y) / 12.0f;
                infTensor.M44 = 1.0f;

                rbo.InertiaTensor       = infTensor;
                rbo.InvertInertiaTensor = Matrix.Invert(infTensor);
                return;
            }

            MyRBElement elem = rbo.GetRBElementList()[0];

            switch (elem.GetElementType())
            {
            case MyRBElementType.ET_TRIANGLEMESH:
            {
                rbo.InertiaTensor       = infTensor;
                infTensor.M11           = 0.0f;
                infTensor.M22           = 0.0f;
                infTensor.M33           = 0.0f;
                infTensor.M44           = 0.0f;
                rbo.InvertInertiaTensor = infTensor;
                return;
            }
            break;

            case MyRBElementType.ET_VOXEL:
            {
                rbo.InertiaTensor       = infTensor;
                infTensor.M11           = 0.0f;
                infTensor.M22           = 0.0f;
                infTensor.M33           = 0.0f;
                infTensor.M44           = 0.0f;
                rbo.InvertInertiaTensor = infTensor;
                return;
            }

            case MyRBElementType.ET_SPHERE:
            {
                float radius = ((MyRBSphereElement)elem).Radius;

                infTensor.M11 = 2.0f / 5.0f * mass * radius * radius;
                infTensor.M22 = 2.0f / 5.0f * mass * radius * radius;
                infTensor.M33 = 2.0f / 5.0f * mass * radius * radius;
                infTensor.M44 = 1.0f;

                rbo.InertiaTensor = infTensor;
                //rbo.InvertInertiaTensor = Matrix.Invert(infTensor);
                return;
            }
            break;

            case MyRBElementType.ET_BOX:
            {
                //Vector3 size = ((MyRBBoxElement)elem).Size;

                //infTensor.M11 = mass * (size.Y * size.Y + size.Z * size.Z) / 12.0f;
                //infTensor.M22 = mass * (size.X * size.X + size.Z * size.Z) / 12.0f;
                //infTensor.M33 = mass * (size.X * size.X + size.Y * size.Y) / 12.0f;
                //infTensor.M44 = 1.0f;

                //rbo.InertiaTensor = infTensor;
                //rbo.InvertInertiaTensor = Matrix.Invert(infTensor);

                // HACK: After speaking with PetrM, computing changed like box is sphere
                float radius = ((MyRBBoxElement)elem).Size.Length() / 2;

                infTensor.M11 = 2.0f / 5.0f * mass * radius * radius;
                infTensor.M22 = 2.0f / 5.0f * mass * radius * radius;
                infTensor.M33 = 2.0f / 5.0f * mass * radius * radius;
                infTensor.M44 = 1.0f;

                rbo.InertiaTensor = infTensor;
                //rbo.InvertInertiaTensor = Matrix.Invert(infTensor);
                return;
            }
            break;

            default:
                MyCommonDebugUtils.AssertDebug(false);
                break;
            }
        }