Пример #1
0
        private int[] GetRestartIndices_UnsignedInt(out IntPtr[] count)
        {
            unsafe
            {
                List <int>    offsets      = new List <int>();
                List <IntPtr> counts       = new List <IntPtr>();
                uint *        indicesPtr   = (uint *)ClientBufferAddress.ToPointer();
                uint          restartIndex = RestartIndexKey;

                for (int i = 0; i < ItemCount; i++)
                {
                    if (indicesPtr[i] == restartIndex)
                    {
                        int previousIndex = offsets[offsets.Count - 1];

                        counts.Add(new IntPtr(i - previousIndex));
                        offsets.Add(i + 1);
                    }
                }
                counts.Add(new IntPtr((int)ItemCount - offsets[offsets.Count - 1]));

                Debug.Assert(offsets.Count == counts.Count);
                count = counts.ToArray();

                return(offsets.ToArray());
            }
        }
Пример #2
0
        /// <summary>
        /// Copy from an ArrayBufferObject with an indirection defined by an index.
        /// </summary>
        /// <param name="buffer">
        /// An <see cref="ArrayBufferObject"/> that specify the source data buffer to copy.
        /// </param>
        /// <param name="indices">
        /// An array of indices indicating the order of the vertices copied from <paramref name="buffer"/>.
        /// </param>
        /// <param name="count">
        /// A <see cref="UInt32"/> that specify how many elements to copy from <paramref name="buffer"/>.
        /// </param>
        /// <param name="offset">
        /// A <see cref="UInt32"/> that specify the first index considered from <paramref name="indices"/>. A
        /// value of 0 indicates that the indices are considered from the first one.
        /// </param>
        /// <param name="stride">
        /// A <see cref="UInt32"/> that specify the offset between two indexes considered for the copy operations
        /// from <paramref name="indices"/>. A value of 1 indicates that all considered indices are contiguos.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Exception thrown if <paramref name="buffer"/> or <paramref name="indices"/> are null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Exception thrown if <paramref name="count"/> or <paramref name="stride"/> equals to 0.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Exception thrown if the combination of <paramref name="count"/>, <paramref name="offset"/> and
        /// <paramref name="stride"/> will cause a <paramref name="indices"/> array access out of its bounds.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Exception thrown if this <see cref="ArrayBufferObject"/> have a complex data layout, of it has a vertex
        /// base type different from <paramref name="buffer"/>.
        /// </exception>
        /// <remarks>
        /// <para>
        /// After a successfull copy operation, the previous buffer is discarded replaced by the copied buffer from
        /// <paramref name="buffer"/>.
        /// </para>
        /// </remarks>
        public void Copy(ArrayBufferObject buffer, uint[] indices, uint count, uint offset, uint stride)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }
            if (indices == null)
            {
                throw new ArgumentNullException("indices");
            }
            if (count == 0)
            {
                throw new ArgumentException("invalid", "count");
            }
            if (stride == 0)
            {
                throw new ArgumentException("invalid", "stride");
            }
            if (offset + ((count - 1) * stride) > indices.Length)
            {
                throw new InvalidOperationException("indices out of bounds");
            }
            if (ArrayBufferItem.GetArrayBaseType(_ArrayType) != ArrayBufferItem.GetArrayBaseType(buffer._ArrayType))
            {
                throw new InvalidOperationException("base type mismatch");
            }

            Create(count);

            unsafe {
                byte *dstPtr = (byte *)ClientBufferAddress.ToPointer();

                for (uint i = 0; i < count; i++, dstPtr += ItemSize)
                {
                    uint arrayIndex = indices[(i * stride) + offset];

                    // Position 'srcPtr' to the indexed element
                    byte *srcPtr = ((byte *)buffer.ClientBufferAddress.ToPointer()) + (ItemSize * arrayIndex);

                    // Copy the 'arrayIndex'th element
                    Memory.MemoryCopy(dstPtr, srcPtr, ItemSize);
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Copy from an ArrayBufferObject with an indirection defined by an index (polygon tessellation).
        /// </summary>
        /// <param name="buffer">
        /// An <see cref="ArrayBufferObject"/> that specify the source data buffer to copy.
        /// </param>
        /// <param name="vcount">
        /// An array of integers indicating the number of the vertices of the polygon copied from <paramref name="buffer"/>. This parameter
        /// indicated how many polygons to copy (the array length). Each item specify the number of vertices composing the polygon.
        /// </param>
        /// <param name="indices">
        /// An array of indices indicating the order of the vertices copied from <paramref name="buffer"/>.
        /// </param>
        /// <param name="offset">
        /// A <see cref="UInt32"/> that specify the first index considered from <paramref name="indices"/>. A
        /// value of 0 indicates that the indices are considered from the first one.
        /// </param>
        /// <param name="stride">
        /// A <see cref="UInt32"/> that specify the offset between two indexes considered for the copy operations
        /// from <paramref name="indices"/>. A value of 1 indicates that all considered indices are contiguos.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Exception thrown if <paramref name="buffer"/>, <paramref name="indices"/> or <paramref name="vcount"/> are null.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Exception thrown if this <see cref="ArrayBufferObject"/> have a complex data layout, of it has a vertex
        /// base type different from <paramref name="buffer"/>.
        /// </exception>
        /// <remarks>
        /// <para>
        /// After a successfull copy operation, the previous buffer is discarded replaced by the copied buffer from
        /// <paramref name="buffer"/>.
        /// </para>
        /// </remarks>
        public void Copy(ArrayBufferObject buffer, uint[] indices, uint[] vcount, uint offset, uint stride)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }
            if (indices == null)
            {
                throw new ArgumentNullException("indices");
            }
            if (vcount == null)
            {
                throw new ArgumentNullException("indices");
            }
            if (stride == 0)
            {
                throw new ArgumentException("invalid", "stride");
            }
            if (ArrayBufferItem.GetArrayBaseType(_ArrayType) != ArrayBufferItem.GetArrayBaseType(buffer._ArrayType))
            {
                throw new InvalidOperationException("base type mismatch");
            }

            // Allocate array buffer
            uint minVertices = UInt32.MaxValue, maxVertices = UInt32.MinValue;

            Array.ForEach(vcount, delegate(uint v) {
                minVertices = Math.Min(v, minVertices);
                maxVertices = Math.Max(v, maxVertices);
            });

            if ((minVertices < 3) && (maxVertices >= 3))
            {
                throw new ArgumentException("ambigous polygons set", "vcount");
            }

            uint totalVerticesCount = 0;

            Array.ForEach(vcount, delegate(uint v) {
                if (v == 4)
                {
                    totalVerticesCount += 6;                                // Triangulate quad with two triangles
                }
                else if (v > 4)
                {
                    totalVerticesCount += (v - 2) * 3;                      // Triangulate as if it is a polygon
                }
                else
                {
                    Debug.Assert(v == 3);
                    totalVerticesCount += 3;                                // Exactly a triangle
                }
            });

            Create(totalVerticesCount);

            // Copy polygons (triangulate)
            uint count = 0;

            unsafe {
                byte *dstPtr       = (byte *)ClientBufferAddress.ToPointer();
                uint  indicesIndex = offset;

                for (uint i = 0; i < vcount.Length; i++)
                {
                    uint   verticesCount = vcount[i];
                    uint[] verticesIndices;

                    if (verticesCount == 4)
                    {
                        verticesIndices    = new uint[6];
                        verticesIndices[0] = indices[indicesIndex + (0 * stride)];
                        verticesIndices[1] = indices[indicesIndex + (1 * stride)];
                        verticesIndices[2] = indices[indicesIndex + (2 * stride)];
                        verticesIndices[3] = indices[indicesIndex + (0 * stride)];
                        verticesIndices[4] = indices[indicesIndex + (2 * stride)];
                        verticesIndices[5] = indices[indicesIndex + (3 * stride)];

                        indicesIndex += 4 * stride;
                    }
                    else if (verticesCount > 4)
                    {
                        uint triCount   = verticesCount - 2;
                        uint pivotIndex = indicesIndex;

                        verticesIndices = new uint[triCount * 3];

                        // Copy polygon indices
                        for (uint tri = 0; tri < triCount; tri++)
                        {
                            verticesIndices[tri * 3 + 0] = indices[pivotIndex];
                            verticesIndices[tri * 3 + 1] = indices[indicesIndex + (tri + 2) * stride];
                            verticesIndices[tri * 3 + 2] = indices[indicesIndex + (tri + 1) * stride];
                        }

                        indicesIndex += verticesCount * stride;
                    }
                    else
                    {
                        verticesIndices = new uint[verticesCount];
                        for (int j = 0; j < verticesCount; j++, indicesIndex += stride)
                        {
                            verticesIndices[j] = indices[indicesIndex];
                        }
                    }

                    count += (uint)verticesIndices.Length;

                    for (uint j = 0; j < verticesIndices.Length; j++, dstPtr += ItemSize)
                    {
                        // Position 'srcPtr' to the indexed element
                        byte *srcPtr = ((byte *)buffer.ClientBufferAddress.ToPointer()) + (ItemSize * verticesIndices[j]);
                        // Copy the 'arrayIndex'th element
                        Memory.MemoryCopy(dstPtr, srcPtr, ItemSize);
                    }
                }
            }
        }