/// <summary> /// Initializes the constraint and creates the guid for contact reporting /// </summary> public void Init(MyRBElementInteraction interaction, MySmallCollPointInfo[] pointInfos, int numPointInfos) { this.m_Interaction = interaction; m_Magnitude = 0.0f; numPointInfos = (numPointInfos > MaxCollisionPoints) ? MaxCollisionPoints : numPointInfos; m_NumCollPts = 0; MyContactConstraintModule mod = MyPhysics.physicsSystem.GetContactConstraintModule(); for (int i = 0; i < numPointInfos; ++i) { this.m_PointInfo[m_NumCollPts] = mod.PopCollPointInfo(); this.m_PointInfo[m_NumCollPts++].Init(ref pointInfos[i]); } uint guid1 = (uint) interaction.RBElement1.GUID; uint guid2 = (uint) interaction.RBElement2.GUID; if (guid1 > guid2) { uint tm = guid2; guid2 = guid1; guid1 = tm; } m_Guid = guid1 + (guid2 << 16); }
public override void DestroyVolume(MyElement element) { if (element.ProxyData == MyElement.PROXY_UNASSIGNED) { return; } m_DAABBTree.RemoveProxy(element.ProxyData); element.ProxyData = MyElement.PROXY_UNASSIGNED; if ((element.Flags & MyElementFlag.EF_SENSOR_ELEMENT) > 0) { MySensorElement se = (MySensorElement)element; } if ((element.Flags & MyElementFlag.EF_RB_ELEMENT) > 0) { MyRBElement elm = (MyRBElement)element; //clear all iterations from me and from objects i iterate with while (elm.GetRBElementInteractions().Count > 0) { MyRBElementInteraction intr = elm.GetRBElementInteractions()[0]; MyPhysics.physicsSystem.GetRBInteractionModule().RemoveRBElementInteraction(intr.RBElement1, intr.RBElement2); } elm.GetRBElementInteractions().Clear(); } }
/// <summary> /// Initializes the constraint and creates the guid for contact reporting /// </summary> public void Init(MyRBElementInteraction interaction, MySmallCollPointInfo[] pointInfos, int numPointInfos) { this.m_Interaction = interaction; m_Magnitude = 0.0f; numPointInfos = (numPointInfos > MaxCollisionPoints) ? MaxCollisionPoints : numPointInfos; m_NumCollPts = 0; MyContactConstraintModule mod = MyPhysics.physicsSystem.GetContactConstraintModule(); for (int i = 0; i < numPointInfos; ++i) { this.m_PointInfo[m_NumCollPts] = mod.PopCollPointInfo(); this.m_PointInfo[m_NumCollPts++].Init(ref pointInfos[i]); } uint guid1 = (uint)interaction.RBElement1.GUID; uint guid2 = (uint)interaction.RBElement2.GUID; if (guid1 > guid2) { uint tm = guid2; guid2 = guid1; guid1 = tm; } m_Guid = guid1 + (guid2 << 16); }
/// <summary> /// Registering the interation between 2 rbelement types /// </summary> public void RegisterRBElementInteraction(MyRBElementType type1, MyRBElementType type2, MyRBElementInteraction intr) { int t1 = (int)type1; int t2 = (int)type2; List <MyRBElementInteraction> intrList = null; if (t1 < t2) { intrList = m_IslandsPool[t1, t2]; m_IslandsPoolStatic[t1, t2] = intr.CreateNewInstance(); } else { intrList = m_IslandsPool[t2, t1]; m_IslandsPoolStatic[t2, t1] = intr.CreateNewInstance(); } intrList.Capacity = m_preAllocCount; intrList.Add(intr); for (int i = 1; i < m_preAllocCount; i++) { MyRBElementInteraction ins = intr.CreateNewInstance(); intrList.Add(ins); } }
/// <summary> /// Do static Test of intersection /// </summary> public bool DoStaticTestInteraction(MyRBElement el1, MyRBElement el2) { MyRBElementInteraction myElemInteraction = FindRBElementInteractionForStaticTesting(el1.GetElementType(), el2.GetElementType()); if (myElemInteraction != null) { myElemInteraction.RBElement1 = el1; myElemInteraction.RBElement2 = el2; return(myElemInteraction.DoStaticInitialTest()); } return(false); }
public void AddContactConstraint(MyRBElementInteraction interaction, MySmallCollPointInfo[] pointInfos, int numCollPts) { lock (m_Locker) { if (m_FreeCc.Count == 0) { m_FreeCc.Push(new MyRBContactConstraint()); } MyRBContactConstraint cc = m_FreeCc.Pop(); cc.Init(interaction, pointInfos, numCollPts); m_ActiveContactConstrains.Add(cc); } }
public List <MyTriangle_Vertex_Normal> GetFreeTriangleList(MyRBElementInteraction itr) { List <MyTriangle_Vertex_Normal> retVal = null; lock (m_Locker) { if (m_Cache.Count == 0) { m_Cache.Push(new List <MyTriangle_Vertex_Normal>(TRIANGLES_SIZE)); } retVal = m_Cache.Pop(); } return(retVal); }
/// <summary> /// Looks if interaction between those elements already exist /// </summary> public MyRBElementInteraction FindRBElementInteraction(MyRBElement el1, MyRBElement el2) { // look for interaction on element for (int i = 0; i < el1.GetRBElementInteractions().Count; i++) { MyRBElementInteraction intr = el1.GetRBElementInteractions()[i]; if (intr.RBElement1 == el2 || intr.RBElement2 == el2) { return(intr); } } return(null); }
/// <summary> /// Removes interaction between these 2 elements /// </summary> public void RemoveRBElementInteraction(MyRBElement el1, MyRBElement el2) { if (el1 != null) { // look for interaction on element for (int i = 0; i < el1.GetRBElementInteractions().Count; i++) { MyRBElementInteraction intr = el1.GetRBElementInteractions()[i]; if ((intr.RBElement1 == el1 && intr.RBElement2 == el2) || (intr.RBElement1 == el2 && intr.RBElement2 == el1)) { // add it back int t1 = (int)el1.GetElementType(); int t2 = (int)el2.GetElementType(); List <MyRBElementInteraction> intrList = null; if (t1 < t2) { intrList = m_IslandsPool[t1, t2]; } else { intrList = m_IslandsPool[t2, t1]; } intrList.Add(intr); el1.GetRBElementInteractions().Remove(intr); break; } } } if (el2 != null) { for (int i = 0; i < el2.GetRBElementInteractions().Count; i++) { MyRBElementInteraction intr = el2.GetRBElementInteractions()[i]; if ((intr.RBElement1 == el1 && intr.RBElement2 == el2) || (intr.RBElement1 == el2 && intr.RBElement2 == el1)) { intr.RBElement1 = null; intr.RBElement2 = null; el2.GetRBElementInteractions().Remove(intr); break; } } } }
/// <summary> /// find interaction method from pool /// </summary> public MyRBElementInteraction FindRBElementInteractionForStaticTesting(MyRBElementType type1, MyRBElementType type2) { int t1 = (int)type1; int t2 = (int)type2; MyRBElementInteraction intrList = null; if (t1 < t2) { intrList = m_IslandsPoolStatic[t1, t2]; } else { intrList = m_IslandsPoolStatic[t2, t1]; } return(intrList); }
/// <summary> /// Adds interaction between 2 given elements /// </summary> public MyRBElementInteraction AddRBElementInteraction(MyRBElement el1, MyRBElement el2) { // get it int t1 = (int)el1.GetElementType(); int t2 = (int)el2.GetElementType(); List <MyRBElementInteraction> intrList = null; if (t1 < t2) { intrList = m_IslandsPool[t1, t2]; } else { intrList = m_IslandsPool[t2, t1]; } //pada to jinak if (intrList.Count == 0) { return(null); } MyCommonDebugUtils.AssertDebug(intrList.Count != 0); if (intrList.Count == 1) { MyRBElementInteraction ins = intrList[0].CreateNewInstance(); intrList.Add(ins); } MyRBElementInteraction intr = intrList[intrList.Count - 1]; intrList.RemoveAt(intrList.Count - 1); intr.RBElement1 = el1; intr.RBElement2 = el2; el1.GetRBElementInteractions().Add(intr); el2.GetRBElementInteractions().Add(intr); return(intr); }
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> /// Adding rigid body recursively to check for constraint connections and make sure that its only in 1 island /// </summary> private void AddRigidBody(MyRigidBody rbo, MyRigidBody secondRigidBody, MyRigidBodyIsland addIsland) { if (rbo.IsStatic()) { rbo.PutToSleep(); return; } if (!m_proccesedList.Add(rbo)) { return; } // add rigid bodies to island recursively int numInteractions = 0; for (int j = 0; j < rbo.GetRBElementList().Count; j++) { MyRBElement el = rbo.GetRBElementList()[j]; numInteractions += el.GetRBElementInteractions().Count; for (int k = 0; k < el.GetRBElementInteractions().Count; k++) { if (addIsland == null && !rbo.IsStatic()) { addIsland = m_islandsPool.Allocate(); addIsland.Clear(); addIsland.IterationCount = 0; addIsland.AddRigidBody(rbo); m_islands.Add(addIsland); } else { if (!rbo.IsStatic()) { addIsland.AddRigidBody(rbo); } } MyRBElementInteraction intr = el.GetRBElementInteractions()[k]; if (intr.GetRigidBody1() != rbo && intr.GetRigidBody2() != secondRigidBody) { AddRigidBody(intr.GetRigidBody1(), rbo, addIsland); } if (intr.GetRigidBody2() != rbo && intr.GetRigidBody1() != secondRigidBody) { AddRigidBody(intr.GetRigidBody2(), rbo, addIsland); } } } // isolated rbo if (numInteractions == 0 && !rbo.IsStatic()) { MyRigidBodyIsland island = m_islandsPool.Allocate(); island.Clear(); island.IterationCount = 0; island.AddRigidBody(rbo); m_islands.Add(island); } }
/// <summary> /// Registering the interation between 2 rbelement types /// </summary> public void RegisterRBElementInteraction(MyRBElementType type1, MyRBElementType type2, MyRBElementInteraction intr) { int t1 = (int)type1; int t2 = (int)type2; List<MyRBElementInteraction> intrList = null; if (t1 < t2) { intrList = m_IslandsPool[t1, t2]; m_IslandsPoolStatic[t1, t2] = intr.CreateNewInstance(); } else { intrList = m_IslandsPool[t2, t1]; m_IslandsPoolStatic[t2, t1] = intr.CreateNewInstance(); } intrList.Capacity = m_preAllocCount; intrList.Add(intr); for (int i = 1; i < m_preAllocCount; i++) { MyRBElementInteraction ins = intr.CreateNewInstance(); intrList.Add(ins); } }