Code Vonc

Fenêtrage et primitives graphiques

v 1.0

Win

TéléchargerDownload
Faire un donMake a donation
CommentairesComments
Programme C permettant de dessiner des formes graphiques.

Rendu avec la bibliothèque GLUT.

Projet réalisé avec Cédric Bitsch.



Fonctionnalités

- Palette de couleurs (clic gauche) : change la couleur des lignes et des contours des formes.
- Palette de couleurs (clic milieu) : change la couleur de remplissage des formes.
- Palette de couleurs (clic droit) : change la couleur du fond.
- Fenêtrage de polygones.
- Traçage de segments avec la méthode de Brensenham.
- Traçage de courbes de Bézier avec un niveau de subdivision personnalisable (touches + et -).
- Dessin de carrés avec remplissage.
- Dessin de cercles et ellipses avec remplissage.
- Zoom et dézoom de la vue (clic droit).
- Déplacement de la zone de dessin (clic milieu).
- Outil gomme : efface l'écran.
- Aimantation de la souris aux points tracés.


Codes sourcesSources code

main.c

#include <windows.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <gl/glaux.h>
#include <gl/gl.h>
#include <math.h>
#include "prototypes.h"
//#include <gl/glu.h>


double* ptsmodes[7];
int nbptsmode[7];
int mode = 0, modeNb = 7;
int mode_tmp = 0;
int rxa = -200, rya = -200;
int rxb = 200, ryb = 200;
int Xmin, Xmax, Ymin, Ymax;
int pts = 0;
int bouton = 0;
int subd = 10;
double coul[3] = {1.0, 1.0, 1.0};
double coulremp[3] = {.0, 1.0, 1.0};
int posX = 0, posY = 0, zoom = 0;

GLuint texture;

int main(int argc, char **argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(1024, 640);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("Projet");

	gluOrtho2D(-512.0,512.0,-320.0,320.0);

	glClearColor(0.0, 0.0, 0.0, 0.0);
	glPointSize(1.0);

    initPoints();
    LoadGLTextures();

    glutDisplayFunc(affichage);
	glutKeyboardFunc(clavier);
	glutMouseFunc(mouse);
	glutMotionFunc(mouseMove);

    glutMainLoop();

    videPoints();
    return 0;
}

AUX_RGBImageRec *LoadBMP( char *Filename ) {
	FILE *File = NULL;
	if (!Filename) return NULL;
	File = fopen(Filename, "r");
	if (File) {
		fclose(File);
		return auxDIBImageLoadA(Filename);
	}
	return NULL;
}

int LoadGLTextures() {
	int Status = 0;
	AUX_RGBImageRec *TextureImage[1];
	memset(TextureImage, 0, sizeof( void * )*1);
	if ((TextureImage[0] = LoadBMP("interface.bmp"))) {
		Status = 1;
		glGenTextures(1, &texture);
		glBindTexture(GL_TEXTURE_2D, texture);
		glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	}

	if (TextureImage[0]) {
		if (TextureImage[0] -> data) free( TextureImage[0] -> data);
		free(TextureImage[0]);
	}

	return Status;
}

void afficheMenu() {
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texture);
    glBegin(GL_POLYGON);
    glColor3f(1,1,1);
    glTexCoord2f( 0.0f, 0.0f ); glVertex2f(-512, 320-94);
    glTexCoord2f( 1.0f, 0.0f ); glVertex2f(512, 320-94);
    glTexCoord2f( 1.0f, 1.0f ); glVertex2f(512, 320);
    glTexCoord2f( 0.0f, 1.0f ); glVertex2f(-512, 320);
    glEnd();
}



void initPoints() {
    int i;
    for (i = 0 ; i < modeNb ; i++) {
        ptsmodes[i] = NULL;
        nbptsmode[i] = 0;
    }
    ajoutePoint(6, 0, 0); // 6 : Couleur, point par défaut
    pts = 0; // Pour bézier, premier point par défaut
}

void videPoints() {
    int i;
    for (i = 0 ; i < modeNb ; i++) {
        if (ptsmodes[i] != NULL) {
            free(ptsmodes[i]);
            ptsmodes[i] = NULL;
        }
        nbptsmode[i] = 0;
    }
}

