V1 et V2: Vecteurs (P2, P3) et (P3, P4)
T1 et T2: Vecteurs tangents calculés en P3
Le source : BezierAssemblage.cpp
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Fevrier 2019 */
/* Assemblage de deux courbes */
/* de Bezier a quatre sommets */
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "ModuleCouleurs.h"
#include "ModuleFont.h"
#include "ModuleManipulateur.h"
#include "ModuleMenus.h"
#include "ModuleReshape.h"
struct coord_3D {
GLfloat x = 0.0F;
GLfloat y = 0.0F;
GLfloat z = 0.0F;
GLfloat w = 1.0F; };
struct polygone {
int n = 0;
coord_3D *p = NULL; };
typedef struct coord_3D coord_3D;
typedef struct polygone polygone;
typedef float matrice[4][4];
static GLfloat pts[7][4] = {
{ -4.0F,-2.0F, 4.0F, 1.0F },
{ -7.0F, 0.0F, 2.0F, 1.0F},
{ -2.0F, 3.0F,-2.0F, 1.0F},
{ -1.0F, 0.0F,-1.0F, 1.0F},
{ 0.0F,-3.0F, 0.0F, 1.0F},
{ 3.0F,-4.0F,-4.0F, 1.0F},
{ 5.0F, 2.0F, 4.0F, 1.0F}};
static int pt = 0;
static int mode = 0;
static int disc = 30;
static matrice mbezier =
{ -1.0F, 3.0F,-3.0F, 1.0F,
3.0F,-6.0F, 3.0F, 0.0F,
-3.0F, 3.0F, 0.0F, 0.0F,
1.0F, 0.0F, 0.0F, 0.0F };
static polygone pl1;
static polygone pl2;
void point(float x,float y,float z) {
glVertex3f(x,y,z);
}
void tangente(coord_3D *p,int n,matrice m,float t,float *tx,float *ty,float *tz) {
int j,k;
float tt[3],ttt[4],x,y,z;
tt[0] = 3*t*t;
tt[1] = 2*t;
tt[2] = 1.0F;
for ( j = 0 ; j < 4 ; j++ )
for ( k = 0,ttt[j] = 0 ; k < 3 ; k++ )
ttt[j] += tt[k] * m[k][j];
x = y = z = 0;
for ( j = 0 ; j < 4 ; j++ ) {
x += ttt[j] * p[j].x;
y += ttt[j] * p[j].y;
z += ttt[j] * p[j].z; }
float d =(float) pow((double) (x*x+y*y+z*z),0.5);
*tx = x/d;
*ty = y/d;
*tz = z/d;
}
void morceauBezier(coord_3D *p,int n,matrice m) {
int j,k;
float tt[4],ttt[4],x,y,z;
for ( int i = 0 ; i < n ; i++ ) {
float t =(float) i/(n-1);
tt[0] = t*t*t;
tt[1] = t*t;
tt[2] = t;
tt[3] = 1;
for ( j = 0 ; j < 4 ; j++ )
for ( k = 0,ttt[j] = 0 ; k < 4 ; k++ )
ttt[j] += tt[k] * m[k][j];
x = y = z = 0;
for ( j = 0 ; j < 4 ; j++ ) {
x += ttt[j] * p[j].x;
y += ttt[j] * p[j].y;
z += ttt[j] * p[j].z; }
point(x,y,z); }
}
void display(void) {
int i;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glEnable(GL_DEPTH_TEST);
manipulateurSouris();
manipulateurClavier();
glColor4fv(couleurBlanc());
glBegin(GL_LINE_STRIP);
for ( i = 0 ; i < 7 ; i++ )
glVertex3fv(&pts[i][0]);
glEnd();
glPointSize(5.0);
glBegin(GL_POINTS);
for ( i = 0 ; i < 7 ; i++ ) {
glColor4fv((i == pt) ? couleurRouge() : couleurJaune());
glVertex3fv(&pts[i][0]); }
glEnd();
glPointSize(3.0);
if ( ( mode == 0 ) || ( mode == 2 ) ) {
glColor4fv(couleurCyan());
glBegin(GL_LINE_STRIP);
morceauBezier(pl1.p,disc,mbezier);
glEnd();
glBegin(GL_LINE_STRIP);
morceauBezier(pl2.p,disc,mbezier);
glEnd(); }
if ( ( mode == 1 ) || ( mode == 2 ) ) {
glColor4fv(couleurMagenta());
glBegin(GL_POINTS);
morceauBezier(pl1.p,disc,mbezier);
glEnd();
glBegin(GL_POINTS);
morceauBezier(pl2.p,disc,mbezier);
glEnd(); }
glDisable(GL_DEPTH_TEST);
for ( i = 0 ; i < 7 ; i++ ) {
glColor4fv((i == pt) ? couleurRouge() : couleurJaune());
placeFontCursor(pts[i][0]+0.3F,pts[i][1]+0.3F,pts[i][2]+0.3F);
simpleBitmapOutput("%d",i); }
glPopMatrix();
float xmin = getXmin();
float ymin = getYmin();
float ymax = getYmax();
float tpix = getTaillePixel();
setAntialiased(1);
setBold(1);
setEcartementCaracteres(25.0F);
glPushMatrix();
glColor4fv(couleurBlanc());
strokeOutput(xmin+0.1F,ymax-0.7F,1.0F,"V1: %f %f %f",pts[3][0]-pts[2][0],pts[3][1]-pts[2][1],pts[3][2]-pts[2][2]);
strokeOutput(xmin+0.1F,ymax-1.7F,1.0F,"V2: %f %f %f",pts[4][0]-pts[3][0],pts[4][1]-pts[3][1],pts[4][2]-pts[3][2]);
float tx;
float ty;
float tz;
tangente(pl1.p,disc,mbezier,1.0F,&tx,&ty,&tz);
strokeOutput(xmin+0.1F,ymin+1.5F,1.0F,"T1: %f %f %f",tx,ty,tz);
tangente(pl2.p,disc,mbezier,0.0F,&tx,&ty,&tz);
strokeOutput(xmin+0.1F,ymin+0.5F,1.0F,"T2: %f %f %f",tx,ty,tz);
glPopMatrix();
setAntialiased(0);
setBold(0);
setEcartementCaracteres(0.0F);
glFlush();
glutSwapBuffers();
}
void init(void) {
glClearColor(0.0,0.0,0.0,1.0);
}
void special(int k, int x, int y) {
switch (k) {
case GLUT_KEY_LEFT : pts[pt][0]-= 0.1F;
glutPostRedisplay();
break;
case GLUT_KEY_RIGHT : pts[pt][0] += 0.1F;
glutPostRedisplay();
break;
case GLUT_KEY_UP : pts[pt][1] += 0.1F;
glutPostRedisplay();
break;
case GLUT_KEY_DOWN : pts[pt][1] -= 0.1F;
glutPostRedisplay();
break;
case GLUT_KEY_PAGE_UP : pts[pt][2] -= 0.1F;
glutPostRedisplay();
break;
case GLUT_KEY_PAGE_DOWN : pts[pt][2] += 0.1F;
glutPostRedisplay();
break; }
}
void key(unsigned char key,int x,int y) {
if ( keyManipulateur(key,x,y) )
glutPostRedisplay();
else
switch ( key ) {
case 43 : disc++;
glutPostRedisplay();
break;
case 45 : disc--;
if ( disc < 3 )
disc = 3;
glutPostRedisplay();
break;
case 'a' : mode = (mode+1)%3;
glutPostRedisplay();
break;
case 32 : pt = (pt+1)%4;
glutPostRedisplay();
break; }
}
void select2(int selection) {
switch (selection) {
case 4 : pt = (pt+1)%4;
glutPostRedisplay();
break;
case 5 : mode = 0;
glutPostRedisplay();
break;
case 6 : mode = 1;
glutPostRedisplay();
break;
case 7 : mode = 2;
glutPostRedisplay();
break; }
}
void select3(int selection) {
switch (selection) {
case 10 : disc = 3;
glutPostRedisplay();
break;
case 11 : disc = 10;
glutPostRedisplay();
break;
case 12 : disc = 30;
glutPostRedisplay();
break;
case 13 : disc = 50;
glutPostRedisplay();
break;
case 14 : disc = 100;
glutPostRedisplay();
break;
case 6 : disc++;
glutPostRedisplay();
break;
case 7 : disc--;
if ( disc < 3 )
disc = 3;
glutPostRedisplay();
break; }
}
void select(int selection) {
switch (selection) {
case 0 : exit(0); }
}
void creationMenu(void) {
int menu2 = glutCreateMenu(select2);
glutAddMenuEntry("Changer point",4);
glutAddMenuEntry("Fil de fer",5);
glutAddMenuEntry("Points",6);
glutAddMenuEntry("Fil de fer et points",7);
int menu3 = glutCreateMenu(select3);
glutAddMenuEntry("3",10);
glutAddMenuEntry("10",11);
glutAddMenuEntry("30",12);
glutAddMenuEntry("50",13);
glutAddMenuEntry("100",14);
glutAddMenuEntry("Augmenter",6);
glutAddMenuEntry("Reduire",7);
glutCreateMenu(select);
glutAddSubMenu("Affichage",menu2);
glutAddSubMenu("Discretisation",menu3);
glutAddMenuEntry("Quitter",0);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
int main(int argc,char **argv) {
pl1.n = 4;
pl1.p =(coord_3D *) &pts[0][0];
pl2.n = 4;
pl2.p =(coord_3D *) &pts[3][0];
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
glutInitWindowSize(300,300);
glutInitWindowPosition(50,50);
glutCreateWindow("Assemblage de courbes de Bezier");
init();
creationMenu();
setParametresOrthoBasique(-8.0,8.0,-8.0,8.0,-100.0,100.0);
setManipulateurDistance(1.0F);
glutReshapeFunc(reshapeOrthoBasique);
glutKeyboardFunc(key);
glutSpecialFunc(special);
glutMotionFunc(motionBasique);
glutMouseFunc(sourisBasique);
glutDisplayFunc(display);
glutMainLoop();
return(0);
}