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);
}