void ajoutePoint(int m, int x, int y) {
    nbptsmode[m]++;
    if (ptsmodes[m] == NULL) {
        ptsmodes[m] = malloc(sizeof(double) * 2);
    }
    else {
        ptsmodes[m] = realloc(ptsmodes[m], sizeof(double) * 2 * nbptsmode[m]);
    }
    ptsmodes[m][(nbptsmode[m] - 1) * 2] = x;
    ptsmodes[m][(nbptsmode[m] - 1) * 2 + 1] = y;
}

void modifPoint(int m, int x, int y, int id) {
    ptsmodes[m][(nbptsmode[m] + id) * 2] = x;
    ptsmodes[m][(nbptsmode[m] + id) * 2 + 1] = y;
}

void couleur(int x, int y, int id) {
    if (x > 300 || y > 200) return;

    double cx = (x - 150.) / 62.;
    double cy = 1. - ((y - 16.) / 62.);
    double cz = 0.5;
    if (cx >= 1.0) cz = 1.0;
    else if (cx <= 0.0) cz = 0.0;

    if (id == 1) { // Fond
        glClearColor(cx, cy, cz, 1.0);
    }
    else if (id == 2) { // Remplissage
        coulremp[0] = cx;
        coulremp[1] = cy;
        coulremp[2] = cz;
    }
    else { // Lignes
        coul[0] = cx;
        coul[1] = cy;
        coul[2] = cz;
    }
}

// ------------ Affichage des formes ------------

void affichage() {
    glClear(GL_COLOR_BUFFER_BIT);

    afficheMenu();

    glBegin(GL_POINTS);
    glPointSize(1);
    glColor3f(coul[0], coul[1], coul[2]);

    switch(mode) {
        case 4 :
            affichageRecadre(rxa, rya, rxb, ryb);
            break;
    }

    affichageSegments();
    affichageCercles();
    affichageCarres();
    affichageEllipses();
    affichageBeziers();
    affichageRecadre(rxa, rya, rxb, ryb);

    glEnd();
    glFlush();
}

void affichageSegments() {
    int i, xa, xb, ya, yb;
    if (nbptsmode[0] % 2) return;
    for (i = 0 ; i < nbptsmode[0] ; i += 2) {
        xa = ptsmodes[0][i * 2];
        ya = ptsmodes[0][i * 2 + 1];
        xb = ptsmodes[0][i * 2 + 2];
        yb = ptsmodes[0][i * 2 + 3];
        fenetrage(xa, ya, xb, yb, 0, coul);
    }
}

void affichageCercles() {
    int i, xa, xb, ya, yb;
    if (nbptsmode[1] % 2) return;
    for (i = 0 ; i < nbptsmode[1] ; i += 2) {
        xa = ptsmodes[1][i * 2];
        ya = ptsmodes[1][i * 2 + 1];
        xb = ptsmodes[1][i * 2 + 2];
        yb = ptsmodes[1][i * 2 + 3];
        affichageCercle(xa, ya, xb, yb);
    }
}

void affichageCarres() {
    int i, xa, xb, ya, yb;
    if (nbptsmode[2] % 2) return;
    for (i = 0 ; i < nbptsmode[2] ; i += 2) {
        xa = ptsmodes[2][i * 2];
        ya = ptsmodes[2][i * 2 + 1];
        xb = ptsmodes[2][i * 2 + 2];
        yb = ptsmodes[2][i * 2 + 3];
        affichageCarre(xa, ya, xb, yb);
    }
}

void affichageEllipses() {
    int i, xa, xb, ya, yb;
    if (nbptsmode[5] % 2) return;
    for (i = 0 ; i < nbptsmode[5] ; i += 2) {
        xa = ptsmodes[5][i * 2];
        ya = ptsmodes[5][i * 2 + 1];
        xb = ptsmodes[5][i * 2 + 2];
        yb = ptsmodes[5][i * 2 + 3];
        affichageEllipse(xa, ya, xb, yb);
    }
}

