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