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;
            }
        }
Пример #2
0
        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();
        }
Пример #3
0
        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);
        }
Пример #4
0
 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);
 }
Пример #5
0
        public void CustomLinearDamping(int bodyIndex, float linearDamping, IUnmanagedMemoryPool pool)
        {
            if (linearDamping == LinearDamping)
            {
                _linearDampingDictionary.FastRemove(bodyIndex);
                return;
            }

            _linearDampingDictionary.Add(bodyIndex, linearDamping, pool);
        }
Пример #6
0
        public void CustomAngularDamping(int bodyIndex, float angularDamping, IUnmanagedMemoryPool pool)
        {
            if (angularDamping == AngularDamping)
            {
                _angularDampingDictionary.FastRemove(bodyIndex);
                return;
            }

            _angularDampingDictionary.Add(bodyIndex, angularDamping, pool);
        }
Пример #7
0
        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);
        }
Пример #10
0
        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));
            }
        }
Пример #11
0
        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));
            }
        }
Пример #12
0
 /// <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();
        }