void affichageBeziers() {
    int i, xa, xb, xc, xd, ya, yb, yc, yd;
    if (nbptsmode[3] % 4) return;
    for (i = 0 ; i < nbptsmode[3] ; i += 4) {
        xa = ptsmodes[3][i * 2];
        ya = ptsmodes[3][i * 2 + 1];
        xb = ptsmodes[3][i * 2 + 2];
        yb = ptsmodes[3][i * 2 + 3];
        xc = ptsmodes[3][i * 2 + 4];
        yc = ptsmodes[3][i * 2 + 5];
        xd = ptsmodes[3][i * 2 + 6];
        yd = ptsmodes[3][i * 2 + 7];
        affichageBezier(xa, ya, xb, yb, xc, yc, xd, yd);
    }
}

// ------------ Fenêtrage et remplissage ------------

struct CodeSegment calculCode(int x, int y) {
    struct CodeSegment c;

    c.somme = 0;
    c.haut = 0;
    c.bas = 0;
    c.droite = 0;
    c.gauche = 0;

    if (y > Ymax) {
        c.haut = 1;
        c.somme++;
    }
    else if (y < Ymin) {
        c.bas = 1;
        c.somme++;
    }
    if (x > Xmax) {
        c.droite = 1;
        c.somme++;
    }
    else if (x < Xmin) {
        c.gauche = 1;
        c.somme++;
    }

    c.code = 0;
    c.code = c.bas;
    c.code = (c.haut << 1) | c.code;
    c.code = (c.droite << 2) | c.code;
    c.code = (c.gauche << 3) | c.code;
  /*  c.code = (c.bas << 3) | c.code;
    c.code = (c.haut << 2) | c.code;
    c.code = (c.droite << 1) | c.code;
    c.code = (c.gauche << 0) | c.code;*/

    return c;
}

void fenetrage(int xa, int ya, int xb, int yb, int rempCote, double* c) {
    double m, x, y;
    struct CodeSegment CodeExt, CodeA, CodeB;
    int fini = 0, accepte = 0;

    // Pour remplissage
    affichageSegment(xa, ya, xb, yb, rempCote, NULL);


    CodeA = calculCode(xa, ya);
    CodeB = calculCode(xb, yb);

    m = ((double)yb - (double)ya) / ((double)xb - (double)xa);

    do {
        if (CodeA.somme == 0 && CodeB.somme == 0) {
            accepte = 1;
            fini = 1;
        }
        else {
            if ((CodeA.code & CodeB.code) != 0) fini = 1;
            else {
                CodeExt = CodeA;
                if (CodeA.somme == 0) CodeExt = CodeB;

                if (CodeExt.haut == 1) {
                    y = Ymax;
                    x = xa + (Ymax - ya) / m;
                }
                else if (CodeExt.bas == 1) {
                    y = Ymin;
                    x = xa + (Ymin - ya) / m;
                }
                else if (CodeExt.droite == 1) {
                    x = Xmax;
                    y = ya + (Xmax - xa) * m;
                }
                else if (CodeExt.gauche == 1) {
                    x = Xmin;
                    y = ya + (Xmin - xa) * m;
                }
                if (CodeExt.code == CodeA.code) {
                    xa = x;
                    ya = y;
                    CodeA = calculCode(x, y);
                }
                else {
                    xb = x;
                    yb = y;
                    CodeB = calculCode(x, y);
                }
            }
        }
    }
    while (!fini);
    if (accepte) affichageSegment(xa, ya, xb, yb, 0, c);
}

void fenetragePixel(int x, int y, double* c) {
    if (x < Xmin) return;
    if (x > Xmax) return;
    if (y < Ymin) return;
    if (y > Ymax) return;
    if (c[0] > 2) return;
    glColor3f(c[0], c[1], c[2]);
    glVertex2f(x, y);
}

void remplissageX(int xa, int xb, int y) {
    int x;
    for (x = xa+1 ; x < xb ; x++) {
        fenetragePixel(x, y, coulremp);
    }
}

// ------------ Calcul des formes ------------

void affichageRecadre(int xa, int ya, int xb, int yb) {
    affichageSegment(xa, ya, xb, ya, 0, coul);
    affichageSegment(xb, ya, xb, yb, 0, coul);
    affichageSegment(xb, yb, xa, yb, 0, coul);
    affichageSegment(xa, yb, xa, ya, 0, coul);
    if (xa > xb) {
        Xmin = xb;
        Xmax = xa;
    }
    else {
        Xmin = xa;
        Xmax = xb;
    }
    if (ya > yb) {
        Ymin = yb;
        Ymax = ya;
    }
    else {
        Ymin = ya;
        Ymax = yb;
    }

}

