internal void End(object o) { var endTimeStamp = Stopwatch.GetTimestamp(); //Could avoid a double lookup here too. If it mattered. But it doesn't! var startIndex = startTimeStamps.IndexOf(o); if (startIndex < 0) { throw new InvalidOperationException("Can't end a stage which wasn't started first."); } var stageTime = (endTimeStamp - startTimeStamps.Values[startIndex]) / (double)Stopwatch.Frequency; startTimeStamps.FastRemove(o); //We allow stages to be started multiple times. Could be useful at some point, maybe. var stageIndex = stages.IndexOf(o); if (stageIndex < 0) { stages.Add(o, stageTime, objectPool, doublePool, intPool); } else { stages.Values[stageIndex] += stageTime; } }
public override void Update(double dt) { RigidTransform transform = new RigidTransform(mesh.Position); RigidTransform convexTransform = convex.WorldTransform; ContactRefresher.ContactRefresh(contacts, supplementData, ref convexTransform, ref transform, contactIndicesToRemove); RemoveQueuedContacts(); var overlaps = new QuickList <Vector3i>(BufferPools <Vector3i> .Thread); mesh.ChunkShape.GetOverlaps(mesh.Position, convex.BoundingBox, ref overlaps); var candidatesToAdd = new QuickList <ContactData>(BufferPools <ContactData> .Thread, BufferPool <int> .GetPoolIndex(overlaps.Count)); for (int i = 0; i < overlaps.Count; i++) { if (!ActivePairs.TryGetValue(overlaps.Elements[i], out GeneralConvexPairTester manifold)) { manifold = GetPair(ref overlaps.Elements[i]); } else { ActivePairs.FastRemove(overlaps.Elements[i]); } activePairsBackBuffer.Add(overlaps.Elements[i], manifold); if (manifold.GenerateContactCandidate(out ContactData contactCandidate)) { candidatesToAdd.Add(ref contactCandidate); } } overlaps.Dispose(); for (int i = ActivePairs.Count - 1; i >= 0; i--) { ReturnPair(ActivePairs.Values[i]); ActivePairs.FastRemove(ActivePairs.Keys[i]); } var temp = ActivePairs; ActivePairs = activePairsBackBuffer; activePairsBackBuffer = temp; if (contacts.Count + candidatesToAdd.Count > 4) { var reducedCandidates = new QuickList <ContactData>(BufferPools <ContactData> .Thread, 3); ContactReducer.ReduceContacts(contacts, ref candidatesToAdd, contactIndicesToRemove, ref reducedCandidates); RemoveQueuedContacts(); for (int i = reducedCandidates.Count - 1; i >= 0; i--) { Add(ref reducedCandidates.Elements[i]); reducedCandidates.RemoveAt(i); } reducedCandidates.Dispose(); } else if (candidatesToAdd.Count > 0) { for (int i = 0; i < candidatesToAdd.Count; i++) { Add(ref candidatesToAdd.Elements[i]); } } candidatesToAdd.Dispose(); }
private void AddAllocation(ulong id, long start, long end, ref Allocation allocation, ref Allocation nextAllocation) { var newAllocation = new Allocation { Next = allocation.Next, Previous = nextAllocation.Previous, Start = start, End = end }; //Note that the pointer modifications come BEFORE the new addition. //This avoids a potential pointer invalidation caused by a resize in the allocations dictionary. allocation.Next = id; nextAllocation.Previous = id; allocations.Add(id, newAllocation); }
public DefaultPoseIntegratorCallbacks(IUnmanagedMemoryPool pool, Vector3?gravity = null, float linearDamping = .03f, float angularDamping = .03f) : this() { Gravity = gravity ?? new Vector3(0, -9.81f, 0); LinearDamping = linearDamping; AngularDamping = angularDamping; _angularDampingDictionary = new QuickDictionary <int, float, IntComparer>(1, pool); _linearDampingDictionary = new QuickDictionary <int, float, IntComparer>(1, pool); _linearDampingDictionary.Add(-1, LinearDamping, pool); _angularDampingDictionary.Add(-1, AngularDamping, pool); }
public void CustomLinearDamping(int bodyIndex, float linearDamping, IUnmanagedMemoryPool pool) { if (linearDamping == LinearDamping) { _linearDampingDictionary.FastRemove(bodyIndex); return; } _linearDampingDictionary.Add(bodyIndex, linearDamping, pool); }
public void CustomAngularDamping(int bodyIndex, float angularDamping, IUnmanagedMemoryPool pool) { if (angularDamping == AngularDamping) { _angularDampingDictionary.FastRemove(bodyIndex); return; } _angularDampingDictionary.Add(bodyIndex, angularDamping, pool); }
private void AddAllocation(ulong id, long start, long end, ref Allocation allocation, ref Allocation nextAllocation) { var newAllocation = new Allocation { Next = allocation.Next, Previous = nextAllocation.Previous, Start = start, End = end }; //Note that the pointer modifications come BEFORE the new addition. //This avoids a potential pointer invalidation caused by a resize in the allocations dictionary. allocation.Next = id; nextAllocation.Previous = id; //About to add a new allocation. We had space here this time, so there's a high chance we'll have some more space next time. Point the search to this index. searchStartIndex = allocations.Count; allocations.Add(id, newAllocation, new PassthroughArrayPool <ulong>(), new PassthroughArrayPool <Allocation>(), new PassthroughArrayPool <int>()); }
internal void Start(object o) { //This technically does a double lookup, but the performance of this doesn't matter in the slightest. It'll be invoked a handful of times per frame. //Even the value of deferring the measurement until after the add is questionable. if (!startTimeStamps.Add(o, 0, objectPool, longPool, intPool)) { throw new InvalidOperationException("Can't start a stage which was already started without ending it first."); } var index = startTimeStamps.IndexOf(o); startTimeStamps.Values[index] = Stopwatch.GetTimestamp(); }
public static void TestDictionaryResizing(IUnmanagedMemoryPool pool) { Random random = new Random(5); var dictionary = new QuickDictionary <int, int, PrimitiveComparer <int> >(4, pool); Dictionary <int, int> controlDictionary = new Dictionary <int, int>(); for (int iterationIndex = 0; iterationIndex < 100000; ++iterationIndex) { if (random.NextDouble() < 0.7) { dictionary.Add(iterationIndex, iterationIndex, pool); controlDictionary.Add(iterationIndex, iterationIndex); } if (random.NextDouble() < 0.2) { var indexToRemove = random.Next(dictionary.Count); var toRemove = dictionary.Keys[indexToRemove]; dictionary.FastRemove(toRemove); controlDictionary.Remove(toRemove); } if (iterationIndex % 1000 == 0) { dictionary.EnsureCapacity(dictionary.Count * 3, pool); } else if (iterationIndex % 7777 == 0) { dictionary.Compact(pool); } } Debug.Assert(dictionary.Count == controlDictionary.Count); for (int i = 0; i < dictionary.Count; ++i) { Debug.Assert(controlDictionary.ContainsKey(dictionary.Keys[i])); } foreach (var element in controlDictionary.Keys) { Debug.Assert(dictionary.ContainsKey(element)); } dictionary.Dispose(pool); }
public static void TestDictionaryResizing() { Random random = new Random(5); UnsafeBufferPool <int> pool = new UnsafeBufferPool <int>(); QuickDictionary <int, int> dictionary = new QuickDictionary <int, int>(pool, pool, pool); Dictionary <int, int> controlDictionary = new Dictionary <int, int>(); for (int iterationIndex = 0; iterationIndex < 100000; ++iterationIndex) { if (random.NextDouble() < 0.7) { dictionary.Add(iterationIndex, iterationIndex); controlDictionary.Add(iterationIndex, iterationIndex); } if (random.NextDouble() < 0.2) { var indexToRemove = random.Next(dictionary.Count); var toRemove = dictionary.Keys[indexToRemove]; dictionary.FastRemove(toRemove); controlDictionary.Remove(toRemove); } if (iterationIndex % 1000 == 0) { dictionary.EnsureCapacity(dictionary.Count * 3); } else if (iterationIndex % 7777 == 0) { dictionary.Compact(); } } Assert.IsTrue(dictionary.Count == controlDictionary.Count); for (int i = 0; i < dictionary.Count; ++i) { Assert.IsTrue(controlDictionary.ContainsKey(dictionary.Keys[i])); } foreach (var element in controlDictionary.Keys) { Assert.IsTrue(dictionary.ContainsKey(element)); } }
public static void TestDictionaryResizing() { Random random = new Random(5); UnsafeBufferPool<int> pool = new UnsafeBufferPool<int>(); QuickDictionary<int, int> dictionary = new QuickDictionary<int, int>(pool, pool, pool); Dictionary<int, int> controlDictionary = new Dictionary<int, int>(); for (int iterationIndex = 0; iterationIndex < 100000; ++iterationIndex) { if (random.NextDouble() < 0.7) { dictionary.Add(iterationIndex, iterationIndex); controlDictionary.Add(iterationIndex, iterationIndex); } if (random.NextDouble() < 0.2) { var indexToRemove = random.Next(dictionary.Count); var toRemove = dictionary.Keys[indexToRemove]; dictionary.FastRemove(toRemove); controlDictionary.Remove(toRemove); } if (iterationIndex % 1000 == 0) { dictionary.EnsureCapacity(dictionary.Count * 3); } else if (iterationIndex % 7777 == 0) { dictionary.Compact(); } } Assert.IsTrue(dictionary.Count == controlDictionary.Count); for (int i = 0; i < dictionary.Count; ++i) { Assert.IsTrue(controlDictionary.ContainsKey(dictionary.Keys[i])); } foreach (var element in controlDictionary.Keys) { Assert.IsTrue(dictionary.ContainsKey(element)); } }
/// <summary> /// Begins listening for events related to the given collidable. /// </summary> /// <param name="collidable">Collidable to monitor for events.</param> public void RegisterListener(CollidableReference collidable) { listeners.Add(collidable, default, pool);
public override void Update(float dt) { //Refresh the contact manifold for this frame. var transform = new RigidTransform(voxelGrid.Position); var convexTransform = convex.WorldTransform; ContactRefresher.ContactRefresh(contacts, supplementData, ref convexTransform, ref transform, contactIndicesToRemove); RemoveQueuedContacts(); //Collect the set of overlapped cell indices. //Not the fastest way to do this, but it's relatively simple and easy. var overlaps = new QuickList <Int3>(BufferPools <Int3> .Thread); voxelGrid.Shape.GetOverlaps(voxelGrid.Position, convex.BoundingBox, ref overlaps); var candidatesToAdd = new QuickList <ContactData>(BufferPools <ContactData> .Thread, BufferPool <int> .GetPoolIndex(overlaps.Count)); for (int i = 0; i < overlaps.Count; ++i) { GeneralConvexPairTester manifold; if (!ActivePairs.TryGetValue(overlaps.Elements[i], out manifold)) { //This manifold did not previously exist. manifold = GetPair(ref overlaps.Elements[i]); } else { //It did previously exist. ActivePairs.FastRemove(overlaps.Elements[i]); } activePairsBackBuffer.Add(overlaps.Elements[i], manifold); ContactData contactCandidate; if (manifold.GenerateContactCandidate(out contactCandidate)) { candidatesToAdd.Add(ref contactCandidate); } } overlaps.Dispose(); //Any pairs remaining in the activePairs set no longer exist. Clean them up. for (int i = ActivePairs.Count - 1; i >= 0; --i) { ReturnPair(ActivePairs.Values[i]); ActivePairs.FastRemove(ActivePairs.Keys[i]); } //Swap the pair sets. var temp = ActivePairs; ActivePairs = activePairsBackBuffer; activePairsBackBuffer = temp; //Check if adding the new contacts would overflow the manifold. if (contacts.Count + candidatesToAdd.Count > 4) { //Adding all the contacts would overflow the manifold. Reduce to the best subset. var reducedCandidates = new QuickList <ContactData>(BufferPools <ContactData> .Thread, 3); ContactReducer.ReduceContacts(contacts, ref candidatesToAdd, contactIndicesToRemove, ref reducedCandidates); RemoveQueuedContacts(); for (int i = reducedCandidates.Count - 1; i >= 0; i--) { Add(ref reducedCandidates.Elements[i]); reducedCandidates.RemoveAt(i); } reducedCandidates.Dispose(); } else if (candidatesToAdd.Count > 0) { //Won't overflow the manifold, so just toss it in. for (int i = 0; i < candidatesToAdd.Count; i++) { Add(ref candidatesToAdd.Elements[i]); } } candidatesToAdd.Dispose(); }