SparrowRenderer/phongentity.cpp
2015-11-18 09:37:24 +01:00

198 lines
6.7 KiB
C++

#include "phongentity.h"
#include "shader.h"
#include <glm/glm.hpp>
#include "phongmaterial.h"
#include "mesh.h"
#include <glm/ext.hpp>
#include "glassert.h"
#include "sparrowrenderer.h"
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
PhongEntity::PhongEntity(Mesh* myMesh) :
mesh(myMesh),
vao(0),
nb_buffers(0),
vbo(NULL),
displayList(0),
modelMatrix()
{}
void PhongEntity::draw(const glm::mat4 &viewMatrix, const glm::mat4 &projectionMatrix, Lights::Light* dirLight, Lights* pointLights)
{
if(SparrowRenderer::isModernOpenGLAvailable())
modernDraw(viewMatrix, projectionMatrix, dirLight, pointLights);
else
crappyDraw(viewMatrix, projectionMatrix, dirLight, pointLights);
}
void PhongEntity::modernDraw(const glm::mat4 &viewMatrix, const glm::mat4 &projectionMatrix, Lights::Light* dirLight, Lights* pointLights)
{
glm::mat4 modelViewMatrix = viewMatrix * modelMatrix;
glm::mat4 mvp = projectionMatrix * modelViewMatrix;
glm::mat4 normalMatrix = glm::transpose(glm::inverse(modelViewMatrix));
for(int i=0; i<mesh->indiceGroups.size(); ++i)
{
Material* mat = mesh->indiceGroups[i].material;
mat->bindAttributes();
Shader* shader = mat->getShader();
shader->bindMatrix(shader->getLocation("viewMatrix"), viewMatrix);
shader->bindMatrix(shader->getLocation("modelViewMatrix"), modelViewMatrix);
shader->bindMatrix(shader->getLocation("normalMatrix"), normalMatrix);
shader->bindMatrix(shader->getLocation("MVP"), mvp);
shader->bindVec3Array(shader->getLocation("dirLight"), (glm::vec3*)dirLight, 2);
pointLights->bind(shader->getLocation("pointLights"), shader->getLocation("nbPointLights"), shader);
drawGroup(i);
}
}
void PhongEntity::crappyDraw(const glm::mat4 &viewMatrix, const glm::mat4 &projectionMatrix, Lights::Light* dirLight, Lights* pointLights)
{
glMatrixMode(GL_MODELVIEW);
glm::mat4 modelViewMatrix = viewMatrix * modelMatrix;
glLoadMatrixf(glm::value_ptr(modelViewMatrix));
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(glm::value_ptr(projectionMatrix));
glCallList(displayList);
}
void PhongEntity::modernInit(bool isDynamic)
{
GLenum buffer_type = isDynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
// create VAO
glAssert(glGenVertexArrays(1, &vao));
glAssert(glBindVertexArray(vao));
nb_buffers = 1; // positions buffer
if(mesh->hasNormals())
++nb_buffers;
if(mesh->hasTexCoords())
++nb_buffers;
if(mesh->hasTangents())
++nb_buffers;
nb_buffers += mesh->indiceGroups.size();
// create VBOs
vbo = new GLuint[nb_buffers]();
glAssert(glGenBuffers(nb_buffers, vbo));
for(const Mesh::Group &g : mesh->indiceGroups)
{
// init indices vbos
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[INDICES_BUFFER]));
glAssert(glBufferData(GL_ARRAY_BUFFER, g.indices.size() * sizeof(GLuint), g.indices.data(), buffer_type));
}
// init positions vbo
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[POSITION_BUFFER]));
glAssert(glBufferData(GL_ARRAY_BUFFER, mesh->positions.size() * sizeof(glm::vec3), mesh->positions.data(), buffer_type));
if(mesh->hasNormals())
{
// init normals vbo
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[NORMAL_BUFFER]));
glAssert(glBufferData(GL_ARRAY_BUFFER, mesh->normals.size() * sizeof(glm::vec3), mesh->normals.data(), buffer_type));
}
if(mesh->hasNormals())
{
// init texCoords vbo
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TEXCOORD_BUFFER]));
glAssert(glBufferData(GL_ARRAY_BUFFER, mesh->texCoords.size() * sizeof(glm::vec2), mesh->texCoords.data(), buffer_type));
}
if(mesh->hasTangents())
{
// init tangents vbo
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TANGENT_BUFFER]));
glAssert(glBufferData(GL_ARRAY_BUFFER, mesh->tangents.size() * sizeof(glm::vec3)*2, mesh->tangents.data(), buffer_type));
}
// unbind vao
glAssert(glBindVertexArray(0));
}
void PhongEntity::crappyInit()
{
displayList = glAssert(glGenLists(1));
glAssert(glNewList(displayList, GL_COMPILE));
for(int i=0; i<mesh->indiceGroups.size(); ++i)
{
PhongMaterial* mat = (PhongMaterial*)(mesh->indiceGroups[i].material);
mat->bindAttributes();
glAssert(glBegin(GL_TRIANGLES));
for(int j=0; j<mesh->indiceGroups[i].indices.size(); ++j)
{
int vid = mesh->indiceGroups[i].indices[j];
glNormal3fv(glm::value_ptr(mesh->normals[vid]));
glTexCoord2fv(glm::value_ptr(mesh->texCoords[vid]));
glVertex3fv(glm::value_ptr(mesh->positions[vid]));
}
glAssert(glEnd());
}
glAssert(glEndList());
}
void PhongEntity::initGL(bool isDynamic)
{
if(SparrowRenderer::isModernOpenGLAvailable())
modernInit(isDynamic);
else
crappyInit();
}
void PhongEntity::destroyGL()
{
if(SparrowRenderer::isModernOpenGLAvailable())
{
glAssert(glDeleteVertexArrays(1, &vao));
glAssert(glDeleteBuffers(nb_buffers, vbo));
delete[] vbo;
vbo = NULL;
}
else
glAssert(glDeleteLists(displayList, 1));
}
void PhongEntity::drawGroup(int groupId)
{
glAssert(glBindVertexArray(vao));
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[POSITION_BUFFER]));
glAssert(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0)));
glAssert(glEnableVertexAttribArray(0));
if(mesh->hasNormals())
{
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[NORMAL_BUFFER]));
glAssert(glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0)));
glAssert(glEnableVertexAttribArray(1));
}
if(mesh->hasTexCoords())
{
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TEXCOORD_BUFFER]));
glAssert(glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), BUFFER_OFFSET(0)));
glAssert(glEnableVertexAttribArray(2));
}
if(mesh->hasTangents())
{
glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TANGENT_BUFFER]));
glAssert(glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Mesh::Tangents), BUFFER_OFFSET(0)));
glAssert(glEnableVertexAttribArray(3));
glAssert(glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Mesh::Tangents), BUFFER_OFFSET(sizeof(glm::vec3))));
glAssert(glEnableVertexAttribArray(4));
}
glAssert(glDrawElements(GL_TRIANGLES, mesh->indiceGroups[groupId].indices.size(), GL_UNSIGNED_INT, mesh->indiceGroups[groupId].indices.data()));
}
PhongEntity* PhongEntity::clone()
{
PhongEntity* myClone = new PhongEntity(mesh);
myClone->modelMatrix = modelMatrix;
myClone->displayList = displayList;
myClone->nb_buffers = nb_buffers;
myClone->vao = vao;
myClone->vbo = vbo;
return myClone;
}