sphere and grid are now in the same file : parametricmesh

This commit is contained in:
Anselme 2015-10-13 22:46:57 +02:00
parent 124ef6ec2e
commit 9c2c8315b0
10 changed files with 222 additions and 196 deletions

View File

@ -15,8 +15,7 @@ set(LIB_SRC_LIST
asciientity.cpp
asciimodule.cpp
framebuffer.cpp
gbuffermodule.cpp
gridmesh.cpp
gbuffermodule.cpp
lights.cpp
meshbuilder.cpp
phongentity.cpp
@ -25,7 +24,7 @@ set(LIB_SRC_LIST
shader.cpp
skyboxmodule.cpp
sparrowrenderer.cpp
sphere.cpp
parametricmesh.cpp
texture.cpp
)

View File

@ -1,43 +0,0 @@
#include "gridmesh.h"
GridMesh::GridMesh(Material* mat, int width, int height, bool alternate)
{
addGroup(mat);
for(int i=0; i<=width; ++i)
{
for(int j=0; j<=height; ++j)
{
float x = (float)i/(float)width;
float y = (float)j/(float)height;
addPosition(x-0.5f, 0, y-0.5f);
addNormal(0, 1, 0);
addTexCoord(x, y);
if(i > 0 && j > 0)
{
if(alternate && (i+j)%2)
{
addTriangle(getVertexId(i, j, height),
getVertexId(i, j-1, height),
getVertexId(i-1, j, height));
addTriangle(getVertexId(i-1, j-1, height),
getVertexId(i-1, j, height),
getVertexId(i, j-1, height));
}
else
{
addTriangle(getVertexId(i, j, height),
getVertexId(i-1, j-1, height),
getVertexId(i-1, j, height));
addTriangle(getVertexId(i, j, height),
getVertexId(i, j-1, height),
getVertexId(i-1, j-1, height));
}
}
}
}
}
int GridMesh::getVertexId(int i, int j, int height)
{
return i*(height+1) + j;
}

View File

@ -1,14 +0,0 @@
#ifndef GRIDMESH_H
#define GRIDMESH_H
#include "meshbuilder.h"
class GridMesh : public MeshBuilder
{
public:
GridMesh(Material* mat, int width, int height, bool alternate = true);
private:
int getVertexId(int i, int j, int height);
};
#endif // GRIDMESH_H

3
mesh.h
View File

@ -7,9 +7,8 @@
class Material;
class Mesh
struct Mesh
{
public:
typedef struct
{
glm::vec3 tangent;

154
parametricmesh.cpp Normal file
View File

@ -0,0 +1,154 @@
#include "parametricmesh.h"
#include "glm/ext.hpp"
#include "phongmaterial.h"
#define M_PI 3.14159265358979323846
#define MAGIC_RATIO 0.37139f
Sphere::Sphere(Material* mat, int n)
{
// icosahedron :
addGroup(mat);
Group* group = &(indiceGroups[0]);
// top cap
createVertex(0, 1);
for(int i=0; i<5; i++)
createVertex(i/5.f, 1-MAGIC_RATIO);
// bottom cap
createVertex(0, 0);
for(int i=0; i<5; i++)
createVertex((i+0.5f)/5.f, MAGIC_RATIO);
// Compute faces
for(int i=0; i<5; i++){
int top = 1;
int bottom = 7;
int offset = (i+1)%5;
// top cap
addTriangle(0, top+i, top+offset);
// bottom cap
addTriangle(6, bottom+offset, bottom+i);
// middle ribbon
addTriangle(top+i, bottom+i, top+offset);
addTriangle(top+offset, bottom+i, bottom+offset);
}
// geodesic subdivisions :
for(int i=0; i<n; i++)
subdivide(group);
}
int Sphere::getEdge(int a, int b)
{
Edge* current = edges+a;
int vid = -1;
while(vid == -1)
{
if(current->b == b)
vid = current->vertex;
else if(current->next == NULL)
{
vid = positions.size();
// creating subdivision vertex
glm::vec3 pos = glm::normalize(positions[a] + positions[b] / 2.f);
addPosition(pos);
addNormal(pos);
// u/v sphériques, cohérents sur toute la sphère sauf des artefacts au niveau des u==0
float newU = (pos.x < 0 ? 1.5f : 1.f) + atan(pos.z/pos.x)/(2*M_PI);
float newV = acos(pos.y)/M_PI;
addTexCoord(newU - floor(newU), newV);
// alternative, u/v moyennés :
//v.texCoord = (v0.texCoord + v1.texCoord)/2.f;
// inserting the new vertex in the edge collection
if(current->b == -1)
{
current->vertex = vid;
current->b = b;
}
else
current->next = new Edge(b, vid);
}
else
current = current->next;
}
return vid;
}
void Sphere::subdivide(Group* group)
{
edges = new Edge[positions.size()-1];
int nb_triangles = group->indices.size()/3;
for(int j=0; j<nb_triangles; j++)
{
int vid[3];
for(int k=0; k<3; k++)
{
int idA = group->indices[j*3 + k];
int idB = group->indices[j*3 + (k+1)%3];
int a = idA < idB ? idA : idB;
int b = idA > idB ? idA : idB;
vid[k] = getEdge(a, b);
}
for(int k=0; k<3; k++)
addTriangle(group->indices[j*3 + k], vid[k], vid[(k+2)%3]);
addTriangle(vid[0], vid[1], vid[2]);
}
delete[](edges);
group->indices.erase(group->indices.begin(), group->indices.begin()+nb_triangles*3);
}
void Sphere::createVertex(float u, float v)
{
glm::vec3 pos(cos(u*2*M_PI)*sin(v*M_PI),
cos(v*M_PI),
sin(u*2*M_PI)*sin(v*M_PI));
addPosition(pos);
addNormal(pos);
addTexCoord(u, v);
}
GridMesh::GridMesh(Material* mat, int width, int height, bool alternate)
{
addGroup(mat);
for(int i=0; i<=width; ++i)
{
for(int j=0; j<=height; ++j)
{
float x = (float)i/(float)width;
float y = (float)j/(float)height;
addPosition(x-0.5f, 0, y-0.5f);
addNormal(0, 1, 0);
addTexCoord(x, y);
if(i > 0 && j > 0)
{
if(alternate && (i+j)%2)
{
addTriangle(getVertexId(i, j, height),
getVertexId(i, j-1, height),
getVertexId(i-1, j, height));
addTriangle(getVertexId(i-1, j-1, height),
getVertexId(i-1, j, height),
getVertexId(i, j-1, height));
}
else
{
addTriangle(getVertexId(i, j, height),
getVertexId(i-1, j-1, height),
getVertexId(i-1, j, height));
addTriangle(getVertexId(i, j, height),
getVertexId(i, j-1, height),
getVertexId(i-1, j-1, height));
}
}
}
}
}
int GridMesh::getVertexId(int i, int j, int height)
{
return i*(height+1) + j;
}

38
parametricmesh.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef PARAMETRIC_MESH_H
#define PARAMETRIC_MESH_H
#include "meshbuilder.h"
class Sphere : public MeshBuilder
{
private:
class Edge{
public:
int b;
int vertex;
Edge* next;
Edge(int myB = -1, int myVertex = -1) :
b(myB),
vertex(myVertex),
next(NULL)
{}
~Edge(){ if(next != NULL) delete(next); }
};
Edge* edges;
int getEdge(int a, int b);
void createVertex(float u, float v);
void subdivide(Group* group);
public:
Sphere(Material* mat, int n = 0);
};
class GridMesh : public MeshBuilder
{
public:
GridMesh(Material* mat, int width, int height, bool alternate = true);
private:
int getVertexId(int i, int j, int height);
};
#endif // PARAMETRIC_MESH_H

View File

@ -9,7 +9,14 @@
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
PhongEntity::PhongEntity(Mesh* myMesh) : mesh(myMesh) {}
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)
{
@ -143,6 +150,7 @@ void PhongEntity::destroyGL()
glAssert(glDeleteVertexArrays(1, &vao));
glAssert(glDeleteBuffers(nb_buffers, vbo));
delete[] vbo;
vbo = NULL;
}
else
glAssert(glDeleteLists(displayList, 1));
@ -177,3 +185,12 @@ void PhongEntity::drawGroup(int groupId)
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;
}

View File

@ -42,6 +42,9 @@ protected:
void crappyDraw(const glm::mat4 &viewMatrix, const glm::mat4 &projectionMatrix, Lights::Light* dirLight, Lights* pointLights);
public:
/**
* @brief the model matrix is public, so the user can manipulate it in any way he desires.
*/
glm::mat4 modelMatrix;
PhongEntity(Mesh* myMesh);
@ -52,6 +55,12 @@ public:
void destroyGL();
Mesh* getMesh() {return mesh;}
/**
* @brief this method returns a clone of the current entity.
* The same VAO will be used to render both, so there is no need to call initGL on the clone
*/
PhongEntity* clone();
};
#endif // PHONGENTITY_H

