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; }
/// <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); } }
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; }
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); } } } } } }
/// <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; } }