279 lines
9.3 KiB
C++
279 lines
9.3 KiB
C++
#ifndef MESH_H
|
|
#define MESH_H
|
|
|
|
#include "opengl.h"
|
|
#include <vector>
|
|
#include <string>
|
|
#include <glm/vec3.hpp>
|
|
#include <glm/vec2.hpp>
|
|
|
|
class Buffer;
|
|
class Material;
|
|
class Shader;
|
|
|
|
struct Mesh
|
|
{
|
|
public:
|
|
|
|
/*************************************************************/
|
|
/* MESH AND MATERIAL FLAGS */
|
|
/*************************************************************/
|
|
|
|
// Mesh properties
|
|
enum {
|
|
// Geometric properties
|
|
MESH_INDEXED,
|
|
MESH_TEXTURABLE,
|
|
MESH_INSTANCED,
|
|
|
|
// Mesh type
|
|
MESH_3D,
|
|
MESH_2D,
|
|
|
|
// 3D Geometric properties
|
|
MESH_TANGENT_SPACE,
|
|
MESH_DOUBLE_SIDED,
|
|
MESH_BILLBOARD,
|
|
MESH_SHADOWED,
|
|
|
|
// simple material (no lighting)
|
|
MATERIAL_COLOR_TEXTURE,
|
|
MATERIAL_ALPHA_MASK,
|
|
|
|
// 3D phong material
|
|
MATERIAL_PHONG,
|
|
MATERIAL_PHONG_DIFFUSE_TEXTURE,
|
|
MATERIAL_PHONG_EMISSION_TEXTURE,
|
|
MATERIAL_PHONG_SPECULAR_TEXTURE,
|
|
MATERIAL_PHONG_NORMAL_MAP,
|
|
|
|
// 3D Beckman-like materials
|
|
MATERIAL_BACKMANN_BUMP_MAP,
|
|
|
|
NB_FLAGS
|
|
};
|
|
|
|
// shader "#define" strings associated to the properties
|
|
static const char* const flagStr[NB_FLAGS];
|
|
|
|
/*************************************************************/
|
|
/* GEOMETRY DATA */
|
|
/*************************************************************/
|
|
|
|
// 3D public data
|
|
std::vector<glm::vec3> positions3D;
|
|
std::vector<glm::vec3> normals;
|
|
|
|
typedef struct
|
|
{
|
|
glm::vec3 tangent;
|
|
glm::vec3 binormal;
|
|
} Tangents;
|
|
|
|
std::vector<Tangents> tangents;
|
|
|
|
// 2D public data
|
|
std::vector<glm::vec2> positions2D;
|
|
|
|
// public data common to 2D and 3D
|
|
std::vector<glm::vec2> texCoords;
|
|
std::vector<glm::vec3> instances_offsets;
|
|
std::vector<GLuint> indices;
|
|
|
|
/*************************************************************/
|
|
/* MAIN METHODS */
|
|
/*************************************************************/
|
|
|
|
/**
|
|
* @brief Mesh builds an empty mesh, to be renderable, a mesh must have vertices and a material.
|
|
*/
|
|
Mesh(const std::string &name = "mesh");
|
|
~Mesh();
|
|
|
|
void setName(const std::string &name) { m_name = name; }
|
|
std::string getName() { return m_name; }
|
|
|
|
/**
|
|
* OpenGL methods :
|
|
* - initGL allocates the GPU buffers and sends the mesh data to the GPU
|
|
* - draw binds the material attributes and draws the mesh geometry
|
|
* - destroyGL releases the allocated GPU memory, destroyGL is called automatically in Mesh's destructor and at the beginning of initGL
|
|
*/
|
|
void initGL();
|
|
void draw(Shader* shader, bool drawNormals = true, bool drawTexCoord = true, bool drawTangents = true);
|
|
void destroyGL();
|
|
|
|
/**
|
|
* @brief clearData clears all data vectors, but keeps GPU data allocated.
|
|
*/
|
|
void clearData();
|
|
|
|
/**
|
|
* @brief getFlags returns the flags that defines the specificities of the mesh and his material
|
|
*/
|
|
unsigned int getFlags();
|
|
|
|
/*************************************************************/
|
|
/* MESH BUILDING METHODS */
|
|
/*************************************************************/
|
|
|
|
// add vertex
|
|
void addVertex(float x, float y, float z) {addVertex(glm::vec3(x, y, z));}
|
|
void addVertex(const glm::vec3 &position) {positions3D.push_back(position);}
|
|
void addVertex(float x, float y) {addVertex(glm::vec2(x, y));}
|
|
void addVertex(const glm::vec2 &position) {positions2D.push_back(position);}
|
|
void addVertex(const glm::vec3 &position, const glm::vec2 &texCoord) {addVertex(position); addTexCoord(texCoord);}
|
|
void addVertex(const glm::vec2 &position, const glm::vec2 &texCoord) {addVertex(position); addTexCoord(texCoord);}
|
|
void addVertex(const glm::vec3 &position, const glm::vec3 &normal) {addVertex(position); addNormal(normal);}
|
|
void addVertex(const glm::vec3 &position, const glm::vec3 &normal, const glm::vec2 &texCoord) {addVertex(position, normal); addTexCoord(texCoord);}
|
|
void addRectangle2D(const glm::vec2 &pos, const glm::vec2 &dim, const glm::vec2 &texCoord, const glm::vec2 &texRange, bool indexed = false);
|
|
void addRectangle2D(const glm::vec2 &pos, const glm::vec2 &dim, bool indexed = false) {addRectangle2D(pos, dim, glm::vec2(0), glm::vec2(1), indexed);}
|
|
void addRectangle2D(float x, float y, float width, float height, bool indexed = false) {addRectangle2D(glm::vec2(x, y), glm::vec2(width, height), indexed);}
|
|
|
|
// add indices
|
|
void addTriangle(int i1, int i2, int i3) {indices.push_back(i1), indices.push_back(i2), indices.push_back(i3);}
|
|
void addLine(int i1, int i2) {indices.push_back(i1), indices.push_back(i2);}
|
|
|
|
// Material accessers
|
|
void setMaterial(Material* mat) {material = mat;}
|
|
Material *getMaterial() {return material;}
|
|
|
|
// other accessers
|
|
void addNormal(float x, float y, float z) {addNormal(glm::vec3(x, y, z));}
|
|
void addNormal(const glm::vec3 &normal) {normals.push_back(normal);}
|
|
void addTexCoord(float u, float v) {addTexCoord(glm::vec2(u, v));}
|
|
void addTexCoord(const glm::vec2 &texCoord) {texCoords.push_back(texCoord);}
|
|
|
|
/*************************************************************/
|
|
/* 2D MESH PROPERTIES */
|
|
/*************************************************************/
|
|
|
|
/**
|
|
* @brief setDepth allows to set the depth of a 2D mesh, the depth must be between -1 and 1, -1 being the closest to the camera
|
|
*/
|
|
void setDepth(float d) { depth = d; }
|
|
float getDepth() { return depth; }
|
|
|
|
/*************************************************************/
|
|
/* 3D MESH PROPERTIES */
|
|
/*************************************************************/
|
|
|
|
/**
|
|
* @brief setIsDoubleSided allows to enable or disable face culling for this Mesh
|
|
*/
|
|
void setIsDoubleSided(bool val) {isDoubleSided = val;}
|
|
|
|
/**
|
|
* @brief setIsBillboard allows to enable or disable billboarding,
|
|
* a billboard mesh will always follow the camera orientation
|
|
*/
|
|
void setIsBillboard(bool val) {isBillboard = val;}
|
|
|
|
/**
|
|
* @brief setIsShadowCaster allows to enable or disable,
|
|
* rendering of this mesh in the shadowmaps
|
|
*/
|
|
void setIsShadowCaster(bool val) {isShadowCaster = val;}
|
|
|
|
/*************************************************************/
|
|
/* 3D MESH TOOLS */
|
|
/*************************************************************/
|
|
|
|
/**
|
|
* @brief mergeVertices simplifies an indexed mesh by merging all vertices that
|
|
* have exactly the same position, texcoord, and normals, the tangents will be averaged.
|
|
*/
|
|
void mergeVertices();
|
|
|
|
/**
|
|
* @brief computeNormals computes adjacency for a triangle mesh, the mesh type changes to GL_TRIANGLES_ADJACENCY
|
|
*/
|
|
void computeNeighbors();
|
|
|
|
/**
|
|
* compute normals from an indexed mesh (positions + indices)
|
|
*/
|
|
void computeNormals();
|
|
|
|
/**
|
|
* compute tangent space from a textured indexed mesh (positions + normals + texcoords + indices)
|
|
*/
|
|
void computeTangents();
|
|
|
|
/**
|
|
* compute the bounding box of the mesh based on the 3D positions
|
|
*/
|
|
void computeBoundingBox(glm::vec3 &min, glm::vec3 &max);
|
|
|
|
/*************************************************************/
|
|
/* SERIALISATION */
|
|
/*************************************************************/
|
|
|
|
/**
|
|
* @brief serializeMesh can be used to save a mesh
|
|
* @return true if the mesh has succesfully been saved
|
|
*/
|
|
static bool serialize(Mesh* mesh, FILE *file);
|
|
|
|
bool serialize(FILE *file) { return serialize(this, file); }
|
|
|
|
/**
|
|
* @brief deserializeMesh can be used to load a mesh
|
|
* @return the loaded mesh of NULL if a reading error has occured
|
|
*/
|
|
static Mesh* deserialize(FILE *file);
|
|
|
|
/*************************************************************/
|
|
/* ADVANCED CUSTOMISATION */
|
|
/*************************************************************/
|
|
|
|
/**
|
|
* Specifies what kind of primitives to render. Symbolic constants GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_LINE_STRIP_ADJACENCY,
|
|
* GL_LINES_ADJACENCY, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_TRIANGLE_STRIP_ADJACENCY, GL_TRIANGLES_ADJACENCY and GL_PATCHES are accepted.
|
|
*
|
|
* default is GL_TRIANGLES
|
|
*/
|
|
void setPrimitiveType(GLenum type) {primitive_type = type;}
|
|
|
|
protected:
|
|
std::string m_name;
|
|
|
|
Material* material;
|
|
bool isDoubleSided;
|
|
bool isBillboard;
|
|
bool isShadowCaster;
|
|
float depth;
|
|
|
|
GLenum primitive_type;
|
|
|
|
std::vector<Buffer*> buffers;
|
|
|
|
enum {
|
|
// required buffer
|
|
POSITION2D_BUFFER,
|
|
POSITION3D_BUFFER,
|
|
|
|
// indices buffers
|
|
INDICES_BUFFER,
|
|
|
|
// optionnal buffers :
|
|
NORMAL_BUFFER,
|
|
TEXCOORD_BUFFER,
|
|
TANGENT_BUFFER,
|
|
|
|
// instanciation buffer
|
|
INSTANCE_BUFFER,
|
|
|
|
NB_BUFFERS
|
|
};
|
|
|
|
int buffersId[NB_BUFFERS];
|
|
|
|
void addBuffer(Buffer *b, int bufferType);
|
|
void clearBuffers();
|
|
|
|
GLuint vao;
|
|
};
|
|
|
|
#endif // MESH_H
|