L'exécutable

Fichier source : Bresenham2.cpp

/* Auteur: Nicolas JANEY                 */
/* nicolas.janey@univ-fcomte.fr          */
/* Novembre 2007                         */
/* Rasterisation de segments de droites  */
/* trois dimensions et de facettes       */
/* deux dimensions                       */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>

/* Variables globales de definition de couleurs */

static float noir[] = { 0.0F,0.0F,0.0F,1.0F };
static float rouge[] = { 1.0F,0.0F,0.0F,1.0F };
static float bleu[] = { 0.0F,0.0F,1.0F,1.0F };
static float jaune[] = { 1.0F,1.0F,0.0F,1.0F };
static float vertFonce[] = { 0.0F,0.5F,0.0F,1.0F };

/* Variables globales de gestion                */
/* de l'interactivite clavier et souris         */

static int clic = 0;
static int mx;
static int my;
static float rx = 0.0F;
static float ry = 0.0F;
static float zoom = 1.0F;

struct coordonnees {
  int x;
  int y;
  int z;
  int t; };

struct segment {
  coordonnees pi;
  coordonnees pf; };

struct facette {
  coordonnees p1;
  coordonnees p2;
  coordonnees p3; };

static int aff = 0;
static int mode = 0;

static segment seg1 = { {  -9,  2,  3,1 },
                        {   8,  8, -4,1 } };
static segment seg2 = { {   3, -9, -6,1 },
                        {   9,  6,  5,1 } };
static segment seg3 = { {  -8, -2,-10,1 },
                        {  -1, -7,  9,1 } };
static facette f = { {  -9,  2,  0,1 },
                     {   9,  6,  0,1 },
                     {   6, -8,  0,1 } };

void pixel(int x,int y,float *c) {
  glColor4fv(c);
  glBegin(GL_QUADS);
  glVertex2i(x,y);
  glVertex2i(x+1,y);
  glVertex2i(x+1,y+1);
  glVertex2i(x,y+1);
  glEnd();
  glColor4fv(noir);
  glBegin(GL_LINE_LOOP);
  glVertex2i(x,y);
  glVertex2i(x+1,y);
  glVertex2i(x+1,y+1);
  glVertex2i(x,y+1);
  glEnd();
}

void pixel(int x,int y,int z,float *c) {
  glColor4fv(c);
  glPushMatrix();
  glTranslatef(x+0.5F,y+0.5F,z+0.5F);
  glutWireCube(1.0);
  glPopMatrix();
}

void lignePixels(int xi,int yi,int xf,int yf,float *c) {
  int i,cumul;
  int x = xi;
  int y = yi;
  int dx = xf - xi;
  int dy = yf - yi;
  int xinc = ( dx > 0 ) ? 1 : -1;
  int yinc = ( dy > 0 ) ? 1 : -1;
  dx = abs(dx);
  dy = abs(dy);
  pixel(x,y,c);
  if ( dx > dy ) {
    cumul = dx / 2;
    for ( i = 1 ; i <= dx ; i++ ) {
      x += xinc;
      cumul += dy;
      if (cumul >= dx) {
        cumul -= dx;
        y += yinc; }
      pixel(x,y,c); } }
    else {
    cumul = dy / 2;
    for ( i = 1 ; i <= dy ; i++ ) {
      y += yinc;
      cumul += dx;
      if ( cumul >= dy ) {
        cumul -= dy;
        x += xinc; }
      pixel(x,y,c); } }
}

