예제 #1
0
        public void Init(MySensorElement sensorElement, MyRBElement rbElement)
        {
            Debug.Assert(rbElement.GetRigidBody() != null);
            Debug.Assert(sensorElement.Sensor != null);
            m_SensorElement = sensorElement;
            m_RBElement = rbElement;            

            int guid1 = sensorElement.GUID;
            int guid2 = rbElement.GUID;

            if (guid1 > guid2)
            {
                int tm = guid2;
                guid2 = guid1;
                guid1 = tm;
            }

            m_Guid = guid1 + (guid2 << 16);

            m_IsInside = false;
            m_IsInUse = true;
            m_RBElement.GetRigidBody().OnDeactivated.Event += m_onRigidBodyDeactivatedEventHandler;
        }
예제 #2
0
        /// <summary>
        /// we have the aabb updated and just update the tree using the info from velocity as a hint
        /// </summary>
        public override void MoveVolumeFast(MyElement element)
        {
            if (element.ProxyData == MyElement.PROXY_UNASSIGNED)
            {
                return;
            }

            if ((element.Flags & MyElementFlag.EF_RB_ELEMENT) > 0)
            {
                MyRBElement rel = (MyRBElement)element;

                float dt = MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep;

                Vector3     movement = rel.GetRigidBody().LinearVelocity *dt;
                BoundingBox aabb     = element.GetWorldSpaceAABB();
                m_DAABBTree.MoveProxy(element.ProxyData, ref aabb, movement);
            }
            else
            {
                BoundingBox aabb = element.GetWorldSpaceAABB();
                m_DAABBTree.MoveProxy(element.ProxyData, ref aabb, Vector3.Zero);
            }
        }
예제 #3
0
        public void Init(MySensorElement sensorElement, MyRBElement rbElement)
        {
            Debug.Assert(rbElement.GetRigidBody() != null);
            Debug.Assert(sensorElement.Sensor != null);
            m_SensorElement = sensorElement;
            m_RBElement     = rbElement;

            int guid1 = sensorElement.GUID;
            int guid2 = rbElement.GUID;

            if (guid1 > guid2)
            {
                int tm = guid2;
                guid2 = guid1;
                guid1 = tm;
            }

            m_Guid = guid1 + (guid2 << 16);

            m_IsInside = false;
            m_IsInUse  = true;
            m_RBElement.GetRigidBody().OnDeactivated.Event += m_onRigidBodyDeactivatedEventHandler;
        }
예제 #4
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);
                            }
                        }
                    }
                }
            }
        }
