RtB/src/RenderScene.cpp

229 lines
8.7 KiB
C++

/* ================================================================
RenderScene
----------------
This header file defines the RenderScene class.
================================================================ */
#include "RenderScene.hpp"
#include "RenderObject.hpp"
#include "Log.hpp"
#include <stdexcept> // for std::out_of_range
#include <iostream> // for std::cerr
#include <algorithm> // for std::find
/* ======== Constructors and Destructors ======== */
RenderScene::RenderScene() {
}
RenderScene::~RenderScene() {
}
/* renderTo
This function attempts to render the given scene to the target_view using the contained RenderCamera(s).
It iterates over all RenderSets and their RenderObjects and attempts to render to the RenderCamera's attached RenderViews.
*/
int RenderScene::renderTo(RenderView *target_view, Program *render_program) {
RenderCamera *camera;
RenderView *view;
RenderSet *set;
RenderObject *object;
std::vector<RenderCamera*>::iterator camera_it, camera_end;
for (camera_it = cameras.begin(), camera_end = cameras.end(); camera_it != camera_end; ++camera_it) {
camera = *camera_it;
if ((view = camera->getRenderView()) == NULL) continue;
glBindFramebuffer(GL_FRAMEBUFFER, view->fbo);
std::vector<RenderSet*>::iterator set_it, set_end;
for (set_it = sets.begin(), set_end = sets.end(); set_it != set_end; ++set_it) {
set = *set_it;
std::vector<RenderObject*>::iterator obj_it, obj_end;
for (obj_it = set->objects.begin(), obj_end = set->objects.end(); obj_it != obj_end; ++obj_it) {
object = *obj_it;
}
}
}
// Use this provided program for rendering. Should refer to a framebuffer shader
glUseProgram(render_program->getProgram());
// Bind to the provided target view's fbo
glBindFramebuffer(GL_FRAMEBUFFER, target_view->fbo);
// Render each of our camera's framebuffers with the appropriate changes
for (camera_it = cameras.begin(), camera_end = cameras.end(); camera_it != camera_end; ++camera_it) {
camera = *camera_it;
if ((view = camera->getRenderView()) == NULL) continue;
glBindFramebuffer(GL_FRAMEBUFFER, view->fbo);
}
return 0;
}
int RenderScene::doRender() {
RenderCamera *camera;
RenderView *view;
RenderSet *set;
RenderObject *object;
// Begin iteration over the scene's cameras
std::vector<RenderCamera*>::iterator camera_it, camera_end;
for (camera_it = cameras.begin(), camera_end = cameras.end(); camera_it != camera_end; ++camera_it) {
camera = *camera_it;
if ((view = camera->getRenderView()) == NULL) continue; // bail if camera has no rendering target
glBindFramebuffer(GL_FRAMEBUFFER, view->fbo);
glViewport(0, 0, view->w, view->h);
if (camera->render_flags & RenderCamera::CLEAR_DEPTH) glClear(GL_DEPTH_BUFFER_BIT);
if (camera->render_flags & RenderCamera::CLEAR_COLOR) glClear(GL_COLOR_BUFFER_BIT);
// Iterate over the scene's render sets
std::vector<RenderSet*>::iterator set_it, set_end;
for (set_it = sets.begin(), set_end = sets.end(); set_it != set_end; ++set_it) {
set = *set_it;
if (set->program == NULL) continue; // bail if set has no rendering program to use
GLuint glsl_program = set->program->getProgram();
//LOG(LOG_INFO) << "set program is: " << glsl_program;
glUseProgram(glsl_program);
// FIXME: We are temporarily getting the locations here - this needs to be moved elsewhere (Program?)
GLuint shader_projection = glGetUniformLocation(glsl_program, "proj_matrix");
GLuint shader_modelview = glGetUniformLocation(glsl_program, "mv_matrix");
GLuint shader_texture = glGetUniformLocation(glsl_program, "texture_sampler");
GLuint shader_vp = glGetAttribLocation(glsl_program, "vp");
GLuint shader_uv = glGetAttribLocation(glsl_program, "uv");
GLuint shader_normal = glGetAttribLocation(glsl_program, "normal");
// Send the camera's perspective
float pm[16];
glUniformMatrix4fv(shader_projection, 1, GL_FALSE, camera->p_matrix.toFloats(pm));
// enable attribs
glEnableVertexAttribArray(shader_vp);
glEnableVertexAttribArray(shader_uv);
glEnableVertexAttribArray(shader_normal);
// Iterate over the set's render objects
std::vector<RenderObject*>::iterator obj_it, obj_end;
for (obj_it = set->objects.begin(), obj_end = set->objects.end(); obj_it != obj_end; ++obj_it) {
object = *obj_it;
if (object->flags & RenderObject::HIDDEN) continue;
Mat4 mv_matrix; // modelview matrix
float mv[16]; // converted modelview to send to OpenGL
Mesh *mesh;
Texture *texture;
GLuint gl_texture = 0;
if ((mesh = object->mesh) == NULL) continue; // No mesh to render with, bail
if ((texture = object->texture) == NULL) {
// TODO: add a "missing texture" texture here
} else {
gl_texture = object->texture->texture;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gl_texture);
glUniform1i(shader_texture, 0);
}
// TODO: if object is not in camera's view, continue (probably reverse projection on each screen corner)
// send computed modelview to shader
mv_matrix = camera->mv_matrix * object->model;
glUniformMatrix4fv(shader_modelview, 1, GL_FALSE, mv_matrix.toFloats(mv));
// TODO: enable and attach texture
// bind vp
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
glVertexAttribPointer(shader_vp, 3, GL_FLOAT, GL_FALSE, 0, NULL);
// bind uvs/texture coords
glBindBuffer(GL_ARRAY_BUFFER, mesh->uvbo);
glVertexAttribPointer(shader_uv, 2, GL_FLOAT, GL_FALSE, 0, 0);
// bind normals
glBindBuffer(GL_ARRAY_BUFFER, mesh->nbo);
glVertexAttribPointer(shader_normal, 3, GL_FLOAT, GL_FALSE, 0, NULL);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->ibo);
//glDrawElements(GL_TRIANGLES, mesh->indices.size(), GL_UNSIGNED_INT, 0);
glDrawArrays(GL_TRIANGLES, 0, mesh->vertices.size());
// TODO: maybe other things? Should this be managed by Program somehow?
}
}
}
return 0;
}
/* ======== Camera Functionality ======== */
// This function adds the ptr to Camera and returns its "id" which is simply its index+1
int RenderScene::addCamera(RenderCamera* camera) {
try {
cameras.push_back(camera);
} catch(...) {
LOG(LOG_ERROR) << FUNC_NAME << ": Could not add RenderCamera";
}
// return size regardless of success, likely The Wrong Thing
return cameras.size();
}
// Remove camera by ID
int RenderScene::remCamera(int id) {
RenderCamera *camera = getCamera(id);
if (camera) {
cameras.erase(cameras.begin()+(id-1));
return 0;
}
LOG(LOG_WARNING) << FUNC_NAME << ": Could not remove RenderCamera " << id;
return 1;
}
// Remove camera by pointer
int RenderScene::remCamera(RenderCamera *camera) {
std::vector<RenderCamera*>::iterator it;
if ((it = std::find(cameras.begin(), cameras.end(), camera)) != cameras.end()) {
cameras.erase(it);
return 0;
}
LOG(LOG_WARNING) << FUNC_NAME << ": Could not remove RenderCamera";
return 1;
}
// Get camera by ID
RenderCamera* RenderScene::getCamera(int id) {
try {
return cameras.at(id-1);
} catch (const std::out_of_range& oor) {
LOG(LOG_WARNING) << FUNC_NAME << ": RenderCamera index out of range: " << oor.what();
}
return NULL;
}
// Get cameras vector
std::vector<RenderCamera*> *RenderScene::getCameras() {
return &cameras;
}
/* ======== RenderSet Functionality ======== */
int RenderScene::addSet(RenderSet* set) {
try {
sets.push_back(set);
} catch(...) {
LOG(LOG_ERROR) << FUNC_NAME << ": Could not add RenderSet";
}
// return size regardless of success, likely The Wrong Thing
return sets.size();
}
int RenderScene::remSet(int id) {
RenderSet *set = getSet(id);
if (set) {
sets.erase(sets.begin()+(id-1));
return 0;
}
LOG(LOG_WARNING) << FUNC_NAME << ": Could not remove RenderSet " << id;
return 1;
}
int RenderScene::remSet(RenderSet *set) {
std::vector<RenderSet*>::iterator it;
if ((it = std::find(sets.begin(), sets.end(), set)) != sets.end()) {
sets.erase(it);
return 0;
}
LOG(LOG_WARNING) << FUNC_NAME << ": Could not remove RenderSet";
return 1;
}
int RenderScene::delSet(RenderSet *set) {
std::vector<RenderSet*>::iterator it;
if ((it = std::find(sets.begin(), sets.end(), set)) != sets.end()) {
sets.erase(it);
delete set;
return 0;
}
LOG(LOG_WARNING) << FUNC_NAME << ": Could not delete RenderSet";
return 1;
}
RenderSet* RenderScene::getSet(int id) {
try {
return sets.at(id-1);
} catch (const std::out_of_range& oor) {
LOG(LOG_ERROR) << FUNC_NAME << ": RenderSet index out of range: " << oor.what();
}
return NULL;
}
std::vector<RenderSet*> *RenderScene::getSets() {
return &sets;
}