#include "parametricmesh.h" #include "glm/ext.hpp" #include "pbrmaterial.h" #define M_PI 3.14159265358979323846 #define MAGIC_RATIO 0.37139f Mesh* MeshGenerator::generateParametricMesh(Material* mat, int width, int height, float size, bool alternate) { m_size = size; m_mesh = new Mesh("parametric_mesh"); m_mesh->setMaterial(mat); for(int i=0; i<=width; ++i) { for(int j=0; j<=height; ++j) { createVertex(float(i)/float(width), float(j)/float(height)); if(i > 0 && j > 0) { if(alternate && (i+j)%2) { m_mesh->addTriangle(getVertexId(i, j, height), getVertexId(i, j-1, height), getVertexId(i-1, j, height)); m_mesh->addTriangle(getVertexId(i-1, j-1, height), getVertexId(i-1, j, height), getVertexId(i, j-1, height)); } else { m_mesh->addTriangle(getVertexId(i, j, height), getVertexId(i-1, j-1, height), getVertexId(i-1, j, height)); m_mesh->addTriangle(getVertexId(i, j, height), getVertexId(i, j-1, height), getVertexId(i-1, j-1, height)); } } } } return m_mesh; } Mesh* MeshGenerator::generateGeodesicMesh(Material* mat, int n, float size) { m_size = size; m_mesh = new Mesh("geodesic_mesh"); m_mesh->setMaterial(mat); // icosahedron : // 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 m_mesh->addTriangle(0, top+offset, top+i); // bottom cap m_mesh->addTriangle(6, bottom+i, bottom+offset); // middle ribbon m_mesh->addTriangle(top+i, top+offset, bottom+i); m_mesh->addTriangle(top+offset, bottom+offset, bottom+i); } // geodesic subdivisions : for(int i=0; iaddVertex(evalUV(u, v)*m_size, glm::vec2(u, v)); } int MeshGenerator::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 = m_mesh->m_positions3D.size(); // creating subdivision vertex // u/v sphériques, cohérents sur toute la sphère sauf des artefacts au niveau des u==0 glm::vec3 pos = glm::normalize((m_mesh->m_positions3D[a] + m_mesh->m_positions3D[b]) / 2.f); float newU = (pos.x < 0 ? 1.5f : 1.f) + atan(pos.z/pos.x)/(2*M_PI); float newV = acos(pos.y)/M_PI; // alternative, u/v moyennés : /*float newU = (m_mesh->texCoords[a].x + m_mesh->texCoords[b].x) / 2.f; float newV = (m_mesh->texCoords[a].y + m_mesh->texCoords[b].y) / 2.f;*/ createVertex(-(newU - floor(newU)), newV); // 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 MeshGenerator::subdivide() { edges = new Edge[m_mesh->m_positions3D.size()-1]; int nb_triangles = m_mesh->m_indices.size()/3; for(int j=0; jm_indices[j*3 + k]; int idB = m_mesh->m_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++) m_mesh->addTriangle(m_mesh->m_indices[j*3 + k], vid[k], vid[(k+2)%3]); m_mesh->addTriangle(vid[0], vid[1], vid[2]); } delete[](edges); m_mesh->m_indices.erase(m_mesh->m_indices.begin(), m_mesh->m_indices.begin()+nb_triangles*3); } int MeshGenerator::getVertexId(int i, int j, int height) { return i*(height+1) + j; }