예제 #5
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();
        }
        /// <summary>
        /// adds new sensor interaction between sensor and rigid
        /// </summary>
        public void AddSensorInteraction(MySensorElement sensorElement, MyRBElement rbElement)
        {
            if (sensorElement.DetectRigidBodyTypes != null && rbElement.GetRigidBody().Type != sensorElement.DetectRigidBodyTypes.Value)
            {
                return;
            }

            MySensorInteraction si = null;

            int guid1 = sensorElement.GUID;
            int guid2 = rbElement.GUID;

            if (guid1 > guid2)
            {
                int tm = guid2;
                guid2 = guid1;
                guid1 = tm;
            }

            int guid = guid1 + (guid2 << 16);

            // if this interaction is in current interactions
            if (m_CurrentInteractions.ContainsKey(guid))
            {
                return;
            }

            //if (sensorElement.Sensor.m_Interactions.TryGetValue(guid, out si))
            //{
            //    Debug.Assert(guid == si.m_Guid);
            //    m_CurrentInteractions.Add(guid, si);
            //    return;
            //}

            if (m_InteractionsInUse.TryGetValue(guid, out si))
            {
                Debug.Assert(guid == si.m_Guid);
                m_CurrentInteractions.Add(guid, si);
                return;
            }

            switch (sensorElement.GetElementType())
            {
            case MySensorElementType.ET_SPHERE:
            {
                switch (rbElement.GetElementType())
                {
                case MyRBElementType.ET_SPHERE:
                {
                    if (m_FreeSSSi.Count == 0)
                    {
                        m_FreeSSSi.Push(new MySphereSphereSensorInteraction());
                        m_newAllocatedInteractions++;
                    }
                    si = m_FreeSSSi.Pop();
                }
                break;

                case MyRBElementType.ET_BOX:
                {
                    if (m_FreeSBSi.Count == 0)
                    {
                        m_FreeSBSi.Push(new MySphereBoxSensorInteraction());
                        m_newAllocatedInteractions++;
                    }
                    si = m_FreeSBSi.Pop();
                }
                break;

                default:
                {
                    if (m_FreeSOSi.Count == 0)
                    {
                        m_FreeSOSi.Push(new MySphereOtherSensorInteraction());
                        m_newAllocatedInteractions++;
                    }
                    si = m_FreeSOSi.Pop();
                }
                break;
                }
            }
            break;

            case MySensorElementType.ET_BOX:
                switch (rbElement.GetElementType())
                {
                case MyRBElementType.ET_SPHERE:
                {
                    if (m_FreeBSSi.Count == 0)
                    {
                        m_FreeBSSi.Push(new MyBoxSphereSensorInteraction());
                        m_newAllocatedInteractions++;
                    }
                    si = m_FreeBSSi.Pop();
                }
                break;

                case MyRBElementType.ET_BOX:
                {
                    if (m_FreeBBSi.Count == 0)
                    {
                        m_FreeBBSi.Push(new MyBoxBoxSensorInteraction());
                        m_newAllocatedInteractions++;
                    }
                    si = m_FreeBBSi.Pop();
                }
                break;

                default:
                {
                    if (m_FreeBOSi.Count == 0)
                    {
                        m_FreeBOSi.Push(new MyBoxOtherSensorInteraction());
                        m_newAllocatedInteractions++;
                    }
                    si = m_FreeBOSi.Pop();
                }
                break;
                }
                break;

            default:
                break;
            }

            if (si == null)
            {
                return;
            }

            Debug.Assert(!si.m_IsInUse);
            si.Init(sensorElement, rbElement);
            Debug.Assert(guid == si.m_Guid);
            m_CurrentInteractions.Add(guid, si);
            m_InteractionsInUse.Add(guid, si);
            m_interactionsInUse++;
            if (m_interactionsInUse > m_interactionsInUseMax)
            {
                m_interactionsInUseMax = m_interactionsInUse;
            }
        }
        /// <summary>
        /// adds new sensor interaction between sensor and rigid
        /// </summary>
        public void AddSensorInteraction(MySensorElement sensorElement, MyRBElement rbElement)
        {
            if (sensorElement.DetectRigidBodyTypes != null && rbElement.GetRigidBody().Type != sensorElement.DetectRigidBodyTypes.Value) 
            {
                return;
            }            
            
            MySensorInteraction si = null;

            int guid1 = sensorElement.GUID;
            int guid2 = rbElement.GUID;

            if (guid1 > guid2)
            {
                int tm = guid2;
                guid2 = guid1;
                guid1 = tm;
            }

            int guid = guid1 + (guid2 << 16);

            // if this interaction is in current interactions
            if (m_CurrentInteractions.ContainsKey(guid)) 
            {
                return;
            }            

            //if (sensorElement.Sensor.m_Interactions.TryGetValue(guid, out si))
            //{
            //    Debug.Assert(guid == si.m_Guid);
            //    m_CurrentInteractions.Add(guid, si);
            //    return;
            //}

            if (m_InteractionsInUse.TryGetValue(guid, out si))
            {
                Debug.Assert(guid == si.m_Guid);
                m_CurrentInteractions.Add(guid, si);
                return;
            }            

            switch (sensorElement.GetElementType())
            {
                case MySensorElementType.ET_SPHERE:
                    {
                        switch (rbElement.GetElementType())
                        {
                            case MyRBElementType.ET_SPHERE:
                                {
                                    if (m_FreeSSSi.Count == 0)
                                    {
                                        m_FreeSSSi.Push(new MySphereSphereSensorInteraction());
                                        m_newAllocatedInteractions++;
                                    }
                                    si = m_FreeSSSi.Pop();
                                }
                                break;
                            case MyRBElementType.ET_BOX:
                                {
                                    if (m_FreeSBSi.Count == 0)
                                    {
                                        m_FreeSBSi.Push(new MySphereBoxSensorInteraction());
                                        m_newAllocatedInteractions++;
                                    }
                                    si = m_FreeSBSi.Pop();
                                }
                                break;
                            default:
                                {
                                    if (m_FreeSOSi.Count == 0) 
                                    {
                                        m_FreeSOSi.Push(new MySphereOtherSensorInteraction());
                                        m_newAllocatedInteractions++;
                                    }
                                    si = m_FreeSOSi.Pop();
                                }
                                break;
                        }
                    }
                    break;
                case MySensorElementType.ET_BOX:
                    switch (rbElement.GetElementType())
                    {
                        case MyRBElementType.ET_SPHERE:
                            {
                                if (m_FreeBSSi.Count == 0)
                                {
                                    m_FreeBSSi.Push(new MyBoxSphereSensorInteraction());
                                    m_newAllocatedInteractions++;
                                }
                                si = m_FreeBSSi.Pop();
                            }
                            break;
                        case MyRBElementType.ET_BOX:
                            {
                                if (m_FreeBBSi.Count == 0)
                                {
                                    m_FreeBBSi.Push(new MyBoxBoxSensorInteraction());
                                    m_newAllocatedInteractions++;
                                }
                                si = m_FreeBBSi.Pop();
                            }
                            break;
                        default:
                            {
                                if (m_FreeBOSi.Count == 0)
                                {
                                    m_FreeBOSi.Push(new MyBoxOtherSensorInteraction());
                                    m_newAllocatedInteractions++;
                                }
                                si = m_FreeBOSi.Pop();
                            }
                            break;
                    }
                    break;
                default:
                    break;
            }

            if (si == null)
            {
                return;
            }

            Debug.Assert(!si.m_IsInUse);             
            si.Init(sensorElement, rbElement);            
            Debug.Assert(guid == si.m_Guid);
            m_CurrentInteractions.Add(guid, si);
            m_InteractionsInUse.Add(guid, si);
            m_interactionsInUse++;
            if (m_interactionsInUse > m_interactionsInUseMax) 
            {
                m_interactionsInUseMax = m_interactionsInUse;
            }
        }