Commentaires

Le développement a été réalisé en utilisant des tableaux de pointeurs sur Pos3D.
Les matrices de base pour les B-Spline NRU et Catmull-Rom sont définie à partir de tableaux de 4x4 float.
Dans la fonction de génération d'une courbe de Bézier les Cni sont précalculés dans le tableau de long long nommé cn de façon à ce que n puisse aller jusqu'à la valeur 62 (détermination expérimentale réalisée par ailleurs). Si on souhaite dépasser cette valeur, il faut alors envisager d'utiliser un type de base réel pour cn. Ce précalcul a pour but d'optimiser les performances globales de calcul de la courbe de Bézier.

L'exécutable


Deux vues de la ligne polygonale à 37 sommets


Courbe de Bézier avec 100 points (points de taille 3 pixels)


B-Spline NRU générée avec 100 points


Spline de Catmull-Rom générée avec 100 points


Courbes superposées (plusieurs centaines de points sur chaque courbe lissée)
Bézier en vert, B-Spline NRU en cyan, Spline de Catmull-Rom en rose

Fichier source : BSplineEtBezier.cpp

static int nbPoints = 37;
static Pos3D *tPos[] = { new Pos3D( 6.5F, 4.9F,-3.00F), new Pos3D( 7.0F, 5.0F,-3.00F), new Pos3D( 7.5F, 4.9F,-2.00F),
                         new Pos3D( 8.0F, 4.6F, 0.00F), new Pos3D( 7.5F, 4.4F, 2.00F), new Pos3D( 7.0F, 4.2F, 3.50F),
                         new Pos3D( 6.0F, 3.8F, 4.00F), new Pos3D( 5.0F, 2.8F, 4.00F), new Pos3D( 4.0F, 1.8F, 4.00F),
                         new Pos3D( 3.0F, 0.8F, 4.00F), new Pos3D( 0.0F, 0.0F, 4.00F), new Pos3D(-1.4F, 0.7F, 3.75F),
                         new Pos3D(-2.0F, 2.0F, 3.50F), new Pos3D(-1.4F, 3.3F, 3.25F), new Pos3D( 0.0F, 4.0F, 3.00F),
                         new Pos3D( 1.4F, 3.3F, 2.75F), new Pos3D( 2.0F, 2.0F, 2.50F), new Pos3D( 1.0F, 0.7F, 2.25F),
                         new Pos3D(-1.0F, 0.0F, 2.00F), new Pos3D(-2.4F, 0.7F, 1.75F), new Pos3D(-3.0F, 2.0F, 1.50F),
                         new Pos3D(-2.4F, 3.3F, 1.25F), new Pos3D(-1.0F, 4.0F, 1.00F), new Pos3D( 0.4F, 3.3F, 0.75F),
                         new Pos3D( 1.0F, 2.0F, 0.50F), new Pos3D( 0.0F, 0.7F, 0.25F), new Pos3D(-2.0F, 0.2F, 0.00F),
                         new Pos3D(-7.0F, 0.0F, 1.50F), new Pos3D(-8.0F, 0.0F,-1.30F), new Pos3D(-7.0F, 0.3F,-1.90F),
                         new Pos3D(-6.0F, 1.8F,-2.40F), new Pos3D(-4.5F, 4.9F,-2.40F), new Pos3D(-3.0F, 3.2F,-2.40F),
                         new Pos3D( 0.5F, 2.4F,-2.80F), new Pos3D( 3.5F, 4.4F,-2.80F), new Pos3D( 4.5F, 4.7F,-2.90F),
                         new Pos3D( 5.5F, 4.8F,-3.00F) };

static float NRUBS[4][4]       = { { -1.0F/6.0F,  3.0F/6.0F, -3.0F/6.0F,  1.0F/6.0F },
                                   {  3.0F/6.0F, -6.0F/6.0F,  3.0F/6.0F,       0.0F },
                                   { -3.0F/6.0F,       0.0F,  3.0F/6.0F,       0.0F },
                                   {  1.0F/6.0F,  4.0F/6.0F,  1.0F/6.0F,       0.0F } };

static float CATMULL_ROM[4][4] = { { -1.0F/2.0F,  3.0F/2.0F, -3.0F/2.0F,  1.0F/2.0F },
                                   {  2.0F/2.0F, -5.0F/2.0F,  4.0F/2.0F, -1.0F/2.0F },
                                   { -1.0F/2.0F,       0.0F,  1.0F/2.0F,       0.0F },
                                   {       0.0F,  2.0F/2.0F,       0.0F,       0.0F } };

