using System;
using Tao.OpenGl;
using Engine;
using Engine.DataTypes;
using Engine.MathLib;
namespace VBOShaders
{
class VBO : Singleton<VBO>
{
public void BuildVBO(Segment objSegment)
{
// Calculate sizes
int tri_buf_size = objSegment.intTriangleCount * Vector3s.SizeInBytes; // Size of triangle array in bytes
int vrt_buf_size = objSegment.intVertexCount * Vector3f.SizeInBytes; // vertex
int nrm_buf_size = objSegment.intVertexCount * Vector3f.SizeInBytes; // normal
int txl_buf_size = objSegment.intVertexCount * Vector2f.SizeInBytes; // texel
int geo_buf_size = vrt_buf_size + nrm_buf_size + txl_buf_size; // all geometry arrays in bytes
int offset = 0; // current buffer starting location
// Setup geometry array and allocate space
Gl.glGenBuffers(1, out objSegment.geometryVBOId);
Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, objSegment.geometryVBOId);
Gl.glBufferData(Gl.GL_ARRAY_BUFFER, (IntPtr)geo_buf_size, IntPtr.Zero, Gl.GL_STATIC_DRAW);
// Copy geometry data to the hardware buffer starting at offset
Gl.glBufferSubData(Gl.GL_ARRAY_BUFFER, (IntPtr)offset, (IntPtr)vrt_buf_size, objSegment.aryVertexes);
offset += vrt_buf_size;
Gl.glBufferSubData(Gl.GL_ARRAY_BUFFER, (IntPtr)offset, (IntPtr)nrm_buf_size, objSegment.aryVNormals);
offset += nrm_buf_size;
Gl.glBufferSubData(Gl.GL_ARRAY_BUFFER, (IntPtr)offset, (IntPtr)txl_buf_size, objSegment.aryVertexes);
// Setup indices array and allocate space
Gl.glGenBuffers(1, out objSegment.indicesVBOId);
Gl.glBindBuffer(Gl.GL_ELEMENT_ARRAY_BUFFER, objSegment.indicesVBOId);
Gl.glBufferData(Gl.GL_ELEMENT_ARRAY_BUFFER, (IntPtr)tri_buf_size, IntPtr.Zero, Gl.GL_STATIC_DRAW);
// Copy index data to the hardware buffer starting at offset 0
Gl.glBufferSubData(Gl.GL_ELEMENT_ARRAY_BUFFER, IntPtr.Zero, (IntPtr)tri_buf_size, objSegment.aryTriangles);
// Unbind any buffers so remaining GL stays happy
Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, 0);
Gl.glBindBuffer(Gl.GL_ELEMENT_ARRAY_BUFFER, 0);
}
public void RenderVBO(Segment objSegment, int a_vVertex, int a_vNormal, int a_vTexel)
{
// Step 1
Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, objSegment.geometryVBOId);
Gl.glBindBuffer(Gl.GL_ELEMENT_ARRAY_BUFFER, objSegment.indicesVBOId);
// Step 2
Gl.glEnableVertexAttribArray(a_vVertex);
Gl.glVertexAttribPointer(a_vVertex, 3, Gl.GL_FLOAT, Gl.GL_FALSE, 0, IntPtr.Zero);
Gl.glEnableVertexAttribArray(a_vNormal);
Gl.glVertexAttribPointer(a_vNormal, 3, Gl.GL_FLOAT, Gl.GL_FALSE, 0, IntPtr.Zero);
Gl.glEnableVertexAttribArray(a_vTexel);
Gl.glVertexAttribPointer(a_vTexel, 2, Gl.GL_FLOAT, Gl.GL_FALSE, 0, IntPtr.Zero);
// Step 3
int tcount = objSegment.intTriangleCount * 3;
Gl.glDrawElements(Gl.GL_TRIANGLES, tcount, Gl.GL_UNSIGNED_SHORT, IntPtr.Zero);
// Step 4
Gl.glDisableVertexAttribArray(a_vVertex);
Gl.glDisableVertexAttribArray(a_vNormal);
Gl.glDisableVertexAttribArray(a_vTexel);
// Step 5
Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, 0);
Gl.glBindBuffer(Gl.GL_ELEMENT_ARRAY_BUFFER, 0);
}
public void RenderArrays(Segment objSegment, int a_vVertex, int a_vNormal, int a_vTexel)
{
// Step 2
Gl.glEnableVertexAttribArray(a_vVertex);
Gl.glVertexAttribPointer(a_vVertex, 3, Gl.GL_FLOAT, Gl.GL_FALSE, 0, objSegment.aryVertexes);
Gl.glEnableVertexAttribArray(a_vNormal);
Gl.glVertexAttribPointer(a_vNormal, 3, Gl.GL_FLOAT, Gl.GL_FALSE, 0, objSegment.aryVNormals);
Gl.glEnableVertexAttribArray(a_vTexel);
Gl.glVertexAttribPointer(a_vTexel, 2, Gl.GL_FLOAT, Gl.GL_FALSE, 0, objSegment.aryVTexels);
// Step 3
int tcount = objSegment.intTriangleCount * 3;
Gl.glDrawElements(Gl.GL_TRIANGLES, tcount, Gl.GL_UNSIGNED_SHORT, objSegment.aryTriangles);
// Step 4
Gl.glDisableVertexAttribArray(a_vVertex);
Gl.glDisableVertexAttribArray(a_vNormal);
Gl.glDisableVertexAttribArray(a_vTexel);
}
}
}