You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

182 lines
7.1 KiB

#include "Object.h"
#include "OFFMesh.h"
#include "Camera.h"
#include "ExternalLib/glm/gtx/euler_angles.hpp"
#include "ExternalLib/glm/gtx/transform.hpp"
#include "ExternalLib/glm/gtc/type_ptr.hpp"
#include <math.h>
#define BUFFER_OFFSET(i) reinterpret_cast<GLvoid *>(i)
/******************
* Constructors *
******************/
Object::Object()
{}
Object::Object(const glm::vec3& position_, const glm::vec3& rotation_, const glm::vec3& scale_, const Mesh& mesh_, const ObjectType objectType_)
:objectType(objectType_), mesh(mesh_), position(position_), rotation(rotation_), scale(scale_)
{
/**
* \brief Create an OpenGL Object and send associated data on the GPU
* \param mesh <=> contains the object mesh
* \limitations : For now every mesh is stored the same way in a common VBO regardless the type of mesh and its data
* Assume data contains only "vertices, normal"
*/
// Declaring and binding VAO's object
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// verticesBO initialization
glGenBuffers(1, &vbo); // generate a buffer and link it t tho VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo); // bind VBO buffer to GL_ARRAY_BUFFER global buffer describing vertices
// fill the buffer
int meshSize = static_cast<int>(sizeof(Vertex)) * static_cast<int>(mesh.vertices.size());
glBufferData(GL_ARRAY_BUFFER, meshSize, nullptr, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0,
meshSize, mesh.vertices.data() );
// Sending Vertices on location 0 for shaders
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float) * 2, nullptr); // specify the VBO structure
glEnableVertexAttribArray(0); // activating vertices on layout 0 for vertex shader
// Sending Normals on location 1 for shaders
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float) * 2, BUFFER_OFFSET(12)); // specify the VBO structure
glEnableVertexAttribArray(1); // activating vertices on layout 1 for vertex shader
// Unbind VAO
glBindVertexArray(0);
// Create Object's Model Matrix
setModel();
}
/***********
* Getters *
***********/
int Object::getNbVertices() const
{ return nbVertices; }
GLuint Object::getVAO() const
{ return vao; }
GLuint Object::getVBO() const
{ return vbo; }
Mesh Object::getMesh() const
{ return mesh; }
glm::vec3 Object::getPosition() const
{ return position; }
glm::vec3 Object::getRotation() const
{ return rotation; }
glm::vec3 Object::getScale() const
{ return scale; }
glm::mat4 Object::getModel() const
{ return model; }
/***********
* Setters *
***********/
void Object::setPosition(glm::vec3 position_)
{ position = glm::vec3(fmod(position_.x,360.0f), fmod(position_.y,360.0f), fmod(position_.z,360.0f)); setModel(); }
void Object::setRotation(glm::vec3 rotation_)
{ rotation = rotation_; setModel();}
void Object::setScale(glm::vec3 scale_)
{ scale = scale_; setModel(); }
void Object::setModel()
{
// TODO : Think about how to resolve the "rotate, translate, scale" order problem.
// scale -> rotate -> translate seems to be the best option but stick to the T->R->S for now
model = glm::translate(glm::mat4(), position);
model *= glm::eulerAngleXYZ(glm::radians(rotation.x), glm::radians(rotation.y), glm::radians(rotation.z));
model = glm::scale(model, scale);
}
/***********
* Methods *
***********/
void Object::Draw(const ShaderProgram& sp) const
{
/**
* \brief Bind object's VAO send some uniforms (TODO : store each uniform needed per ShaderProgram),
* and call the correct glDraw method for every type of Object
* \param sp <=> ShaderProgram being used to draw object's instance
* \limitations : Assume sp is linked
*/
switch(objectType)
{
case SimpleMesh :
{
glBindVertexArray(vao);
GLint modelLoc; // uniforms's key
modelLoc = glGetUniformLocation(sp.getId(), "model"); /* query the adress of the uniform variable named "model"
* in the shader */
glProgramUniformMatrix4fv(sp.getId(), modelLoc, 1, GL_FALSE, glm::value_ptr(model));
/* setting the content of the model uniform variable
* designated by its id modelLoc (arg1),
* we initialize it with 1 matrix (arg2),
* we don't want the matrix to be transposed (arg3),
* and its content is the model matrix (arg4) */
glDrawArrays(GL_TRIANGLES, 0, static_cast<int>(mesh.vertices.size())); // Draw it
glBindVertexArray(0);
break;
}
case Mirror : // TODO : not working yet because for every mirror rendering a second pass is needed
// and Object cannot (and shouldn't be able to) call for a new DrawScecne()
// => Need to build a new structure, graphscene
{
glBindVertexArray(vao);
/*** Draw the mirror ***/
glEnable(GL_STENCIL_TEST); // Just to be safe let's enable and disable stencil only for mirror
glStencilFunc(GL_ALWAYS, 1, 0xFF); // Set stencil to a full 1 grid
glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
glStencilMask(0xFF); // Allow full write
glDepthMask(GL_FALSE); // Turn off depthTesting
glClear(GL_STENCIL_BUFFER_BIT); // Clear stencil
/* Model Matrix NODE SPECIFIC */
/* Allow conversion from LocalSpace To WorldSpace coordinates */
// TODO : add translation and scale
glm::mat4 modelObject = glm::mat4() * glm::eulerAngleXYZ(glm::radians(rotation.x), glm::radians(rotation.y), glm::radians(rotation.z));
GLint modelLoc; // uniforms's key
modelLoc = glGetUniformLocation(sp.getId(), "model"); /* query the adress of the uniform variable named "model"
* in the shader */
glProgramUniformMatrix4fv(sp.getId(), modelLoc, 1, GL_FALSE, glm::value_ptr(modelObject));
glDrawArrays(GL_TRIANGLES, 0, static_cast<int>(mesh.vertices.size())); // Draw it
/*** Draw the reflection ***/
glStencilFunc(GL_EQUAL, 1, 0xFF); // Set stencil to draw only if 1 <=> where mirror has been drew before
glStencilMask(0x00); // Disable stencil writing
glDepthMask(GL_TRUE); // Turn back on depthTesting
glClear(GL_DEPTH_BUFFER_BIT);
// Camera mirroredCamera = cam.mirrorCamera(modelObject, glm::vec4(rotation.x, rotation.y, -rotation.z, 0.0f), glm::vec4(0,0,0,0));
// drawScene(mirroredCamera);
glDisable(GL_STENCIL_TEST);
glBindVertexArray(0);
break;
}
case SkyBox : // TODO : Move sky rendering here
{
break;
}
}
}