Beispiel #1
0
        private static Array CreateArray <T>()
        {
            T[]    array         = new T[16];
            Random random        = new Random();
            int    arrayItemSize = Marshal.SizeOf(typeof(T));

            switch (ArrayBufferItem.GetArrayBaseType(typeof(T)))
            {
            case VertexBaseType.Float:
                unsafe {
                    GCHandle arrayHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
                    try {
                        float *arrayPtr = (float *)arrayHandle.AddrOfPinnedObject().ToPointer();

                        for (int i = 0; i < (array.Length * arrayItemSize) / Marshal.SizeOf(typeof(float)); i++)
                        {
                            arrayPtr[i] = (float)random.NextDouble();
                        }
                    } finally {
                        arrayHandle.Free();
                    }
                }
                break;
            }

            return(array);
        }
Beispiel #2
0
        /// <summary>
        /// Copy this array buffer object to another one, but having a different array item type.
        /// </summary>
        /// <param name="vertexArrayType">
        /// A <see cref="ArrayBufferItemType"/> that specify the returned <see cref="ArrayBufferObject"/> item type.
        /// </param>
        /// <returns>
        /// It returns a copy of this ArrayBufferObject, but having a different array item. The returned instance is actually
        /// a <see cref="ArrayBufferObject"/>.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// Exception thrown if the array base type of this ArrayBufferObject (<see cref="ArrayBaseType"/>) is different to the one
        /// derived from <paramref name="vertexArrayType"/>.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Exception thrown if the number of base components of this ArrayBufferObject cannot be mapped into the base components
        /// count derived from <paramref name="vertexArrayType"/>.
        /// </exception>
        public ArrayBufferObject ConvertItemType(ArrayBufferItemType vertexArrayType)
        {
            if (ArrayBufferItem.GetArrayBaseType(_ArrayType) != ArrayBufferItem.GetArrayBaseType(vertexArrayType))
            {
                throw new ArgumentException("base type mismatch", "vertexArrayType");
            }

            uint componentsCount     = ItemCount * ArrayBufferItem.GetArrayLength(ArrayType) * ArrayBufferItem.GetArrayRank(ArrayType);
            uint convComponentsCount = ArrayBufferItem.GetArrayLength(vertexArrayType) * ArrayBufferItem.GetArrayRank(vertexArrayType);

            Debug.Assert(componentsCount >= convComponentsCount);
            if ((componentsCount % convComponentsCount) != 0)
            {
                throw new InvalidOperationException("components length incompatibility");
            }

            ArrayBufferObject arrayObject = CreateArrayObject(vertexArrayType, Hint);

            // Different item count due different lengths
            arrayObject.Create(componentsCount / convComponentsCount);
            // Memory is copied
            Memory.MemoryCopy(arrayObject.ClientBufferAddress, ClientBufferAddress, ClientBufferSize);

            return(arrayObject);
        }
Beispiel #3
0
            private void EnableVertexAttribute(GraphicsContext ctx, ShaderProgram.AttributeBinding attributeBinding)
            {
                ArrayBufferObjectBase.IArraySection arraySection = ArrayBuffer.GetArraySection(ArraySectionIndex);

                int arrayBaseType = (int)ArrayBufferItem.GetArrayBaseType(arraySection.ItemType);
                int arrayLength   = (int)ArrayBufferItem.GetArrayLength(arraySection.ItemType);
                int arrayStride   = arraySection.Stride.ToInt32();

                // Avoid rendundant buffer binding and relative vertex array setup
                if (ctx.Caps.GlExtensions.VertexArrayObject_ARB && IsDirty == false)
                {
                    CheckVertexAttribute(ctx, attributeBinding);
                    return;
                }

                // Bind the array buffer
                ArrayBuffer.Bind(ctx);

                // Bind varying attribute to currently bound buffer object
                switch (ArrayBufferItem.GetArrayBaseType(attributeBinding.Type))
                {
                case VertexBaseType.Float:
                    Gl.VertexAttribPointer(
                        attributeBinding.Location,
                        arrayLength, arrayBaseType, arraySection.Normalized,
                        arrayStride, arraySection.Offset
                        );
                    break;

                case VertexBaseType.Int:
                case VertexBaseType.UInt:
                    Gl.VertexAttribIPointer(
                        attributeBinding.Location,
                        arrayLength, arrayBaseType,
                        arrayStride, arraySection.Offset
                        );
                    break;

                case VertexBaseType.Double:
                    Gl.VertexAttribLPointer(
                        attributeBinding.Location,
                        arrayLength, arrayBaseType,
                        arrayStride, arraySection.Offset
                        );
                    break;

                default:
                    throw new NotSupportedException(String.Format("vertex attribute type {0} not supported", attributeBinding.Type));
                }

                // Enable vertex attribute
                Gl.EnableVertexAttribArray(attributeBinding.Location);
            }
