/// <summary> /// Buffers a part of the client data /// </summary> /// <param name="index">Starting element in the vertex definition</param> /// <param name="count">Number of elements from the vertex definition to buffer</param> /// <remarks>This function cannot be called once the client data has been freed</remarks> public void BufferSubData(int index, int count) { int offset = 0; int size = 0; if (internal_array == null || internal_array.Length == 0) { throw new InvalidOperationException("Cannot buffer data from empty client array"); } for (int i = 0; i < index; i++) { offset += VertexBufferDescriptor.GetElementSize(desc.types[i]); } for (int i = index; i < index + count; i++) { size += VertexBufferDescriptor.GetElementSize(desc.types[i]); } var ptr = System.Runtime.InteropServices.GCHandle.Alloc(internal_array, System.Runtime.InteropServices.GCHandleType.Pinned); OpenGL.glBufferSubData(target, new IntPtr(offset), new IntPtr(size), ptr.AddrOfPinnedObject()); ptr.Free(); }
/// <summary> /// Standard constructor for vertex buffers /// </summary> /// <param name="desc">VertexBufferDescriptor which describes each element in the structure T</param> /// <exception cref="InvalidCastException">Throws InvalidCastException if VertexBufferDescriptor describes anything other that T /// </exception> public VertexBuffer(VertexBufferDescriptor desc) : base() { uint[] arr = new uint[1]; OpenGL.glGenVertexArrays(1, arr); vertex_array = arr[0]; target = (uint)VboTarget.GL_ARRAY_BUFFER; if (typeof(T) != desc.Type) { throw new InvalidCastException("Vertex buffer descriptor does not describe contained type"); } this.desc = desc; int offset = 0; int tot_size = desc.Types.Count() == 1 ? 0 : desc.TotalSize; initialize = new List <Action <VertexBuffer <T> .ElementInfo> >(); elements = new List <VertexBuffer <T> .ElementInfo>(); types = new List <uint>(); uint gl_datatype = 0; foreach (var el in desc.Types) { int tt = (int)el; ElementType type; int size; ElementType data_type; data_type = (ElementType)(tt & 0x00003000); type = (ElementType)(tt & 0xf); int dim = (tt & 0x00000ff0) >> 4; int bits = ((tt & 0x00ff0000) >> 16); size = dim * bits; uint ch = ((uint)el & 0xff000000) >> 24; if (bits == 2 && data_type == ElementType.Integer) { gl_datatype = (uint)OpenGL.Const.GL_SHORT; } else if (bits == 4 && data_type == ElementType.Integer) { gl_datatype = (uint)OpenGL.Const.GL_INT; } else if (bits == 2 && data_type == ElementType.Float) { gl_datatype = OpenGL.Const.GL_HALF_FLOAT; } else if (bits == 4 && data_type == ElementType.Float) { gl_datatype = (uint)OpenGL.Const.GL_FLOAT; } else if (bits == 8 && data_type == ElementType.Float) { gl_datatype = (uint)OpenGL.Const.GL_DOUBLE; } elements.Add(new VertexBuffer <T> .ElementInfo() { dimensions = dim, gl_type = gl_datatype, offset_value = new IntPtr(offset), channel = ch, attribute = 0xffffffff }); /*switch (type) * { * case ElementType.Position: * initialize.Add(new Action<ElementInfo>(SetVertexPointer)); * types.Add(OpenGL.Const.GL_VERTEX_ARRAY); * break; * case ElementType.Normals: * initialize.Add(new Action<ElementInfo>(SetNormalPointer)); * types.Add(OpenGL.Const.GL_NORMAL_ARRAY); * break; * case ElementType.TexCoord: * initialize.Add(new Action<ElementInfo>(SetTexCoordPointer)); * types.Add(OpenGL.Const.GL_TEXTURE_COORD_ARRAY); * break; * case ElementType.Color: * initialize.Add(new Action<ElementInfo>(SetColorPointer)); * types.Add(OpenGL.Const.GL_COLOR_ARRAY); * break; * default: * initialize.Add(null); * types.Add(0); * break; * * }*/ offset += size; } }