/* Modelise une ligne polygonale definie         */
/* par un ensemble de points                     */
/* nbPoints : le nombre de points                */
/* tPos : le tableau des points                  */
/* typePrimitive : le type de primitive OpenGL   */
/*                 a utiliser                    */

static void dessinerOpenGL(int nbPoints,Pos3D **tPos,GLenum typePrimitive) {
  glBegin(GL_LINE_STRIP);
  for ( int i = 0 ; i < nbPoints ; i++ ) {
    glVertex3d(tPos[i]->x,tPos[i]->y,tPos[i]->z); }
  glEnd();
}

/* Modelise une courbe de Bezier definie         */
/* par un ensemble de points de controle         */
/* nbPoints : le nombre de points de contrôle    */
/* tPos : le tableau des points de controle      */
/* nb : le nombre de points a calculer           */
/* tRes : le tableau de points resultat          */
/* typePrimitive : le type de primitive OpenGL   */
/*                 a utiliser                    */

static void bezier(int nbPoints,Pos3D **tPos,int n,GLenum typePrimitive) {
  float t,mt;
  float x,y,z,fac;
  long long *cn =(long long *) calloc(nbPoints,sizeof(long long));
  cn[0] = 1;
  cn[1] = nbPoints-1;
  for ( int i = 2 ; i < nbPoints ; i++ )
    cn[i] = (cn[i-1]*(nbPoints-i))/i;
  glBegin(typePrimitive);
  for ( int i = 0 ; i < n ; i++ ) {
    t =(float) i/(n-1);
    mt = 1.0F-t;
    x = y = z = 0.0F;
    for ( int j = 0 ; j < nbPoints ; j++ ) {
      fac = cn[j]*pow(t,j)*pow(mt,nbPoints-1-j);
      x += fac * tPos[j]->x;
      y += fac * tPos[j]->y;
      z += fac * tPos[j]->z; }
    glVertex3f(x,y,z); }
  glEnd();
  free(cn);
}

/* Calcul la position d'un point sur une courbe  */
/* B-Spline controlee par quatre points          */
/* tPos : le tableau des 4 points de controle    */
/* t : la valeur de calcul du point              */
/*     t a prendre dans l'intervalle [0.0,1.0]   */
/* mb : la matrice de base                       */
/* point : le point resultat                     */

static void positionSurBSpline(Pos3D **tPos,float t,float mb[4][4],Pos3D *point) {
  float vt[4] = { t*t*t,t*t,t,1.0F };
  float vtmb[4] = { 0.0F,0.0F,0.0F,0.0F };
  for ( int j = 0 ; j < 4 ; j++ ) {
    for ( int k = 0 ; k < 4 ; k++ )
      vtmb[j] += vt[k] * mb[k][j] ; }
  point->x = point->y = point->z = 0.0;
  for ( int j = 0 ; j < 4 ; j++ ) {
    point->x += vtmb[j] * tPos[j]->x ;
    point->y += vtmb[j] * tPos[j]->y ;
    point->z += vtmb[j] * tPos[j]->z ; }
}

/* Modelise une courbe B-Spline par morceaux     */
/* definie par un ensemble de points de controle */
/* nbPoints : le nombre de points de contrôle    */
/* tPos : le tableau des points de controle      */
/* mb : la matrice de base                       */
/* n : le nombre de points a calculer            */
/* typePrimitive : le type de primitive OpenGL   */
/*                 a utiliser                    */

static void BSpline(int nbPoints,Pos3D **tPos,float mb[4][4],int n,GLenum typePrimitive) {
  glBegin(typePrimitive);
  for ( int i = 0 ; i < n ; i++ ) {
    float t = i/(n-1.0)*(nbPoints-3);
    int nb =(int) t;
    if ( nb == nbPoints-3 )
      nb = nbPoints-4;
    Pos3D point;
    positionSurBSpline(&tPos[nb],t-nb,mb,&point);
    glVertex3f(point.x,point.y,point.z); }
  glEnd();
}

Fichier source : CH3D.h

Fichier source : CH3D.cpp

Fichier source : Pos3D.h

Fichier source : Pos3D.cpp

Fichier source : TG3D.h

RETOUR