void affichageEllipse(int xc, int yc, int xb, int yb) {

    int largeur, hauteur;

    largeur = xb - xc;
    hauteur = yb - yc;
    if (largeur < 0) largeur = -largeur;
    if (hauteur < 0) hauteur = -hauteur;
    if (hauteur == 0) return;
    if (largeur == 0) return;


    int a2 = largeur * largeur;
    int b2 = hauteur * hauteur;
    int fa2 = 4 * a2, fb2 = 4 * b2;
    int x ,y, sigma, xmin = 0;

    for (x = 0, y = hauteur, sigma = 2*b2+a2*(1-2*hauteur); b2*x <= a2*y; x++)
    {
        remplissageX(-xmin + xc, xmin + xc, y + yc); // haut
        remplissageX(-xmin + xc, xmin + xc, -y + yc); // bas

        fenetragePixel(xc + x, yc + y, coul);
        fenetragePixel(xc - x, yc + y, coul);
        fenetragePixel(xc + x, yc - y, coul);
        fenetragePixel(xc - x, yc - y, coul);
        if (sigma >= 0)
        {
            sigma += fa2 * (1 - y);
            y--;

            xmin = x+1;
        }
        sigma += b2 * ((4 * x) + 6);
    }

    xmin = largeur;
    for (x = largeur, y = 0, sigma = 2*a2+b2*(1-2*largeur); a2*y <= b2*x; y++)
    {
        remplissageX(-xmin + xc, xmin + xc, y + yc); // milieu haut
        remplissageX(-xmin + xc, xmin + xc, -y + yc); // bas

        fenetragePixel(xc + x, yc + y, coul);
        fenetragePixel(xc - x, yc + y, coul);
        fenetragePixel(xc + x, yc - y, coul);
        fenetragePixel(xc - x, yc - y, coul);
        if (sigma >= 0)
        {
            sigma += fb2 * (1 - x);
            x--;

            xmin = x+1;
        }
        sigma += a2 * ((4 * y) + 6);
    }
}

void affichageCercle(int xc, int yc, int xb, int yb) {
    int r, x, y, dp, xmin;
    int a, b;

    a = xb - xc;
    b = yb - yc;
    r = sqrt(a * a + b * b);

    xmin = 0;
    x = 0;
    y = r;
    dp = 5 - 4 * r;

    fenetragePixel(x + xc, y + yc, coul);
    fenetragePixel(y + xc, x + yc, coul);
    fenetragePixel(x + xc, -y + yc, coul);
    fenetragePixel(-y + xc, x + yc, coul);

    remplissageX(-r + xc, r + xc, yc); // Milieu

    while (y > x) {
        if (dp <= 0) dp = dp + 8 * x + 12; // Est
        else { // SE
            dp = dp + 8 * (x - y) + 20;
            y--;
            // On récupère la première valeur de x
            // avant qu'il s'incrémente pour éviter
            // de remplir par-dessus
            xmin = x + 1;
        }
        x++;

        remplissageX(-xmin + xc, xmin + xc, y + yc); // haut
        remplissageX(-y + xc, y + xc, x + yc); // haut
        remplissageX(-y + xc, y + xc, -x + yc); // bas
        remplissageX(-xmin + xc, xmin + xc, -y + yc); // bas

        fenetragePixel(x + xc, y + yc, coul); // Octant 2
        fenetragePixel(y + xc, x + yc, coul); // Octant 1
        fenetragePixel(x + xc, -y + yc, coul); // Octant 7
        fenetragePixel(-y + xc, x + yc, coul); // Octant 4

        fenetragePixel(-x + xc, y + yc, coul); // Octant 3
        fenetragePixel(y + xc, -x + yc, coul); // Octant 8
        fenetragePixel(-x + xc, -y + yc, coul); // Octant 6
        fenetragePixel(-y + xc, -x + yc, coul); // Octant 5
    }
}

