updated parametric mesh
This commit is contained in:
parent
72466f7ef7
commit
d41476226c
@ -5,11 +5,50 @@
|
||||
#define M_PI 3.14159265358979323846
|
||||
#define MAGIC_RATIO 0.37139f
|
||||
|
||||
Sphere::Sphere(Material* mat, int n, float myRadius) :
|
||||
radius(myRadius)
|
||||
Mesh* MeshGenerator::generateParametricMesh(Material* mat, int width, int height, float size, bool alternate)
|
||||
{
|
||||
setMaterial(mat);
|
||||
m_size = size;
|
||||
m_mesh = new 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();
|
||||
m_mesh->setMaterial(mat);
|
||||
|
||||
// icosahedron :
|
||||
|
||||
// top cap
|
||||
@ -28,23 +67,27 @@ Sphere::Sphere(Material* mat, int n, float myRadius) :
|
||||
int bottom = 7;
|
||||
int offset = (i+1)%5;
|
||||
// top cap
|
||||
addTriangle(0, top+i, top+offset);
|
||||
m_mesh->addTriangle(0, top+i, top+offset);
|
||||
// bottom cap
|
||||
addTriangle(6, bottom+offset, bottom+i);
|
||||
m_mesh->addTriangle(6, bottom+offset, bottom+i);
|
||||
// middle ribbon
|
||||
addTriangle(top+i, bottom+i, top+offset);
|
||||
addTriangle(top+offset, bottom+i, bottom+offset);
|
||||
m_mesh->addTriangle(top+i, bottom+i, top+offset);
|
||||
m_mesh->addTriangle(top+offset, bottom+i, bottom+offset);
|
||||
}
|
||||
|
||||
// geodesic subdivisions :
|
||||
for(int i=0; i<n; i++)
|
||||
subdivide();
|
||||
|
||||
for(glm::vec3 &vertex : positions3D)
|
||||
vertex *= radius;
|
||||
|
||||
return m_mesh;
|
||||
}
|
||||
|
||||
int Sphere::getEdge(int a, int b)
|
||||
void MeshGenerator::createVertex(float u, float v)
|
||||
{
|
||||
m_mesh->addVertex(evalUV(u, v)*m_size, glm::vec2(u, v));
|
||||
}
|
||||
|
||||
int MeshGenerator::getEdge(int a, int b)
|
||||
{
|
||||
Edge* current = edges+a;
|
||||
int vid = -1;
|
||||
@ -54,16 +97,14 @@ int Sphere::getEdge(int a, int b)
|
||||
vid = current->vertex;
|
||||
else if(current->next == NULL)
|
||||
{
|
||||
vid = positions3D.size();
|
||||
vid = m_mesh->positions3D.size();
|
||||
// creating subdivision vertex
|
||||
glm::vec3 pos = glm::normalize(positions3D[a] + positions3D[b] / 2.f);
|
||||
addPosition(pos);
|
||||
addNormal(pos);
|
||||
glm::vec3 pos = glm::normalize(m_mesh->positions3D[a] + m_mesh->positions3D[b] / 2.f);
|
||||
|
||||
// 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);
|
||||
createVertex(newU - floor(newU), newV);
|
||||
// alternative, u/v moyennés :
|
||||
//v.texCoord = (v0.texCoord + v1.texCoord)/2.f;
|
||||
|
||||
@ -82,77 +123,30 @@ int Sphere::getEdge(int a, int b)
|
||||
return vid;
|
||||
}
|
||||
|
||||
void Sphere::subdivide()
|
||||
void MeshGenerator::subdivide()
|
||||
{
|
||||
edges = new Edge[positions3D.size()-1];
|
||||
int nb_triangles = indices.size()/3;
|
||||
edges = new Edge[m_mesh->positions3D.size()-1];
|
||||
int nb_triangles = m_mesh->indices.size()/3;
|
||||
for(int j=0; j<nb_triangles; j++)
|
||||
{
|
||||
int vid[3];
|
||||
for(int k=0; k<3; k++)
|
||||
{
|
||||
int idA = indices[j*3 + k];
|
||||
int idB = indices[j*3 + (k+1)%3];
|
||||
int idA = m_mesh->indices[j*3 + k];
|
||||
int idB = m_mesh->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(indices[j*3 + k], vid[k], vid[(k+2)%3]);
|
||||
addTriangle(vid[0], vid[1], vid[2]);
|
||||
m_mesh->addTriangle(m_mesh->indices[j*3 + k], vid[k], vid[(k+2)%3]);
|
||||
m_mesh->addTriangle(vid[0], vid[1], vid[2]);
|
||||
}
|
||||
delete[](edges);
|
||||
indices.erase(indices.begin(), indices.begin()+nb_triangles*3);
|
||||
m_mesh->indices.erase(m_mesh->indices.begin(), m_mesh->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)
|
||||
{
|
||||
setMaterial(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)
|
||||
int MeshGenerator::getVertexId(int i, int j, int height)
|
||||
{
|
||||
return i*(height+1) + j;
|
||||
}
|
||||
|
@ -1,11 +1,27 @@
|
||||
#ifndef PARAMETRIC_MESH_H
|
||||
#define PARAMETRIC_MESH_H
|
||||
|
||||
#include "meshbuilder.h"
|
||||
#include "mesh.h"
|
||||
|
||||
class Sphere : public MeshBuilder
|
||||
class MeshGenerator
|
||||
{
|
||||
public:
|
||||
virtual glm::vec3 evalUV(float u, float v) = 0;
|
||||
|
||||
/**
|
||||
* @brief generateParametricMesh creates a mesh from a rectangular grid of size width:height
|
||||
*/
|
||||
Mesh* generateParametricMesh(Material* mat, int width = 10, int height = 10, float size = 1, bool alternate = true);
|
||||
|
||||
/**
|
||||
* @brief generateGeodesicMesh creates a closed mesh from an icosahedron subdivided n times
|
||||
*/
|
||||
Mesh* generateGeodesicMesh(Material* mat, int n = 0, float size = 1);
|
||||
private:
|
||||
float m_size;
|
||||
Mesh *m_mesh;
|
||||
|
||||
// geodesic methods
|
||||
class Edge{
|
||||
public:
|
||||
int b;
|
||||
@ -20,23 +36,59 @@ private:
|
||||
};
|
||||
|
||||
Edge* edges;
|
||||
float radius;
|
||||
|
||||
int getEdge(int a, int b);
|
||||
void createVertex(float u, float v);
|
||||
void subdivide();
|
||||
public:
|
||||
Sphere(Material* mat, int n = 0, float myRadius = 1.f);
|
||||
};
|
||||
|
||||
class GridMesh : public MeshBuilder
|
||||
{
|
||||
public:
|
||||
GridMesh(Material* mat, int width, int height, bool alternate = true);
|
||||
private:
|
||||
|
||||
// parametric methods
|
||||
int getVertexId(int i, int j, int height);
|
||||
};
|
||||
|
||||
// TODO TextMesh (with glyph map)
|
||||
// here are some basic implementations of parametric mesh generators
|
||||
|
||||
/**
|
||||
* @brief The GridGenerator class is the simplest parametric mesh, a uniform mapped grid
|
||||
*/
|
||||
class GridGenerator : public MeshGenerator
|
||||
{
|
||||
public:
|
||||
virtual glm::vec3 evalUV(float u, float v)
|
||||
{return glm::vec3(u-0.5f, 0, v-0.5f);}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The CylinderGenerator class creates a vertical open cylinder
|
||||
*/
|
||||
class CylinderGenerator : public MeshGenerator
|
||||
{
|
||||
public:
|
||||
virtual glm::vec3 evalUV(float u, float v)
|
||||
{return glm::vec3(cos(u*6.2832f), v-0.5f, sin(u*6.2832f));}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The ConeGenerator class creates an open cone pointing down
|
||||
*/
|
||||
class ConeGenerator : public MeshGenerator
|
||||
{
|
||||
public:
|
||||
virtual glm::vec3 evalUV(float u, float v)
|
||||
{return glm::vec3(cos(u*6.2832f)*v, v, sin(u*6.2832f)*v);}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The SphereGenerator class creates a sphere uv-mapped like a planisphere
|
||||
* it is recommended to use a grid where the width value is twice the value of height
|
||||
*/
|
||||
class SphereGenerator : public MeshGenerator
|
||||
{
|
||||
public:
|
||||
virtual glm::vec3 evalUV(float u, float v)
|
||||
{
|
||||
float r = sin(v*3.1416f);
|
||||
return glm::vec3(cos(u*6.2832f)*r, cos(v*3.1416f), sin(u*6.2832f)*r);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // PARAMETRIC_MESH_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user