void lignePixels(int xi,int yi,int zi,int xf,int yf,int zf,float *c) {
  int i;
  int x = xi;
  int y = yi;
  int z = zi;
  int dx = xf - xi;
  int dy = yf - yi;
  int dz = zf - zi;
  int xinc = ( dx > 0 ) ? 1 : -1;
  int yinc = ( dy > 0 ) ? 1 : -1;
  int zinc = ( dz > 0 ) ? 1 : -1;
  dx = abs(dx);
  dy = abs(dy);
  dz = abs(dz);
  pixel(x,y,z,c);
  if ( ( dx >= dy ) && ( dx >= dz ) ) {
    int cumuly = dx / 2;
    int cumulz = dx / 2;
    for ( i = 1 ; i <= dx ; i++ ) {
      x += xinc;
      cumuly += dy;
      cumulz += dz;
      if (cumuly >= dx) {
        cumuly -= dx;
        y += yinc; }
      if (cumulz >= dx) {
        cumulz -= dx;
        z += zinc; }
      pixel(x,y,z,c); } }
    else
    if ( dy > dz ) {
      int cumulx = dy / 2;
      int cumulz = dy / 2;
      for ( i = 1 ; i <= dy ; i++ ) {
        y += yinc;
        cumulx += dx;
        cumulz += dz;
        if ( cumulx >= dy ) {
          cumulx -= dy;
          x += xinc; }
        if ( cumulz >= dy ) {
          cumulz -= dy;
          z += zinc; }
        pixel(x,y,z,c); } }
      else {
      int cumulx = dz / 2;
      int cumuly = dz / 2;
      for ( i = 1 ; i <= dz ; i++ ) {
        z += zinc;
        cumulx += dx;
        cumuly += dy;
        if ( cumulx >= dz ) {
          cumulx -= dz;
          x += xinc; }
        if ( cumuly >= dz ) {
          cumuly -= dz;
          y += yinc; }
        pixel(x,y,z,c); } }
}

void dessineSegment(float *c,coordonnees *pi,coordonnees *pf) {
  glColor4fv(c);
  glLineWidth(3.0);
  glBegin(GL_LINES);
  glVertex3d(pi->x+0.5,pi->y+0.5,0.5);
  glVertex3d(pf->x+0.5,pf->y+0.5,0.5);
  glEnd();
  glLineWidth(1.0);
}

void dessineSegment(float *c,segment *s) {
  dessineSegment(c,&s->pi,&s->pf);
}

void dessineQuadrillage(float *c,int n) {
  int i;
  glColor4fv(c);
  glBegin(GL_LINES);
  for ( i = -n ; i <= n ; i++ ) {
    glVertex2d(-n,i);
    glVertex2d(n,i); }
  for ( i = -n ; i <= n ; i++ ) {
    glVertex2d(i,-n);
    glVertex2d(i,n); }
  glEnd();
}

void display1() {
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  glPushMatrix();
  switch (aff) {
    case 0 : dessineSegment(rouge,&seg1);
             dessineSegment(rouge,&seg2);
             dessineSegment(rouge,&seg3);
             break;
    case 1 : dessineQuadrillage(bleu,11);
             dessineSegment(rouge,&seg1);
             dessineSegment(rouge,&seg2);
             dessineSegment(rouge,&seg3);
             break;
    case 2 : dessineQuadrillage(bleu,11);
             lignePixels(seg1.pi.x,seg1.pi.y,
                         seg1.pf.x,seg1.pf.y,
                         vertFonce);
             lignePixels(seg2.pi.x,seg2.pi.y,
                         seg2.pf.x,seg2.pf.y,
                         vertFonce);
             lignePixels(seg3.pi.x,seg3.pi.y,
                         seg3.pf.x,seg3.pf.y,
                         vertFonce);
             dessineSegment(rouge,&seg1);
             dessineSegment(rouge,&seg2);
             dessineSegment(rouge,&seg3);
             break; }
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
}

void dessineSegment3D(float *c,coordonnees *pi,coordonnees *pf) {
  glColor4fv(c);
  glLineWidth(3.0);
  glBegin(GL_LINES);
  glVertex3d(pi->x+0.5,pi->y+0.5,pi->z+0.5);
  glVertex3d(pf->x+0.5,pf->y+0.5,pf->z+0.5);
  glEnd();
  glLineWidth(1.0);
}

void dessineSegment3D(float *c,segment *s) {
  dessineSegment3D(c,&s->pi,&s->pf);
}

void dessineQuadrillage3D(float *c,int n) {
  glColor4fv(c);
  glPushMatrix();
  glutWireCube(2*n);
  glPopMatrix();
}

