|
|
|
|
@ -5,8 +5,6 @@
|
|
|
|
|
#include "render_object.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// forward declarations
|
|
|
|
|
|
|
|
|
|
struct default_render_object |
|
|
|
|
{ |
|
|
|
|
glm::mat4 node_xform; |
|
|
|
|
@ -19,52 +17,30 @@ struct default_render_object
|
|
|
|
|
uint index_buffer_count; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct simple_render_object |
|
|
|
|
{ |
|
|
|
|
glm::mat4 model_transform; |
|
|
|
|
GLuint vertex_buffer_id; |
|
|
|
|
GLuint vertex_color_buffer_id; |
|
|
|
|
uint vertex_count; |
|
|
|
|
GLenum draw_mode; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct render_objects |
|
|
|
|
{ |
|
|
|
|
void* objects; |
|
|
|
|
default_render_object* objects; |
|
|
|
|
uint count; |
|
|
|
|
mesh_t mesh_type; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// forward declarations
|
|
|
|
|
|
|
|
|
|
void drawDefault(render_objects* r_objs, |
|
|
|
|
glm::mat4 world_transform, |
|
|
|
|
camera& cam, |
|
|
|
|
shader_wrapper sw, |
|
|
|
|
light_group* lights); |
|
|
|
|
void drawSimple(render_objects* r_objs, |
|
|
|
|
glm::mat4 world_transform, |
|
|
|
|
camera& cam, |
|
|
|
|
camera* cam, |
|
|
|
|
shader_wrapper sw, |
|
|
|
|
light_group* lights); |
|
|
|
|
inline void enableGLFloatBuffer(uint buffer_id, uint location); |
|
|
|
|
bool initGLFloatBuffer(glm::vec3* buffer, |
|
|
|
|
uint count, |
|
|
|
|
GLuint& buffer_id, |
|
|
|
|
GLenum usage = GL_STATIC_DRAW); |
|
|
|
|
bool initGLIndexBuffer(uint* buffer, uint num_indices, GLuint& buffer_id); |
|
|
|
|
bool initGLTexture(const util_image image, GLuint& tex_id); |
|
|
|
|
bool loadMeshIntoGL(default_render_object* ro_out, mesh_info* mi_in); |
|
|
|
|
inline void updateMatrices(default_shader_program* shader, |
|
|
|
|
camera& cam, |
|
|
|
|
glm::mat4 world_xform, |
|
|
|
|
glm::mat4 node_xform); |
|
|
|
|
bool loadMeshIntoGL(default_render_object* ro_out, mesh* me_in); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// interface
|
|
|
|
|
|
|
|
|
|
render_objects* |
|
|
|
|
roInitModel(mesh_group mg) |
|
|
|
|
roInitModel(model* mdl) |
|
|
|
|
{ |
|
|
|
|
uint count = mg.num_meshes; |
|
|
|
|
uint count = mdl->num_meshes; |
|
|
|
|
assert(count > 0); |
|
|
|
|
|
|
|
|
|
render_objects* r_objs = UTIL_ALLOC(1, render_objects); |
|
|
|
|
@ -75,7 +51,7 @@ roInitModel(mesh_group mg)
|
|
|
|
|
default_render_object* objects = (default_render_object*) r_objs->objects; |
|
|
|
|
|
|
|
|
|
for (uint i = 0; i < count; i++) { |
|
|
|
|
if (!loadMeshIntoGL(&objects[i], mg.meshes[i])) { |
|
|
|
|
if (!loadMeshIntoGL(&objects[i], &mdl->meshes[i])) { |
|
|
|
|
roFree(r_objs); |
|
|
|
|
return nullptr; |
|
|
|
|
} |
|
|
|
|
@ -84,44 +60,13 @@ roInitModel(mesh_group mg)
|
|
|
|
|
return r_objs; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
render_objects* |
|
|
|
|
roInitSimpleMesh(simple_mesh& mesh_in, GLenum draw_mode) |
|
|
|
|
{ |
|
|
|
|
render_objects* r_objs = UTIL_ALLOC(1, render_objects); |
|
|
|
|
r_objs->count = 1; |
|
|
|
|
r_objs->mesh_type = SIMPLE_MESH; |
|
|
|
|
r_objs->objects = UTIL_ALLOC(1, simple_render_object); |
|
|
|
|
|
|
|
|
|
simple_render_object* objects = (simple_render_object*) r_objs->objects; |
|
|
|
|
|
|
|
|
|
if (initGLFloatBuffer(mesh_in.vertices, |
|
|
|
|
mesh_in.num_vertices, |
|
|
|
|
objects->vertex_buffer_id, |
|
|
|
|
GL_DYNAMIC_DRAW) && |
|
|
|
|
initGLFloatBuffer(mesh_in.vert_colors, |
|
|
|
|
mesh_in.num_vertices, |
|
|
|
|
objects->vertex_color_buffer_id, |
|
|
|
|
GL_DYNAMIC_DRAW)) |
|
|
|
|
{ |
|
|
|
|
objects->model_transform = mesh_in.model_transform; |
|
|
|
|
objects->vertex_count = mesh_in.num_vertices; |
|
|
|
|
objects->draw_mode = draw_mode; |
|
|
|
|
return r_objs; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
LOG(Error) << "Failed to initialize render_object\n"; |
|
|
|
|
roFree(r_objs); |
|
|
|
|
return nullptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
roFree(render_objects* r_objs) |
|
|
|
|
{ |
|
|
|
|
if (r_objs->mesh_type == SIMPLE_MESH) { |
|
|
|
|
//
|
|
|
|
|
} else if (r_objs->mesh_type == DEFAULT_MESHES) { |
|
|
|
|
default_render_object* objects = |
|
|
|
|
(default_render_object*) r_objs->objects; |
|
|
|
|
default_render_object* objects = r_objs->objects; |
|
|
|
|
|
|
|
|
|
for (uint i = 0; i < r_objs->count; i++) { |
|
|
|
|
glDeleteBuffers(1, &objects[i].vertex_buffer_id); |
|
|
|
|
@ -140,98 +85,39 @@ roFree(render_objects* r_objs)
|
|
|
|
|
void |
|
|
|
|
roDraw(render_objects* r_objs, |
|
|
|
|
glm::mat4 world_transform, |
|
|
|
|
camera& cam, |
|
|
|
|
camera* cam, |
|
|
|
|
shader_wrapper sw, |
|
|
|
|
light_group* lights) |
|
|
|
|
{ |
|
|
|
|
if (r_objs->mesh_type == SIMPLE_MESH) |
|
|
|
|
drawSimple(r_objs, world_transform, cam, sw, lights); |
|
|
|
|
else if (r_objs->mesh_type == DEFAULT_MESHES) |
|
|
|
|
drawDefault(r_objs, world_transform, cam, sw, lights); |
|
|
|
|
assert(r_objs->mesh_type == DEFAULT_MESHES); |
|
|
|
|
drawDefault(r_objs, world_transform, cam, sw, lights); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
roUpdateSimpleMesh(render_objects* r_objs, simple_mesh* mesh, GLenum draw_mode) |
|
|
|
|
{ |
|
|
|
|
assert(r_objs != nullptr && r_objs->objects != nullptr); |
|
|
|
|
assert(mesh != nullptr && mesh->vertices != nullptr); |
|
|
|
|
simple_render_object* sro = (simple_render_object*) r_objs->objects; |
|
|
|
|
assert(sro->vertex_count == mesh->num_vertices); |
|
|
|
|
|
|
|
|
|
sro->draw_mode = draw_mode; |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, sro->vertex_buffer_id); |
|
|
|
|
glBufferSubData( |
|
|
|
|
GL_ARRAY_BUFFER, |
|
|
|
|
0, |
|
|
|
|
3 * sro->vertex_count * sizeof(GLfloat), |
|
|
|
|
mesh->vertices); |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, sro->vertex_color_buffer_id); |
|
|
|
|
glBufferSubData( |
|
|
|
|
GL_ARRAY_BUFFER, |
|
|
|
|
0, |
|
|
|
|
3 * sro->vertex_count * sizeof(GLfloat), |
|
|
|
|
mesh->vert_colors); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// internal
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
drawDefault(render_objects* r_objs, |
|
|
|
|
glm::mat4 world_transform, |
|
|
|
|
camera& cam, |
|
|
|
|
shader_wrapper sw, |
|
|
|
|
light_group* lights) |
|
|
|
|
bool |
|
|
|
|
initGLBuffer(void* buffer, |
|
|
|
|
uint count, |
|
|
|
|
GLuint* buffer_id, |
|
|
|
|
uint el_count = 3, |
|
|
|
|
uint el_size = sizeof(float), |
|
|
|
|
GLenum target = GL_ARRAY_BUFFER, |
|
|
|
|
GLenum usage = GL_STATIC_DRAW) |
|
|
|
|
{ |
|
|
|
|
default_shader_program* shader = sw.default_shader; |
|
|
|
|
default_render_object* objects = (default_render_object*) r_objs->objects; |
|
|
|
|
glUseProgram(shader->program_id); |
|
|
|
|
updateMatrices(shader, cam, world_transform, objects->node_xform); |
|
|
|
|
if (lights->needs_update) lightsUpdate(lights, shader); |
|
|
|
|
|
|
|
|
|
for (uint i = 0; i < r_objs->count; i++) { |
|
|
|
|
enableGLFloatBuffer(objects[i].vertex_buffer_id, 0); |
|
|
|
|
enableGLFloatBuffer(objects[i].normal_buffer_id, 1); |
|
|
|
|
// TODO: could pass in a stride parameter here to enableGLFloatBuffer()
|
|
|
|
|
// could then use a 2d buffer for uv coords
|
|
|
|
|
enableGLFloatBuffer(objects[i].uv_buffer_id, 2); |
|
|
|
|
glBindTexture(GL_TEXTURE_2D, objects[i].tex_id); |
|
|
|
|
glUniform1i(shader->sampler_id, 0); |
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, objects[i].index_buffer_id); |
|
|
|
|
glDrawElements(GL_TRIANGLES, |
|
|
|
|
objects[i].index_buffer_count, |
|
|
|
|
GL_UNSIGNED_INT, |
|
|
|
|
0); |
|
|
|
|
if ((el_count == 3 && el_size == sizeof(float)) |
|
|
|
|
|| (el_count == 2 && el_size == sizeof(float)) |
|
|
|
|
|| (el_count == 1 && el_size == sizeof(unsigned short))) |
|
|
|
|
{ |
|
|
|
|
glGenBuffers(1, buffer_id); |
|
|
|
|
glBindBuffer(target, *buffer_id); |
|
|
|
|
glBufferData(target, count * el_count * el_size, buffer, usage); |
|
|
|
|
|
|
|
|
|
glDisableVertexAttribArray(0); |
|
|
|
|
glDisableVertexAttribArray(1); |
|
|
|
|
glDisableVertexAttribArray(2); |
|
|
|
|
return (glGetError() == GL_NO_ERROR); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
glUseProgram(0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
drawSimple(render_objects* r_objs, |
|
|
|
|
glm::mat4 world_transform, |
|
|
|
|
camera& cam, |
|
|
|
|
shader_wrapper sw, |
|
|
|
|
light_group* lights) |
|
|
|
|
{ |
|
|
|
|
simple_render_object* ro = (simple_render_object*) r_objs->objects; |
|
|
|
|
simple_shader_program* shader = |
|
|
|
|
(simple_shader_program*) sw.simple_shader; |
|
|
|
|
glUseProgram(shader->program_id); |
|
|
|
|
cam.MVP = cam.projection * cam.view * ro->model_transform; |
|
|
|
|
glUniformMatrix4fv( |
|
|
|
|
shader->world_transform_id, 1, GL_FALSE, &world_transform[0][0]); |
|
|
|
|
glUniformMatrix4fv(shader->MVP_id, 1, GL_FALSE, &cam.MVP[0][0]); |
|
|
|
|
enableGLFloatBuffer(ro->vertex_buffer_id, 0); |
|
|
|
|
enableGLFloatBuffer(ro->vertex_color_buffer_id, 1); |
|
|
|
|
glDrawArrays(ro->draw_mode, 0, ro->vertex_count); |
|
|
|
|
glDisableVertexAttribArray(0); |
|
|
|
|
glDisableVertexAttribArray(1); |
|
|
|
|
glUseProgram(0); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
inline void |
|
|
|
|
@ -242,35 +128,6 @@ enableGLFloatBuffer(uint buffer_id, uint location)
|
|
|
|
|
glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
initGLFloatBuffer(glm::vec3* buffer, |
|
|
|
|
uint count, |
|
|
|
|
GLuint& buffer_id, |
|
|
|
|
GLenum usage) |
|
|
|
|
{ |
|
|
|
|
glGenBuffers(1, &buffer_id); |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, buffer_id); |
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, |
|
|
|
|
count * 3 * sizeof(GLfloat), // NOTE: 3 floats per vertex prop
|
|
|
|
|
buffer, |
|
|
|
|
usage); |
|
|
|
|
|
|
|
|
|
return (glGetError() == GL_NO_ERROR); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
initGLIndexBuffer(uint* buffer, uint num_indices, GLuint& buffer_id) |
|
|
|
|
{ |
|
|
|
|
glGenBuffers(1, &buffer_id); |
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_id); |
|
|
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, |
|
|
|
|
num_indices * sizeof(uint), |
|
|
|
|
buffer, |
|
|
|
|
GL_STATIC_DRAW); |
|
|
|
|
|
|
|
|
|
return (glGetError() == GL_NO_ERROR); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
initGLTexture(const util_image image, GLuint& tex_id) |
|
|
|
|
{ |
|
|
|
|
@ -287,27 +144,26 @@ initGLTexture(const util_image image, GLuint& tex_id)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
loadMeshIntoGL(default_render_object* ro_out, mesh_info* mi_in) |
|
|
|
|
{ |
|
|
|
|
assert(mi_in != nullptr && ro_out != nullptr); |
|
|
|
|
|
|
|
|
|
if (initGLFloatBuffer(mi_in->vertices, |
|
|
|
|
mi_in->num_vertices, |
|
|
|
|
ro_out->vertex_buffer_id) && |
|
|
|
|
initGLFloatBuffer(mi_in->normals, |
|
|
|
|
mi_in->num_vertices, |
|
|
|
|
ro_out->normal_buffer_id) && |
|
|
|
|
// FIXME: this is broken now with tinygltf, need to use vec2
|
|
|
|
|
initGLFloatBuffer(mi_in->texture_coords, |
|
|
|
|
mi_in->num_vertices, |
|
|
|
|
ro_out->uv_buffer_id) && |
|
|
|
|
initGLIndexBuffer(mi_in->indices, |
|
|
|
|
mi_in->num_indices, |
|
|
|
|
ro_out->index_buffer_id) && |
|
|
|
|
initGLTexture(mi_in->diffuse_texture, ro_out->tex_id)) |
|
|
|
|
loadMeshIntoGL(default_render_object* ro_out, mesh* mesh_in) |
|
|
|
|
{ |
|
|
|
|
assert(mesh_in != nullptr && ro_out != nullptr); |
|
|
|
|
|
|
|
|
|
if (initGLBuffer(mesh_in->vertices, mesh_in->num_vertices, |
|
|
|
|
&ro_out->vertex_buffer_id) |
|
|
|
|
&& initGLBuffer(mesh_in->normals, mesh_in->num_vertices, |
|
|
|
|
&ro_out->normal_buffer_id) |
|
|
|
|
&& initGLBuffer(mesh_in->texture_coords, mesh_in->num_vertices, |
|
|
|
|
&ro_out->uv_buffer_id, 2) |
|
|
|
|
&& initGLBuffer(mesh_in->indices, mesh_in->num_indices, |
|
|
|
|
&ro_out->index_buffer_id, 1, sizeof(unsigned short), |
|
|
|
|
GL_ELEMENT_ARRAY_BUFFER) |
|
|
|
|
// FIXME: re-implement diffuse texture, but with index into an array
|
|
|
|
|
// on render_state
|
|
|
|
|
//&& initGLTexture(mesh_in->diffuse_texture, ro_out->tex_id))
|
|
|
|
|
) |
|
|
|
|
{ |
|
|
|
|
ro_out->node_xform = mi_in->model_transform; |
|
|
|
|
ro_out->index_buffer_count = mi_in->num_indices; |
|
|
|
|
ro_out->node_xform = *mesh_in->xform; |
|
|
|
|
ro_out->index_buffer_count = mesh_in->num_indices; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -320,19 +176,55 @@ loadMeshIntoGL(default_render_object* ro_out, mesh_info* mi_in)
|
|
|
|
|
// renRenderFrame
|
|
|
|
|
inline void |
|
|
|
|
updateMatrices(default_shader_program* shader, |
|
|
|
|
camera& cam, |
|
|
|
|
camera* cam, |
|
|
|
|
glm::mat4 world_xform, |
|
|
|
|
glm::mat4 node_xform) |
|
|
|
|
{ |
|
|
|
|
glUniformMatrix4fv( |
|
|
|
|
shader->world_transform_id, 1, GL_FALSE, &world_xform[0][0]); |
|
|
|
|
glUniformMatrix4fv(shader->model_matrix_id, 1, GL_FALSE, &node_xform[0][0]); |
|
|
|
|
glUniformMatrix4fv(shader->view_matrix_id, 1, GL_FALSE, &cam.view[0][0]); |
|
|
|
|
glUniformMatrix4fv(shader->view_matrix_id, 1, GL_FALSE, &cam->view[0][0]); |
|
|
|
|
glUniformMatrix4fv(shader->projection_matrix_id, 1, GL_FALSE, |
|
|
|
|
&cam.projection[0][0]); |
|
|
|
|
&cam->projection[0][0]); |
|
|
|
|
glm::mat3 normal_matrix = glm::transpose( |
|
|
|
|
glm::inverse(glm::mat3(cam.model))); |
|
|
|
|
glm::inverse(glm::mat3(cam->model))); |
|
|
|
|
glUniformMatrix3fv(shader->normal_matrix_id, 1, GL_FALSE, |
|
|
|
|
&normal_matrix[0][0]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
drawDefault(render_objects* r_objs, |
|
|
|
|
glm::mat4 world_transform, |
|
|
|
|
camera* cam, |
|
|
|
|
shader_wrapper sw, |
|
|
|
|
light_group* lights) |
|
|
|
|
{ |
|
|
|
|
default_shader_program* shader = sw.default_shader; |
|
|
|
|
default_render_object* objects = r_objs->objects; |
|
|
|
|
glUseProgram(shader->program_id); |
|
|
|
|
updateMatrices(shader, cam, world_transform, objects->node_xform); |
|
|
|
|
if (lights->needs_update) lightsUpdate(lights, shader); |
|
|
|
|
|
|
|
|
|
for (uint i = 0; i < r_objs->count; i++) { |
|
|
|
|
enableGLFloatBuffer(objects[i].vertex_buffer_id, 0); |
|
|
|
|
enableGLFloatBuffer(objects[i].normal_buffer_id, 1); |
|
|
|
|
// TODO: could pass in a stride parameter here to enableGLFloatBuffer()
|
|
|
|
|
// could then use a 2d buffer for uv coords
|
|
|
|
|
enableGLFloatBuffer(objects[i].uv_buffer_id, 2); |
|
|
|
|
glBindTexture(GL_TEXTURE_2D, objects[i].tex_id); |
|
|
|
|
glUniform1i(shader->sampler_id, 0); |
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, objects[i].index_buffer_id); |
|
|
|
|
glDrawElements(GL_TRIANGLES, |
|
|
|
|
objects[i].index_buffer_count, |
|
|
|
|
GL_UNSIGNED_INT, |
|
|
|
|
0); |
|
|
|
|
|
|
|
|
|
glDisableVertexAttribArray(0); |
|
|
|
|
glDisableVertexAttribArray(1); |
|
|
|
|
glDisableVertexAttribArray(2); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
glUseProgram(0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|