Exemplo n.º 1
0
        public void Pool()
        {
            if (this.pool)
            {
                ArrayPool <int> .Release(ref this.triangles, false);

                ArrayPool <Vector3> .Release(ref this.vertices, false);
            }
        }
Exemplo n.º 2
0
        /** Pool the #vertices and #triangles arrays if the #pool field is true */
        public void Pool()
        {
            if (pool)
            {
                ArrayPool <int> .Release(ref triangles);

                ArrayPool <Vector3> .Release(ref vertices);
            }
        }
Exemplo n.º 3
0
        /** Releases contents of a contour set to caches */
        static void ReleaseContours(VoxelContourSet cset)
        {
            for (int i = 0; i < cset.conts.Count; i++)
            {
                VoxelContour cont = cset.conts[i];
                ArrayPool <int> .Release(ref cont.verts);

                ArrayPool <int> .Release(ref cont.rverts);
            }
            cset.conts = null;
        }
Exemplo n.º 4
0
        private void Disconnect(SocketAsyncEventArgs e)
        {
            if (m_Client == null)
            {
                return;
            }

            if (m_BufferPool != null)
            {
                lock (m_BufferPool)
                {
                    m_SendEventArgs = null;
                    m_BufferPool.ReleaseBuffer(m_SendingBuffer);
                    m_SendingBuffer = null;
                    m_BufferPool.ReleaseBuffer(m_WaitSendBuffer);
                    m_WaitSendBuffer = null;

                    m_ReceiveEventArgs = null;
                    m_BufferPool.ReleaseBuffer(m_ReceiveBuffer);
                    m_ReceiveBuffer = null;
                    if (m_ReceiveBodyBuffer != null)
                    {
                        m_BufferPool.ReleaseBuffer(m_ReceiveBodyBuffer);
                        m_ReceiveBodyBuffer = null;
                    }

                    m_BufferPool.ReleaseBuffer(m_ReceiveHeaderBuffer);
                    m_ReceiveHeaderBuffer = null;
                }

                lock (m_BufferPool)
                {
                    lock (m_ReceiveLock)
                    {
                        while (m_ReceivedPackages.Count > 0)
                        {
                            m_BufferPool.ReleaseBuffer(m_ReceivedPackages.Dequeue());
                        }
                    }
                }

                m_BufferPool.Release();
                m_BufferPool = null;
            }

            m_Client.Close();
            m_Client = null;

            lock (m_TcpConnectActionLock)
            {
                m_TcpConnectData = new TcpConnectData(this, e, ConnectState.Disconnected);
            }
        }
Exemplo n.º 5
0
        void EnsureNodeCapacity(int c)
        {
            if (c > nodeLookup.Length)
            {
                var newArr = ArrayPool <TriangleMeshNode> .Claim(c);

                nodeLookup.CopyTo(newArr, 0);
                ArrayPool <TriangleMeshNode> .Release(ref nodeLookup);

                nodeLookup = newArr;
            }
        }
Exemplo n.º 6
0
        private void EnsureCapacity(int c)
        {
            if (c > this.tree.Length)
            {
                BBTree.BBTreeBox[] array = ArrayPool <BBTree.BBTreeBox> .Claim(c);

                this.tree.CopyTo(array, 0);
                ArrayPool <BBTree.BBTreeBox> .Release(ref this.tree, false);

                this.tree = array;
            }
        }
Exemplo n.º 7
0
		public void TestCase ()
		{
			ArrayPool<byte> pool = new ArrayPool<byte> ();
			byte[] buffer; 
			bool isNewArray = pool.Take (10, out buffer);
			Assert.IsTrue (isNewArray);
			pool.Release (buffer);
			byte[] second;
			isNewArray = pool.Take (5, out second);			
			Assert.IsFalse (isNewArray);
			Assert.AreSame (buffer, second);
		}
Exemplo n.º 8
0
        private void EnsureNodeCapacity(int c)
        {
            if (c > this.nodeLookup.Length)
            {
                TriangleMeshNode[] array = ArrayPool <TriangleMeshNode> .Claim(c);

                this.nodeLookup.CopyTo(array, 0);
                ArrayPool <TriangleMeshNode> .Release(ref this.nodeLookup, false);

                this.nodeLookup = array;
            }
        }
Exemplo n.º 9
0
        void EnsureCapacity(int c)
        {
            if (c > tree.Length)
            {
                var newArr = ArrayPool <BBTreeBox> .Claim(c);

                tree.CopyTo(newArr, 0);
                ArrayPool <BBTreeBox> .Release(ref tree);

                tree = newArr;
            }
        }
