Tracé de lignes (utile pour tester les XImages)
#include <stdio.h> #include <math.h> #include <limits.h> /* INT_MAX/INT_MIN */ #include "object.h" char *G_buffer; int HW_SCREEN_X_SIZE; int HW_SCREEN_Y_SIZE; /*-------------------------------*/ void SetImageBuffer(Camera *cam) /*-------------------------------*/ /* Initialisation du buffer camera. DOIT ETRE APPELEE AVANT TOUTES LES AUTRES ! */ { G_buffer = cam->image; HW_SCREEN_X_SIZE=cam->resX; HW_SCREEN_Y_SIZE=cam->resY;
/* Allocation du tableau pour le trace des polygones */ AllocateTableau(); } /*----------------------------------------------------------*/ void G_line(int x,int y,int x2,int y2,unsigned char colour) /*----------------------------------------------------------*/ /* Trace de ligne de type Bresenham, version optimisee pour l'utilisation d'une XImage */ { int dx,dy,long_d,short_d; int d,add_dh,add_dl; int inc_xh,inc_yh,inc_xl,inc_yl; register int inc_ah,inc_al; register int i; register unsigned char *adr=G_buffer; dx=x2-x; dy=y2-y; /* ranges */ if(dx<0){dx=-dx; inc_xh=-1; inc_xl=-1;} /* making sure dx and dy >0 */ else { inc_xh=1; inc_xl=1; } /* adjusting increments */ if(dy<0){dy=-dy; inc_yh=-HW_SCREEN_X_SIZE; inc_yl=-HW_SCREEN_X_SIZE;}/* to get to the neighboring */ else { inc_yh= HW_SCREEN_X_SIZE; /* point along Y have to add */ inc_yl= HW_SCREEN_X_SIZE;}/* or subtract this */ if(dx>dy){long_d=dx; short_d=dy; inc_yl=0;}/* long range,&making sure either */ else {long_d=dy; short_d=dx; inc_xl=0;}/* x or y is changed in L case */ inc_ah=inc_xh+inc_yh; inc_al=inc_xl+inc_yl; /* increments for point adress */ adr+=y*HW_SCREEN_X_SIZE+x; /* address of first point */ d=2*short_d-long_d; /* initial value of d */ add_dl=2*short_d; /* d adjustment for H case */ add_dh=2*short_d-2*long_d; /* d adjustment for L case */ for(i=0;i<=long_d;i++) /* for all points in longer range */ { *adr=colour; /* rendering */ if(d>=0){adr+=inc_ah; d+=add_dh;} /* previous point was H type */ else {adr+=inc_al; d+=add_dl;} /* previous point was L type */ } }Tracé de polygones
int *G_start; int *G_end; int G_miny,G_maxy; /* vertical boundaries */ void AllocateTableau() {
/* Allocation du tableau des lignes */ G_start = (int *) malloc(HW_SCREEN_Y_SIZE * sizeof(int)); G_end = (int *) malloc(HW_SCREEN_Y_SIZE * sizeof(int)); } void GI_scan(int x1, int y1, int x2, int y2) /* Balayage de l'arete et remplissage des tableaux G_start et G_end */
{ int dx,dy,long_d,short_d; int d,add_dh,add_dl; int inc_xh,inc_yh,inc_xl,inc_yl; register int i; dx=x2-x1; dy=y2-y1; /* ranges */ if(y1<G_miny) G_miny=y1; if(y1>G_maxy) G_maxy=y1; if(y2<G_miny) G_miny=y2; if(y2>G_maxy) G_maxy=y2; /* updating vertical size */ if(dx<0){dx=-dx; inc_xh=-1; inc_xl=-1;} /* making sure dx and dy >0 */ else { inc_xh=1; inc_xl=1; } /* adjusting increments */ if(dy<0){dy=-dy; inc_yh=-1; inc_yl=-1;} else { inc_yh=1; inc_yl=1; } if(dx>dy){long_d=dx;short_d=dy;inc_yl=0;} /* long range,&making sure either */ else {long_d=dy;short_d=dx;inc_xl=0;} /* x or y is changed in L case */ d=2*short_d-long_d; /* initial value of d */ add_dl=2*short_d; /* d adjustment for H case */ add_dh=2*short_d-2*long_d; /* d adjustment for L case */ for(i=0;i<=long_d;i++) { /* for all points in longer range */ if(x1<G_start[y1]) /* further then rightmost */ G_start[y1]=x1; /* the begining of scan line */ if(G_end[y1]<x1) /* further the leftmost */ G_end[y1]=x1; /* the end of scan line */ if(d>=0){x1+=inc_xh;y1+=inc_yh;d+=add_dh;} /* previous point was H type */ else {x1+=inc_xl;y1+=inc_yl;d+=add_dl;} /* previous point was L type */ } } void GI_boarder_array_init(void) { G_miny=INT_MAX; /* polygon starts here */ G_maxy=INT_MIN; /* polygon ends here */ G_start = (int *) memset((char *)G_start, 127, HW_SCREEN_Y_SIZE*sizeof(char*)); G_end =(int *) memset((char *)G_end, 0, HW_SCREEN_Y_SIZE*sizeof(char*)); } void G_ambient_polygon(Tri* tri, Object *obj, unsigned char colour) { register unsigned char *l_adr,*adr; register int beg,end,i; int i0, i1, i2; /* Initialisation du tableau */ GI_boarder_array_init(); /* initializing the arrays */ /* Parcours des faces */ i0 = tri->PtVertex[0]; i1 = tri->PtVertex[1]; i2 = tri->PtVertex[2]; GI_scan(obj->Vertex[i0].ScreenVertex.x, obj->Vertex[i0].ScreenVertex.y, obj->Vertex[i1].ScreenVertex.x, obj->Vertex[i1].ScreenVertex.y); GI_scan(obj->Vertex[i1].ScreenVertex.x, obj->Vertex[i1].ScreenVertex.y, obj->Vertex[i2].ScreenVertex.x, obj->Vertex[i2].ScreenVertex.y); GI_scan(obj->Vertex[i2].ScreenVertex.x, obj->Vertex[i2].ScreenVertex.y, obj->Vertex[i0].ScreenVertex.x, obj->Vertex[i0].ScreenVertex.y); /* nothing to do? */ if(G_miny<=G_maxy) { l_adr=G_buffer+G_miny*HW_SCREEN_X_SIZE; /* addr of 1st byte of 1st line */ /* rendering all lines */ for(; G_miny<=G_maxy; G_miny++, l_adr+=HW_SCREEN_X_SIZE) { adr=l_adr+(beg=G_start[G_miny]); /* addr of the current line */ end=G_end[G_miny]-beg+1; /* ends here */ memset((char *) adr, colour, end); } } }