Beispiel #4
0
            internal void CheckVertexAttribute(GraphicsContext ctx, ShaderProgram.AttributeBinding attributeBinding)
            {
                if (ArrayBuffer != null)
                {
                    ArrayBufferObjectBase.IArraySection arraySection = ArrayBuffer.GetArraySection(ArraySectionIndex);

                    int arrayBaseType = (int)ArrayBufferItem.GetArrayBaseType(arraySection.ItemType);
                    int arrayLength   = (int)ArrayBufferItem.GetArrayLength(arraySection.ItemType);
                    int arrayStride   = arraySection.Stride.ToInt32();

                    // Check effective state
                    IntPtr vertexAttribPointer;
                    int    vertexAttribArrayBufferBinding;
                    int    vertexAttribArraySize;
                    int    vertexAttribArrayType;
                    int    vertexAttribArrayNormalized;
                    int    vertexAttribArrayStride;
                    int    vertexAttribArrayEnabled;

                    // Attribute pointer/offset
                    Gl.GetVertexAttribPointer(attributeBinding.Location, Gl.VERTEX_ATTRIB_ARRAY_POINTER, out vertexAttribPointer);
                    Debug.Assert(vertexAttribPointer == new IntPtr(arraySection.Pointer.ToInt64() + arraySection.Offset.ToInt64()));
                    // Array buffer binding
                    Gl.GetVertexAttrib(attributeBinding.Location, Gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, out vertexAttribArrayBufferBinding);
                    Debug.Assert(vertexAttribArrayBufferBinding == ArrayBuffer.ObjectName);
                    // Array size
                    Gl.GetVertexAttrib(attributeBinding.Location, Gl.VERTEX_ATTRIB_ARRAY_SIZE, out vertexAttribArraySize);
                    Debug.Assert(vertexAttribArraySize == arrayLength);
                    // Array type
                    Gl.GetVertexAttrib(attributeBinding.Location, Gl.VERTEX_ATTRIB_ARRAY_TYPE, out vertexAttribArrayType);
                    Debug.Assert(vertexAttribArrayType == arrayBaseType);
                    // Array normalized
                    Gl.GetVertexAttrib(attributeBinding.Location, Gl.VERTEX_ATTRIB_ARRAY_NORMALIZED, out vertexAttribArrayNormalized);
                    Debug.Assert((vertexAttribArrayNormalized != 0) == arraySection.Normalized);
                    // Array size
                    Gl.GetVertexAttrib(attributeBinding.Location, Gl.VERTEX_ATTRIB_ARRAY_STRIDE, out vertexAttribArrayStride);
                    Debug.Assert(vertexAttribArrayStride == arrayStride);
                    // Attribute enabled
                    Gl.GetVertexAttrib(attributeBinding.Location, Gl.VERTEX_ATTRIB_ARRAY_ENABLED, out vertexAttribArrayEnabled);
                    Debug.Assert(vertexAttribArrayEnabled == Gl.TRUE);
                }
                else
                {
                    int vertexAttribArrayEnabled;

                    // Attribute disabled
                    Gl.GetVertexAttrib(attributeBinding.Location, Gl.VERTEX_ATTRIB_ARRAY_ENABLED, out vertexAttribArrayEnabled);
                    Debug.Assert(vertexAttribArrayEnabled == Gl.FALSE);
                }
            }
Beispiel #5
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);
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Convert this array buffer object in a strongly-typed array.
        /// </summary>
        /// <typeparam name="T">
        /// An arbitrary structure defining the returned array item. It doesn't need to be correlated with the ArrayBufferObject
        /// layout.
        /// </typeparam>
        /// <param name="arrayLength">
        /// A <see cref="UInt32"/> that specify the number of elements of the returned array.
        /// </param>
        /// <returns>
        /// It returns an array having all items stored by this ArrayBufferObject.
        /// </returns>
        public T[] ToArray <T>(uint arrayLength) where T : struct
        {
            if (arrayLength > ItemCount)
            {
                throw new ArgumentOutOfRangeException("arrayLength", arrayLength, "cannot exceed items count");
            }
            if (ClientBufferAddress == IntPtr.Zero)
            {
                throw new InvalidOperationException("no client buffer");
            }

            Type arrayElementType = typeof(T);

            if (arrayElementType == null || !arrayElementType.IsValueType)
            {
                throw new InvalidOperationException("invalid array element type");
            }

            // The base type should be corresponding
            ArrayBufferItemType arrayElementVertexType = ArrayBufferItem.GetArrayType(arrayElementType);

            if (ArrayBufferItem.GetArrayBaseType(_ArrayType) != ArrayBufferItem.GetArrayBaseType(arrayElementVertexType))
            {
                throw new InvalidOperationException(String.Format("source base type of {0} incompatible with destination base type of {1}", arrayElementType.Name, ArrayBufferItem.GetArrayBaseType(_ArrayType)));
            }

            // Array element item size cannot exceed ItemSize
            uint arrayItemSize = ArrayBufferItem.GetArrayItemSize(arrayElementVertexType);

            if (arrayItemSize > ItemSize)
            {
                throw new ArgumentException("array element type too big", "array");
            }

            T[] array = new T[arrayLength];

            // Copy from buffer data to array data
            CopyArray(array, arrayItemSize, ClientBufferAddress, ItemSize, 0, arrayLength);

            return(array);
        }
 /// <summary>
 ///
 /// </summary>
 /// <param name="vertexArrayType"></param>
 public ArrayBufferItemAttribute(ArrayBufferItemType vertexArrayType)
 {
     ArrayBaseType = ArrayBufferItem.GetArrayBaseType(vertexArrayType);
     ArrayLength   = ArrayBufferItem.GetArrayLength(vertexArrayType);
     ArrayRank     = ArrayBufferItem.GetArrayRank(vertexArrayType);
 }
Beispiel #8
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);
                    }
                }
            }
        }