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()); } }
/// <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); } } }
/// <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); } } } }