void affichageSegment(int xa, int ya, int xb, int yb, int rempCote, double* c) {
    int x, y, dx, dy, incrE, incrNE, di, incrX, incrY, xcen, xceninc;

    dy = yb - ya;
    dx = xb - xa;

    if (dx >= 0) incrX = 1;
    else {
        incrX = -1;
        dx = -dx;
    }

    if (dy >= 0) incrY = 1;
    else {
        incrY = -1;
        dy = -dy;
    }

    if (rempCote == -1) { // Vers xb
        xcen = xb;
        xceninc = -incrX;
    }
    else if (rempCote == 1) { // vers xa
        xcen = xa;
        xceninc = incrX;
    }

    if (dx >= dy) { // Octants 1 4 5 8
        incrE = 2 * dy;
        incrNE = 2 * (dy - dx);
        di = 2 * dy - dx;

        x = xa;
        y = ya;
        while (x < xb || xb < x) {

            if (c) {
                glColor3f(c[0], c[1], c[2]);
                glVertex2f(x, y);   // Affiche pixel
            }

            if (di <= 0) di += incrE;
            else {
                y += incrY;
                di += incrNE;

                if (rempCote) {
                    // On remplit qu'à chaque changement de Y
                    remplissageX(xcen, x+incrX, y);
                    remplissageX(x+incrX, xcen+1, y);
                }
            }
            x += incrX;
        }
    }
    else { // Octants 2 3 6 7
        di = 2 * dx - dy;
        incrE = 2 * dx;
        incrNE = 2 * (dx - dy);

        x = xa;
        y = ya;
        while (y < yb || yb < y) {

            if (c) {
                glColor3f(c[0], c[1], c[2]);
                glVertex2f(x, y);   // Affiche pixel
            }

            if (di <= 0) di += incrE;
            else {
                x += incrX;
                di += incrNE;
            }
            y += incrY;

            if (rempCote) {
                // Remplissage tout le temps car y est inc.
                remplissageX(xcen, x+xceninc, y);
                remplissageX(x+xceninc, xcen+1, y);
            }
        }

    }
}

void affichageCarre(int xa, int ya, int xb, int yb) {
    int dx, dy, y, r, r2, renv = 0;

    dx = xb - xa;
    dy = yb - ya;

    r = abs(xb - xa);
    r2 = abs(yb - ya);
    if (r2 < r) {
        r = r2;
        renv = 1;
    }
    r++;

    for (y = ya - r ; y < ya + r ; y++) { // Carré central
        remplissageX(xa - r, xa + r, y);
        remplissageX(xa + r, xa - r, y);
    }

    if (renv) {
        fenetrage(xb, yb, xa-dy, ya+dx, -1, coul);
        fenetrage(xa-dy, ya+dx, xa-dx, ya-dy, 1, coul);
        fenetrage(xa-dx, ya-dy, xa+dy, ya-dx, -1, coul);
        fenetrage(xa+dy, ya-dx, xb, yb, 1, coul);
    }
    else { // Inverse le côté du remplissage
        fenetrage(xb, yb, xa-dy, ya+dx, 1, coul);
        fenetrage(xa-dy, ya+dx, xa-dx, ya-dy, -1, coul);
        fenetrage(xa-dx, ya-dy, xa+dy, ya-dx, 1, coul);
        fenetrage(xa+dy, ya-dx, xb, yb, -1, coul);
    }
}

void affichageBezier(int xa, int ya, int xb, int yb, int xc, int yc, int xd, int yd) {
    int i, x, y, ax=xa, ay=ya, imax;
    double t;

    imax = 2 * subd;

    //fenetrage(xa, ya, xb, yb, coul);
    //fenetrage(xc, yc, xd, yd, coul);

    for (i = 0 ; i <= imax ; i++) {
        t = i / (double)imax;
        x = (int)( (1-t)*(1-t)*(1-t)*xa + (1-t)*(1-t)*3*t*xb + (1-t)*3*t*t*xc + t*t*t*xd );
        y = (int)( (1-t)*(1-t)*(1-t)*ya + (1-t)*(1-t)*3*t*yb + (1-t)*3*t*t*yc + t*t*t*yd );
        fenetrage(ax, ay, x, y, 0, coul);
        ax = x;
        ay = y;
    }

}

// ------------ Commandes ------------

void bougeVue(int x, int y) {
    int dx, dy;
    int i, j;

    dx = x - posX;
    dy = y - posY;

    for (i = 0 ; i < modeNb ; i++) {
        for (j = 0 ; j < nbptsmode[i] ; j++) {
            ptsmodes[i][j*2] += dx;
            ptsmodes[i][j*2+1] += -dy;
        }
    }

    posX = x;
    posY = y;
}