Exemplo n.º 10
0
        public void UpdateInstance(CellView view, Vector2Int coords, CellStatusFlags cellStatus)
        {
            if (view == null)
            {
                return;
            }

            bool isRevealed = cellStatus.HasFlag(CellStatusFlags.IsRevealed);
            bool isMarked   = !isRevealed && cellStatus.HasFlag(CellStatusFlags.IsMarked);

            view.textMesh.enabled = isRevealed;
            view.ToggleFlag(isMarked);
            SetCellBackground(view, isRevealed, isMarked);
            if (isMarked)
            {
                view.FlagColor = colorSheet.flagColor;
            }

            if (isRevealed)
            {
                if (cellStatus.HasFlag(CellStatusFlags.HasMine))
                {
                    SetMineMode(view, true);
                }
                else
                {
                    SetMineMode(view, false);
                    const int neighborCount = 8;
                    var       neighbors     = ArrayPool <Vector2Int> .Get(neighborCount);

                    LevelUtility.GetAdjacentCellsSquare(coords, neighbors);
                    int cellValue = 0;
                    for (int i = 0; i < neighborCount; ++i)
                    {
                        var neighborStatus = levelDataManager.GetCellStatus(neighbors[i]);
                        if (neighborStatus.HasFlag(CellStatusFlags.HasMine))
                        {
                            cellValue++;
                        }
                    }

                    ArrayPool <Vector2Int> .Release(neighbors);

                    view.textMesh.text  = cellValue == 0 ? "" : cellValue.ToString();
                    view.textMesh.color = colorSheet.GetColorForCellValue(cellValue);
                }
            }
            else
            {
                view.mineSprite.enabled = false;
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Compress the mesh by removing duplicate vertices.
        ///
        /// Vertices that differ by only 1 along the y coordinate will also be merged together.
        /// Warning: This function is not threadsafe. It uses some cached structures to reduce allocations.
        /// </summary>
        /// <param name="vertices">Vertices of the input mesh</param>
        /// <param name="triangles">Triangles of the input mesh</param>
        /// <param name="outVertices">Vertices of the output mesh.</param>
        /// <param name="outTriangles">Triangles of the output mesh.</param>
        public static void CompressMesh(List <Int3> vertices, List <int> triangles, out Int3[] outVertices, out int[] outTriangles)
        {
            Dictionary <Int3, int> firstVerts = cached_Int3_int_dict;

            firstVerts.Clear();

            // Use cached array to reduce memory allocations
            int[] compressedPointers = ArrayPool <int> .Claim(vertices.Count);

            // Map positions to the first index they were encountered at
            int count = 0;

            for (int i = 0; i < vertices.Count; i++)
            {
                // Check if the vertex position has already been added
                // Also check one position up and one down because rounding errors can cause vertices
                // that should end up in the same position to be offset 1 unit from each other
                // TODO: Check along X and Z axes as well?
                int ind;
                if (!firstVerts.TryGetValue(vertices[i], out ind) && !firstVerts.TryGetValue(vertices[i] + new Int3(0, 1, 0), out ind) && !firstVerts.TryGetValue(vertices[i] + new Int3(0, -1, 0), out ind))
                {
                    firstVerts.Add(vertices[i], count);
                    compressedPointers[i] = count;
                    vertices[count]       = vertices[i];
                    count++;
                }
                else
                {
                    compressedPointers[i] = ind;
                }
            }

            // Create the triangle array or reuse the existing buffer
            outTriangles = new int[triangles.Count];

            // Remap the triangles to the new compressed indices
            for (int i = 0; i < outTriangles.Length; i++)
            {
                outTriangles[i] = compressedPointers[triangles[i]];
            }

            // Create the vertex array or reuse the existing buffer
            outVertices = new Int3[count];

            for (int i = 0; i < count; i++)
            {
                outVertices[i] = vertices[i];
            }

            ArrayPool <int> .Release(ref compressedPointers);
        }
Exemplo n.º 12
0
        /** Rebuilds the tree using the specified nodes */
        public void RebuildFrom(TriangleMeshNode[] nodes)
        {
            Clear();

            if (nodes.Length == 0)
            {
                return;
            }

            // We will use approximately 2N tree nodes
            EnsureCapacity(Mathf.CeilToInt(nodes.Length * 2.1f));
            // We will use approximately N node references
            EnsureNodeCapacity(Mathf.CeilToInt(nodes.Length * 1.1f));

            // This will store the order of the nodes while the tree is being built
            // It turns out that it is a lot faster to do this than to actually modify
            // the nodes and nodeBounds arrays (presumably since that involves shuffling
            // around 20 bytes of memory (sizeof(pointer) + sizeof(IntRect)) per node
            // instead of 4 bytes (sizeof(int)).
            // It also means we don't have to make a copy of the nodes array since
            // we do not modify it
            var permutation = ArrayPool <int> .Claim(nodes.Length);

            for (int i = 0; i < nodes.Length; i++)
            {
                permutation[i] = i;
            }

            // Precalculate the bounds of the nodes in XZ space.
            // It turns out that calculating the bounds is a bottleneck and precalculating
            // the bounds makes it around 3 times faster to build a tree
            var nodeBounds = ArrayPool <IntRect> .Claim(nodes.Length);

            for (int i = 0; i < nodes.Length; i++)
            {
                VInt3 v0, v1, v2;
                nodes[i].GetVertices(out v0, out v1, out v2);

                var rect = new IntRect(v0.x, v0.z, v0.x, v0.z);
                rect          = rect.ExpandToContain(v1.x, v1.z);
                rect          = rect.ExpandToContain(v2.x, v2.z);
                nodeBounds[i] = rect;
            }

            RebuildFromInternal(nodes, permutation, nodeBounds, 0, nodes.Length, false);

            ArrayPool <int> .Release(ref permutation);

            ArrayPool <IntRect> .Release(ref nodeBounds);
        }
Exemplo n.º 13
0
 // Token: 0x060023CA RID: 9162 RVA: 0x0019A4D8 File Offset: 0x001986D8
 public override void ClearConnections(bool alsoReverse)
 {
     if (alsoReverse && this.connections != null)
     {
         for (int i = 0; i < this.connections.Length; i++)
         {
             if (this.connections[i].node != null)
             {
                 this.connections[i].node.RemoveConnection(this);
             }
         }
     }
     ArrayPool <Connection> .Release(ref this.connections, true);
 }
Exemplo n.º 14
0
        public static bool MergeContours(ref VoxelContour ca, ref VoxelContour cb, int ia, int ib)
        {
            int maxVerts = ca.nverts + cb.nverts + 2;

            int[] verts = ArrayPool <int> .Claim(maxVerts *4);

            //if (!verts)
            //	return false;

            int nv = 0;

            // Copy contour A.
            for (int i = 0; i <= ca.nverts; i++)
            {
                int dst = nv * 4;
                int src = ((ia + i) % ca.nverts) * 4;
                verts[dst + 0] = ca.verts[src + 0];
                verts[dst + 1] = ca.verts[src + 1];
                verts[dst + 2] = ca.verts[src + 2];
                verts[dst + 3] = ca.verts[src + 3];
                nv++;
            }

            // Copy contour B
            for (int i = 0; i <= cb.nverts; i++)
            {
                int dst = nv * 4;
                int src = ((ib + i) % cb.nverts) * 4;
                verts[dst + 0] = cb.verts[src + 0];
                verts[dst + 1] = cb.verts[src + 1];
                verts[dst + 2] = cb.verts[src + 2];
                verts[dst + 3] = cb.verts[src + 3];
                nv++;
            }

            ArrayPool <int> .Release(ref ca.verts);

            ArrayPool <int> .Release(ref cb.verts);

            ca.verts  = verts;
            ca.nverts = nv;

            cb.verts = ArrayPool <int> .Claim(0);

            cb.nverts = 0;

            return(true);
        }
Exemplo n.º 15
0
        public void GetMesh(ref Int3[] vbuffer, out int[] tbuffer, GraphTransform inverseTransform = null)
        {
            if (this.verts == null)
            {
                this.RebuildMesh();
            }
            if (this.verts == null)
            {
                tbuffer = ArrayPool <int> .Claim(0);

                return;
            }
            if (vbuffer == null || vbuffer.Length < this.verts.Length)
            {
                if (vbuffer != null)
                {
                    ArrayPool <Int3> .Release(ref vbuffer, false);
                }
                vbuffer = ArrayPool <Int3> .Claim(this.verts.Length);
            }
            tbuffer = this.tris;
            if (this.useRotationAndScale)
            {
                Matrix4x4 matrix4x = Matrix4x4.TRS(this.tr.position + this.center, this.tr.rotation, this.tr.localScale * this.meshScale);
                for (int i = 0; i < this.verts.Length; i++)
                {
                    Vector3 vector = matrix4x.MultiplyPoint3x4(this.verts[i]);
                    if (inverseTransform != null)
                    {
                        vector = inverseTransform.InverseTransform(vector);
                    }
                    vbuffer[i] = (Int3)vector;
                }
            }
            else
            {
                Vector3 a = this.tr.position + this.center;
                for (int j = 0; j < this.verts.Length; j++)
                {
                    Vector3 vector2 = a + this.verts[j] * this.meshScale;
                    if (inverseTransform != null)
                    {
                        vector2 = inverseTransform.InverseTransform(vector2);
                    }
                    vbuffer[j] = (Int3)vector2;
                }
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// Add a connection from this node to the specified node.
        /// See: Pathfinding.Connection.edge
        ///
        /// If the connection already exists, the cost will simply be updated and
        /// no extra connection added.
        ///
        /// Note: Only adds a one-way connection. Consider calling the same function on the other node
        /// to get a two-way connection.
        /// </summary>
        /// <param name="node">Node to add a connection to</param>
        /// <param name="cost">Cost of traversing the connection. A cost of 1000 corresponds approximately to the cost of moving 1 world unit.</param>
        /// <param name="shapeEdge">Which edge on the shape of this node to use or -1 if no edge is used.</param>
        public void AddConnection(GraphNode node, uint cost, int shapeEdge)
        {
            if (node == null)
            {
                throw new System.ArgumentNullException();
            }

            // Check if we already have a connection to the node
            if (connections != null)
            {
                for (int i = 0; i < connections.Length; i++)
                {
                    if (connections[i].node == node)
                    {
                        // Just update the cost for the existing connection
                        connections[i].cost = cost;
                        // Update edge only if it was a definite edge, otherwise reuse the existing one
                        // This makes it possible to use the AddConnection(node,cost) overload to only update the cost
                        // without changing the edge which is required for backwards compatibility.
                        connections[i].shapeEdge = shapeEdge >= 0 ? (byte)shapeEdge : connections[i].shapeEdge;
                        return;
                    }
                }
            }

            // Create new arrays which include the new connection
            int connLength = connections != null ? connections.Length : 0;

            var newconns = ArrayPool <Connection> .ClaimWithExactLength(connLength + 1);

            for (int i = 0; i < connLength; i++)
            {
                newconns[i] = connections[i];
            }

            newconns[connLength] = new Connection(node, cost, (byte)shapeEdge);

            if (connections != null)
            {
                ArrayPool <Connection> .Release(ref connections, true);
            }

            connections = newconns;
            AstarPath.active.hierarchicalGraph.AddDirtyNode(this);
        }
Exemplo n.º 17
0
            public void Execute()
            {
                Profiler.BeginSample("Allocating nodes");
                var hierarchicalGraph = pathProcessor.astar.hierarchicalGraph;

                // Allocate more internal pathfinding data for the new nodes
                hierarchicalGraph.ReserveNodeIndices(reservedPathNodeData);
                for (int i = 0; i < pathProcessor.pathHandlers.Length; i++)
                {
                    pathProcessor.pathHandlers[i].ReserveNodeIndices(reservedPathNodeData);
                }

                // Allocate the actual nodes
                for (int i = 0; i < count; i++)
                {
                    if (result[i] != null)
                    {
                        continue;
                    }
                    var node = result[i] = createNode();

                    // Get a new node index. Re-use one from a previously destroyed node if possible
                    if (i < numRecycledNodeIndices)
                    {
                        node.NodeIndex = recyledNodeIndices[i];
                    }
                    else
                    {
                        node.NodeIndex = startingNodeIndex + i - numRecycledNodeIndices;
                    }

                    for (int j = pathProcessor.pathHandlers.Length - 1; j >= 0; j--)
                    {
                        pathProcessor.pathHandlers[j].InitializeNode(node);
                    }
                }

                for (int i = 0; i < count; i++)
                {
                    hierarchicalGraph.AddDirtyNode(result[i]);
                }
                ArrayPool <int> .Release(ref recyledNodeIndices);

                Profiler.EndSample();
            }
Exemplo n.º 18
0
            /*
             *      v0  ----  v1
             \  /
             \/
             \               v2
             */
            void BlitTriangle(Vector2 v0, Vector2 v1, Vector2 v2, Vector2 uv0, Vector2 uv1, Vector2 uv2, PlotDelegate plotDelegate)
            {
                if (v0.x > v1.x)
                {
                    MUtils.Swap(ref v0, ref v1);
                }

                var L1 = new RasterizedLine(v0, v2);
                var L2 = new RasterizedLine(v1, v2);
                var i1 = L1.CreatePixelIterator();
                var i2 = L2.CreatePixelIterator();

                Vector2 newUv0 = Vector2.zero;
                Vector3 newUv1 = Vector2.zero;

                var pList1 = ArrayPool <RasterizedLine.Pixel> .Get();

                var pList2 = ArrayPool <RasterizedLine.Pixel> .Get();

                CacheYOnChanged(i1, pList1);
                CacheYOnChanged(i2, pList2);

                if (CheckSequence(pList1, pList2))
                {
                    for (int i = 0; i < pList1.length; ++i)
                    {
                        var a = pList1[i];
                        var b = pList2[i];
                        BlitHorizontalLine(a.x, b.x, a.y, newUv0, newUv1, plotDelegate);
                    }
                }
                else
                {
                    for (int i = 0; i < pList1.length; ++i)
                    {
                        var a = pList1[i];
                        var b = pList2[-i - 1];
                        BlitHorizontalLine(a.x, b.x, a.y, newUv0, newUv1, plotDelegate);
                    }
                }
                ArrayPool <RasterizedLine.Pixel> .Release(pList1);

                ArrayPool <RasterizedLine.Pixel> .Release(pList2);
            }
Exemplo n.º 19
0
        public override void ClearConnections(bool alsoReverse)
        {
            // Remove all connections to this node from our neighbours
            if (alsoReverse && connections != null)
            {
                for (int i = 0; i < connections.Length; i++)
                {
                    // Null check done here because NavmeshTile.Destroy
                    // requires it for some optimizations it does
                    // Normally connection elements are never null
                    if (connections[i].node != null)
                    {
                        connections[i].node.RemoveConnection(this);
                    }
                }
            }

            ArrayPool <Connection> .Release(ref connections, true);
        }
Exemplo n.º 20
0
        public static void RevealCellsRecursively(LevelTable level, int x, int y, Dictionary <Vector2Int, Cell> revealList)
        {
            if (revealList.Count > level.CellCount)
            {
                throw new OverflowException();
            }

            var pos = new Vector2Int(x, y);

            if (revealList.ContainsKey(pos))
            {
                return;
            }

            if (!LevelUtility.IsCellWithinBounds(x, y, level.Size))
            {
                return; // Indexes out of range.
            }
            Cell cell = level[x, y];

            if (cell.isRevealed || cell.hasFlag)
            {
                return; // cell is not subject revelation.
            }
            level.MarkCellRevealed(pos);
            revealList[pos] = level[x, y];

            if (cell.value == 0)
            {
                const int neighborCount = 8;
                var       neighbors     = ArrayPool <Vector2Int> .Get(neighborCount);

                LevelUtility.GetAdjacentCellsSquare(pos, neighbors);
                for (int i = 0; i < neighborCount; i++)
                {
                    Vector2Int nPos = neighbors[i];
                    RevealCellsRecursively(level, nPos.x, nPos.y, revealList);
                }

                ArrayPool <Vector2Int> .Release(neighbors);
            }
        }
Exemplo n.º 21
0
        /** Add a connection from this node to the specified node.
         * If the connection already exists, the cost will simply be updated and
         * no extra connection added.
         *
         * \note Only adds a one-way connection. Consider calling the same function on the other node
         * to get a two-way connection.
         */
        public override void AddConnection(GraphNode node, uint cost)
        {
            if (node == null)
            {
                throw new System.ArgumentNullException();
            }

            // Check if we already have a connection to the node
            if (connections != null)
            {
                for (int i = 0; i < connections.Length; i++)
                {
                    if (connections[i].node == node)
                    {
                        // Just update the cost for the existing connection
                        connections[i].cost = cost;
                        return;
                    }
                }
            }

            // Create new arrays which include the new connection
            int connLength = connections != null ? connections.Length : 0;

            var newconns = ArrayPool <Connection> .ClaimWithExactLength(connLength + 1);

            for (int i = 0; i < connLength; i++)
            {
                newconns[i] = connections[i];
            }

            newconns[connLength] = new Connection {
                node = node, cost = cost
            };

            if (connections != null)
            {
                ArrayPool <Connection> .Release(ref connections, true);
            }

            connections = newconns;
        }
Exemplo n.º 22
0
        public void ArrayPool_Concurrency()
        {
            var pool = new ArrayPool <int>(1);

            Parallel.ForEach(
                Enumerable.Range(0, 1000),
                _ =>
            {
                var arr = pool.Get();
                try
                {
                    Assert.IsNotNull(arr);
                }
                finally
                {
                    pool.Release(arr);
                }
            }
                );
        }
Exemplo n.º 23
0
        public void Clear()
        {
            this.count     = 0;
            this.leafNodes = 0;
            if (this.tree != null)
            {
                ArrayPool <BBTree.BBTreeBox> .Release(ref this.tree, false);
            }
            if (this.nodeLookup != null)
            {
                for (int i = 0; i < this.nodeLookup.Length; i++)
                {
                    this.nodeLookup[i] = null;
                }
                ArrayPool <TriangleMeshNode> .Release(ref this.nodeLookup, false);
            }
            this.tree = ArrayPool <BBTree.BBTreeBox> .Claim(0);

            this.nodeLookup = ArrayPool <TriangleMeshNode> .Claim(0);
        }
Exemplo n.º 24
0
        /** Clear the tree.
         * Note that references to old nodes will still be intact so the GC cannot immediately collect them.
         */
        public void Clear()
        {
            count     = 0;
            leafNodes = 0;
            if (tree != null)
            {
                ArrayPool <BBTreeBox> .Release(ref tree);
            }
            if (nodeLookup != null)
            {
                // Prevent memory leaks as the pool does not clear the array
                for (int i = 0; i < nodeLookup.Length; i++)
                {
                    nodeLookup[i] = null;
                }
                ArrayPool <TriangleMeshNode> .Release(ref nodeLookup);
            }
            tree = ArrayPool <BBTreeBox> .Claim(0);

            nodeLookup = ArrayPool <TriangleMeshNode> .Claim(0);
        }
Exemplo n.º 25
0
        /// <summary>
        /// Removes any connection from this node to the specified node.
        /// If no such connection exists, nothing will be done.
        ///
        /// Note: This only removes the connection from this node to the other node.
        /// You may want to call the same function on the other node to remove its eventual connection
        /// to this node.
        /// </summary>
        public override void RemoveConnection(GraphNode node)
        {
            if (connections == null)
            {
                return;
            }

            // Iterate through all connections and check if there are any to the node
            for (int i = 0; i < connections.Length; i++)
            {
                if (connections[i].node == node)
                {
                    // Create new arrays which have the specified node removed
                    int connLength = connections.Length;

                    var newconns = ArrayPool <Connection> .ClaimWithExactLength(connLength - 1);

                    for (int j = 0; j < i; j++)
                    {
                        newconns[j] = connections[j];
                    }

                    for (int j = i + 1; j < connLength; j++)
                    {
                        newconns[j - 1] = connections[j];
                    }

                    if (connections != null)
                    {
                        ArrayPool <Connection> .Release(ref connections, true);
                    }

                    connections = newconns;
                    AstarPath.active.hierarchicalGraph.AddDirtyNode(this);
                    return;
                }
            }
        }
Exemplo n.º 26
0
        public static void CompressMesh(List <Int3> vertices, List <int> triangles, out Int3[] outVertices, out int[] outTriangles)
        {
            Dictionary <Int3, int> dictionary = Polygon.cached_Int3_int_dict;

            dictionary.Clear();
            int[] array = ArrayPool <int> .Claim(vertices.Count);

            int num = 0;

            for (int i = 0; i < vertices.Count; i++)
            {
                int num2;
                if (!dictionary.TryGetValue(vertices[i], out num2) && !dictionary.TryGetValue(vertices[i] + new Int3(0, 1, 0), out num2) && !dictionary.TryGetValue(vertices[i] + new Int3(0, -1, 0), out num2))
                {
                    dictionary.Add(vertices[i], num);
                    array[i]      = num;
                    vertices[num] = vertices[i];
                    num++;
                }
                else
                {
                    array[i] = num2;
                }
            }
            outTriangles = new int[triangles.Count];
            for (int j = 0; j < outTriangles.Length; j++)
            {
                outTriangles[j] = array[triangles[j]];
            }
            outVertices = new Int3[num];
            for (int k = 0; k < num; k++)
            {
                outVertices[k] = vertices[k];
            }
            ArrayPool <int> .Release(ref array, false);
        }
Exemplo n.º 27
0
        public override void AddConnection(GraphNode node, uint cost)
        {
            if (node == null)
            {
                throw new ArgumentNullException();
            }
            if (this.connections != null)
            {
                for (int i = 0; i < this.connections.Length; i++)
                {
                    if (this.connections[i].node == node)
                    {
                        this.connections[i].cost = cost;
                        return;
                    }
                }
            }
            int num = (this.connections == null) ? 0 : this.connections.Length;

            Connection[] array = ArrayPool <Connection> .ClaimWithExactLength(num + 1);

            for (int j = 0; j < num; j++)
            {
                array[j] = this.connections[j];
            }
            array[num] = new Connection
            {
                node = node,
                cost = cost
            };
            if (this.connections != null)
            {
                ArrayPool <Connection> .Release(ref this.connections, true);
            }
            this.connections = array;
        }
Exemplo n.º 28
0
        /// <summary>
        /// Calculate the shortest path through the funnel.
        ///
        /// If the unwrap option is disabled the funnel will simply be projected onto the XZ plane.
        /// If the unwrap option is enabled then the funnel may be oriented arbitrarily and may have twists and bends.
        /// This makes it possible to support the funnel algorithm in XY space as well as in more complicated cases, such
        /// as on curved worlds.
        /// [Open online documentation to see images]
        ///
        /// [Open online documentation to see images]
        ///
        /// See: Unwrap
        /// </summary>
        /// <param name="funnel">The portals of the funnel. The first and last vertices portals must be single points (so for example left[0] == right[0]).</param>
        /// <param name="unwrap">Determines if twists and bends should be straightened out before running the funnel algorithm.</param>
        /// <param name="splitAtEveryPortal">If true, then a vertex will be inserted every time the path crosses a portal
        ///  instead of only at the corners of the path. The result will have exactly one vertex per portal if this is enabled.
        ///  This may introduce vertices with the same position in the output (esp. in corners where many portals meet).</param>
        public static List <Vector3> Calculate(FunnelPortals funnel, bool unwrap, bool splitAtEveryPortal)
        {
            if (funnel.left.Count != funnel.right.Count)
            {
                throw new System.ArgumentException("funnel.left.Count != funnel.right.Count");
            }

            // Get arrays at least as large as the number of portals
            var leftArr = ArrayPool <Vector2> .Claim(funnel.left.Count);

            var rightArr = ArrayPool <Vector2> .Claim(funnel.left.Count);

            if (unwrap)
            {
                Unwrap(funnel, leftArr, rightArr);
            }
            else
            {
                // Copy to arrays
                for (int i = 0; i < funnel.left.Count; i++)
                {
                    leftArr[i]  = ToXZ(funnel.left[i]);
                    rightArr[i] = ToXZ(funnel.right[i]);
                }
            }

            int startIndex         = FixFunnel(leftArr, rightArr, funnel.left.Count);
            var intermediateResult = ListPool <int> .Claim();

            if (startIndex == -1)
            {
                // If funnel algorithm failed, fall back to a simple line
                intermediateResult.Add(0);
                intermediateResult.Add(funnel.left.Count - 1);
            }
            else
            {
                bool lastCorner;
                Calculate(leftArr, rightArr, funnel.left.Count, startIndex, intermediateResult, int.MaxValue, out lastCorner);
            }

            // Get list for the final result
            var result = ListPool <Vector3> .Claim(intermediateResult.Count);

            Vector2 prev2D  = leftArr[0];
            var     prevIdx = 0;

            for (int i = 0; i < intermediateResult.Count; i++)
            {
                var idx = intermediateResult[i];

                if (splitAtEveryPortal)
                {
                    // Check intersections with every portal segment
                    var next2D = idx >= 0 ? leftArr[idx] : rightArr[-idx];
                    for (int j = prevIdx + 1; j < System.Math.Abs(idx); j++)
                    {
                        var factor = VectorMath.LineIntersectionFactorXZ(FromXZ(leftArr[j]), FromXZ(rightArr[j]), FromXZ(prev2D), FromXZ(next2D));
                        result.Add(Vector3.Lerp(funnel.left[j], funnel.right[j], factor));
                    }

                    prevIdx = Mathf.Abs(idx);
                    prev2D  = next2D;
                }

                if (idx >= 0)
                {
                    result.Add(funnel.left[idx]);
                }
                else
                {
                    result.Add(funnel.right[-idx]);
                }
            }

            // Release lists back to the pool
            ListPool <int> .Release(ref intermediateResult);

            ArrayPool <Vector2> .Release(ref leftArr);

            ArrayPool <Vector2> .Release(ref rightArr);

            return(result);
        }
Exemplo n.º 29
0
        private void OnDrawGraphGizmos(GridGraph graph)
        {
            using (var helper = gizmos.GetSingleFrameGizmoHelper(this))
            {
                var bounds = new Bounds();
                int depth  = m_Graph.Depth,
                    width  = m_Graph.Width;
                bounds.SetMinMax(Vector3.zero, new Vector3(width, 0, depth));
                var m = m_Graph.UpdateTransform();
                helper.builder.DrawWireCube(m, bounds, Color.white);

                var color = new Color(1, 1, 1, 0.2f);
                for (int z = 0; z < depth; z++)
                {
                    helper.builder.DrawLine(m.Transform(new Vector3(0, 0, z)), m.Transform(new Vector3(width, 0, z)), color);
                }
                for (int x = 0; x < width; x++)
                {
                    helper.builder.DrawLine(m.Transform(new Vector3(x, 0, 0)), m.Transform(new Vector3(x, 0, depth)), color);
                }
            }

            const int chunkWidth = 1;

            GridNode[] allNodes = ArrayPool <GridNode> .Claim(chunkWidth *chunkWidth);

            for (int cx = m_Graph.Width / chunkWidth; cx >= 0; cx--)
            {
                for (int cz = m_Graph.Depth / chunkWidth; cz >= 0; cz--)
                {
                    var allNodesCount = m_Graph.GetNodesInRegion(new IntRect(cx * chunkWidth, cz * chunkWidth, (cx + 1) * chunkWidth - 1, (cz + 1) * chunkWidth - 1), allNodes);
                    var hasher        = new RetainedGizmos.Hasher(this);
                    hasher.AddHash(showMeshOutline ? 1 : 0);
                    hasher.AddHash(showMeshSurface ? 1 : 0);
                    hasher.AddHash(showNodeConnections ? 1 : 0);

                    for (int i = 0; i < allNodesCount; i++)
                    {
                        hasher.HashNode(allNodes[i]);
                    }

                    if (!gizmos.Draw(hasher))
                    {
                        using (var helper = gizmos.GetGizmoHelper(this, hasher))
                        {
                            if (showNodeConnections)
                            {
                                for (int i = 0; i < allNodesCount; i++)
                                {
                                    if (allNodes[i].Walkable)
                                    {
                                        helper.DrawConnections(allNodes[i]);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            ArrayPool <GridNode> .Release(ref allNodes);
        }
Exemplo n.º 30
0
    void SerializeUnityNavMesh(NavMeshTriangulation unityNavMesh, ref RecastGraph recast)
    {
        if (active == null || active.data == null)
        {
            return;
        }

        var vertMap = ObjectPoolSimple <Dictionary <int, int> > .Claim();

        var totalVoxelWidth = (int)(recast.forcedBoundsSize.x / recast.cellSize + 0.5f);
        var totalVoxelDepth = (int)(recast.forcedBoundsSize.z / recast.cellSize + 0.5f);
        var tileSizeX       = recast.editorTileSize;
        var tileSizeZ       = recast.editorTileSize;
        var tileXCount      = (totalVoxelWidth + tileSizeX - 1) / tileSizeX;
        var tileZCount      = (totalVoxelDepth + tileSizeZ - 1) / tileSizeZ;
        var tileWorldSize   = recast.TileWorldSizeX;
        var bucket          = ArrayPool <List <int> > .Claim((tileXCount + 1) *(tileZCount + 1));

        for (int i = 0; i < unityNavMesh.vertices.Length; i++)
        {
            var v         = unityNavMesh.vertices[i];
            var tileIndex = vertexOnTile(
                v, recast.forcedBoundsCenter, recast.forcedBoundsSize, tileWorldSize, tileXCount, tileZCount);
            tileIndex = 0;
            if (bucket[tileIndex] == null)
            {
                bucket[tileIndex] = ListPool <int> .Claim();
            }
            bucket[tileIndex].Add(i);
        }
        foreach (var b in bucket)
        {
            if (b == null)
            {
                continue;
            }
            for (int i = 0; i < b.Count; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    if (b[i] >= unityNavMesh.vertices.Length || b[j] >= unityNavMesh.vertices.Length)
                    {
                        continue;
                    }
                    if (Vector3.Distance(unityNavMesh.vertices[b[i]], unityNavMesh.vertices[b[j]]) < 1e-3)
                    {
                        vertMap[b[i]] = b[j];
                        break;
                    }
                }
            }
        }
        ArrayPool <List <int> > .Release(ref bucket, true);

        // only one tile
        recast.transform  = recast.CalculateTransform();
        recast.tileXCount = 1;
        recast.tileZCount = 1;
        recast.tileSizeX  = totalVoxelWidth + 1;
        recast.tileSizeZ  = totalVoxelDepth + 1;
        recast.ResetTiles(recast.tileXCount * recast.tileZCount);
        TriangleMeshNode.SetNavmeshHolder((int)recast.graphIndex, recast);
        var graphUpdateLock = active.PausePathfinding();

        for (int z = 0; z < recast.tileZCount; z++)
        {
            for (int x = 0; x < recast.tileXCount; x++)
            {
                var tileOffset = recast.forcedBoundsCenter - recast.forcedBoundsSize * 0.5f + new Vector3(
                    x * tileWorldSize,
                    0,
                    z * tileWorldSize
                    );
                var trisClaim = ArrayPool <int> .Claim(unityNavMesh.indices.Length);

                var tris = Memory.ShrinkArray(trisClaim, unityNavMesh.indices.Length);
                ArrayPool <int> .Release(ref trisClaim, true);

                for (int i = 0; i < tris.Length; i++)
                {
                    var tri = unityNavMesh.indices[i];
                    if (vertMap.ContainsKey(tri))
                    {
                        tri = vertMap[tri];
                    }
                    tris[i] = tri;
                }
                var vertsClaim = ArrayPool <Int3> .Claim(unityNavMesh.vertices.Length);

                var verts = Memory.ShrinkArray(vertsClaim, unityNavMesh.vertices.Length);
                ArrayPool <Int3> .Release(ref vertsClaim, true);

                for (int i = 0; i < verts.Length; i++)
                {
                    var vertInWorld = unityNavMesh.vertices[i];
                    var vertInTile  = vertInWorld - tileOffset;
                    verts[i] = new Int3(vertInTile);
                }
                recast.ReplaceTile(x, z, 1, 1, verts, tris);
            }
        }
        graphUpdateLock.Release();

        ObjectPoolSimple <Dictionary <int, int> > .Release(ref vertMap);
    }
Exemplo n.º 31
0
        /** Builds a polygon mesh from a contour set.
         *
         * \param cset contour set to build a mesh from.
         * \param nvp Maximum allowed vertices per polygon. \warning Currently locked to 3.
         * \param mesh Results will be written to this mesh.
         */
        public void BuildPolyMesh(VoxelContourSet cset, int nvp, out VoxelMesh mesh)
        {
            AstarProfiler.StartProfile("Build Poly Mesh");

            nvp = 3;

            int maxVertices     = 0;
            int maxTris         = 0;
            int maxVertsPerCont = 0;

            for (int i = 0; i < cset.conts.Count; i++)
            {
                // Skip null contours.
                if (cset.conts[i].nverts < 3)
                {
                    continue;
                }

                maxVertices    += cset.conts[i].nverts;
                maxTris        += cset.conts[i].nverts - 2;
                maxVertsPerCont = System.Math.Max(maxVertsPerCont, cset.conts[i].nverts);
            }

            Int3[] verts = ArrayPool <Int3> .Claim(maxVertices);

            int[] polys = ArrayPool <int> .Claim(maxTris *nvp);

            int[] areas = ArrayPool <int> .Claim(maxTris);

            Memory.MemSet <int>(polys, 0xff, sizeof(int));

            int[] indices = ArrayPool <int> .Claim(maxVertsPerCont);

            int[] tris = ArrayPool <int> .Claim(maxVertsPerCont *3);

            int vertexIndex = 0;
            int polyIndex   = 0;
            int areaIndex   = 0;

            for (int i = 0; i < cset.conts.Count; i++)
            {
                VoxelContour cont = cset.conts[i];

                // Skip degenerate contours
                if (cont.nverts < 3)
                {
                    continue;
                }

                for (int j = 0; j < cont.nverts; j++)
                {
                    indices[j] = j;
                    // Convert the z coordinate from the form z*voxelArea.width which is used in other places for performance
                    cont.verts[j * 4 + 2] /= voxelArea.width;
                }

                // Triangulate the contour
                int ntris = Triangulate(cont.nverts, cont.verts, ref indices, ref tris);

                // Assign the correct vertex indices
                int startIndex = vertexIndex;
                for (int j = 0; j < ntris * 3; polyIndex++, j++)
                {
                    //@Error sometimes
                    polys[polyIndex] = tris[j] + startIndex;
                }

                // Mark all triangles generated by this contour
                // as having the area cont.area
                for (int j = 0; j < ntris; areaIndex++, j++)
                {
                    areas[areaIndex] = cont.area;
                }

                // Copy the vertex positions
                for (int j = 0; j < cont.nverts; vertexIndex++, j++)
                {
                    verts[vertexIndex] = new Int3(cont.verts[j * 4], cont.verts[j * 4 + 1], cont.verts[j * 4 + 2]);
                }
            }

            mesh = new VoxelMesh {
                verts = Memory.ShrinkArray(verts, vertexIndex),
                tris  = Memory.ShrinkArray(polys, polyIndex),
                areas = Memory.ShrinkArray(areas, areaIndex)
            };

            ArrayPool <Int3> .Release(ref verts);

            ArrayPool <int> .Release(ref polys);

            ArrayPool <int> .Release(ref areas);

            ArrayPool <int> .Release(ref indices);

            ArrayPool <int> .Release(ref tris);

            AstarProfiler.EndProfile("Build Poly Mesh");
        }