public void Disconnect() { if (_connectionState == ConnectionState.DISCONNECTED) { return; } __onConnect = null; lock (__lock) { if (_networkStream != null) { _networkStream.Close(); _networkStream = null; } Debugger.Assert(_tcpClient != null); _tcpClient.Close(); _tcpClient = null; __nBytesReceived = 0; __bIsReceiveHeader = true; __sendMsgQueue.Clear(); __sysMsgQueue.Clear(); __rawMsgQueue.Clear(); _rpcCallMap.Clear(); _connectionState = ConnectionState.DISCONNECTED; __fCurrentSeconds = 0; } }
private void __dispatchSysMsgs() { /// Process error msg queue foreach (_InternalMsg errMsg in __sysMsgQueue) { switch (errMsg.type) { case _InternalMsgType.Connected: if (__onConnect != null) { __onConnect(true, null); } __onConnect = null; break; case _InternalMsgType.ConnectFailed: if (__onConnect != null) { __onConnect(false, errMsg.exception); } __onConnect = null; break; case _InternalMsgType.Disconnected: Disconnect(); if (OnDisconnected != null) { OnDisconnected(errMsg.exception); } break; } } __sysMsgQueue.Clear(); }
private static void RemoveInsidePoints(ref QuickList <Vector3> points, ref QuickList <int> triangleIndices, ref QuickList <int> outsidePoints) { var insidePoints = new QuickList <int>(BufferPools <int> .Locking); //We're going to remove points from this list as we go to prune it down to the truly inner points. insidePoints.AddRange(outsidePoints); outsidePoints.Clear(); for (int i = 0; i < triangleIndices.Count && insidePoints.Count > 0; i += 3) { //Compute the triangle's plane in point-normal representation to test other points against. Vector3 normal; FindNormal(ref triangleIndices, ref points, i, out normal); Vector3 p = points.Elements[triangleIndices.Elements[i]]; for (int j = insidePoints.Count - 1; j >= 0; --j) { //Offset from the triangle to the current point, tested against the normal, determines if the current point is visible //from the triangle face. Vector3 offset = points.Elements[insidePoints.Elements[j]] - p; float dot = Vector3.Dot(offset, normal); //If it's visible, then it's outside! if (dot > 0) { //This point is known to be on the outside; put it on the outside! outsidePoints.Add(insidePoints.Elements[j]); insidePoints.FastRemoveAt(j); } } } insidePoints.Dispose(); }
private void FullReset() { var oldCount = _resultList.Count; _fullResetInProgress = true; try { _resultList.Clear(); foreach (var set in _joinerLookup.Values) { set.Dispose(); } _joinerLookup.Clear(); _leftJoiners.Clear(); _rightJoiners.Clear(); OnLeftReset(_leftItems); OnRightReset(_rightItems); } finally { _fullResetInProgress = false; if (oldCount != _resultList.Count) { NotifyOfPropertyChange(new PropertyChangedEventArgs(nameof(Count))); } NotifyOfCollectionChange(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } }
// Update is called once per frame public void Update() { lock (__lock) { /// Processing receiving queue foreach (MsgBase message in __receiveMsgQueue) { /// if < 0, it is type of SocketMsgTypes if (message.type >= 0) { /* * Debugger.Log("-------------------------------------\n Received message, type is: " + _pConnectionHost.ServerMsgToString(message.type) + " Body: " + message.messageText + "\n-------------------------------------"); */ } DispatchEvent(message); _pConnectionHost.ReceivedListener(message); } __receiveMsgQueue.Clear(); /// Process sending queue if (__sendMsgQueue.Count != 0 && (_connectionState == ConnectionState.CONNECTED || _connectionState == ConnectionState.VALIDATED) && !__bInWriting && !_bInUpdateSessionKey) { MsgBase pMessage = __sendMsgQueue.Dequeue(); _sendMessage(pMessage); } } }
protected override void OnReset(IReadOnlyList <TSource> newItems) { _sourceList.Clear(); for (int i = 0; i < newItems.Count; ++i) { _sourceList.Add(i, new ItemSet(_keySelector.Invoke(newItems[i]), newItems[i]) { SourceIndex = i }); } IEnumerable <ItemSet> sortedItems; if (ParameterValue == ListSortDirection.Ascending) { sortedItems = _sourceList.OrderBy(set => set.Key); } else { sortedItems = _sourceList.OrderByDescending(set => set.Key); } sortedItems = sortedItems.Select((set, index) => { set.TargetIndex = index; return(set); }); ResultList.Reset(sortedItems); }
/// <summary> /// Finds contacts between the query object and any intersected objects within the character's bounding box. /// </summary> /// <param name="queryObject">Collidable to query for contacts with.</param> /// <param name="tractionContacts">Output contacts that would provide traction.</param> /// <param name="supportContacts">Output contacts that would provide support.</param> /// <param name="sideContacts">Output contacts on the sides of the query object.</param> /// <param name="headContacts">Output contacts on the head of the query object.</param> public void QueryContacts(EntityCollidable queryObject, ref QuickList <CharacterContact> tractionContacts, ref QuickList <CharacterContact> supportContacts, ref QuickList <CharacterContact> sideContacts, ref QuickList <CharacterContact> headContacts) { var downDirection = characterBody.orientationMatrix4.Down; tractionContacts.Clear(); supportContacts.Clear(); sideContacts.Clear(); headContacts.Clear(); foreach (var collidable in characterBody.CollisionInformation.OverlappedCollidables) { //The query object is assumed to have a valid bounding box. if (collidable.BoundingBox.Intersects(queryObject.BoundingBox)) { var pair = new CollidablePair(collidable, queryObject); var pairHandler = NarrowPhaseHelper.GetPairHandler(ref pair); if (pairHandler.CollisionRule == CollisionRule.Normal) { pairHandler.SuppressEvents = true; pairHandler.UpdateCollision(0); pairHandler.SuppressEvents = false; contactCategorizer.CategorizeContacts(pairHandler, characterBody.CollisionInformation, ref downDirection, ref tractionContacts, ref supportContacts, ref sideContacts, ref headContacts); } //TODO: It would be nice if this was a bit easier. //Having to remember to clean up AND give it back is a bit weird, especially with the property-diving. //No one would ever just guess this correctly. //At least hide it behind a NarrowPhaseHelper function. pairHandler.CleanUp(); pairHandler.Factory.GiveBack(pairHandler); } } }
/// <summary> /// 清空缓存池 /// </summary> /// <param name="_force"></param> public void Clear(bool _force = false) { // 销毁空闲队列 if (FreePools.Count > 0) { foreach (var freeItem in FreePools) { var poolItem = freeItem.GetComponent<ItemEntity>(); poolItem.PoolDisposeEvent(); poolItem.IsDestroyTag = true; // 标记为将要释放掉 rawResResponse.Destroy(poolItem.gameObject); } FreePools.Clear(); } // 销毁使用队列 if (UsePools.Count > 0) { foreach (var useItem in UsePools) { var poolItem = useItem.GetComponent<ItemEntity>(); poolItem.PoolDisposeEvent(); poolItem.IsDestroyTag = true; // 标记为将要释放掉 rawResResponse.Destroy(poolItem.gameObject); } this.Warr("使用队列不为空,强制清空 " + rawObjectName + " count = " + UsePools.Count); } }
/// <summary> /// Finds contacts between the query object and any intersected objects within the character's bounding capsule. /// </summary> /// <param name="queryObject">Collidable to query for contacts with.</param> /// <param name="tractionContacts">Output contacts that would provide traction.</param> /// <param name="supportContacts">Output contacts that would provide support.</param> /// <param name="sideContacts">Output contacts on the sides of the query object.</param> /// <param name="headContacts">Output contacts on the head of the query object.</param> /// <param name="forceStandardPairsToBeQueries">An extremely hacky control parameter that makes any mesh-cylinder pair treat the mesh as double sided. Useful for not going through the ceiling when changing stances.</param> public void QueryContacts(EntityCollidable queryObject, ref QuickList <CharacterContact> tractionContacts, ref QuickList <CharacterContact> supportContacts, ref QuickList <CharacterContact> sideContacts, ref QuickList <CharacterContact> headContacts, bool forceStandardPairsToBeQueries = false) { var downDirection = characterBody.orientationMatrix.Down; tractionContacts.Clear(); supportContacts.Clear(); sideContacts.Clear(); headContacts.Clear(); foreach (var collidable in characterBody.CollisionInformation.OverlappedCollidables) { //The query object is assumed to have a valid bounding capsule. if (collidable.BoundingBox.Intersects(queryObject.BoundingBox)) { var pair = new CollidablePair(collidable, queryObject); var pairHandler = NarrowPhaseHelper.GetPairHandler(ref pair); if (pairHandler.CollisionRule == CollisionRule.Normal) { if (forceStandardPairsToBeQueries) { //TODO: This is a massive hack that assumes a fixed set of collidable types. This won't work in the long run. //The only reason it's here is that it was the easiest solution, combined with the fact that the character has to be rewritten for v2 anyway. //Hopefully no one gets bit by this before the replacement is available. //The core reason it exists is that one sided meshes don't generate contacts on their backside. That means a query shape can end up above a ceiling //and it won't detect the ceiling. A better solution would be to let the caller choose whether or not to filter the contacts, and then use a //direct test rather than stateful pair to perform the query here. Still some type-related annoyance to deal with, but a bit better. var standardPair = pairHandler as StandardPairHandler; if (standardPair != null) { standardPair.ContactManifold.IsQuery = true; } } pairHandler.SuppressEvents = true; pairHandler.UpdateCollision(0); pairHandler.SuppressEvents = false; if (forceStandardPairsToBeQueries) { //TODO: Again, superhack! Avoid this in v2. var standardPair = pairHandler as StandardPairHandler; if (standardPair != null) { standardPair.ContactManifold.IsQuery = false; } } contactCategorizer.CategorizeContacts(pairHandler, characterBody.CollisionInformation, ref downDirection, ref tractionContacts, ref supportContacts, ref sideContacts, ref headContacts); } //TODO: It would be nice if this was a bit easier. //Having to remember to clean up AND give it back is a bit weird, especially with the property-diving. //No one would ever just guess this correctly. //At least hide it behind a NarrowPhaseHelper function. pairHandler.CleanUp(); pairHandler.Factory.GiveBack(pairHandler); } } }
protected override void OnDisposed() { foreach (var wrapper in _sourceLists) { wrapper.Dispose(); } _sourceLists.Clear(); base.OnDisposed(); }
public void ResetNodes() { nodes.Clear(); allGameObjects.Clear(); foreach (GameObject go in GameEngine.AllGameObjects) { if (go.Transform.Parent == null) { nodes.Add(new HierarchyNode(this, go)); } } }
protected override void OnReset(int collectionIndex, IReadOnlyList <TSource> newItems) { foreach (var value in _rightKeys) { Remove(value.Key, value.Value, _rightCount, _leftCount, OnRemovedFromRight); } _rightKeys.Clear(); foreach (var value in newItems) { var key = _keySelector.Invoke(value); _rightKeys.Add(_rightKeys.Count, new SourcePair(key, value)); Add(key, value, _rightCount, _leftCount, OnAddedToRight); } }
/// <summary> /// 成员变量重置,为的是对象可以重用; /// 继承自IPooledObjSupporter; /// </summary> public void Reset() { if (mParameters != null) { mParameters.Clear(); } else { mParameters = new QuickList <object>(2); } mID = GameEventID.GEIdCount; mTimeLock = 0; mDeleteFlg = false; }
private void UpdateCollections() { PointsOfInterest.Clear(); QuickList.Clear(); foreach (RhitLocation location in Locations) { if (location.Type == LocationType.OnQuickList) { QuickList.Add(location); PointsOfInterest.Add(location); } else if (location.Type == LocationType.PointOfInterest) { PointsOfInterest.Add(location); } } }
private IEnumerable <TSource> ResetEnumerable(IReadOnlyList <TSource> newItems) { _indexList.Clear(); int index = 0; foreach (var item in newItems) { if (_predicate.Invoke(item)) { yield return(item); _indexList.Add(_indexList.Count, index++); } else { _indexList.Add(_indexList.Count, -1); } } }
public void Reset() { objects.Clear(); if (Internal.Serializer == null) { return; } for (int i = 0; i < Internal.Serializer.ValueWrappers.Count; i++) { SerializedValue value = Internal.Serializer.ValueWrappers.Array[i]; if (value == null || value.Value == null) { continue; } objects.Add(new PropertiesValue(i, this, value)); } }
private IEnumerable <TSource> GetResetValues() { _indexes.Clear(); int count = 0; foreach (var index in SourceLists[0]) { if (index >= 0 && index < SourceList.Count) { var item = new Item(true, count++); _indexes.Add(_indexes.Count, item); yield return(SourceList[index]); } else { _indexes.Add(_indexes.Count, new Item(false, count)); } } }
/// <summary> /// Clears current rendering data from the draw-call entries. /// </summary> public void Reset() { if (DrawCallDatabase.LookupArray.Count + 1 > Data.Count) { Data.Clear(); int goal = DrawCallDatabase.LookupArray.Count + 1; Data = new QuickList <ThreadSafeList <IRenderable> >(); for (int i = 0; i < goal; i++) { Data.Add(new ThreadSafeList <IRenderable>(newListCapacity)); } } else { foreach (ThreadSafeList <IRenderable> list in Data) { list.Clear(); } } }
protected override void OnReset(IReadOnlyList <TSource> newItems) { _sourceData.Clear(); var deferrals = _resultSet.Values.Concat(_emptyGroups.Values).Select(group => group.Items.DeferChangeNotifications()).ToArray(); try { foreach (var set in _resultSet) { try { set.Value.Items.Reset(Enumerable.Empty <ItemData>()); } catch { } set.Value.TargetIndex = 0; _emptyGroups.Add(set.Key, set.Value); } _resultSet.Clear(); foreach (var value in newItems) { var item = new ItemData(_keySelector.Invoke(value), value); item.SourceIndex = _sourceData.Count; _sourceData.Add(_sourceData.Count, item); AddToGroup(item, true); } } finally { foreach (var deferral in deferrals) { deferral.Dispose(); } } ResultList.Reset(_resultSet.Values.Select((g, i) => { g.TargetIndex = i; return(g); })); }
/// <summary> /// Updates the input system. Should be called once per frame. /// </summary> /// <param name="deltaTime">Time in seconds which has passed since the last frame.</param> public static void Update(float deltaTime) { // TODO: Multiple gamepad support (local multiplayer). // Check for capabilities each second. Reduces GC allocations. if (curCapabilityTimer >= _CAPABILITY_CHECK_TIMER) { for (int i = 0; i < GamePadCapabilities.Length; i++) { GamePadCapabilities[i] = GamePad.GetCapabilities(i); } curCapabilityTimer = 0.0f; } else { curCapabilityTimer += deltaTime; } for (int i = 0; i < GamePadCapabilities.Length; i++) { GamePadStates[i] = GamePadCapabilities[i].IsConnected ? GamePad.GetState(i) : default; } // Clear pressed keys. PressedKeys.Clear(); PressedChars.Clear(); // Update inputs. if (IsActive) { UpdateInputs(deltaTime); } // Clean-up for next frame. oldScrollValue = scrollValue; oldPressedChars.Clear(); }
/// <summary> /// 销毁 /// </summary> public void Dispose() { Type supType = typeof(System.IDisposable); if (supType.IsAssignableFrom(m_destType)) { int num = this.m_keyList.Count - 1; for (int n = num; n >= 0; n--) { this.DestroyOneObject(this.m_keyList[n]); } //ArrayList list = (ArrayList)this.m_keyList.Clone(); //for (int n = 0; n < list.Count; ++n) //{ // this.DestroyOneObject((int)list[n]); //} } m_hashTableStatus.Clear(); m_hashTableObjs.Clear(); m_keyList.Clear(); }
public void ClearTest() { var master = new QuickList <int>(5); for (var i = 0; i < 255; i++) { master.Push(i); } master.Clear(); for (var i = 0; i < 255; i++) { master.Push(i); } Assert.AreEqual(255 / 5, master.Length); Assert.AreEqual(255, master.Count); for (var i = 0; i < 255; i++) { Assert.AreEqual(i, master[i]); } }
private static void RemoveInsidePoints(ref QuickList<Vector3> points, ref QuickList<int> triangleIndices, ref QuickList<int> outsidePoints) { var insidePoints = new QuickList<int>(BufferPools<int>.Locking); //We're going to remove points from this list as we go to prune it down to the truly inner points. insidePoints.AddRange(outsidePoints); outsidePoints.Clear(); for (int i = 0; i < triangleIndices.Count && insidePoints.Count > 0; i += 3) { //Compute the triangle's plane in point-normal representation to test other points against. Vector3 normal; FindNormal(ref triangleIndices, ref points, i, out normal); Vector3 p = points.Elements[triangleIndices.Elements[i]]; for (int j = insidePoints.Count - 1; j >= 0; --j) { //Offset from the triangle to the current point, tested against the normal, determines if the current point is visible //from the triangle face. Vector3 offset = points.Elements[insidePoints.Elements[j]] - p; float dot = Vector3.Dot(offset, normal); //If it's visible, then it's outside! if (dot > 0) { //This point is known to be on the outside; put it on the outside! outsidePoints.Add(insidePoints.Elements[j]); insidePoints.FastRemoveAt(j); } } } insidePoints.Dispose(); }
/// <summary> /// 释放资源 /// </summary> public void Release() { m_EventInfoPool.ClearPool(); m_EventActionList.Clear(); }
internal void _Update(float fTime, float fRealTime) { _InUpdating = true; _Time = fTime; _RealTime = fRealTime; if (__arrAddedCoroutines.Count != 0) { foreach (Coroutine addedCoroutine in __arrAddedCoroutines) { _arrCoroutines.Add(addedCoroutine); } __arrAddedCoroutines.Clear(); } ///----- int nAliveCount = _arrCoroutines.Count; Coroutine[] arrCoroutines = _arrCoroutines._Buffer; for (int i = 0; i < nAliveCount; ++i) { Coroutine pCoroutine = arrCoroutines[i]; if (pCoroutine == null) { int a = 0; a++; } Debugger.Assert(pCoroutine._bInQueue); bool bIsDead = pCoroutine._Update(pCoroutine.scalable ? fTime : fRealTime); if (bIsDead) { if (i < nAliveCount - 1) { /// Swap with last element _arrCoroutines[i] = _arrCoroutines[nAliveCount - 1]; i--; nAliveCount--; } else if (i == nAliveCount - 1) { nAliveCount--; } else { Debugger.Assert(false); } _arrCoroutines.RemoveTail(); if (pCoroutine._bPooled) { pCoroutine.DecRef(); } pCoroutine._bInQueue = false; } } _InUpdating = false; }
public void Clear() { pool.Clear(); }
public void ClearSeries() { graphSeries.Clear(); }
public void Clear() { RenderLists.Clear(); }
/// <summary> /// Identifies the indices of points in a set which are on the outer convex hull of the set. /// </summary> /// <param name="points">List of points in the set.</param> /// <param name="outputTriangleIndices">List of indices into the input point set composing the triangulated surface of the convex hull. /// Each group of 3 indices represents a triangle on the surface of the hull.</param> public static void GetConvexHull(ref QuickList<Vector3> points, ref QuickList<int> outputTriangleIndices) { if (points.Count == 0) { throw new ArgumentException("Point set must have volume."); } var outsidePoints = new QuickList<int>(BufferPools<int>.Locking, BufferPool.GetPoolIndex(points.Count - 4)); //Build the initial tetrahedron. //It will also give us the location of a point which is guaranteed to be within the //final convex hull. We can use this point to calibrate the winding of triangles. //A set of outside point candidates (all points other than those composing the tetrahedron) will be returned in the outsidePoints list. //That list will then be further pruned by the RemoveInsidePoints call. Vector3 insidePoint; ComputeInitialTetrahedron(ref points, ref outsidePoints, ref outputTriangleIndices, out insidePoint); //Compute outside points. RemoveInsidePoints(ref points, ref outputTriangleIndices, ref outsidePoints); var edges = new QuickList<int>(BufferPools<int>.Locking); var toRemove = new QuickList<int>(BufferPools<int>.Locking); var newTriangles = new QuickList<int>(BufferPools<int>.Locking); //We're now ready to begin the main loop. while (outsidePoints.Count > 0) { //While the convex hull is incomplete... for (int k = 0; k < outputTriangleIndices.Count; k += 3) { //Find the normal of the triangle Vector3 normal; FindNormal(ref outputTriangleIndices, ref points, k, out normal); //Get the furthest point in the direction of the normal. int maxIndexInOutsideList = GetExtremePoint(ref normal, ref points, ref outsidePoints); int maxIndex = outsidePoints.Elements[maxIndexInOutsideList]; Vector3 maximum = points.Elements[maxIndex]; //If the point is beyond the current triangle, continue. Vector3 offset = maximum - points.Elements[outputTriangleIndices.Elements[k]]; float dot = Vector3.Dot(normal, offset); if (dot > 0) { //It's been picked! Remove the maximum point from the outside. outsidePoints.FastRemoveAt(maxIndexInOutsideList); //Remove any triangles that can see the point, including itself! edges.Clear(); toRemove.Clear(); for (int n = outputTriangleIndices.Count - 3; n >= 0; n -= 3) { //Go through each triangle, if it can be seen, delete it and use maintainEdge on its edges. if (IsTriangleVisibleFromPoint(ref outputTriangleIndices, ref points, n, ref maximum)) { //This triangle can see it! //TODO: CONSIDER CONSISTENT WINDING HAPPYTIMES MaintainEdge(outputTriangleIndices[n], outputTriangleIndices[n + 1], ref edges); MaintainEdge(outputTriangleIndices[n], outputTriangleIndices[n + 2], ref edges); MaintainEdge(outputTriangleIndices[n + 1], outputTriangleIndices[n + 2], ref edges); //Because fast removals are being used, the order is very important. //It's pulling indices in from the end of the list in order, and also ensuring //that we never issue a removal order beyond the end of the list. outputTriangleIndices.FastRemoveAt(n + 2); outputTriangleIndices.FastRemoveAt(n + 1); outputTriangleIndices.FastRemoveAt(n); } } //Create new triangles. for (int n = 0; n < edges.Count; n += 2) { //For each edge, create a triangle with the extreme point. newTriangles.Add(edges[n]); newTriangles.Add(edges[n + 1]); newTriangles.Add(maxIndex); } //Only verify the windings of the new triangles. VerifyWindings(ref newTriangles, ref points, ref insidePoint); outputTriangleIndices.AddRange(ref newTriangles); newTriangles.Count = 0; //Remove all points from the outsidePoints if they are inside the polyhedron RemoveInsidePoints(ref points, ref outputTriangleIndices, ref outsidePoints); //The list has been significantly messed with, so restart the loop. break; } } } outsidePoints.Dispose(); edges.Dispose(); toRemove.Dispose(); newTriangles.Dispose(); }
///--------------- private void _onPollRequest(object userData) { __deadList.Clear(); foreach (HttpRequest request in _aliveRequests) { WWW www = request.www; if (request.www.error != null && www.error != string.Empty) { __nAliveRequestCount--; __deadList.Add(request); ErrorHandler(request); } else if (www.isDone) { __nAliveRequestCount--; __deadList.Add(request); request.handler(request); DataHandler(request); } else { float elapsedTime = Time.time - request.startTime; if (elapsedTime > request.timeout) { __nAliveRequestCount--; __deadList.Add(request); TimeoutHandler(request); } } } foreach (HttpRequest deadRequest in __deadList) { _aliveRequests.Remove(deadRequest); } if (aliveRequestCount < _nMaxParallelRequest && _queuedRequests.Count != 0) { int nNewAliveCount = _nMaxParallelRequest - aliveRequestCount; if (nNewAliveCount > _queuedRequests.Count) { nNewAliveCount = _queuedRequests.Count; } for (int i = 0; i < nNewAliveCount; ++i) { HttpRequest inQueueRequest = _queuedRequests.First.Value; Debugger.Assert(inQueueRequest.www == null); inQueueRequest.www = new WWW(inQueueRequest.url); inQueueRequest.startTime = Time.time; _aliveRequests.Add(inQueueRequest); __nAliveRequestCount++; _queuedRequests.RemoveFirst(); } } }
/// <summary> /// Identifies the indices of points in a set which are on the outer convex hull of the set. /// </summary> /// <param name="points">List of points in the set.</param> /// <param name="outputTriangleIndices">List of indices into the input point set composing the triangulated surface of the convex hull. /// Each group of 3 indices represents a triangle on the surface of the hull.</param> public static void GetConvexHull(ref QuickList <Vector3> points, ref QuickList <int> outputTriangleIndices) { if (points.Count == 0) { throw new ArgumentException("Point set must have volume."); } var outsidePoints = new QuickList <int>(BufferPools <int> .Locking, BufferPool.GetPoolIndex(points.Count - 4)); //Build the initial tetrahedron. //It will also give us the location of a point which is guaranteed to be within the //final convex hull. We can use this point to calibrate the winding of triangles. //A set of outside point candidates (all points other than those composing the tetrahedron) will be returned in the outsidePoints list. //That list will then be further pruned by the RemoveInsidePoints call. Vector3 insidePoint; ComputeInitialTetrahedron(ref points, ref outsidePoints, ref outputTriangleIndices, out insidePoint); //Compute outside points. RemoveInsidePoints(ref points, ref outputTriangleIndices, ref outsidePoints); var edges = new QuickList <int>(BufferPools <int> .Locking); var toRemove = new QuickList <int>(BufferPools <int> .Locking); var newTriangles = new QuickList <int>(BufferPools <int> .Locking); //We're now ready to begin the main loop. while (outsidePoints.Count > 0) { //While the convex hull is incomplete... for (int k = 0; k < outputTriangleIndices.Count; k += 3) { //Find the normal of the triangle Vector3 normal; FindNormal(ref outputTriangleIndices, ref points, k, out normal); //Get the furthest point in the direction of the normal. int maxIndexInOutsideList = GetExtremePoint(ref normal, ref points, ref outsidePoints); int maxIndex = outsidePoints.Elements[maxIndexInOutsideList]; Vector3 maximum = points.Elements[maxIndex]; //If the point is beyond the current triangle, continue. Vector3 offset = maximum - points.Elements[outputTriangleIndices.Elements[k]]; float dot = Vector3.Dot(normal, offset); if (dot > 0) { //It's been picked! Remove the maximum point from the outside. outsidePoints.FastRemoveAt(maxIndexInOutsideList); //Remove any triangles that can see the point, including itself! edges.Clear(); toRemove.Clear(); for (int n = outputTriangleIndices.Count - 3; n >= 0; n -= 3) { //Go through each triangle, if it can be seen, delete it and use maintainEdge on its edges. if (IsTriangleVisibleFromPoint(ref outputTriangleIndices, ref points, n, ref maximum)) { //This triangle can see it! //TODO: CONSIDER CONSISTENT WINDING HAPPYTIMES MaintainEdge(outputTriangleIndices[n], outputTriangleIndices[n + 1], ref edges); MaintainEdge(outputTriangleIndices[n], outputTriangleIndices[n + 2], ref edges); MaintainEdge(outputTriangleIndices[n + 1], outputTriangleIndices[n + 2], ref edges); //Because fast removals are being used, the order is very important. //It's pulling indices in from the end of the list in order, and also ensuring //that we never issue a removal order beyond the end of the list. outputTriangleIndices.FastRemoveAt(n + 2); outputTriangleIndices.FastRemoveAt(n + 1); outputTriangleIndices.FastRemoveAt(n); } } //Create new triangles. for (int n = 0; n < edges.Count; n += 2) { //For each edge, create a triangle with the extreme point. newTriangles.Add(edges[n]); newTriangles.Add(edges[n + 1]); newTriangles.Add(maxIndex); } //Only verify the windings of the new triangles. VerifyWindings(ref newTriangles, ref points, ref insidePoint); outputTriangleIndices.AddRange(ref newTriangles); newTriangles.Count = 0; //Remove all points from the outsidePoints if they are inside the polyhedron RemoveInsidePoints(ref points, ref outputTriangleIndices, ref outsidePoints); //The list has been significantly messed with, so restart the loop. break; } } } outsidePoints.Dispose(); edges.Dispose(); toRemove.Dispose(); newTriangles.Dispose(); }
/// <summary> /// Finds contacts between the query object and any intersected objects within the character's bounding box. /// </summary> /// <param name="queryObject">Collidable to query for contacts with.</param> /// <param name="tractionContacts">Output contacts that would provide traction.</param> /// <param name="supportContacts">Output contacts that would provide support.</param> /// <param name="sideContacts">Output contacts on the sides of the query object.</param> /// <param name="headContacts">Output contacts on the head of the query object.</param> public void QueryContacts(EntityCollidable queryObject, ref QuickList<CharacterContact> tractionContacts, ref QuickList<CharacterContact> supportContacts, ref QuickList<CharacterContact> sideContacts, ref QuickList<CharacterContact> headContacts) { var downDirection = characterBody.orientationMatrix.Down; tractionContacts.Clear(); supportContacts.Clear(); sideContacts.Clear(); headContacts.Clear(); foreach (var collidable in characterBody.CollisionInformation.OverlappedCollidables) { //The query object is assumed to have a valid bounding box. if (collidable.BoundingBox.Intersects(queryObject.BoundingBox)) { var pair = new CollidablePair(collidable, queryObject); var pairHandler = NarrowPhaseHelper.GetPairHandler(ref pair); if (pairHandler.CollisionRule == CollisionRule.Normal) { pairHandler.SuppressEvents = true; pairHandler.UpdateCollision(0); pairHandler.SuppressEvents = false; contactCategorizer.CategorizeContacts(pairHandler, characterBody.CollisionInformation, ref downDirection, ref tractionContacts, ref supportContacts, ref sideContacts, ref headContacts); } //TODO: It would be nice if this was a bit easier. //Having to remember to clean up AND give it back is a bit weird, especially with the property-diving. //No one would ever just guess this correctly. //At least hide it behind a NarrowPhaseHelper function. pairHandler.CleanUp(); pairHandler.Factory.GiveBack(pairHandler); } } }
public void Uninit() { _timerPool.Clear(); _arrInQueueTickers.Clear(); }