View File

@ -1,108 +0,0 @@
#include "sphere.h"
#include "glm/ext.hpp"
#include "phongmaterial.h"
#define M_PI 3.14159265358979323846
#define MAGIC_RATIO 0.37139f
Sphere::Sphere(Material* mat, int n)
{
// icosahedron :
addGroup(mat);
Group* group = &(indiceGroups[0]);
// top cap
createVertex(0, 1);
for(int i=0; i<5; i++)
createVertex(i/5.f, 1-MAGIC_RATIO);
// bottom cap
createVertex(0, 0);
for(int i=0; i<5; i++)
createVertex((i+0.5f)/5.f, MAGIC_RATIO);
// Compute faces
for(int i=0; i<5; i++){
int top = 1;
int bottom = 7;
int offset = (i+1)%5;
// top cap
addTriangle(0, top+i, top+offset);
// bottom cap
addTriangle(6, bottom+offset, bottom+i);
// middle ribbon
addTriangle(top+i, bottom+i, top+offset);
addTriangle(top+offset, bottom+i, bottom+offset);
}
// geodesic subdivisions :
for(int i=0; i<n; i++){
edges = new Edge[positions.size()-1];
int nb_triangles = group->indices.size()/3;
for(int j=0; j<nb_triangles; j++)
{
int vid[3];
for(int k=0; k<3; k++)
{
int idA = group->indices[j*3 + k];
int idB = group->indices[j*3 + (k+1)%3];
int a = idA < idB ? idA : idB;
int b = idA > idB ? idA : idB;
vid[k] = getEdge(a, b);
}
for(int k=0; k<3; k++)
addTriangle(group->indices[j*3 + k], vid[k], vid[(k+2)%3]);
addTriangle(vid[0], vid[1], vid[2]);
}
delete[](edges);
group->indices.erase(group->indices.begin(), group->indices.begin()+nb_triangles*3);
}
}
int Sphere::getEdge(int a, int b)
{
Edge* current = edges+a;
int vid = -1;
while(vid == -1)
{
if(current->b == b)
vid = current->vertex;
else if(current->next == NULL)
{
vid = positions.size();
// creating subdivision vertex
glm::vec3 pos = glm::normalize(positions[a] + positions[b] / 2.f);
addPosition(pos);
addNormal(pos);
// u/v sphériques, cohérents sur toute la sphère sauf des artefacts au niveau des u==0
float newU = (pos.x < 0 ? 1.5f : 1.f) + atan(pos.z/pos.x)/(2*M_PI);
float newV = acos(pos.y)/M_PI;
addTexCoord(newU - floor(newU), newV);
// alternative, u/v moyennés :
//v.texCoord = (v0.texCoord + v1.texCoord)/2.f;
// inserting the new vertex in the edge collection
if(current->b == -1)
{
current->vertex = vid;
current->b = b;
}
else
current->next = new Edge(b, vid);
}
else
current = current->next;
}
return vid;
}
void Sphere::createVertex(float u, float v)
{
glm::vec3 pos(cos(u*2*M_PI)*sin(v*M_PI),
cos(v*M_PI),
sin(u*2*M_PI)*sin(v*M_PI));
addPosition(pos);
addNormal(pos);
addTexCoord(u, v);
}

View File

@ -1,25 +0,0 @@
#ifndef SPHERE_H
#define SPHERE_H
#include "meshbuilder.h"
class Sphere : public MeshBuilder
{
private:
class Edge{
public:
int b;
int vertex;
Edge* next;
Edge(int myB = -1, int myVertex = -1):b(myB),vertex(myVertex),next(NULL){}
~Edge(){ if(next != NULL) delete(next); }
};
Edge* edges;
int getEdge(int a, int b);
void createVertex(float u, float v);
public:
Sphere(Material* mat, int n = 0);
};
#endif // SPHERE_H