void display2() {
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  glPushMatrix();
  glRotatef(rx,1.0F,0.0F,0.0F);
  glRotatef(ry,0.0F,1.0F,0.0F);
  glScalef(zoom,zoom,zoom);
  switch (aff) {
    case 0 : dessineSegment3D(rouge,&seg1);
             dessineSegment3D(rouge,&seg2);
             dessineSegment3D(rouge,&seg3);
             break;
    case 1 : dessineQuadrillage3D(bleu,11);
             dessineSegment3D(rouge,&seg1);
             dessineSegment3D(rouge,&seg2);
             dessineSegment3D(rouge,&seg3);
             break;
    case 2 : dessineQuadrillage3D(bleu,11);
             lignePixels(seg1.pi.x,seg1.pi.y,seg1.pi.z,
                         seg1.pf.x,seg1.pf.y,seg1.pf.z,
                         vertFonce);
             lignePixels(seg2.pi.x,seg2.pi.y,seg2.pi.z,
                         seg2.pf.x,seg2.pf.y,seg2.pf.z,
                         vertFonce);
             lignePixels(seg3.pi.x,seg3.pi.y,seg3.pi.z,
                         seg3.pf.x,seg3.pf.y,seg3.pf.z,
                         vertFonce);
             dessineSegment3D(rouge,&seg1);
             dessineSegment3D(rouge,&seg2);
             dessineSegment3D(rouge,&seg3);
             break; }
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
}

void pixel(int x,int y,int *tx) {
  tx[y] = x;
}

void calculBordure(int xi,int yi,int xf,int yf,int *tx) {
  int i,cumul;
  int x = xi;
  int y = yi;
  int dx = xf - xi;
  int dy = yf - yi;
  int xinc = ( dx > 0 ) ? 1 : -1;
  int yinc = ( dy > 0 ) ? 1 : -1;
  dx = abs(dx);
  dy = abs(dy);
  pixel(x,y,tx);
  if ( dx > dy ) {
    cumul = dx / 2;
    for ( i = 1 ; i <= dx ; i++ ) {
      x += xinc;
      cumul += dy;
      if (cumul >= dx) {
        cumul -= dx;
        y += yinc; }
      pixel(x,y,tx); } }
    else {
    cumul = dy / 2;
    for ( i = 1 ; i <= dy ; i++ ) {
      y += yinc;
      cumul += dx;
      if ( cumul >= dy ) {
        cumul -= dy;
        x += xinc; }
      pixel(x,y,tx); } }
}

void permute(coordonnees *c1,coordonnees *c2) {
  coordonnees c = *c1;
  *c1 = *c2;
  *c2 = c;
}

void traceFacette(facette *f,float *c) {
  facette fc = *f;
  if ( fc.p3.y < fc.p2.y )
    permute(&fc.p3,&fc.p2);
  if ( fc.p2.y < fc.p1.y )
    permute(&fc.p2,&fc.p1);
  if ( fc.p3.y < fc.p2.y )
    permute(&fc.p3,&fc.p2);
  int xmin = min(fc.p1.x,min(fc.p2.x,fc.p3.x));
  int ymin = fc.p1.y;
  int ymax = fc.p3.y;
  int dy = ymax-ymin+1;
  int *x1 =(int *) calloc(dy,sizeof(int));
  int *x2 =(int *) malloc(dy*sizeof(int));
  int i;
  calculBordure(fc.p1.x-xmin+1,fc.p1.y-ymin,fc.p2.x-xmin+1,fc.p2.y-ymin,x2);
  calculBordure(fc.p2.x-xmin+1,fc.p2.y-ymin,fc.p3.x-xmin+1,fc.p3.y-ymin,x2);
  calculBordure(fc.p3.x-xmin+1,fc.p3.y-ymin,fc.p1.x-xmin+1,fc.p1.y-ymin,x1);
  for ( i = 0 ; i < dy ; i++ ) {
    int dx = abs(x1[i]-x2[i])+1;
    int x = min(x1[i],x2[i])+xmin-1;
    for ( int j = 0 ; j < dx ; j++ ) {
      pixel(x,i+ymin,c);
      x++; } }
  free(x1);
  free(x2);
}

