Flawless BSpline 1D
This commit is contained in:
parent
060aaeb0bf
commit
6c39ee710a
292
src/bspline.cpp
292
src/bspline.cpp
|
@ -1,97 +1,231 @@
|
|||
#include "bspline.h"
|
||||
#include <cmath>
|
||||
|
||||
BSpline::BSpline(int k, double step, int np1)
|
||||
BSpline::BSpline(
|
||||
ESpline typeSpline,
|
||||
int k,
|
||||
EPolygone typePolygone,
|
||||
EVecteurNodal typeVecteur,
|
||||
int nbPtsCtrlX,
|
||||
int nbPtsCtrlZ,
|
||||
float stepX,
|
||||
float stepY)
|
||||
{
|
||||
// Simple vérification
|
||||
switch (typeSpline) {
|
||||
case ESpline::SPLINE1D:
|
||||
assert(k <= nbPtsCtrlX);
|
||||
break;
|
||||
case ESpline::SPLINE2D:
|
||||
assert(k <= nbPtsCtrlX && k <= nbPtsCtrlZ);
|
||||
break;
|
||||
}
|
||||
|
||||
// Initialisation des valeurs
|
||||
// Ordre k = 2
|
||||
_k = k;
|
||||
_step = step;
|
||||
_np1 = np1;
|
||||
// Vecteur Nodal Uniforme de np1 valeurs
|
||||
for(int i = 0; i < k+np1; ++i)
|
||||
_vecteurNodal.push_back(i);
|
||||
// Points de contrôle
|
||||
_stepX = stepX;
|
||||
_stepY = stepY;
|
||||
srand(time(NULL));
|
||||
|
||||
// Génération du polygone de contrôle
|
||||
construirePolygone(typePolygone, nbPtsCtrlX, nbPtsCtrlZ);
|
||||
|
||||
// Calcul du vecteur nodal de nbPtsCtrl valeurs
|
||||
construireVecteurNodal(typeVecteur);
|
||||
switch (typeSpline) {
|
||||
case ESpline::SPLINE1D:
|
||||
calculerSpline1D();
|
||||
break;
|
||||
case ESpline::SPLINE2D:
|
||||
calculerSpline2D();
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Type de spline inconnu" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BSpline::calculerSpline1D()
|
||||
{
|
||||
// Init
|
||||
int dec = 0, m = _k - 1;
|
||||
uint i = 0;
|
||||
double u = 0;
|
||||
std::vector<glm::vec3> vecteursPointsControle (_nbPtsCtrlX);
|
||||
|
||||
// Parcours de u
|
||||
for(u = _vecteurNodal[m]; u <= _vecteurNodal[_nbPtsCtrlX]; u += _stepX){
|
||||
dec = 0;
|
||||
// Calcul du décalage
|
||||
for(int i = _k; u > _vecteurNodal[i]; ++i)
|
||||
++dec;
|
||||
|
||||
// Récupération des k points de contrôles nécessaires à la floraison
|
||||
for(int i = 0; i < _k; i++){
|
||||
vecteursPointsControle[i] = _pointsDeControle[dec + i];
|
||||
}
|
||||
|
||||
// Appel de la floraison récursive
|
||||
glm::vec3 newVertex = floraison(u, dec, _k, vecteursPointsControle);
|
||||
|
||||
// Sauvegardes des paramètres de la B-spline
|
||||
_vertices.insert(_vertices.end(), {newVertex.x, newVertex.y, newVertex.z});
|
||||
_normals.insert(_normals.end(), {1, -1, -1});
|
||||
_indices.insert(_indices.end(), {i, i, ++i});
|
||||
}
|
||||
|
||||
// Enlever la ligne d'indices en trop
|
||||
for(int i = 0; i < 3; ++i)
|
||||
_indices.pop_back();
|
||||
|
||||
// Ajouter le polygone de controle aux vecteurs
|
||||
for(unsigned int i = 0; i < _pointsDeControle.size(); ++i) {
|
||||
_indices.insert(_indices.end(), {static_cast<unsigned int>(_vertices.size())/3, static_cast<unsigned int>(_vertices.size()/3), static_cast<unsigned int>(_vertices.size())/3+1});
|
||||
_vertices.insert(_vertices.end(), {_pointsDeControle[i].x, _pointsDeControle[i].y, _pointsDeControle[i].z});
|
||||
_normals.insert(_normals.end(), {0, 0, 0});
|
||||
}
|
||||
|
||||
// Enlever la ligne d'indices en trop
|
||||
for(int i = 0; i < 3; ++i)
|
||||
_indices.pop_back();
|
||||
}
|
||||
|
||||
|
||||
void BSpline::calculerSpline2D()
|
||||
{
|
||||
}
|
||||
|
||||
glm::vec3 BSpline::floraison(float u, int dec, int k, std::vector<glm::vec3> vecteursPointsControle)
|
||||
{
|
||||
if(k <= 1)
|
||||
return vecteursPointsControle.front();
|
||||
|
||||
for(int i = 0; i < k - 1; ++i) {
|
||||
float max = _vecteurNodal[dec + k + i];
|
||||
float min = _vecteurNodal[dec + 1 + i];
|
||||
vecteursPointsControle[i] =
|
||||
((( max - u) / (max - min)) * vecteursPointsControle[i]) +
|
||||
((( u - min) / (max - min)) * vecteursPointsControle[i+1]);
|
||||
}
|
||||
|
||||
return floraison(u, dec+1, k-1, vecteursPointsControle);
|
||||
}
|
||||
|
||||
void BSpline::construirePolygone(EPolygone typePolygone, int nbPtsCtrlX, int nbPtsCtrlZ)
|
||||
{
|
||||
// Intervalle pour afficher dans le repère caméra
|
||||
float xMin = -3, xMax = 3;
|
||||
float yMin = -2, yMax = 2;
|
||||
float zMin = -3, zMax = -6;
|
||||
|
||||
switch (typePolygone) {
|
||||
case EPolygone::FIXE2D:
|
||||
_pointsDeControle.push_back(glm::vec3(-2, 0, -5));
|
||||
_pointsDeControle.push_back(glm::vec3(-1, 0, -5));
|
||||
_pointsDeControle.push_back(glm::vec3(-1, 1, -5));
|
||||
_pointsDeControle.push_back(glm::vec3( 1, 1, -5));
|
||||
_pointsDeControle.push_back(glm::vec3( 1, 0, -5));
|
||||
_pointsDeControle.push_back(glm::vec3( 2, 0, -5));
|
||||
_nbPtsCtrlX = 6;
|
||||
_nbPtsCtrlZ = 0;
|
||||
break;
|
||||
|
||||
computeSpline();
|
||||
case EPolygone::RANDOM2D: {
|
||||
float x, y, z;
|
||||
for(int i = 0; i < nbPtsCtrlX; ++i) {
|
||||
//x = xMin + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(xMax-xMin)));
|
||||
x = (i * xMin + (nbPtsCtrlX - i) * xMax) / (xMax - xMin);
|
||||
y = yMin + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(yMax-yMin)));
|
||||
z = zMin + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(zMax-zMin)));
|
||||
_pointsDeControle.push_back(glm::vec3(x, y, z));
|
||||
}
|
||||
_nbPtsCtrlX = _pointsDeControle.size();
|
||||
_nbPtsCtrlZ = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
void BSpline::computeSpline()
|
||||
case EPolygone::GAUSSIEN3D: {
|
||||
// Sigma = 1.0f
|
||||
float r, s = 2.0f;
|
||||
for(int x = - (nbPtsCtrlX / 2) + 1; x < nbPtsCtrlX / 2; ++x) {
|
||||
for(int z = - (nbPtsCtrlZ / 2) + 1; x < nbPtsCtrlZ / 2; ++x) {
|
||||
r = sqrt(x * x + z * z);
|
||||
_pointsDeControle.push_back(glm::vec3( x, (exp(-(r * r) / s)) / (M_PI * s), z));
|
||||
}
|
||||
}
|
||||
_nbPtsCtrlX = nbPtsCtrlX - 1 - (nbPtsCtrlX % 2);
|
||||
_nbPtsCtrlZ = nbPtsCtrlZ - 1 - (nbPtsCtrlZ % 2);
|
||||
break;
|
||||
}
|
||||
|
||||
case EPolygone::FIXE3D: {
|
||||
float x, y, z;
|
||||
for(int i = 0; i < nbPtsCtrlX; ++i) {
|
||||
for(int j = 0; j < nbPtsCtrlZ; ++j) {
|
||||
x = (i * xMin + (nbPtsCtrlX - i) * xMax) / (xMax - xMin);
|
||||
y = fmod(x + z, 3);
|
||||
z = (j * zMin + (nbPtsCtrlZ - j) * zMax) / (zMax - zMin);
|
||||
_pointsDeControle.push_back(glm::vec3(x, y, z));
|
||||
}
|
||||
}
|
||||
_nbPtsCtrlX = nbPtsCtrlX;
|
||||
_nbPtsCtrlZ = nbPtsCtrlZ;
|
||||
break;
|
||||
}
|
||||
|
||||
case EPolygone::RANDOM3D: {
|
||||
float x, y, z;
|
||||
for(int i = 0; i < nbPtsCtrlX; ++i) {
|
||||
for(int j = 0; j < nbPtsCtrlZ; ++i) {
|
||||
x = (i * xMin + (nbPtsCtrlX - i) * xMax) / (xMax - xMin);
|
||||
y = yMin + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(yMax-yMin)));
|
||||
z = (j * zMin + (nbPtsCtrlZ - j) * zMax) / (zMax - zMin);
|
||||
_pointsDeControle.push_back(glm::vec3(x, y, z));
|
||||
}
|
||||
}
|
||||
_nbPtsCtrlX = nbPtsCtrlX;
|
||||
_nbPtsCtrlZ = nbPtsCtrlZ;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
std::cerr << "Type de polygone inconnu" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BSpline::construireVecteurNodal(EVecteurNodal typeVecteur)
|
||||
{
|
||||
// Init
|
||||
int dec = 0, i = _k;
|
||||
double u = 0;
|
||||
|
||||
std::vector<glm::vec3> vecteursPointsControle (_np1);
|
||||
|
||||
for(u = _k - 1; u < _np1; u += _step){
|
||||
// Réinitialiser dec et i ?
|
||||
while(u > _vecteurNodal[i]){
|
||||
++dec;
|
||||
++i;
|
||||
switch (typeVecteur) {
|
||||
case EVecteurNodal::UNIFORME:
|
||||
for(int i = 0; i <= _k + _nbPtsCtrlX; ++i) {
|
||||
_vecteurNodal.push_back(i);
|
||||
}
|
||||
break;
|
||||
case EVecteurNodal::OUVERTUNIFORME:
|
||||
for(int i = 0; i <= _k + _nbPtsCtrlX; ++i) {
|
||||
if (i < _k)
|
||||
_vecteurNodal.push_back(0);
|
||||
else if (i > _nbPtsCtrlX)
|
||||
_vecteurNodal.push_back(_nbPtsCtrlX - _k + 1);
|
||||
else
|
||||
_vecteurNodal.push_back(i - _k + 1);
|
||||
std::cout << _vecteurNodal.back() << " ";
|
||||
}
|
||||
break;
|
||||
case EVecteurNodal::QUELCONQUE: {
|
||||
int r = 0;
|
||||
_vecteurNodal.push_back(0);
|
||||
for(int i = 1; i <= _k + _nbPtsCtrlX; ++i) {
|
||||
r = rand() / (RAND_MAX/5);
|
||||
_vecteurNodal.push_back(_vecteurNodal.back() + r);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
std::cerr << "Type de vecteur nodal inconnu" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// int i à virer ?
|
||||
for(int i = 0; i < _k; i++){
|
||||
vecteursPointsControle[i] = _pointsDeControle[dec + i];
|
||||
}
|
||||
|
||||
glm::vec3 newVertex = floraison(u, dec, _k, vecteursPointsControle);
|
||||
//std::cout << newVertex.x << " " << newVertex.y << " " << newVertex.z << std::endl;
|
||||
_vertices.push_back(newVertex);
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 BSpline::floraison(float u, int dec, int k, std::vector<glm::vec3> vecteursPointsControle)
|
||||
{
|
||||
if(k == 0)
|
||||
return vecteursPointsControle.front();
|
||||
for(int i = 0; i < k - 1; ++i)
|
||||
vecteursPointsControle[i] =
|
||||
(((_vecteurNodal[dec + k + i] - u) / (_vecteurNodal[dec + k + i] - _vecteurNodal[dec + 1 + i])) * vecteursPointsControle[i]) *
|
||||
(((u - _vecteurNodal[dec + 1 + i]) / (_vecteurNodal[dec + k + i] - _vecteurNodal[dec + 1 + i])) * vecteursPointsControle[i+1]);
|
||||
floraison(u, dec+1, k-1, vecteursPointsControle);
|
||||
}
|
||||
|
||||
std::vector<GLfloat> const BSpline::getVertices()
|
||||
{
|
||||
std::vector<GLfloat> vertices;
|
||||
// Ajout des points de contrôle
|
||||
for(glm::vec3 point: _pointsDeControle)
|
||||
vertices.insert(vertices.end(), {point.x, point.y, point.z});
|
||||
|
||||
// Ajout des points issus de la floraison
|
||||
for(glm::vec3 point: _vertices)
|
||||
vertices.insert(vertices.end(), {point.x, point.y, point.z});
|
||||
|
||||
return vertices;
|
||||
}
|
||||
|
||||
std::vector<GLfloat> const BSpline::getNormals()
|
||||
{
|
||||
std::vector<GLfloat> normals;
|
||||
for(glm::vec3 point: _pointsDeControle)
|
||||
normals.insert(normals.end(), {point.x, point.y, point.z});
|
||||
// Ajout des normales des points issus de la floraison
|
||||
for(glm::vec3 point: _vertices)
|
||||
normals.insert(normals.end(), {point.x, point.y, point.z});
|
||||
|
||||
return normals;
|
||||
}
|
||||
|
||||
std::vector<GLuint> const BSpline::getIndices()
|
||||
{
|
||||
std::vector<GLuint> indices;
|
||||
for(uint i = 0; i < _pointsDeControle.size() - 1; ++i)
|
||||
indices.insert(indices.end(), {i, i, i+1});
|
||||
// Ajout des indices pour les points issus de la floraison
|
||||
for(uint i = 0; i < _vertices.size() - 1; ++i)
|
||||
indices.insert(indices.end(), {i, i, i+1});
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
|
|
@ -7,22 +7,53 @@
|
|||
|
||||
class BSpline
|
||||
{
|
||||
|
||||
public:
|
||||
BSpline(int k = 2, double step = 0.1, int np1 = 6);
|
||||
std::vector<GLfloat> const getVertices();
|
||||
std::vector<GLfloat> const getNormals();
|
||||
std::vector<GLuint> const getIndices();
|
||||
enum class ESpline {SPLINE1D, SPLINE2D};
|
||||
enum class EPolygone {FIXE2D, RANDOM2D, GAUSSIEN3D, FIXE3D, RANDOM3D};
|
||||
enum class EVecteurNodal {UNIFORME, OUVERTUNIFORME, QUELCONQUE};
|
||||
|
||||
BSpline(ESpline typeSpline = ESpline::SPLINE1D,
|
||||
int k = 3,
|
||||
EPolygone typePolygone = EPolygone::RANDOM2D,
|
||||
EVecteurNodal typeVecteur = EVecteurNodal::UNIFORME,
|
||||
int nbPtsCtrlX = 10,
|
||||
int nbPtsCtrlZ = 10,
|
||||
float stepX = 0.1,
|
||||
float stepY = 0.1);
|
||||
std::vector<GLfloat> const & getVertices() const {return _vertices;}
|
||||
std::vector<GLfloat> const & getNormals() const {return _normals;}
|
||||
std::vector<GLuint> const & getIndices() const {return _indices;}
|
||||
|
||||
private:
|
||||
std::vector<float> _vecteurNodal;
|
||||
// Vecteurs
|
||||
std::vector<glm::vec3> _pointsDeControle;
|
||||
int _k;
|
||||
int _np1;
|
||||
double _step;
|
||||
std::vector<float> _vecteurNodal;
|
||||
|
||||
std::vector<glm::vec3> _vertices;
|
||||
// Paramètres
|
||||
int _k, _nbPtsCtrlX, _nbPtsCtrlZ;
|
||||
float _stepX, _stepY;
|
||||
|
||||
void computeSpline();
|
||||
ESpline _typeSpline;
|
||||
EPolygone _typePolygone;
|
||||
EVecteurNodal _typeVecteur;
|
||||
|
||||
// Résultats
|
||||
std::vector<GLfloat> _vertices;
|
||||
std::vector<GLfloat> _normals;
|
||||
std::vector<GLuint> _indices;
|
||||
|
||||
// B-spline
|
||||
void calculerSpline1D();
|
||||
void calculerSpline2D();
|
||||
// Floraison récursive
|
||||
glm::vec3 floraison(float u, int dec, int k, std::vector<glm::vec3> vecteursPointsControle);
|
||||
|
||||
// Polygone
|
||||
void construirePolygone(EPolygone typePolygone, int nbPtsCtrlX, int nbPtsCtrlZ);
|
||||
// Vecteur Nodal
|
||||
void construireVecteurNodal(EVecteurNodal typeVecteur);
|
||||
|
||||
};
|
||||
|
||||
#endif // BSPLINE_H
|
||||
|
|
|
@ -10,8 +10,24 @@ SimpleSpline::SimpleSpline(int width, int height, MainWindow* w) : Scene(width,
|
|||
_lastVertex = _w->vertexShader;
|
||||
_lastFragment = _w->fragmentShader;
|
||||
|
||||
// LOAD B-SPLINE
|
||||
BSpline bspline1D = BSpline();
|
||||
/* Génération B-SPLINE - Paramètres:
|
||||
* Type de BSpline (1D / 2D)
|
||||
* Ordre k
|
||||
* Type de Polygone de contrôle (2D: fixé, random / 3D: gaussien, fixé, random)
|
||||
* Type de vecteur nodal (Uniforme / Ouvert uniforme / Quelconque)
|
||||
*
|
||||
* Pas pour delta u et Pas pour delta v */
|
||||
BSpline bspline1D = BSpline(
|
||||
BSpline::ESpline::SPLINE1D,
|
||||
3,
|
||||
BSpline::EPolygone::RANDOM2D,
|
||||
BSpline::EVecteurNodal::UNIFORME,
|
||||
5,
|
||||
5,
|
||||
0.1,
|
||||
0.1
|
||||
);
|
||||
|
||||
_vertices = bspline1D.getVertices();
|
||||
_indices = bspline1D.getIndices();
|
||||
_normals = bspline1D.getNormals();
|
||||
|
|
|
@ -98,6 +98,6 @@ void MainWindow::addShaders() {
|
|||
}
|
||||
|
||||
// Set default shaders
|
||||
vertexShader = vertexShaders.constBegin().key();
|
||||
fragmentShader = fragmentShaders.constBegin().key();
|
||||
vertexShader = vertexShaders.firstKey();
|
||||
fragmentShader = fragmentShaders.lastKey();
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ public:
|
|||
QMap<QString, std::string> vertexShaders;
|
||||
QMap<QString, std::string> fragmentShaders;
|
||||
|
||||
bool culling = true;
|
||||
bool culling = false;
|
||||
|
||||
private slots:
|
||||
void on_action_Version_OpenGL_triggered();
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Toggle backface culling</string>
|
||||
|
|
|
@ -6,6 +6,7 @@ Scene::Scene(int width, int height, MainWindow* w) : _width(width), _height(heig
|
|||
glEnable(GL_DEPTH_TEST);
|
||||
glViewport(0, 0, width, height);
|
||||
glPointSize(5.0f);
|
||||
_drawfill = 2;
|
||||
}
|
||||
|
||||
Scene::~Scene() {
|
||||
|
|
|
@ -32,7 +32,7 @@ protected:
|
|||
|
||||
private:
|
||||
// Rendering mode
|
||||
int _drawfill = 1;
|
||||
int _drawfill;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user