#include
#include
#include
#include
#include
void
glisyVAOInit(GlisyVAO *vao) {
if (!vao) return;
vao->length = 0;
vao->useElements = GL_FALSE;
GLsizei attrsize = sizeof(GlisyVAOAttribute) * GLISY_MAX_VAO_ATTRIBS;
memset(vao->attributes, 0, attrsize);
glGenVertexArrays(1, &vao->handle);
}
void
glisyVAOBind(GlisyVAO *vao) {
if (!vao) return;
glBindVertexArray(vao->handle);
}
void
glisyVAOUnbind(GlisyVAO *vao) {
if (!vao) return;
glBindVertexArray(0);
}
void
glisyVAODispose(GlisyVAO *vao) {
if (!vao) return;
glDeleteVertexArrays(1, &vao->handle);
vao->handle = 0;
vao->length = 0;
vao->useElements = GL_FALSE;
}
void
glisyVAOUpdate(GlisyVAO *vao, GlisyBuffer *elements) {
if (!vao) return;
// number of bound attributes for this VAO
GLuint length = vao->length;
// vertex buffer objects of VAO attribute length
GLuint vbo[length];
// bind vao
glisyVAOBind(vao);
// init vbo
glGenBuffers(length, vbo);
// bind elements if given
if (elements) {
glisyBufferBind(elements);
vao->useElements= GL_TRUE;
} else {
vao->useElements= GL_FALSE;
}
// bind vao attributes
for (int i = 0; i < length; ++i) {
GLuint location = i;
GlisyVAOAttribute *attr = &vao->attributes[i];
// ensure .normalized is true or false
if (GL_TRUE != attr->buffer.normalized) {
attr->buffer.normalized = GL_FALSE;
}
// bind current vbo
glBindBuffer(GL_ARRAY_BUFFER, vbo[i]);
// set vbo data from attribute
glBufferData(GL_ARRAY_BUFFER,
attr->buffer.size,
attr->buffer.data,
attr->buffer.usage);
// bind attribute to location
glVertexAttribPointer(location,
attr->buffer.dimension,
attr->buffer.type,
attr->buffer.normalized,
0, 0);
// enable attribute at location
glEnableVertexAttribArray(location);
}
}
GLuint
glisyVAOPush(GlisyVAO *vao, GlisyVAOAttribute *attr) {
if (!vao) return GL_FALSE;
if (!attr) return GL_FALSE;
if (vao->length < GLISY_MAX_VAO_ATTRIBS) {
attr->location = vao->length;
vao->attributes[vao->length++] = *attr;
}
return vao->length;
}
GLuint
glisyVAOPop(GlisyVAO *vao) {
if (!vao) return GL_FALSE;
//@TODO(jwerle): implement this
return 0;
}
GLuint
glisyVAOSplice(GlisyVAO *vao, GLint start, GLuint count) {
if (!vao) return GL_FALSE;
//@TODO(jwerle): implement this
return 0;
}
GLuint
glisyVAOSet(GlisyVAO *vao, GLuint location, GlisyVAOAttribute *attr) {
if (!vao) return GL_FALSE;
if (!attr) return GL_FALSE;
GLuint max = GLISY_MAX_VAO_ATTRIBS;
if (vao->length < max && location < max) {
attr->location = location;
vao->attributes[location] = *attr;
vao->length = location < vao->length ? vao->length : location;
}
return vao->length;
}
GLuint
glisyVAORemove(GlisyVAO *vao, GLuint location) {
if (!vao) return GL_FALSE;
//@TODO(jwerle): implement GlisyVAO_remove
return 0;
}
void
glisyVAOAttributeBind(GlisyVAOAttribute *attribute) {
if (!attribute) return;
GLfloat data[4];
GLuint dimension = attribute->buffer.dimension;
GLuint location = attribute->location;
memcpy(&data, &attribute->buffer.data, sizeof(data));
switch (dimension) {
case 4:
glVertexAttrib4f(location, data[0], data[1], data[2], data[3]);
break;
case 3:
glVertexAttrib3f(location, data[0], data[1], data[2]);
break;
case 2:
glVertexAttrib2f(location, data[0], data[1]);
break;
case 1:
glVertexAttrib1f(location, data[0]);
break;
}
}