void traceFacette3D(facette *f,float *c) {
  facette fc = *f;
  if ( fc.p3.y < fc.p2.y )
    permute(&fc.p3,&fc.p2);
  if ( fc.p2.y < fc.p1.y )
    permute(&fc.p2,&fc.p1);
  if ( fc.p3.y < fc.p2.y )
    permute(&fc.p3,&fc.p2);
  int xmin = min(fc.p1.x,min(fc.p2.x,fc.p3.x));
  int ymin = fc.p1.y;
  int ymax = fc.p3.y;
  int dy = ymax-ymin+1;
  int *x1 =(int *) calloc(dy,sizeof(int));
  int *x2 =(int *) malloc(dy*sizeof(int));
  int i;
  calculBordure(fc.p1.x-xmin+1,fc.p1.y-ymin,fc.p2.x-xmin+1,fc.p2.y-ymin,x2);
  calculBordure(fc.p2.x-xmin+1,fc.p2.y-ymin,fc.p3.x-xmin+1,fc.p3.y-ymin,x2);
  calculBordure(fc.p3.x-xmin+1,fc.p3.y-ymin,fc.p1.x-xmin+1,fc.p1.y-ymin,x1);
  for ( i = 0 ; i < dy ; i++ ) {
    int dx = abs(x1[i]-x2[i])+1;
    int x = min(x1[i],x2[i])+xmin-1;
    for ( int j = 0 ; j < dx ; j++ ) {
      pixel(x,i+ymin,0,c);
      x++; } }
  free(x1);
  free(x2);
}

void display3() {
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  glPushMatrix();
  switch (aff) {
    case 0 : dessineSegment(rouge,&f.p1,&f.p2);
             dessineSegment(rouge,&f.p2,&f.p3);
             dessineSegment(rouge,&f.p3,&f.p1);
             break;
    case 1 : dessineQuadrillage(bleu,11);
             dessineSegment(rouge,&f.p1,&f.p2);
             dessineSegment(rouge,&f.p2,&f.p3);
             dessineSegment(rouge,&f.p3,&f.p1);
             break;
    case 2 : dessineQuadrillage(bleu,11);
             lignePixels(f.p1.x,f.p1.y,
                         f.p2.x,f.p2.y,
                         vertFonce);
             lignePixels(f.p2.x,f.p2.y,
                         f.p3.x,f.p3.y,
                         vertFonce);
             lignePixels(f.p3.x,f.p3.y,
                         f.p1.x,f.p1.y,
                         vertFonce);
             dessineSegment(rouge,&f.p1,&f.p2);
             dessineSegment(rouge,&f.p2,&f.p3);
             dessineSegment(rouge,&f.p3,&f.p1);
             break;
    case 3 : dessineQuadrillage(bleu,11);
             traceFacette(&f,jaune);
             lignePixels(f.p1.x,f.p1.y,
                         f.p2.x,f.p2.y,
                         vertFonce);
             lignePixels(f.p2.x,f.p2.y,
                         f.p3.x,f.p3.y,
                         vertFonce);
             lignePixels(f.p3.x,f.p3.y,
                         f.p1.x,f.p1.y,
                         vertFonce);
             dessineSegment(rouge,&f.p1,&f.p2);
             dessineSegment(rouge,&f.p2,&f.p3);
             dessineSegment(rouge,&f.p3,&f.p1);
             break; }
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
}

