public BoolI8 GrLimits(GrBitMap *base,I8 *left,I8 *top,I8 *right,I8 *bottom,I8 width=0,I8 height=0)
{ //returns screen, not window coordinates
*left=0;
*top=0;
*right=base->width-1;
*bottom=base->height-1;
if (base->flags & BMF_SCREEN_BITMAP) {
if (GR_WIDTH-1<*right)
*right=GR_WIDTH-1;
if (GR_HEIGHT-1<*bottom)
*bottom=GR_HEIGHT-1;
if (base->win_task->win_pixel_left>*left)
*left=base->win_task->win_pixel_left;
if (base->win_task->win_pixel_top>*top)
*top=base->win_task->win_pixel_top;
if (base->win_task->win_pixel_right<*right)
*right=base->win_task->win_pixel_right;
if (base->win_task->win_pixel_bottom<*bottom)
*bottom=base->win_task->win_pixel_bottom;
}
*left-=width;
*right+=width;
*top-=height;
*bottom+=height;
return *left<=*right && *top<=*bottom;
}
BoolI8 GrClipLine(GrBitMap *base,I8 *x1,I8 *y1,I8 *x2,I8 *y2,I8 width=0,I8 height=0)
{ //also converts window to screen coordinates
I8 left,top,right,bottom;
if (GrLimits(base,&left,&top,&right,&bottom,width,height)) {
if (base->flags & BMF_SCREEN_BITMAP) {
*x1+=base->win_task->win_pixel_left;
*y1+=base->win_task->win_pixel_top;
*x2+=base->win_task->win_pixel_left;
*y2+=base->win_task->win_pixel_top;
}
return ClipLine(x1,y1,x2,y2,left,top,right,bottom);
} else
return FALSE;
}
public BoolI8 GrPlot(GrBitMap *base,I8 x,I8 y)
{ //Clipping but No transformation or pen width
I4 *db=base->depth_buffer;
base->depth_buffer=NULL;
if (base->brush)
GrBlot(base,x,y,base->brush);
else if (base->flags & BMF_SCREEN_BITMAP) {
if (x>=0 && y>=0) {
x+=base->win_task->win_pixel_left;
y+=base->win_task->win_pixel_top;
if (x<=base->win_task->win_pixel_right &&
y<=base->win_task->win_pixel_bottom &&
0<=x<base->width && 0<=y<base->height &&
(base->win_task->next_task==sys_winmgr_task ||
base->flags&BMF_ON_TOP ||
!IsPixelCovered(base->win_task,x,y)))
GrPlot0(base,x,y);
}
} else
if (0<=x<base->width && 0<=y<base->height)
GrPlot0(base,x,y);
base->depth_buffer=db;
return TRUE;
}
BoolI8 GrPlot1(GrBitMap *base,I8 x,I8 y)
{ //Clipping but No transformation or pen width, called with db_z set
if (base->brush) {
if (base->depth_buffer)
GrBlot3(base,x,y,base->db_z,base->brush);
else
GrBlot(base,x,y,base->brush);
} else if (base->flags & BMF_SCREEN_BITMAP) {
if (x>=0 && y>=0) {
x+=base->win_task->win_pixel_left;
y+=base->win_task->win_pixel_top;
if (x<=base->win_task->win_pixel_right &&
y<=base->win_task->win_pixel_bottom &&
0<=x<base->width && 0<=y<base->height &&
(base->win_task->next_task==sys_winmgr_task ||
base->flags&BMF_ON_TOP ||
!IsPixelCovered(base->win_task,x,y)))
GrPlot0(base,x,y);
}
} else
if (0<=x<base->width && 0<=y<base->height)
GrPlot0(base,x,y);
return TRUE;
}
public I8 GrPeek(GrBitMap *base,I8 x,I8 y)
//Returns pixel color or -1 if off-screen or covered.
{ //Clipping but No transformation
if (base->flags & BMF_SCREEN_BITMAP) {
if (x<0 || y<0) return -1;
x+=base->win_task->win_pixel_left;
y+=base->win_task->win_pixel_top;
if (x<0 || y<0 ||
x>base->win_task->win_pixel_right ||
y>base->win_task->win_pixel_bottom ||
x>=base->width || y>=base->height ||
base->win_task->next_task!=sys_winmgr_task &&
!(base->flags&BMF_ON_TOP) &&
IsPixelCovered(base->win_task,x,y))
return -1;
} else
if (!(0<=x<base->width) || !(0<=y<base->height))
return -1;
return GrPeek0(base,x,y);
}
/*
This is an easier to understand
version of the nonrecursive routine below.
I8 GrFloodFillRay(GrBitMap *base,I8 x,I8 y,I8 z,I4 *db)
{
I8 cnt,j,x1,ray_len,ray_len2;
if (GetStkPtr-Fs->stack_base<0x80)
StkOverflow(Fs);
cnt=ray_len=GrRayLen(base,&x,y,z,db);
y--;
j=ray_len;
x1=x;
while (j>0) {
if (ray_len2=GrRayLenMinus(base,x1,y))
cnt+=GrFloodFillRay(base,x1,y,z,db);
j-=ray_len2+1;
x1-=ray_len2+1;
}
y+=2;
j=ray_len;
x1=x;
while (j>0) {
if (ray_len2=GrRayLenMinus(base,x1,y))
cnt+=GrFloodFillRay(base,x1,y,z,db);
j-=ray_len2+1;
x1-=ray_len2+1;
}
return cnt;
}
*/
class FFRay
{
I8 state,x,y,j,x1,ray_len,ray_len2;
};
I8 GrFloodFillRay(GrBitMap *base,I8 x,I8 y,I8 z,I4 *db)
{//See the above commented-out routine for an easier to understand version.
I8 cnt=0;
//We don't dynamically calculate the size to avoid
//fragmentation of memory.
FFRay *f_base=MAlloc(sizeof(FFRay)*0x80000),*f=f_base;
f->x=x;
f->y=y;
f->state=0;
do {
nobound_switch (f->state) {
case 0:
f->state++;
cnt+=f->ray_len=GrRayLen(base,&f->x,f->y,z,db);
f->y--;
f->j=f->ray_len;
f->x1=f->x;
break;
case 1:
if (f->j>0) {
f->state++;
if (f->ray_len2=GrRayLenMinus(base,f->x1,f->y)) {
f[1].x=f->x1;
f[1].y=f->y;
f[1].state=0;
f++;
}
} else
f->state+=2;
break;
case 2:
f->state--;
f->j-=f->ray_len2+1;
f->x1-=f->ray_len2+1;
break;
case 3:
f->state++;
f->y+=2;
f->j=f->ray_len;
f->x1=f->x;
break;
case 4:
if (f->j>0) {
f->state++;
if (f->ray_len2=GrRayLenMinus(base,f->x1,f->y)) {
f[1].x=f->x1;
f[1].y=f->y;
f[1].state=0;
f++;
}
} else
f->state+=2;
break;
case 5:
f->state--;
f->j-=f->ray_len2+1;
f->x1-=f->ray_len2+1;
break;
case 6:
f--;
break;
}
} while (f>=f_base);
Free(f_base);
return cnt;
}
public I8 GrFloodFill(GrBitMap *base,I8 x,I8 y,BoolI1 not_color=FALSE,I8 z=0,I4 *db=NULL)
{
//Ignore z and db.
//not_color=TRUE means fill up to everything which is not the current color.
//not_color=FALSE means fill all parts equal to the color under the point.
I8 cnt=0,j,c,c2,old_color2=base->color2,old_flags=base->flags;
GrBitMap *old_brush;
if (base->flags & BMF_DONT_DRAW) //TODO
return 0;
old_brush=base->brush;
base->brush=NULL;
if ((j=GrPeek(base,x,y))>=0) {
nobound_switch (base->type) {
case BMT_COLOR4:
if (not_color) {
base->color2=base->color&0xFFFFFF;
base->flags|=BMF_FILL_NOT_COLOR;
} else {
base->color2=j;
if (base->color&ROP_DITHER) {
if (base->color2&0xFFFFFF==base->color&0xFFFFFF &&
base->color&0xFFFFFF==base->color>>32&0xFFFFFF)
break;
} else if (base->color2&0xFFFFFF==base->color&0xFFFFFF)
break;
base->flags&=~BMF_FILL_NOT_COLOR;
}
if (not_color && j!=base->color2 ||
!not_color)
cnt=GrFloodFillRay(base,x,y,z,db);
break;
case BMT_MONO:
c=ToBool(base->color&0xFFFFFF);
c2=ToBool(base->color>>32&0xFFFFFF);
if (not_color) {
base->color2=c;
base->flags|=BMF_FILL_NOT_COLOR;
} else {
base->color2=j;
if (base->color&ROP_DITHER) {
if (base->color2==c && c==c2)
break;
} else if (base->color2==c)
break;
base->flags&=~BMF_FILL_NOT_COLOR;
}
if (not_color && j!=c ||
!not_color)
cnt=GrFloodFillRay(base,x,y,z,db);
break;
}
}
base->brush=old_brush;
base->flags=old_flags|base->flags&BMF_DIRTY;
base->color2=old_color2;
return cnt;
}
public BoolI8 GrPlot3b(GrBitMap *base,I8 x,I8 y,I8 z)
{ //Clipping and transformation but no pen_width
I8 _x,_y,_z;
BoolI1 was_transform=FALSE,was_symmetry=FALSE;
if (base->flags & BMF_TRANSFORMATION) {
base->transform(base,&x,&y,&z);
base->flags&=~BMF_TRANSFORMATION;
was_transform=TRUE;
}
if (base->flags & BMF_SYMMETRY) {
_x=x; _y=y; _z=z;
GrReflect(base,&_x,&_y,&_z);
base->flags&=~BMF_SYMMETRY;
base->db_z=_z;
GrPlot1(base,_x,_y);
was_symmetry=TRUE;
if (base->flags&BMF_JUST_MIRROR)
goto gr_done;
}
base->db_z=z;
GrPlot1(base,x,y);
gr_done:
if (was_transform)
base->flags|=BMF_TRANSFORMATION;
if (was_symmetry)
base->flags|=BMF_SYMMETRY;
return TRUE;
}
public BoolI8 GrPlot3(GrBitMap *base,I8 x,I8 y,I8 z)
{ //clipping and transformation and pen width
I8 _x,_y,_z,i,j,w,old_color=base->color,dist;
BoolI1 record,was_transform=FALSE,was_symmetry=FALSE;
if (base->flags & BMF_TRANSFORMATION) {
base->transform(base,&x,&y,&z);
base->flags&=~BMF_TRANSFORMATION;
was_transform=TRUE;
}
if (base->flags & BMF_SYMMETRY) {
_x=x; _y=y; _z=z;
GrReflect(base,&_x,&_y,&_z);
base->flags&=~BMF_SYMMETRY;
GrPlot3(base,_x,_y,_z);
was_symmetry=TRUE;
if (base->flags&BMF_JUST_MIRROR)
goto gr_done;
}
w=base->pen_width>>1;
base->db_z=z;
if (w<=0)
GrPlot1(base,x,y);
else if (base->pen_width<GR_NUM_PEN_BRUSHES) {
if (base->color.u1[3]==ROPB_EQU)
base->color.u1[3]=ROPB_TRANSPARENT;
if (base->color.u1[3]==ROPB_CLEAR_MASK_EQU)
base->color.u1[3]=ROPB_CLEAR_MASK_TRANSPARENT;
if (base->depth_buffer) {
if (base->color&ROP_DITHER) {
base->color.u1[7]=base->color.u1[3];
if (((x-w)^(y-w))&1) {
record=GrBlot3(base,x-w,y-w,z,gr_odd_pen_brushes[base->pen_width]);
base->color.u4[0]=base->color.u4[1];
record=GrBlot3(base,x-w,y-w,z,gr_even_pen_brushes[base->pen_width]);
} else {
record=GrBlot3(base,x-w,y-w,z,gr_even_pen_brushes[base->pen_width]);
base->color.u4[0]=base->color.u4[1];
record=GrBlot3(base,x-w,y-w,z,gr_odd_pen_brushes[base->pen_width]);
}
} else
record=GrBlot3(base,x-w,y-w,z,gr_pen_brushes[base->pen_width]);
} else {
if (base->color&ROP_DITHER) {
base->color.u1[7]=base->color.u1[3];
if (((x-w)^(y-w))&1) {
record=GrBlot(base,x-w,y-w,gr_odd_pen_brushes[base->pen_width]);
base->color.u4[0]=base->color.u4[1];
record=GrBlot(base,x-w,y-w,gr_even_pen_brushes[base->pen_width]);
} else {
record=GrBlot(base,x-w,y-w,gr_even_pen_brushes[base->pen_width]);
base->color.u4[0]=base->color.u4[1];
record=GrBlot(base,x-w,y-w,gr_odd_pen_brushes[base->pen_width]);
}
} else
record=GrBlot(base,x-w,y-w,gr_pen_brushes[base->pen_width]);
}
if (record) {
if (base->flags & BMF_SCREEN_BITMAP) {
x+=base->win_task->win_pixel_left;
y+=base->win_task->win_pixel_top;
}
if (base->flags & BMF_LOCATE_NEAREST) {
dist=DistI8(x,y,base->cur_x,base->cur_y);
if (dist<base->nearest_dist) {
base->nearest_grelem_num=base->cur_grelem_num;
base->nearest_dist=dist;
}
}
if (base->flags & BMF_RECORD_EXTENTS) {
if (x-w<base->min_x) base->min_x=x-w;
if (y-w<base->min_y) base->min_y=y-w;
if (base->pen_width & 1) {
if (x+w>base->max_x) base->max_x=x+w;
if (y+w>base->max_y) base->max_y=y+w;
} else {
if (x+w-1>base->max_x) base->max_x=x+w-1;
if (y+w-1>base->max_y) base->max_y=y+w-1;
}
}
}
} else if (base->pen_width & 1) { //TODO Dither
for (i=-w;i<=w;i++)
for (j=-w;j<=w;j++)
GrPlot1(base,x+i,y+j);
} else {
for (i=-w;i<w;i++)
for (j=-w;j<w;j++)
GrPlot1(base,x+i,y+j);
}
gr_done:
base->color=old_color;
if (was_transform)
base->flags|=BMF_TRANSFORMATION;
if (was_symmetry)
base->flags|=BMF_SYMMETRY;
return TRUE;
}
BoolI8 GrLinePlot0(GrBitMap *base,I8 x,I8 y,I8 z)
{
if (base->win_task->next_task==sys_winmgr_task ||
!(base->flags & BMF_SCREEN_BITMAP) ||
base->flags&BMF_ON_TOP ||
!IsPixelCovered(base->win_task,x,y)) {
base->db_z=z;
GrPlot0(base,x,y);
}
return TRUE;
}
BoolI8 GrLinePlot(GrBitMap *base,I8 x,I8 y,I8 z)
{
base->db_z=z;
GrPlot1(base,x,y);
return TRUE;
}
public U0 GrLine(GrBitMap *base,I8 x1,I8 y1,I8 x2,I8 y2,I8 step=1,I8 start=0)
{
I4 *db=base->depth_buffer;
base->depth_buffer=NULL;
if (step==1 && !start && !base->brush && !base->depth_buffer) {
if (GrClipLine(base,&x1,&y1,&x2,&y2))
Line(base,x1,y1,0,x2,y2,0,&GrLinePlot0,step,start);
} else
Line(base,x1,y1,0,x2,y2,0,&GrLinePlot,step,start);
base->depth_buffer=db;
}
public U0 GrCircle(GrBitMap *base,I8 cx,I8 cy,I8 radius,
I8 step=1,F8 start_radians=0,F8 len_radians=2*pi)
{
I4 *db=base->depth_buffer;
base->depth_buffer=NULL;
Circle(base,cx,cy,0,radius,&GrLinePlot,step,start_radians,len_radians);
base->depth_buffer=db;
}
public U0 GrEllipse(GrBitMap *base,
I8 cx,I8 cy,
I8 x_radius,I8 y_radius,
F8 rot_angle=0,
I8 step=1,
F8 start_radians=0,
F8 len_radians=2*pi)
{
I4 *db=base->depth_buffer;
base->depth_buffer=NULL;
Ellipse(base,cx,cy,0,x_radius,y_radius,&GrLinePlot,rot_angle,step,start_radians,len_radians);
base->depth_buffer=db;
}
public U0 GrRegPolygon(GrBitMap *base,
I8 cx,I8 cy,
I8 x_radius,I8 y_radius,I8 sides,
F8 rot_angle=0,
I8 step=1,
F8 start_radians=0,
F8 len_radians=2*pi)
{
I4 *db=base->depth_buffer;
base->depth_buffer=NULL;
RegPolygon(base,cx,cy,0,x_radius,y_radius,sides,
&GrLinePlot,rot_angle,step,start_radians,len_radians);
base->depth_buffer=db;
}
public U0 Gr2Bezier(GrBitMap *base,P3I4 *ctrl)
{
Bezier2(base,ctrl,&GrLinePlot);
}
public U0 Gr3Bezier(GrBitMap *base,P3I4 *ctrl)
{
Bezier3(base,ctrl,&GrLinePlot);
}
public U0 Gr2BSpline(GrBitMap *base,P3I4 *ctrl,I8 cnt,BoolI1 closed=FALSE)
{
BSpline2(base,ctrl,cnt,&GrLinePlot,closed);
}
public U0 Gr3BSpline(GrBitMap *base,P3I4 *ctrl,I8 cnt,BoolI1 closed=FALSE)
{
BSpline3(base,ctrl,cnt,&GrLinePlot,closed);
}
public U0 GrLine3b(GrBitMap *base,I8 x1,I8 y1,I8 z1,I8 x2,I8 y2,I8 z2,I8 step=1,I8 start=0)
{ //transformation but not pen width
I8 _x1,_y1,_z1,_x2,_y2,_z2;
BoolI1 was_transform=FALSE,was_symmetry=FALSE;
if (base->flags & BMF_TRANSFORMATION) {
base->transform(base,&x1,&y1,&z1);
base->transform(base,&x2,&y2,&z2);
base->flags&=~BMF_TRANSFORMATION;
was_transform=TRUE;
}
if (base->flags & BMF_SYMMETRY) {
_x1=x1; _y1=y1; _z1=z1;
GrReflect(base,&_x1,&_y1,&_z1);
_x2=x2; _y2=y2; _z2=z2;
GrReflect(base,&_x2,&_y2,&_z2);
base->flags&=~BMF_SYMMETRY;
if (step==1 && !start && !base->brush && !base->depth_buffer) { //TODO: clip z for depth buffer
if (GrClipLine(base,&_x1,&_y1,&_x2,&_y2))
Line(base,_x1,_y1,0,_x2,_y2,0,&GrLinePlot0,step,start);
} else
Line(base,_x1,_y1,_z1,_x2,_y2,_z2,&GrLinePlot,step,start);
was_symmetry=TRUE;
if (base->flags&BMF_JUST_MIRROR)
goto gr_done;
}
if (step==1 && !start && !base->brush && !base->depth_buffer) { //TODO: clip z for depth buffer
if (GrClipLine(base,&x1,&y1,&x2,&y2))
Line(base,x1,y1,0,x2,y2,0,&GrLinePlot0,step,start);
} else
Line(base,x1,y1,z1,x2,y2,z2,&GrLinePlot,step,start);
gr_done:
if (was_transform)
base->flags|=BMF_TRANSFORMATION;
if (was_symmetry)
base->flags|=BMF_SYMMETRY;
}
public U0 GrLine3(GrBitMap *base,I8 x1,I8 y1,I8 z1,I8 x2,I8 y2,I8 z2,I8 step=1,I8 start=0)
{ //transformation with pen width
I8 _x1,_y1,_z1,_x2,_y2,_z2;
BoolI1 was_transform=FALSE,was_symmetry=FALSE;
if (base->flags & BMF_TRANSFORMATION) {
base->transform(base,&x1,&y1,&z1);
base->transform(base,&x2,&y2,&z2);
base->flags&=~BMF_TRANSFORMATION;
was_transform=TRUE;
}
if (base->flags & BMF_SYMMETRY) {
_x1=x1; _y1=y1; _z1=z1;
GrReflect(base,&_x1,&_y1,&_z1);
_x2=x2; _y2=y2; _z2=z2;
GrReflect(base,&_x2,&_y2,&_z2);
base->flags&=~BMF_SYMMETRY;
Line(base,_x1,_y1,_z1,_x2,_y2,_z2,&GrPlot3,step,start);
was_symmetry=TRUE;
if (base->flags&BMF_JUST_MIRROR)
goto gr_done;
}
Line(base,x1,y1,z1,x2,y2,z2,&GrPlot3,step,start);
gr_done:
if (was_transform)
base->flags|=BMF_TRANSFORMATION;
if (was_symmetry)
base->flags|=BMF_SYMMETRY;
}
public BoolI8 GrPutS3(GrBitMap *base,I8 x1,I8 y1,I8 z1,U1 *s)
{ //transformation
//BMF_SYMMETRY is silly.
if (base->flags & BMF_TRANSFORMATION)
base->transform(base,&x1,&y1,&z1);
return GrPutS(base,x1,y1,s);
}
public BoolI8 GrVPutS3(GrBitMap *base,I8 x1,I8 y1,I8 z1,U1 *s)
{ //Vertical text
//transformation
//BMF_SYMMETRY is silly.
if (base->flags & BMF_TRANSFORMATION)
base->transform(base,&x1,&y1,&z1);
return GrVPutS(base,x1,y1,s);
}
public U0 GrPrintF3(GrBitMap *base,I8 x,I8 y,I8 z,U1 *fmt,...)
{
U1 *buf=SPrintFJoin(NULL,fmt,argc,argv);
GrPutS3(base,x,y,z,buf);
Free(buf);
}
public U0 GrVPrintF3(GrBitMap *base,I8 x,I8 y,I8 z,U1 *fmt,...)
{ //Vertical text
U1 *buf=SPrintFJoin(NULL,fmt,argc,argv);
GrVPutS3(base,x,y,z,buf);
Free(buf);
}
public U0 GrEllipse3(GrBitMap *base,
I8 cx,I8 cy,I8 cz,
I8 x_radius,I8 y_radius,
F8 rot_angle=0,
I8 step=1,
F8 start_radians=0,
F8 len_radians=2*pi)
{
I8 x,y,z;
F8 m1,a1,m2,a2,s,c;
I8 xx,yy,zz;
if (base->flags & BMF_TRANSFORMATION) {
base->flags&=~BMF_TRANSFORMATION;
base->transform(base,&cx,&cy,&cz);
c=Cos(rot_angle);
s=Sin(rot_angle);
x_radius<<=16;
y_radius<<=16;
xx=0;
yy=0;
zz=0;
base->transform(base,&xx,&yy,&zz);
x=x_radius*c;
y=x_radius*s;
z=0;
base->transform(base,&x,&y,&z);
x-=xx;
y-=yy;
z-=zz;
R2P(&m1,&a1,x,y);
x=-y_radius*s;
y=y_radius*c;
z=0;
base->transform(base,&x,&y,&z);
x-=xx;
y-=yy;
z-=zz;
R2P(&m2,&a2,x,y);
m2*=Abs(Sin(a2-a1));
Ellipse(base,cx,cy,cz,
m1/0x10000,m2/0x10000,&GrPlot3,-a1,step,start_radians,len_radians);
base->flags|=BMF_TRANSFORMATION;
} else
Ellipse(base,cx,cy,cz,x_radius,y_radius,&GrPlot3,rot_angle,step,start_radians,len_radians);
}
public U0 GrCircle3(GrBitMap *base,I8 cx,I8 cy,I8 cz,I8 radius,
I8 step=1,F8 start_radians=0,F8 len_radians=2*pi)
{ //transformation with pen width
if (base->flags & BMF_TRANSFORMATION)
GrEllipse3(base,cx,cy,cz,radius,radius,0,step,start_radians,len_radians);
else
Circle(base,cx,cy,cz,radius,&GrPlot3,step,start_radians,len_radians);
}
public U0 GrRegPolygon3(GrBitMap *base,
I8 cx,I8 cy,I8 cz,
I8 x_radius,I8 y_radius,I8 sides,
F8 rot_angle=0,
I8 step=1,
F8 start_radians=0,
F8 len_radians=2*pi)
{
I8 x,y,z,xx,yy,zz;
F8 m1,a1,m2,a2,s,c;
if (base->flags & BMF_TRANSFORMATION) {
base->flags&=~BMF_TRANSFORMATION;
base->transform(base,&cx,&cy,&cz);
c=Cos(rot_angle);
s=Sin(rot_angle);
x_radius<<=16;
y_radius<<=16;
xx=0;
yy=0;
zz=0;
base->transform(base,&xx,&yy,&zz);
x=x_radius*c;
y=x_radius*s;
z=0;
base->transform(base,&x,&y,&z);
x-=xx;
y-=yy;
z-=zz;
R2P(&m1,&a1,x,y);
x=-y_radius*s;
y=y_radius*c;
z=0;
base->transform(base,&x,&y,&z);
x-=xx;
y-=yy;
z-=zz;
R2P(&m2,&a2,x,y);
m2*=Abs(Sin(a2-a1));
RegPolygon(base,cx,cy,cz,
m1/0x10000,m2/0x10000,sides,&GrPlot3,-a1,step,start_radians,len_radians);
base->flags|=BMF_TRANSFORMATION;
} else
RegPolygon(base,cx,cy,cz,x_radius,y_radius,sides,&GrPlot3,rot_angle,step,start_radians,len_radians);
}
public I8 GrFloodFill3(GrBitMap *base,I8 x1,I8 y1,I8 z1,BoolI1 not_color=FALSE)
{ //transformation
//not_color=TRUE means fill up to everything which is not the current color.
//not_color=FALSE means fill all parts equal to the color under the point.
I8 cnt,old_flags=base->flags;
I8 _x,_y,_z;
if (base->flags & BMF_TRANSFORMATION) {
base->transform(base,&x1,&y1,&z1);
base->flags&=~BMF_TRANSFORMATION;
}
if (base->flags & BMF_SYMMETRY) {
_x=x1; _y=y1; _z=z1;
GrReflect(base,&_x,&_y,&_z);
base->flags&=~BMF_SYMMETRY;
cnt=GrFloodFill(base,_x,_y,not_color,_z,base->depth_buffer);
if (base->flags&BMF_JUST_MIRROR)
goto gr_done;
}
cnt=GrFloodFill(base,x1,y1,not_color,z1,base->depth_buffer);
gr_done:
base->flags=old_flags|base->flags&BMF_DIRTY;
return cnt;
}
public U0 GrRect3(GrBitMap *base,I8 x,I8 y,I8 z,I8 w,I8 h)
{ //Clipping and transformation
I8 x2,y2,z2,x3,y3,z3;
GrBitMap *old_brush=base->brush;
if (base->flags & BMF_TRANSFORMATION) {
base->brush=NULL;
x2=x+w; y2=y; z2=z;
x3=x; y3=y+h; z3=z;
base->transform(base,&x,&y,&z);
base->transform(base,&x2,&y2,&z2);
base->transform(base,&x3,&y3,&z3);
if (!(base->flags&BMF_JUST_MIRROR) ||
!(base->flags&BMF_SYMMETRY))
Rect(base,x,y,z,x2,y2,z2,x3,y3,z3,&GrLinePlot);
if (base->flags & BMF_SYMMETRY) {
GrReflect(base,&x,&y,&z);
GrReflect(base,&x2,&y2,&z2);
GrReflect(base,&x3,&y3,&z3);
Rect(base,x,y,z,x2,y2,z2,x3,y3,z3,&GrLinePlot);
}
base->brush=old_brush;
} else {
if (!(base->flags&BMF_JUST_MIRROR)||
!(base->flags&BMF_SYMMETRY)) {
if (base->depth_buffer)
Rect(base,x,y,z,x+w,y,z,x,y+h,z,&GrLinePlot);
else
GrRect(base,x,y,w,h);
}
if (base->flags & BMF_SYMMETRY) {
base->brush=NULL;
x2=x+w; y2=y; z2=z;
x3=x; y3=y+h; z3=z;
GrReflect(base,&x,&y,&z);
GrReflect(base,&x2,&y2,&z2);
GrReflect(base,&x3,&y3,&z3);
Rect(base,x,y,z,x2,y2,z2,x3,y3,z3,&GrLinePlot);
base->brush=old_brush;
}
}
}
public BoolI8 GrBlot3(GrBitMap *base,I8 x1,I8 y1,I8 z1,GrBitMap *img)
{ //Clipping and transformation
I8 reg i,j,w=img->width,h=img->height,old_color=base->color,reg color,
d1,dx1,dy1,dz1,
reg d2,dx2,dy2,dz2,
adx1,ady1,adz1,
adx2,ady2,adz2,
x2,y2,z2,x3,y3,z3,
dw,reg dh,x,y,_x1,_y1,_z1,_x2,_y2,_z2,_x3,_y3,_z3,
last_x,last_y;
BoolI1 first,result=FALSE;
GrBitMap *old_brush=base->brush;
if (base->depth_buffer || base->flags & (BMF_TRANSFORMATION | BMF_SYMMETRY)) {
x2=x1+w; y2=y1; z2=z1;
x3=x1; y3=y1+h; z3=z1;
if (base->flags & BMF_TRANSFORMATION) {
base->transform(base,&x1,&y1,&z1);
base->transform(base,&x2,&y2,&z2);
base->transform(base,&x3,&y3,&z3);
}
if (base->flags & BMF_SYMMETRY) {
_x1=x1; _y1=y1; _z1=z1;
GrReflect(base,&_x1,&_y1,&_z1);
_x2=x2; _y2=y2; _z2=z2;
GrReflect(base,&_x2,&_y2,&_z2);
_x3=x3; _y3=y3; _z3=z3;
GrReflect(base,&_x3,&_y3,&_z3);
dx1=_x2-_x1; dy1=_y2-_y1; dz1=_z2-_z1;
dx2=_x3-_x1; dy2=_y3-_y1; dz2=_z3-_z1;
adx1=AbsI8(dx1); ady1=AbsI8(dy1); adz1=AbsI8(dz1);
adx2=AbsI8(dx2); ady2=AbsI8(dy2); adz2=AbsI8(dz2);
if (adx1>=ady1)
d1=adx1>=adz1 ? adx1:adz1;
else
d1=ady1>=adz1 ? ady1:adz1;
if (adx2>=ady2)
d2=adx2>=adz2 ? adx2:adz2;
else
d2=ady2>=adz2 ? ady2:adz2;
if (AbsI8(d1)!=w ||AbsI8(d2)!=h) {
d1<<=1;
d2<<=1;
}
if (d1) {
dx1=dx1<<32/d1;
dy1=dy1<<32/d1;
dz1=dz1<<32/d1;
} else
goto normal_image;
if (d2) {
dx2=dx2<<32/d2;
dy2=dy2<<32/d2;
dz2=dz2<<32/d2;
} else
goto normal_image;
base->brush=NULL;
x=0;y=0;
dw=w<<32/d1;
dh=h<<32/d2;
first=TRUE;
_x1<<=32; _y1<<=32; _z1<<=32;
for (j=0;j<=d1;j++) {
_x2=_x1; _y2=_y1; _z2=_z1;
y=0;
for (i=0;i<=d2;i++) {
if (_x2.i4[1]!=last_x || _y2.i4[1]!=last_y ||first) {
color=GrPeek(img,x.i4[1],y.i4[1]);
if (color>=0 &&
(old_color.u1[3]!=ROPB_TRANSPARENT ||
color&0xFFFFFF!=img->bkcolor&0xFFFFFF)) {
if (img->type==BMT_MONO)
base->color=old_color;
else
base->color=old_color&0xFF000000+color;
if (base->depth_buffer) {
base->db_z=_z2.i4[1];
GrPlot1(base,_x2.i4[1],_y2.i4[1]);
} else
GrPlot(base,_x2.i4[1],_y2.i4[1]);
}
}
first=FALSE;
last_x=_x2.i4[1]; last_y=_y2.i4[1];
_x2+=dx2; _y2+=dy2; _z2+=dz2;
y+=dh;
}
_x1+=dx1; _y1+=dy1; _z1+=dz1;
x+=dw;
}
result=TRUE;
normal_image:
if (base->flags&BMF_JUST_MIRROR)
goto gr_done;
}
dx1=x2-x1; dy1=y2-y1; dz1=z2-z1;
dx2=x3-x1; dy2=y3-y1; dz2=z3-z1;
adx1=AbsI8(dx1); ady1=AbsI8(dy1); adz1=AbsI8(dz1);
adx2=AbsI8(dx2); ady2=AbsI8(dy2); adz2=AbsI8(dz2);
if (adx1>=ady1)
d1=adx1>=adz1 ? adx1:adz1;
else
d1=ady1>=adz1 ? ady1:adz1;
if (adx2>=ady2)
d2=adx2>=adz2 ? adx2:adz2;
else
d2=ady2>=adz2 ? ady2:adz2;
if (AbsI8(d1)!=w ||AbsI8(d2)!=h) {
d1<<=1;
d2<<=1;
}
if (d1) {
dx1=dx1<<32/d1;
dy1=dy1<<32/d1;
dz1=dz1<<32/d1;
} else
goto gr_done;
if (d2) {
dx2=dx2<<32/d2;
dy2=dy2<<32/d2;
dz2=dz2<<32/d2;
} else
goto gr_done;
base->brush=NULL;
x=0;y=0;
dw=w<<32/d1;
dh=h<<32/d2;
first=TRUE;
x1<<=32; y1<<=32; z1<<=32;
for (j=0;j<=d1;j++) {
x2=x1; y2=y1; z2=z1;
y=0;
for (i=0;i<=d2;i++) {
if (x2.i4[1]!=last_x || y2.i4[1]!=last_y || first) {
color=GrPeek(img,x.i4[1],y.i4[1]);
if (color>=0 &&
(old_color.u1[3]!=ROPB_TRANSPARENT ||
color&0xFFFFFF!=img->bkcolor&0xFFFFFF)) {
if (img->type==BMT_MONO)
base->color=old_color;
else
base->color=old_color&0xFF000000+color;
if (base->depth_buffer) {
base->db_z=z2.i4[1];
GrPlot1(base,x2.i4[1],y2.i4[1]);
} else
GrPlot(base,x2.i4[1],y2.i4[1]);
}
}
first=FALSE;
last_x=x2.i4[1]; last_y=y2.i4[1];
x2+=dx2; y2+=dy2; z2+=dz2;
y+=dh;
}
x1+=dx1; y1+=dy1; z1+=dz1;
x+=dw;
}
result=TRUE; //TODO: check off screen
} else
result=GrBlot(base,x1,y1,img);
gr_done:
base->color=old_color;
base->brush=old_brush;
return result;
}
public U0 Gr2Bezier3(GrBitMap *base,P3I4 *ctrl)
{
U8 old_flags=base->flags;
I8 i,x,y,z;
P3I4 *ctrl2=NULL,*ctrl3=NULL;
if (base->flags & BMF_TRANSFORMATION) {
ctrl2=MAlloc(sizeof(P3I4)*3);
for (i=0;i<3;i++) {
x=ctrl[i].x;
y=ctrl[i].y;
z=ctrl[i].z;
base->transform(base,&x,&y,&z);
ctrl2[i].x=x;
ctrl2[i].y=y;
ctrl2[i].z=z;
}
base->flags&=~BMF_TRANSFORMATION;
ctrl=ctrl2;
}
if (base->flags & BMF_SYMMETRY) {
ctrl3=MAlloc(sizeof(P3I4)*3);
for (i=0;i<3;i++) {
x=ctrl[i].x;
y=ctrl[i].y;
z=ctrl[i].z;
GrReflect(base,&x,&y,&z);
ctrl3[i].x=x;
ctrl3[i].y=y;
ctrl3[i].z=z;
}
base->flags&=~BMF_SYMMETRY;
Bezier2(base,ctrl3,&GrPlot3);
if (base->flags & BMF_JUST_MIRROR)
goto gr_done;
}
Bezier2(base,ctrl,&GrPlot3);
gr_done:
Free(ctrl2);
Free(ctrl3);
base->flags=old_flags|base->flags&BMF_DIRTY;
}
public U0 Gr3Bezier3(GrBitMap *base,P3I4 *ctrl)
{
U8 old_flags=base->flags;
I8 i,x,y,z;
P3I4 *ctrl2=NULL,*ctrl3=NULL;
if (base->flags & BMF_TRANSFORMATION) {
ctrl2=MAlloc(sizeof(P3I4)*4);
for (i=0;i<4;i++) {
x=ctrl[i].x;
y=ctrl[i].y;
z=ctrl[i].z;
base->transform(base,&x,&y,&z);
ctrl2[i].x=x;
ctrl2[i].y=y;
ctrl2[i].z=z;
}
base->flags&=~BMF_TRANSFORMATION;
ctrl=ctrl2;
}
if (base->flags & BMF_SYMMETRY) {
ctrl3=MAlloc(sizeof(P3I4)*4);
for (i=0;i<4;i++) {
x=ctrl[i].x;
y=ctrl[i].y;
z=ctrl[i].z;
GrReflect(base,&x,&y,&z);
ctrl3[i].x=x;
ctrl3[i].y=y;
ctrl3[i].z=z;
}
base->flags&=~BMF_SYMMETRY;
Bezier3(base,ctrl3,&GrPlot3);
if (base->flags & BMF_JUST_MIRROR)
goto gr_done;
}
Bezier3(base,ctrl,&GrPlot3);
gr_done:
Free(ctrl2);
Free(ctrl3);
base->flags=old_flags|base->flags&BMF_DIRTY;
}
public U0 Gr2BSpline3(GrBitMap *base,P3I4 *ctrl,I8 cnt,BoolI1 closed=FALSE)
{
U8 old_flags=base->flags;
I8 i,x,y,z;
P3I4 *ctrl2=NULL,*ctrl3=NULL;
if (base->flags & BMF_TRANSFORMATION) {
ctrl2=MAlloc(sizeof(P3I4)*cnt);
for (i=0;i<cnt;i++) {
x=ctrl[i].x;
y=ctrl[i].y;
z=ctrl[i].z;
base->transform(base,&x,&y,&z);
ctrl2[i].x=x;
ctrl2[i].y=y;
ctrl2[i].z=z;
}
base->flags&=~BMF_TRANSFORMATION;
ctrl=ctrl2;
}
if (base->flags & BMF_SYMMETRY) {
ctrl3=MAlloc(sizeof(P3I4)*cnt);
for (i=0;i<cnt;i++) {
x=ctrl[i].x;
y=ctrl[i].y;
z=ctrl[i].z;
GrReflect(base,&x,&y,&z);
ctrl3[i].x=x;
ctrl3[i].y=y;
ctrl3[i].z=z;
}
base->flags&=~BMF_SYMMETRY;
BSpline2(base,ctrl3,cnt,&GrPlot3,closed);
if (base->flags & BMF_JUST_MIRROR)
goto gr_done;
}
BSpline2(base,ctrl,cnt,&GrPlot3,closed);
gr_done:
Free(ctrl2);
Free(ctrl3);
base->flags=old_flags|base->flags&BMF_DIRTY;
}
public U0 Gr3BSpline3(GrBitMap *base,P3I4 *ctrl,I8 cnt,BoolI1 closed=FALSE)
{
U8 old_flags=base->flags;
I8 i,x,y,z;
P3I4 *ctrl2=NULL,*ctrl3=NULL;
if (base->flags & BMF_TRANSFORMATION) {
ctrl2=MAlloc(sizeof(P3I4)*cnt);
for (i=0;i<cnt;i++) {
x=ctrl[i].x;
y=ctrl[i].y;
z=ctrl[i].z;
base->transform(base,&x,&y,&z);
ctrl2[i].x=x;
ctrl2[i].y=y;
ctrl2[i].z=z;
}
base->flags&=~BMF_TRANSFORMATION;
ctrl=ctrl2;
}
if (base->flags & BMF_SYMMETRY) {
ctrl3=MAlloc(sizeof(P3I4)*cnt);
for (i=0;i<cnt;i++) {
x=ctrl[i].x;
y=ctrl[i].y;
z=ctrl[i].z;
GrReflect(base,&x,&y,&z);
ctrl3[i].x=x;
ctrl3[i].y=y;
ctrl3[i].z=z;
}
base->flags&=~BMF_SYMMETRY;
BSpline3(base,ctrl3,cnt,&GrPlot3,closed);
if (base->flags & BMF_JUST_MIRROR)
goto gr_done;
}
BSpline3(base,ctrl,cnt,&GrPlot3,closed);
gr_done:
Free(ctrl2);
Free(ctrl3);
base->flags=old_flags|base->flags&BMF_DIRTY;
}
public U0 GrSpeedLine(GrBitMap *base,I8 x1,I8 y1,I8 x2,I8 y2,F8 speed)
{
I8 old_pen_width=base->pen_width;
I4 *db=base->depth_buffer;
U8 old_flags=base->flags;
base->depth_buffer=NULL;
base->pen_width=base->speedline_scale*speed;
base->flags&=~(BMF_TRANSFORMATION|BMF_SYMMETRY|BMF_JUST_MIRROR);
GrLine3(base,x1,y1,0,x2,y2,0);
base->flags=old_flags|base->flags&BMF_DIRTY;
base->pen_width=old_pen_width;
base->depth_buffer=db;
}
public U0 GrSpeedLine3(GrBitMap *base,I8 x1,I8 y1,I8 z1,I8 x2,I8 y2,I8 z2,F8 speed)
{ //transformation
U8 old_flags=base->flags;
I8 _x1,_y1,_z1,_x2,_y2,_z2;
I8 old_pen_width=base->pen_width;
base->pen_width=base->speedline_scale*speed;
if (base->flags & BMF_TRANSFORMATION) {
base->transform(base,&x1,&y1,&z1);
base->transform(base,&x2,&y2,&z2);
base->flags&=~BMF_TRANSFORMATION;
}
if (base->flags & BMF_SYMMETRY) {
_x1=x1; _y1=y1; _z1=z1;
GrReflect(base,&_x1,&_y1,&_z1);
_x2=x2; _y2=y2; _z2=z2;
GrReflect(base,&_x2,&_y2,&_z2);
base->flags&=~BMF_SYMMETRY;
GrLine3(base,_x1,_y1,_z1,_x2,_y2,_z2);
if (base->flags & BMF_JUST_MIRROR)
goto gr_done;
}
GrLine3(base,x1,y1,z1,x2,y2,z2);
gr_done:
base->pen_width=old_pen_width;
base->flags=old_flags|base->flags&BMF_DIRTY;
}
public I8 GrFillTriangle0(GrBitMap *base,P3I4 *p1,P3I4 *p2,P3I4 *p3)
{
I8 x1,x2,y,z1,z2,dx1,dy1,dz1,dx2,dy2,dz2,cnt=0;
//p1 is min x
if (p3->x<p2->x)
SwapU8(&p3,&p2);
if (p2->x<p1->x)
SwapU8(&p2,&p1);
//p2 is min y of remainder
if (p3->y<p2->y)
SwapU8(&p3,&p2);
if ((dy2=p3->y-p1->y)<0) {
if (dy1=p2->y-p1->y) {
dx1=(p1->x-p2->x)<<32/dy1;
dz1=(p1->z-p2->z)<<32/dy1;
} else {
dx1=0;
dz1=0;
}
dx2=(p1->x-p3->x)<<32/dy2;
dz2=(p1->z-p3->z)<<32/dy2;
x1=x2=p1->x<<32; y=p1->y; z1=z2=p1->z<<32;
while (dy2++) {
cnt+=GrHLine(base,x1.i4[1],x2.i4[1],y,z1.i4[1],z2.i4[1]);
y--;
x1+=dx1;
x2+=dx2;
z1+=dz1;
z2+=dz2;
}
if (dy2=p2->y-p3->y) {
dx2=(p3->x-p2->x)<<32/dy2;
dz2=(p3->z-p2->z)<<32/dy2;
while (dy2++) {
cnt+=GrHLine(base,x1.i4[1],x2.i4[1],y,z1.i4[1],z2.i4[1]);
y--;
x1+=dx1;
x2+=dx2;
z1+=dz1;
z2+=dz2;
}
}
} else if ((dy2=p2->y-p1->y)>0) {
if (dy1=p3->y-p1->y) {
dx1=(p3->x-p1->x)<<32/dy1;
dz1=(p3->z-p1->z)<<32/dy1;
} else {
dx1=0;
dz1=0;
}
dx2=(p2->x-p1->x)<<32/dy2;
dz2=(p2->z-p1->z)<<32/dy2;
x1=x2=p1->x<<32; y=p1->y; z1=z2=p1->z<<32;
while (dy2--) {
cnt+=GrHLine(base,x1.i4[1],x2.i4[1],y,z1.i4[1],z2.i4[1]);
y++;
x1+=dx1;
x2+=dx2;
z1+=dz1;
z2+=dz2;
}
if (dy2=p3->y-p2->y) {
dx2=(p3->x-p2->x)<<32/dy2;
dz2=(p3->z-p2->z)<<32/dy2;
while (dy2--) {
cnt+=GrHLine(base,x1.i4[1],x2.i4[1],y,z1.i4[1],z2.i4[1]);
y++;
x1+=dx1;
x2+=dx2;
z1+=dz1;
z2+=dz2;
}
}
} else {
if (dy1=p2->y-p1->y) {
dx1=(p2->x-p1->x)<<32/dy1;
dz1=(p2->z-p1->z)<<32/dy1;
if (dy2=p2->y-p3->y) {
dx2=(p2->x-p3->x)<<32/dy2;
dz2=(p2->z-p3->z)<<32/dy2;
} else {
dx2=0;
dz2=0;
}
x1=x2=p2->x<<32; y=p2->y; z1=z2=p2->z<<32;
while (dy1++<=0) {
cnt+=GrHLine(base,x1.i4[1],x2.i4[1],y,z1.i4[1],z2.i4[1]);
y++;
x1+=dx1;
x2+=dx2;
z1+=dz1;
z2+=dz2;
}
}
if (dy1=p3->y-p1->y) {
dx1=(p1->x-p3->x)<<32/dy1;
dz1=(p1->z-p3->z)<<32/dy1;
if (dy2=p3->y-p2->y) {
dx2=(p2->x-p3->x)<<32/dy2;
dz2=(p2->z-p3->z)<<32/dy2;
} else {
dx2=0;
dz2=0;
}
x1=x2=p3->x<<32; y=p3->y; z1=z2=p3->z<<32;
while (dy1--) {
cnt+=GrHLine(base,x1.i4[1],x2.i4[1],y,z1.i4[1],z2.i4[1]);
y--;
x1+=dx1;
x2+=dx2;
z1+=dz1;
z2+=dz2;
}
}
}
return cnt;
}
public I8 GrFillPolygon3(GrBitMap *base,I8 n,P3I4 *poly)
{ //Must be convex.
P3I4 tri[3];
I8 i,j,x0,y0,z0,x1,y1,z1,x2,y2,z2,cnt=0;
if (n<3) return 0;
if (base->flags & BMF_SYMMETRY) {
for (i=1;i<n-1;i++) {
j=i-1;
if (i==1) {
x0=poly[j].x; y0=poly[j].y; z0=poly[j].z;
if (base->flags&BMF_TRANSFORMATION)
base->transform(base,&x0,&y0,&z0);
GrReflect(base,&x0,&y0,&z0);
tri[0].x=x0; tri[0].y=y0; tri[0].z=z0;
}
j++;
if (i==1) {
x1=poly[j].x; y1=poly[j].y; z1=poly[j].z;
if (base->flags&BMF_TRANSFORMATION)
base->transform(base,&x1,&y1,&z1);
GrReflect(base,&x1,&y1,&z1);
} else {
x1=x2; y1=y2; z1=z2;
}
tri[1].x=x1; tri[1].y=y1; tri[1].z=z1;
j++;
x2=poly[j].x; y2=poly[j].y; z2=poly[j].z;
if (base->flags&BMF_TRANSFORMATION)
base->transform(base,&x2,&y2,&z2);
GrReflect(base,&x2,&y2,&z2);
tri[2].x=x2; tri[2].y=y2; tri[2].z=z2;
cnt+=GrFillTriangle0(base,&tri[0],&tri[1],&tri[2]);
}
}
if (base->flags&BMF_JUST_MIRROR)
return cnt;
for (i=1;i<n-1;i++) {
j=i-1;
if (i==1) {
x0=poly[j].x; y0=poly[j].y; z0=poly[j].z;
if (base->flags&BMF_TRANSFORMATION)
base->transform(base,&x0,&y0,&z0);
tri[0].x=x0; tri[0].y=y0; tri[0].z=z0;
}
j++;
if (i==1) {
x1=poly[j].x; y1=poly[j].y; z1=poly[j].z;
if (base->flags&BMF_TRANSFORMATION)
base->transform(base,&x1,&y1,&z1);
} else {
x1=x2; y1=y2; z1=z2;
}
tri[1].x=x1; tri[1].y=y1; tri[1].z=z1;
j++;
x2=poly[j].x; y2=poly[j].y; z2=poly[j].z;
if (base->flags&BMF_TRANSFORMATION)
base->transform(base,&x2,&y2,&z2);
tri[2].x=x2; tri[2].y=y2; tri[2].z=z2;
cnt+=GrFillTriangle0(base,&tri[0],&tri[1],&tri[2]);
}
return cnt;
}
#help_index "Graphics/Mesh"
public I8 Gr3Mesh(GrBitMap *base,I8 vertex_cnt,P3I4 *p,I8 triangle_cnt,GrMeshTri *tri)
{
I8 i,x,y,z,old_color=base->color,cnt=0;
P3I4 *pt,*pt_sym,*p_sym,*dst;
GrMeshTri *tri_sym=tri;
if (base->flags&BMF_TRANSFORMATION) {
dst=pt=MAlloc(sizeof(P3I4)*vertex_cnt);
for (i=0;i<vertex_cnt;i++,p++,dst++) {
x=p->x; y=p->y; z=p->z;
base->transform(base,&x,&y,&z);
dst->x=x; dst->y=y; dst->z=z;
}
p=pt;
} else
pt=NULL;
if (base->flags & BMF_SYMMETRY) {
dst=pt_sym=MAlloc(sizeof(P3I4)*vertex_cnt);
p_sym=p;
for (i=0;i<vertex_cnt;i++,p_sym++,dst++) {
x=p_sym->x; y=p_sym->y; z=p_sym->z;
GrReflect(base,&x,&y,&z);
dst->x=x; dst->y=y; dst->z=z;
}
p_sym=pt_sym;
for (i=0;i<triangle_cnt;i++,tri_sym++) {
base->lighting(base,&p_sym[tri_sym->nums[0]],&p_sym[tri_sym->nums[2]],&p_sym[tri_sym->nums[1]],tri_sym->color);
cnt+=GrFillTriangle0(base,&p_sym[tri_sym->nums[0]],&p_sym[tri_sym->nums[2]],&p_sym[tri_sym->nums[1]]);
}
Free(pt_sym);
if (base->flags&BMF_JUST_MIRROR)
goto mesh_done;
}
for (i=0;i<triangle_cnt;i++,tri++) {
base->lighting(base,&p[tri->nums[0]],&p[tri->nums[1]],&p[tri->nums[2]],tri->color);
cnt+=GrFillTriangle0(base,&p[tri->nums[0]],&p[tri->nums[1]],&p[tri->nums[2]]);
}
mesh_done:
base->color=old_color;
Free(pt);
return cnt;
}
#help_index "Graphics"