|
|
|
@ -42,19 +42,14 @@ rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char * |
|
|
|
glDeleteShader(vertex_shader_id); |
|
|
|
glDeleteShader(vertex_shader_id); |
|
|
|
glDeleteShader(fragment_shader_id); |
|
|
|
glDeleteShader(fragment_shader_id); |
|
|
|
|
|
|
|
|
|
|
|
// check for errors
|
|
|
|
|
|
|
|
GLint isLinked = 0; |
|
|
|
GLint isLinked = 0; |
|
|
|
glGetProgramiv(rg->program_id, GL_LINK_STATUS, &isLinked); |
|
|
|
glGetProgramiv(rg->program_id, GL_LINK_STATUS, &isLinked); |
|
|
|
if (isLinked == GL_FALSE) { |
|
|
|
if (isLinked == GL_FALSE) { |
|
|
|
GLint maxLength = 0; |
|
|
|
GLint maxLength = 0; |
|
|
|
glGetProgramiv(rg->program_id, GL_INFO_LOG_LENGTH, &maxLength); |
|
|
|
glGetProgramiv(rg->program_id, GL_INFO_LOG_LENGTH, &maxLength); |
|
|
|
|
|
|
|
|
|
|
|
// The maxLength includes the NULL character
|
|
|
|
|
|
|
|
GLchar infoLog[maxLength]; |
|
|
|
GLchar infoLog[maxLength]; |
|
|
|
glGetProgramInfoLog(rg->program_id, maxLength, &maxLength, &infoLog[0]); |
|
|
|
glGetProgramInfoLog(rg->program_id, maxLength, &maxLength, &infoLog[0]); |
|
|
|
LOG(ERROR) << infoLog << "\n"; |
|
|
|
LOG(ERROR) << infoLog << "\n"; |
|
|
|
|
|
|
|
|
|
|
|
// The program is useless now. So delete it.
|
|
|
|
|
|
|
|
glDeleteProgram(rg->program_id); |
|
|
|
glDeleteProgram(rg->program_id); |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
@ -63,32 +58,44 @@ rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char * |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
gl_buffer * |
|
|
|
rgInitGLBufferObject(gl_buffer* buf_obj, uint len, GLenum usage, GLenum target, GLfloat data[]) |
|
|
|
rgInitGLBuffer(gl_buffer* buffer, uint buffer_len) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// TODO: why not just assing the pointer to the render group instead of copying here?
|
|
|
|
buffer->buffer_len = buffer_len; |
|
|
|
buf_obj->buffer_len = len; |
|
|
|
buffer->buffer = (GLfloat*) std::calloc(buffer_len, sizeof(GLfloat)); |
|
|
|
buf_obj->buffer = (GLfloat*) std::calloc(len, sizeof(GLfloat)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (data) |
|
|
|
if (!buffer->buffer) |
|
|
|
|
|
|
|
LOG(ERROR) << "Error allocating memory\n"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return buffer; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gl_index_buffer * |
|
|
|
|
|
|
|
initGLIndexBuffer(gl_index_buffer* index_buffer, uint buffer_len) |
|
|
|
{ |
|
|
|
{ |
|
|
|
for (uint i = 0; i < len; i++) |
|
|
|
index_buffer->buffer_len = buffer_len; |
|
|
|
buf_obj->buffer[i] = data[i]; |
|
|
|
index_buffer->buffer = (uint*) std::calloc(buffer_len, sizeof(uint)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!index_buffer->buffer) |
|
|
|
|
|
|
|
LOG(ERROR) << "Error allocating memory\n"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return index_buffer; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
glGenBuffers(1, &buf_obj->buffer_id); |
|
|
|
void |
|
|
|
glBindBuffer(target, buf_obj->buffer_id); |
|
|
|
rgSendBufferToGL(gl_buffer* buffer, GLenum usage, GLenum target) |
|
|
|
glBufferData(target, len * sizeof(GLfloat), buf_obj->buffer, usage); |
|
|
|
{ |
|
|
|
|
|
|
|
glGenBuffers(1, &buffer->buffer_id); |
|
|
|
|
|
|
|
glBindBuffer(target, buffer->buffer_id); |
|
|
|
|
|
|
|
glBufferData(target, buffer->buffer_len * sizeof(GLfloat), buffer->buffer, usage); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// NOTE: helper for fillColorBuffer() to convert uint32 color to GLfloat triplet
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
|
convertColor(GLfloat buf[3], uint32 color) |
|
|
|
sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// NOTE: not using the alpha values for now
|
|
|
|
glGenBuffers(1, &index_buffer->buffer_id); |
|
|
|
buf[0] = (GLfloat) ((color >> 24) & 0xFF) / (GLfloat) 255;
|
|
|
|
glBindBuffer(target, index_buffer->buffer_id); |
|
|
|
buf[1] = (GLfloat) ((color >> 16) & 0xFF) / (GLfloat) 255;
|
|
|
|
glBufferData(target, index_buffer->buffer_len * sizeof(uint), index_buffer->buffer, usage); |
|
|
|
buf[2] = (GLfloat) ((color >> 8) & 0xFF) / (GLfloat) 255;
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
|
@ -101,7 +108,7 @@ rgFillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes) |
|
|
|
{ |
|
|
|
{ |
|
|
|
buf_idx = i * buf_len_per_hex; |
|
|
|
buf_idx = i * buf_len_per_hex; |
|
|
|
hex_info hxi = (*hexes)[i]; |
|
|
|
hex_info hxi = (*hexes)[i]; |
|
|
|
convertColor(color_buf, hxi.current_color); |
|
|
|
utilConvertColor(color_buf, hxi.current_color); |
|
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < buf_len_per_hex; j+=3) |
|
|
|
for (int j = 0; j < buf_len_per_hex; j+=3) |
|
|
|
{ |
|
|
|
{ |
|
|
|
@ -112,20 +119,23 @@ rgFillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Copy assimp data to our structures for openGL
|
|
|
|
bool |
|
|
|
bool |
|
|
|
rgInitEntity(gl_render_group* rg, Entity* e) |
|
|
|
rgInitEntity(gl_render_group* rg, Entity* e) |
|
|
|
{ |
|
|
|
{ |
|
|
|
bool retVal = true; |
|
|
|
rg->draw_indexed = true; |
|
|
|
bool useNormals = rg->use_normals = (e->mesh->normals != nullptr); |
|
|
|
rg->use_normals = (e->mesh->normals != nullptr); |
|
|
|
|
|
|
|
|
|
|
|
uint vertex_buf_len = e->mesh->num_vertices * 3; |
|
|
|
uint vertex_buf_len = e->mesh->num_vertices * 3; |
|
|
|
GLfloat* vertex_buf = (GLfloat*) std::calloc(vertex_buf_len, sizeof(GLfloat)); |
|
|
|
|
|
|
|
GLfloat* color_buf = (GLfloat*) std::calloc(vertex_buf_len, sizeof(GLfloat)); |
|
|
|
|
|
|
|
GLfloat* normal_buf; |
|
|
|
|
|
|
|
if (useNormals) |
|
|
|
|
|
|
|
normal_buf = (GLfloat*) std::calloc(vertex_buf_len, sizeof(GLfloat)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// dump vertices, colors, and normals into temporary buffers
|
|
|
|
GLfloat* vertex_buf = rgInitGLBuffer(&rg->vertex_buffer, vertex_buf_len)->buffer; |
|
|
|
|
|
|
|
GLfloat* color_buf = rgInitGLBuffer(&rg->color_buffer, vertex_buf_len)->buffer; |
|
|
|
|
|
|
|
GLfloat* normal_buf = rgInitGLBuffer(&rg->normal_buffer, vertex_buf_len)->buffer; |
|
|
|
|
|
|
|
uint* index_buf = initGLIndexBuffer(&rg->index_buffer, e->mesh->num_indices)->buffer; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!vertex_buf || !color_buf || !normal_buf || !index_buf) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// dump vertices, colors, and normals into render_group buffers
|
|
|
|
uint vertex_index = 0; |
|
|
|
uint vertex_index = 0; |
|
|
|
uint vertex_prop_index = 0; |
|
|
|
uint vertex_prop_index = 0; |
|
|
|
|
|
|
|
|
|
|
|
@ -139,7 +149,7 @@ rgInitEntity(gl_render_group* rg, Entity* e) |
|
|
|
case 2: vertex_buf[i] = vertex.z; break; |
|
|
|
case 2: vertex_buf[i] = vertex.z; break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (useNormals) { |
|
|
|
if (rg->use_normals) { |
|
|
|
switch (vertex_prop_index) { |
|
|
|
switch (vertex_prop_index) { |
|
|
|
case 0: normal_buf[i] = normal.x; break; |
|
|
|
case 0: normal_buf[i] = normal.x; break; |
|
|
|
case 1: normal_buf[i] = normal.y; break; |
|
|
|
case 1: normal_buf[i] = normal.y; break; |
|
|
|
@ -156,41 +166,17 @@ rgInitEntity(gl_render_group* rg, Entity* e) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// send vertex and color data to OpenGL
|
|
|
|
// dump indices
|
|
|
|
rgInitGLBufferObject(&rg->vertex_buffer, vertex_buf_len, |
|
|
|
|
|
|
|
GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER, vertex_buf); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rgInitGLBufferObject(&rg->color_buffer, vertex_buf_len, |
|
|
|
|
|
|
|
GL_STATIC_DRAW, GL_ARRAY_BUFFER, color_buf); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (useNormals) { |
|
|
|
|
|
|
|
rgInitGLBufferObject(&rg->vertex_normals, vertex_buf_len, |
|
|
|
|
|
|
|
GL_STATIC_DRAW, GL_ARRAY_BUFFER, normal_buf); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: combine this somehow with rgInitGLBufferObject()
|
|
|
|
|
|
|
|
// dump indices into temp buffer
|
|
|
|
|
|
|
|
gl_index_buffer index_buffer; |
|
|
|
|
|
|
|
index_buffer.buffer_len = e->mesh->num_indices; |
|
|
|
|
|
|
|
index_buffer.indices = (uint *) std::calloc(e->mesh->num_indices, sizeof(uint)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (uint i = 0; i < e->mesh->num_indices; i++) |
|
|
|
for (uint i = 0; i < e->mesh->num_indices; i++) |
|
|
|
index_buffer.indices[i] = e->mesh->indices[i]; |
|
|
|
index_buf[i] = e->mesh->indices[i]; |
|
|
|
|
|
|
|
|
|
|
|
rg->index_buffer = index_buffer; |
|
|
|
rgSendBufferToGL(&rg->vertex_buffer, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
|
|
|
|
rgSendBufferToGL(&rg->color_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
glGenBuffers(1, &rg->index_buffer.buffer_id); |
|
|
|
if (rg->use_normals) |
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rg->index_buffer.buffer_id); |
|
|
|
rgSendBufferToGL(&rg->normal_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, e->mesh->num_indices * sizeof(uint), |
|
|
|
sendIndexBufferToGL(&rg->index_buffer, GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER); |
|
|
|
rg->index_buffer.indices, GL_STATIC_DRAW); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// free temp buffers
|
|
|
|
|
|
|
|
std::free(vertex_buf); |
|
|
|
|
|
|
|
if (useNormals) std::free(normal_buf); |
|
|
|
|
|
|
|
std::free(color_buf); |
|
|
|
|
|
|
|
vertex_buf = normal_buf = color_buf = nullptr; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return retVal; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
|
@ -229,7 +215,7 @@ rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, |
|
|
|
// 3rd attribute buffer: normals
|
|
|
|
// 3rd attribute buffer: normals
|
|
|
|
if (rg->use_normals) { |
|
|
|
if (rg->use_normals) { |
|
|
|
glEnableVertexAttribArray(2); |
|
|
|
glEnableVertexAttribArray(2); |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_normals.buffer_id); |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, rg->normal_buffer.buffer_id); |
|
|
|
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); |
|
|
|
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); |
|
|
|
|
|
|
|
|
|
|
|
// TODO: testing lighting
|
|
|
|
// TODO: testing lighting
|
|
|
|
@ -239,52 +225,12 @@ rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// draw
|
|
|
|
// draw
|
|
|
|
glDrawArrays(draw_mode, 0, rg->vertex_buffer.buffer_len / 3); |
|
|
|
if (rg->draw_indexed) { |
|
|
|
|
|
|
|
|
|
|
|
// cleanup
|
|
|
|
|
|
|
|
glDisableVertexAttribArray(0); |
|
|
|
|
|
|
|
if (rg->color_buffer.buffer) |
|
|
|
|
|
|
|
glDisableVertexAttribArray(1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
|
|
|
rgDrawIndexed(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, |
|
|
|
|
|
|
|
glm::mat4 view_matrix, glm::mat4 projection_matrix, |
|
|
|
|
|
|
|
glm::vec3 light_position, GLuint light_id) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
glUseProgram(rg->program_id); |
|
|
|
|
|
|
|
glUniformMatrix4fv(rg->model_matrix_id, 1, GL_FALSE, &model_matrix[0][0]); |
|
|
|
|
|
|
|
glUniformMatrix4fv(rg->view_matrix_id, 1, GL_FALSE, &view_matrix[0][0]); |
|
|
|
|
|
|
|
glUniformMatrix4fv(rg->projection_matrix_id, 1, GL_FALSE, &projection_matrix[0][0]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: testing lighting
|
|
|
|
|
|
|
|
glUniform3f(light_id, light_position.x, light_position.y, light_position.z); |
|
|
|
|
|
|
|
glm::mat3 normal_matrix = glm::transpose(glm::inverse(glm::mat3(model_matrix))); |
|
|
|
|
|
|
|
glUniformMatrix3fv(rg->normal_matrix_id, 1, GL_FALSE, &normal_matrix[0][0]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 1st attribute buffer : vertices
|
|
|
|
|
|
|
|
glEnableVertexAttribArray(0); |
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id); |
|
|
|
|
|
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 2nd attribute buffer : colors
|
|
|
|
|
|
|
|
if (rg->color_buffer.buffer) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
glEnableVertexAttribArray(1); |
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, rg->color_buffer.buffer_id); |
|
|
|
|
|
|
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 3rd attribe buffer : normals
|
|
|
|
|
|
|
|
if (rg->use_normals) { |
|
|
|
|
|
|
|
glEnableVertexAttribArray(2); |
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_normals.buffer_id); |
|
|
|
|
|
|
|
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// draw
|
|
|
|
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rg->index_buffer.buffer_id); |
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rg->index_buffer.buffer_id); |
|
|
|
glDrawElements(draw_mode, rg->index_buffer.buffer_len, GL_UNSIGNED_INT, 0); |
|
|
|
glDrawElements(draw_mode, rg->index_buffer.buffer_len, GL_UNSIGNED_INT, 0); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
glDrawArrays(draw_mode, 0, rg->vertex_buffer.buffer_len / 3); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// cleanup
|
|
|
|
// cleanup
|
|
|
|
glDisableVertexAttribArray(0); |
|
|
|
glDisableVertexAttribArray(0); |
|
|
|
@ -301,8 +247,8 @@ rgFree(gl_render_group* rg) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
utilSafeFree(rg->vertex_buffer.buffer); |
|
|
|
utilSafeFree(rg->vertex_buffer.buffer); |
|
|
|
utilSafeFree(rg->vertex_normals.buffer); |
|
|
|
utilSafeFree(rg->normal_buffer.buffer); |
|
|
|
utilSafeFree(rg->index_buffer.indices); |
|
|
|
utilSafeFree(rg->index_buffer.buffer); |
|
|
|
utilSafeFree(rg->color_buffer.buffer); |
|
|
|
utilSafeFree(rg->color_buffer.buffer); |
|
|
|
utilSafeFree(rg); |
|
|
|
utilSafeFree(rg); |
|
|
|
} |
|
|
|
} |
|
|
|
|