void display4() {
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  glPushMatrix();
  glRotatef(rx,1.0F,0.0F,0.0F);
  glRotatef(ry,0.0F,1.0F,0.0F);
  glScalef(zoom,zoom,zoom);
  switch (aff) {
    case 0 : dessineSegment3D(rouge,&f.p1,&f.p2);
             dessineSegment3D(rouge,&f.p2,&f.p3);
             dessineSegment3D(rouge,&f.p3,&f.p1);
             break;
    case 1 : dessineQuadrillage3D(bleu,11);
             dessineSegment3D(rouge,&f.p1,&f.p2);
             dessineSegment3D(rouge,&f.p2,&f.p3);
             dessineSegment3D(rouge,&f.p3,&f.p1);
             break;
    case 2 : dessineQuadrillage3D(bleu,11);
             lignePixels(f.p1.x,f.p1.y,f.p1.z,
                         f.p2.x,f.p2.y,f.p2.z,
                         vertFonce);
             lignePixels(f.p2.x,f.p2.y,f.p2.z,
                         f.p3.x,f.p3.y,f.p3.z,
                         vertFonce);
             lignePixels(f.p3.x,f.p3.y,f.p3.z,
                         f.p1.x,f.p1.y,f.p1.z,
                         vertFonce);
             dessineSegment3D(rouge,&f.p1,&f.p2);
             dessineSegment3D(rouge,&f.p2,&f.p3);
             dessineSegment3D(rouge,&f.p3,&f.p1);
             break;
    case 3 : dessineQuadrillage3D(bleu,11);
             traceFacette3D(&f,jaune);
             lignePixels(f.p1.x,f.p1.y,f.p1.z,
                         f.p2.x,f.p2.y,f.p2.z,
                         vertFonce);
             lignePixels(f.p2.x,f.p2.y,f.p2.z,
                         f.p3.x,f.p3.y,f.p3.z,
                         vertFonce);
             lignePixels(f.p3.x,f.p3.y,f.p3.z,
                         f.p1.x,f.p1.y,f.p1.z,
                         vertFonce);
             dessineSegment3D(rouge,&f.p1,&f.p2);
             dessineSegment3D(rouge,&f.p2,&f.p3);
             dessineSegment3D(rouge,&f.p3,&f.p1);
             break; }
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
}

void myinit() {
  glClearColor(0.8F,0.8F,0.8F,1.0F);
}

/* Fonction executee lors d'un changement       */
/* de la taille de la fenetre OpenGL            */
/* Configuration d'une camera de visualisation  */
/* en projection parallele                      */

void reshape(int tx,int ty) {
  glViewport(0,0,tx,ty);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho((-12.0*tx)/ty,(12.0*tx)/ty,-12.0,12.0,-20.0,20.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

/* Fonction executee lors d'un clic de souris   */
/* dans la fenetre                              */

void mouse(int bouton,int etat,int x,int y) {
  if ( bouton == GLUT_LEFT_BUTTON ) {
    if ( etat == GLUT_DOWN ) {
      clic = 1;
      mx = x;
      my = y; }
    if ( etat == GLUT_UP ) {
      clic = 0; } }
}

/* Fonction executee lors d'un deplacement      */
/* de la souris sur la fenetre                  */
/* avec un bouton appuye                        */

void motion(int x,int y) {
  if ( clic ) {
    ry += (x-mx);
    rx += (y-my);
    mx = x;
    my = y;
    glutPostRedisplay(); }
}

/* Fonction executee lors de la frappe          */
/* d'une touche alphanumerique du clavier       */

void key(unsigned char key,int x,int y) {
  switch ( key ) {
    case 43   : zoom *= 1.01F;
                glutPostRedisplay();
                break;
    case 45   : zoom /= 1.01F;
                glutPostRedisplay();
                break;
    case 0x1B : exit(0);
                break;
    case 0x20 : mode = (mode+1)%4;
                switch (mode) {
                  case 0 : glutDisplayFunc(display1);
                           glutMouseFunc(NULL);
                           glutMotionFunc(NULL);
                           aff = 0;
                           break;
                  case 1 : glutDisplayFunc(display2);
                           glutMouseFunc(mouse);
                           glutMotionFunc(motion);
                           aff = 0;
                           break;
                  case 2 : glutDisplayFunc(display3);
                           glutMouseFunc(NULL);
                           glutMotionFunc(NULL);
                           aff = 0;
                           break;
                  case 3 : glutDisplayFunc(display4);
                           glutMouseFunc(mouse);
                           glutMotionFunc(motion);
                           aff = 0;
                           break; }
                glutPostRedisplay();
                break;
    case 0x0D : aff = (aff+1)%4;
                glutPostRedisplay();
                break; }
}

/* Fonction principale                          */

int main(int argc,char **argv) {
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
  glutInitWindowSize(350,350); 
  glutInitWindowPosition(50,50); 
  glutCreateWindow("Rasterisation selon Bresenham"); 
  myinit(); 
  glutReshapeFunc(reshape);
  glutKeyboardFunc(key);
  glutMouseFunc(mouse);
  glutMotionFunc(motion);
  glutDisplayFunc(display1);
  glutMainLoop();
  return(0);
}

RETOUR