void zoomVue(int x, int y) {
    double dx;
    int i, j;

    dx = x - posX;
    dx = 1 + dx*.001;

    for (i = 0 ; i < modeNb ; i++) {
        for (j = 0 ; j < nbptsmode[i] ; j++) {
            ptsmodes[i][j*2] *= dx;
            ptsmodes[i][j*2+1] *= dx;
        }
    }

    posX = x;
    posY = y;
}

void magnetisme(int* x, int* y, int max, int m) {
    int i, j, xm, ym, dm, m2;
    m2 = m * m;
    // max sert à ne pas magnétiser son propre point

    for (i = 0 ; i < modeNb ; i++) {
        for (j = 0 ; j < nbptsmode[i] + max ; j++) {
            xm = ptsmodes[i][j*2];
            ym = ptsmodes[i][j*2+1];
            // Calcule la distance entre le point cliqué et un point existant
            xm = xm - (*x);
            ym = ym - (*y);
            dm = xm * xm + ym * ym;
            if (dm < m2) {
                *x = ptsmodes[i][j*2];
                *y = ptsmodes[i][j*2+1];
                return;
            }
        }
    }
}

void effaceTout() {
    videPoints();
    initPoints();
    affichage();
}

int menuMode(int x, int y) {
    int decx = 42;
    int lb = 94;
    if (y < 0 || y > 94) {
            if (mode == 6) mode = 0;
            return 0;
    }

    if (x > decx+lb*0 && x < decx+lb*1) effaceTout();
    if (x > decx+lb*1 && x < decx+lb*2) mode = 6; // Couleur
    if (x > decx+lb*2 && x < decx+lb*3) mode = 4; // Recadre
    if (x > decx+lb*3 && x < decx+lb*4) mode = 0; // Segments
    if (x > decx+lb*4 && x < decx+lb*5) mode = 2; // Carrés
    if (x > decx+lb*5 && x < decx+lb*6) mode = 1; // Cercles
    if (x > decx+lb*6 && x < decx+lb*7) mode = 5; // Ellipses
    if (x > decx+lb*7 && x < decx+lb*8) mode = 3; // Bézier

    if (mode == 6) return 0; // Couleur, retourner aucun changement car modif directe

    return 1;
}

void mouse(int button, int state, int x, int y)
{
    int sourisX, sourisY;

	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
        if (menuMode(x, y)) {
            mode_tmp = -1;
            return;
        }
        mode_tmp = mode;

        bouton = 0;
		sourisX = x - glutGet(GLUT_WINDOW_WIDTH) / 2;
		sourisY = -y + glutGet(GLUT_WINDOW_HEIGHT) / 2;

		magnetisme(&sourisX, &sourisY, 0, 10);

        switch (mode) {
            case 0 : // Segments
                ajoutePoint(0, sourisX, sourisY);
                ajoutePoint(0, sourisX, sourisY);
                break;
            case 1 : // Cercles
                ajoutePoint(1, sourisX, sourisY);
                ajoutePoint(1, sourisX, sourisY);
                break;
            case 2 : // Carrés
                ajoutePoint(2, sourisX, sourisY);
                ajoutePoint(2, sourisX, sourisY);
                break;
            case 3 : { // Bézier
                    if (!pts) {
                        ajoutePoint(3, sourisX, sourisY);
                        ajoutePoint(3, sourisX, sourisY);
                        ajoutePoint(3, sourisX, sourisY);
                        ajoutePoint(3, sourisX, sourisY);
                    }
                    else {
                        modifPoint(3, sourisX, sourisY, -1);
                        modifPoint(3, sourisX, sourisY, -2);
                    }
                    pts = !pts;
                }
                break;
            case 4 : // Recadre
                rxa = sourisX;
                rya = sourisY;
                rxb = rxa;
                ryb = rya;
                break;
            case 5 : // Ellipses
                ajoutePoint(5, sourisX, sourisY);
                ajoutePoint(5, sourisX, sourisY);
                break;
            case 6 : // Couleur
                couleur(x, y, 0);
                break;
        }
		affichage();
	}

	if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
        posX = x;
        posY = y;

        menuMode(x, y);
        mode_tmp = mode;
        bouton = 1;
        switch(mode) {
            case 6 : // Couleur
                couleur(x, y, 1);
                break;
        }
        affichage();
	}

	if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) {
        posX = x;
        posY = y;

        menuMode(x, y);
        mode_tmp = mode;
        bouton = 2;
        switch(mode) {
            case 6 : // Couleur
                couleur(x, y, 2);
                break;
        }
        affichage();
	}
}

