Ci-dessus: SegmentEtFacette2D, dessin sans précaution
Ci-dessus: dessin avec gestion des bords droit et gauche
Le source : SegmentEtFacette2Dv2.cpp
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Novembre 2005 */
/* Illustration du remplissage */
/* d'une facette 2D */
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "ModuleCouleurs.h"
#include "ModuleMenus.h"
#include "ModuleReshape.h"
#include "ModuleFont.h"
#define YMAX 40
#define XMAX 40
static int aff = 0;
static int yy = 0;
static int b = 1;
static int f = 0;
static int sx = 0;
static int sy = 0;
static int x1 = 35;
static int y1 = 22;
static int x2 = 11;
static int y2 = 37;
static int x3 = 3;
static int y3 = 4;
static int f1;
static int fv;
struct pix {
int x;
int y; } pix;
int *ligneCote(int xi,int yi,int xf,int yf) {
int *px =(int *) calloc(YMAX,sizeof(int));
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);
px[y] = x;
if ( dx > dy ) {
cumul = dx / 2;
for ( i = 1; i <= dx; i++ ) {
x += xinc;
cumul += dy;
if (cumul >= dx) {
cumul -= dx;
y += yinc; }
px[y] = x; } }
else {
cumul = dy / 2;
for ( i = 1; i <= dy; i++ ) {
y += yinc;
cumul += dx;
if ( cumul >= dy ) {
cumul -= dy;
x += xinc; }
px[y] = x; } }
return(px);
}
void myinit() {
glDepthFunc(GL_LESS);
glShadeModel(GL_SMOOTH);
glClearColor(0.8F,0.8F,0.8F,1.0F);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
}
void bordFacette(int x1,int y1,int x2,int y2,int x3,int y3,float *coul) {
glPushMatrix();
glColor4fv(coul);
glLineWidth(3.0);
glBegin(GL_LINE_LOOP);
glVertex2f(x1+0.5F,y1+0.5F);
glVertex2f(x2+0.5F,y2+0.5F);
glVertex2f(x3+0.5F,y3+0.5F);
glEnd();
glLineWidth(1.0);
glPopMatrix();
}
void facette(int x1,int y1,int x2,int y2,int x3,int y3,float *coul) {
glPushMatrix();
glColor4fv(coul);
glBegin(GL_TRIANGLES);
glVertex2f(x1+0.5F,y1+0.5F);
glVertex2f(x2+0.5F,y2+0.5F);
glVertex2f(x3+0.5F,y3+0.5F);
glEnd();
glPopMatrix();
}
void pixel(int x,int y,float *coul) {
glColor3fv(coul);
glBegin(GL_QUADS);
glVertex2f(x,y);
glVertex2f(x+1,y);
glVertex2f(x+1,y+1);
glVertex2f(x,y+1);
glEnd();
glColor3fv(couleurNoir());
glBegin(GL_LINE_LOOP);
glVertex2f(x,y);
glVertex2f(x+1,y);
glVertex2f(x+1,y+1);
glVertex2f(x,y+1);
glEnd();
}
void pixel(int x,int y) {
glBegin(GL_QUADS);
glVertex2f(x,y);
glVertex2f(x+1,y);
glVertex2f(x+1,y+1);
glVertex2f(x,y+1);
glEnd();
}
void ligneDiscrete(int y,int x1,int x2,float *coul) {
if ( x2 != -100 ) {
int i;
int x = x1;
int dx = x2 - x1;
int xinc = ( dx > 0 ) ? 1 : -1;
dx = abs(dx);
for ( i = 0; i <= dx; i++ ) {
pixel(x,y,coul);
x += xinc; } }
}
void echange(int *x1,int *y1,int *x2,int *y2) {
float aux = *x1;
*x1 = *x2;
*x2 = aux;
aux = *y1;
*y1 = *y2;
*y2 = aux;
}
int typeFacette(int x1,int y1,int x2,int y2,int x3,int y3) {
int dx2 = x2-x1;
int dy2 = y2-y1;
int dx3 = x3-x1;
int dy3 = y3-y1;
int t = dy3*dx2-dy2-dx3;
return((t > 0) ? 1 : 0);
}
void facetteDiscrete(int x1,int y1,int x2,int y2,int x3,int y3,float *coul) {
if ( y1 > y2 )
echange(&x1,&y1,&x2,&y2);
if ( y2 > y3 )
echange(&x2,&y2,&x3,&y3);
if ( y1 > y2 )
echange(&x1,&y1,&x2,&y2);
int type = typeFacette(x1,y1,x2,y2,x3,y3);
int *px1;
int *px2;
int *px3;
if ( type ) {
px1 =( x1 < x2 ) ? ligneCote(x1,y1,x2,y2) : ligneCote(x2,y2,x1,y1);
px2 =( x2 < x3 ) ? ligneCote(x2,y2,x3,y3) : ligneCote(x3,y3,x2,y2);
px3 =( x3 < x1 ) ? ligneCote(x1,y1,x3,y3) : ligneCote(x3,y3,x1,y1); }
else {
px1 =( x1 > x2 ) ? ligneCote(x1,y1,x2,y2) : ligneCote(x2,y2,x1,y1);
px2 =( x2 > x3 ) ? ligneCote(x2,y2,x3,y3) : ligneCote(x3,y3,x2,y2);
px3 =( x3 > x1 ) ? ligneCote(x1,y1,x3,y3) : ligneCote(x3,y3,x1,y1); }
int y;
for ( y = y1 ; y < y2 ; y++ )
ligneDiscrete(y,px1[y],px3[y],coul);
for ( ; y <= y3 ; y++ )
ligneDiscrete(y,px2[y],px3[y],coul);
free(px3);
free(px2);
free(px1);
}
struct pix *lignePixels(int xi,int yi,int xf,int yf,int *t) {
struct pix *p;
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);
if ( dx > dy ) {
p =(struct pix *) calloc(*t = dx+1,sizeof(struct pix));
p[0].x = x;
p[0].y = y;
int ind = 1;
cumul = dx / 2;
for ( i = 1; i <= dx; i++ ) {
x += xinc;
cumul += dy;
if (cumul >= dx) {
cumul -= dx;
y += yinc; }
p[ind].x = x;
p[ind].y = y;
ind++; } }
else {
p =(struct pix *) calloc(*t = dy+1,sizeof(struct pix));
p[0].x = x;
p[0].y = y;
int ind = 1;
cumul = dy / 2;
for ( i = 1; i <= dy; i++ ) {
y += yinc;
cumul += dx;
if ( cumul >= dy ) {
cumul -= dy;
x += xinc; }
p[ind].x = x;
p[ind].y = y;
ind++; } }
return(p);
}
void lignePixels(int xi,int yi,int xf,int yf,float *coul) {
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,coul);
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,coul); } }
else {
cumul = dy / 2;
for ( i = 1; i <= dy; i++ ) {
y += yinc;
cumul += dx;
if ( cumul >= dy ) {
cumul -= dy;
x += xinc; }
pixel(x,y,coul); } }
}
void coteFacette(int x1,int y1,int x2,int y2,float *coul) {
glPushMatrix();
lignePixels(x1,y1,x2,y2,coul);
glPopMatrix();
}
void facetteDiscreteTrame(int x1,int y1,int x2,int y2,int x3,int y3,
int yy,
float *c,float *c1,float *c2,float *c3) {
if ( y1 > y2 )
echange(&x1,&y1,&x2,&y2);
if ( y2 > y3 )
echange(&x2,&y2,&x3,&y3);
if ( y1 > y2 )
echange(&x1,&y1,&x2,&y2);
int type = typeFacette(x1,y1,x2,y2,x3,y3);
int *px1;
int *px2;
int *px3;
if ( type ) {
px1 =( x1 < x2 ) ? ligneCote(x1,y1,x2,y2) : ligneCote(x2,y2,x1,y1);
px2 =( x2 < x3 ) ? ligneCote(x2,y2,x3,y3) : ligneCote(x3,y3,x2,y2);
px3 =( x3 < x1 ) ? ligneCote(x1,y1,x3,y3) : ligneCote(x3,y3,x1,y1); }
else {
px1 =( x1 > x2 ) ? ligneCote(x1,y1,x2,y2) : ligneCote(x2,y2,x1,y1);
px2 =( x2 > x3 ) ? ligneCote(x2,y2,x3,y3) : ligneCote(x3,y3,x2,y2);
px3 =( x3 > x1 ) ? ligneCote(x1,y1,x3,y3) : ligneCote(x3,y3,x1,y1); }
yy += y1;
int y;
for ( y = y1 ; ( y < y2 ) && ( y <= yy) ; y++ )
ligneDiscrete(y,px1[y],px3[y],c);
for ( ; ( y <= y3 ) && ( y <= yy) ; y++ )
ligneDiscrete(y,px2[y],px3[y],c);
free(px3);
free(px2);
free(px1);
}
void pixelsExtremesFacette(int x1,int y1,int x2,int y2,int x3,int y3,float *coul) {
if ( y1 > y2 )
echange(&x1,&y1,&x2,&y2);
if ( y2 > y3 )
echange(&x2,&y2,&x3,&y3);
if ( y1 > y2 )
echange(&x1,&y1,&x2,&y2);
int type = typeFacette(x1,y1,x2,y2,x3,y3);
int *px1;
int *px2;
int *px3;
if ( type ) {
px1 =( x1 < x2 ) ? ligneCote(x1,y1,x2,y2) : ligneCote(x2,y2,x1,y1);
px2 =( x2 < x3 ) ? ligneCote(x2,y2,x3,y3) : ligneCote(x3,y3,x2,y2);
px3 =( x3 < x1 ) ? ligneCote(x1,y1,x3,y3) : ligneCote(x3,y3,x1,y1); }
else {
px1 =( x1 > x2 ) ? ligneCote(x1,y1,x2,y2) : ligneCote(x2,y2,x1,y1);
px2 =( x2 > x3 ) ? ligneCote(x2,y2,x3,y3) : ligneCote(x3,y3,x2,y2);
px3 =( x3 > x1 ) ? ligneCote(x1,y1,x3,y3) : ligneCote(x3,y3,x1,y1); }
int y;
for ( y = y1 ; y < y2 ; y++ ) {
pixel(px1[y],y,coul);
pixel(px3[y],y,coul); }
for ( ; y <= y3 ; y++ ) {
pixel(px2[y],y,coul);
pixel(px3[y],y,coul); }
free(px3);
free(px2);
free(px1);
}
void cotesFacette(int x1,int y1,int x2,int y2,int x3,int y3,
float *c1,float *c2,float *c3) {
if ( y1 > y2 )
echange(&x1,&y1,&x2,&y2);
if ( y2 > y3 )
echange(&x2,&y2,&x3,&y3);
if ( y1 > y2 )
echange(&x1,&y1,&x2,&y2);
coteFacette(x1,y1,x2,y2,c1);
coteFacette(x1,y1,x3,y3,c2);
coteFacette(x2,y2,x3,y3,c3);
}
void display() {
switch (f) {
case 0 : x1 = 35;
y1 = 22;
x2 = 11;
y2 = 37;
x3 = 3;
y3 = 4;
break;
case 1 : x1 = 38;
y1 = 19;
x2 = 21;
y2 = 22;
x3 = 3;
y3 = 14;
break;
case 2 : x1 = 38;
y1 = 24;
x2 = 21;
y2 = 19;
x3 = 3;
y3 = 31;
break; }
if ( sx ) {
y1 = YMAX/2+(YMAX/2-y1);
y2 = YMAX/2+(YMAX/2-y2);
y3 = YMAX/2+(YMAX/2-y3); }
if ( sy ) {
x1 = XMAX/2+(XMAX/2-x1);
x2 = XMAX/2+(XMAX/2-x2);
x3 = XMAX/2+(XMAX/2-x3); }
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
switch (aff) {
case 0 : facette(x1,y1,x2,y2,x3,y3,couleurRouge());
bordFacette(x1,y1,x2,y2,x3,y3,couleurNoir());
break;
case 1 : coteFacette(x1,y1,x2,y2,couleurRouge());
break;
case 2 : coteFacette(x1,y1,x3,y3,couleurVert());
break;
case 3 : coteFacette(x2,y2,x3,y3,couleurBleu());
break;
case 4 : cotesFacette(x1,y1,x2,y2,x3,y3,
couleurRouge(),
couleurVert(),
couleurBleu());
break;
case 5 : pixelsExtremesFacette(x1,y1,x2,y2,x3,y3,
couleurMagenta());
break;
case 6 : facetteDiscreteTrame(x1,y1,x2,y2,x3,y3,
yy,
couleurJaune(),
couleurVert(),
couleurRouge(),
couleurBleu());
if ( b ) {
coteFacette(x1,y1,x2,y2,couleurRouge());
coteFacette(x1,y1,x3,y3,couleurVert());
coteFacette(x2,y2,x3,y3,couleurBleu()); }
break;
case 7 : facetteDiscrete(x1,y1,x2,y2,x3,y3,couleurJaune());
if ( b ) {
coteFacette(x1,y1,x2,y2,couleurRouge());
coteFacette(x1,y1,x3,y3,couleurVert());
coteFacette(x2,y2,x3,y3,couleurBleu()); }
bordFacette(x1,y1,x2,y2,x3,y3,couleurNoir());
break; }
glPopMatrix();
glPushMatrix();
glDisable(GL_DEPTH_TEST);
glPopMatrix();
glFlush();
glutSwapBuffers();
}
void postRedisplay(void) {
glutPostWindowRedisplay(f1);
glutPostWindowRedisplay(fv);
}
void key(unsigned char key,int x,int y) {
switch ( key ) {
case 'y' :
case 'Y' : sy = !sy;
postRedisplay();
break;
case 'x' :
case 'X' : sx = !sx;
postRedisplay();
break;
case 'f' :
case 'F' : f = (f+1)%3;
postRedisplay();
break;
case 'b' :
case 'B' : b = !b;
postRedisplay();
break;
case 0x0D : yy = 0;
aff = (aff+1)%8;
postRedisplay();
break;
case 43 : aff = (aff+1)%8;
postRedisplay();
break;
case 45 : aff = (aff+7)%8;
postRedisplay();
break;
case 32 : yy = (yy+1)%YMAX;
postRedisplay();
break;
case 0x1B : exit(0);
break; }
}
static int vmin(int v1,int v2) {
return(( v1 < v2 ) ? v1 : v2);
}
static int vmax(int v1,int v2) {
return(( v1 > v2 ) ? v1 : v2);
}
int pixelsExtremesFacette(int x1,int y1,int x2,int y2,int x3,int y3,float pos) {
if ( y1 > y2 )
echange(&x1,&y1,&x2,&y2);
if ( y2 > y3 )
echange(&x2,&y2,&x3,&y3);
if ( y1 > y2 )
echange(&x1,&y1,&x2,&y2);
int type = typeFacette(x1,y1,x2,y2,x3,y3);
int *px1;
int *px2;
int *px3;
if ( type ) {
px1 =( x1 < x2 ) ? ligneCote(x1,y1,x2,y2) : ligneCote(x2,y2,x1,y1);
px2 =( x2 < x3 ) ? ligneCote(x2,y2,x3,y3) : ligneCote(x3,y3,x2,y2);
px3 =( x3 < x1 ) ? ligneCote(x1,y1,x3,y3) : ligneCote(x3,y3,x1,y1); }
else {
px1 =( x1 > x2 ) ? ligneCote(x1,y1,x2,y2) : ligneCote(x2,y2,x1,y1);
px2 =( x2 > x3 ) ? ligneCote(x2,y2,x3,y3) : ligneCote(x3,y3,x2,y2);
px3 =( x3 > x1 ) ? ligneCote(x1,y1,x3,y3) : ligneCote(x3,y3,x1,y1); }
int y;
for ( y = y1 ; y < y2 ; y++ ) {
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
int mn = min(px1[y],px3[y]);
int mx = max(px1[y],px3[y]);
simpleBitmapOutput(1,REGULAR6x10,"%2d %3d %3d",y,mn,mx);
pos += 1.0F; }
for ( ; y <= y3 ; y++ ) {
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
int mn = min(px2[y],px3[y]);
int mx = max(px2[y],px3[y]);
simpleBitmapOutput(1,REGULAR6x10,"%2d %3d %3d",y,mn,mx);
pos += 1.0F; }
free(px3);
free(px2);
free(px1);
return(y3-y1+1);
}
void displayV(void) {
glClearColor(0.8F,0.8F,0.8F,1.0F);
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
glPushMatrix();
float pos = 1.0F;
glColor4fv(couleurNoir());
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR8x13,"SOMMETS");
pos += 1.0F;
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR6x10,"P1 : %3d %3d",x1,y1);
pos += 1.0F;
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR6x10,"P2 : %3d %3d",x2,y2);
pos += 1.0F;
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR6x10,"P3 : %3d %3d",x3,y3);
pos += 1.5F;
switch ( aff ) {
case 0 :
case 4 :
case 7 : glutReshapeWindow(85,60);
break;
case 1 : { int t;
struct pix *p = lignePixels(x1,y1,x2,y2,&t);
glutReshapeWindow(85,80+(t+1)*14);
glColor4fv(couleurRougeFonce());
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR8x13,"PIXELS");
pos += 1.0F;
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR6x10," x y");
pos += 1.0F;
for ( int i = 0 ; i < t ; i++ ) {
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR6x10,"%2d %3d %3d",i,p[i].x,p[i].y);
pos += 1.0F; }
free(p); }
break;
case 2 : { int t;
struct pix *p = lignePixels(x1,y1,x3,y3,&t);
glutReshapeWindow(85,80+(t+1)*14);
glColor4fv(couleurVertFonce());
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR8x13,"PIXELS");
pos += 1.0F;
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR6x10," x y");
pos += 1.0F;
for ( int i = 0 ; i < t ; i++ ) {
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR6x10,"%2d %3d %3d",i,p[i].x,p[i].y);
pos += 1.0F; }
free(p); }
break;
case 3 : { int t;
struct pix *p = lignePixels(x2,y2,x3,y3,&t);
glutReshapeWindow(85,80+(t+1)*14);
glColor4fv(couleurBleu());
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR8x13,"PIXELS");
pos += 1.0F;
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR6x10," x y");
pos += 1.0F;
for ( int i = 0 ; i < t ; i++ ) {
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR6x10,"%2d %3d %3d",i,p[i].x,p[i].y);
pos += 1.0F; }
free(p); }
break;
case 5 : { glColor3fv(couleurMagentaFonce());
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR8x13,"EXTREMES");
pos += 1.0F;
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR6x10," y xi xf");
pos += 1.0F;
int h = pixelsExtremesFacette(x1,y1,x2,y2,x3,y3,pos);
glutReshapeWindow(85,80+(h+1)*14); }
break;
case 6 : { glColor3fv(couleurJauneFonce());
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR8x13,"EXTREMES");
pos += 1.0F;
placeFontCursor(5.0F,-pos*14.0F,0.0F) ;
simpleBitmapOutput(1,REGULAR6x10," y xi xf");
pos += 1.0F;
int h = pixelsExtremesFacette(x1,y1,x2,y2,x3,y3,pos);
if ( yy < h )
glutReshapeWindow(85,80+(yy+2)*14);
else
glutReshapeWindow(85,80+(h+1)*14); }
break; }
glPopMatrix();
glFlush();
glutSwapBuffers();
}
void reshapeV(int w,int h) {
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,w,-h,0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc,char **argv) {
glutInit(&argc,argv);
{ glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
glutInitWindowSize(320,320);
glutInitWindowPosition(50,50);
f1 = glutCreateWindow("Remplissage d'une facette 2D");
myinit();
creationMenuBasique();
setParametresOrthoBasique(0.0,XMAX,0.0,YMAX,-1.0,1.0);
glutReshapeFunc(reshapeOrthoBasique);
glutKeyboardFunc(key);
glutDisplayFunc(display); }
{ glutInitWindowSize(80,100);
glutInitWindowPosition(380,50);
glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
fv = glutCreateWindow("Valeurs");
creationMenuBasique();
glutDisplayFunc(displayV);
glutReshapeFunc(reshapeV);
glutKeyboardFunc(key); }
glutMainLoop();
return(0);
}