void mouseMove(int x,int y) {
    int sourisX, sourisY;

    if (mode_tmp != mode) return;

    if (bouton == 0) { // Clic gauche
        sourisX = x - glutGet(GLUT_WINDOW_WIDTH) / 2;
        sourisY = -y + glutGet(GLUT_WINDOW_HEIGHT) / 2;

        switch(mode) {
            case 0 : // Segments
                magnetisme(&sourisX, &sourisY, -2, 10);
                modifPoint(0, sourisX, sourisY, -1);
                break;
            case 1 : // Cercles
                magnetisme(&sourisX, &sourisY, -2, 10);
                modifPoint(1, sourisX, sourisY, -1);
                break;
            case 2 : // Carrés
                magnetisme(&sourisX, &sourisY, -2, 10);
                modifPoint(2, sourisX, sourisY, -1);
                break;
            case 3 : { // Bézier
                    magnetisme(&sourisX, &sourisY, -4, 10);
                    if (pts) modifPoint(3, sourisX, sourisY, -3);
                    else modifPoint(3, sourisX, sourisY, -2);
                }
                break;
            case 4 : // Recadre
                rxb = sourisX;
                ryb = sourisY;
                break;
            case 5 : // Ellipses
                magnetisme(&sourisX, &sourisY, -2, 10);
                modifPoint(5, sourisX, sourisY, -1);
                break;
            case 6 : // Couleur
                couleur(x, y, 0);
                break;
        }
        affichage();
    }

    else if (bouton == 1) { // Clic droit
        if (mode == 6) {
            couleur(x, y, 1);
        }
        else zoomVue(x, y);

        affichage();
    }

    else if (bouton == 2) { // Clic milieu
        if (mode == 6) {
            couleur(x, y, 2);
        }
        else bougeVue(x, y);

        affichage();
    }
}


void clavier(unsigned char touche,int x,int y){
	switch (touche){
		case ' ': // Change mode
			mode++;
			mode = mode % modeNb;
            pts = 0;
			break;

		case '+':
			subd++;
            affichage();
			break;

		case '-':
			subd--;
			if (!subd) subd = 1;
            affichage();
			break;

		case 'q':
			exit(0);
	}
}



prototypes.h

struct CodeSegment {
   int somme;
   int gauche;
   int droite;
   int haut;
   int bas;
   int code;
};

void affichage(void);
void clavier(unsigned char touche,int x,int y);
void mouse(int bouton,int etat,int x,int y);
void mouseMove(int x,int y);

AUX_RGBImageRec *LoadBMP( char *Filename );
int LoadGLTextures();

void afficheMenu();
void initPoints();
void videPoints();
void ajoutePoint(int m, int x, int y);
void modifPoint(int m, int x, int y, int id);
void couleur(int x, int y, int id);

void affichage();
void affichageSegments();
void affichageCercles();
void affichageCarres();
void affichageEllipses();
void affichageBeziers();

void fenetrage(int xa, int ya, int xb, int yb, int rempCote, double* c);
void fenetragePixel(int x, int y, double* c);
void remplissageX(int xa, int xb, int y);

void affichageRecadre(int xa, int ya, int xb, int yb);
void affichageEllipse(int xc, int yc, int xb, int yb);
void affichageCercle(int xc, int yc, int xb, int yb);
void affichageSegment(int xa, int ya, int xb, int yb, int rempCote, double* c);
void affichageCarre(int xa, int ya, int xb, int yb);
void affichageBezier(int xa, int ya, int xb, int yb, int xc, int yc, int xd, int yd);

void bougeVue(int x, int y);
void zoomVue(int x, int y);
void magnetisme(int* x, int* y, int max, int m);
void effaceTout();

int menuMode(int x, int y);
void mouse(int button, int state, int x, int y);
void mouseMove(int x,int y);
void clavier(unsigned char touche,int x,int y);