#define MIN(a,b) ((a<b)?(a):(b))
#define MAX(a,b) ((a>b)?(a):(b))
#define MaxPoint(a,b) ((a.y > b.y) ? a : b)
#define MinPoint(a,b) ((b.y > a.y) ? a : b)
然后我们定义三个宏来区别三个点:
#define MaxPoint3(a,b,c) MaxPoint(MaxPoint(a,b),MaxPoint(b,c))
#define MidPoint3(a,b,c) MaxPoint(MinPoint(a,b),MinPoint(a,c))
#define MinPoint3(a,b,c) MinPoint(MinPoint(a,b),MinPoint(b,c))
你也许注意到MidPoint3宏不总是正常地工作,取决于三个点排列的顺序。例如,a<b & a<c。那么MidPoint3得到的是a,但它不是中间点。我们用if语句来修正这个缺点,下面为函数的代码:
void POLY_Triangle(_2D p1,_2D p2,_2D p3,char c)
{
_2D p1d,p2d,p3d;
int xd1,yd1,xd2,yd2,i;
int Lx,Rx;
首先我们把三个点进行排序:
p1d = MinPoint3(p1,p2,p3);
p2d = MidPoint3(p2,p3,p1);
p3d = MaxPoint3(p3,p1,p2);
当调用这些宏的时候为什么会有点的顺序的改变?(作者也不清楚)可能这些点被逆时针传递。试图改变这些宏你的屏幕显示的是垃圾。现在我们并不确定中间的点,所以我们做一些检查,而且在这种状态下,得到的中间点有似乎是错误的,所以我们修正:
if(p2.y < p1.y)
{
p1d=MinPoint3(p2,p1,p3);
p2d=MidPoint3(p1,p3,p2);
}
这些点的排列顺序看起来很奇怪,但是试图改变他们那么所有的东西就乱套了。只有理解或接受这些结论。现在我们计算增量:
xd1=p2d.x-p1d.x;
yd1=p2d.y-p1d.y;
xd2=p3d.x-p1d.x;
yd2=p3d.y-p1d.y;
好的,第一步已经完成,如果有增量y:
if(yd1)
for(i=p1d.y; i<=p2d.y; i++)
{
// 我们用x的起始坐标计算x值,在当前点和起始点之间加上增量y,乘以斜率(x/y)的相反值。
Lx = p1d.x + ((i - p1d.y) * xd1) / yd1;
Rx = p1d.x + ((i - p1d.y) * xd2) / yd2;
// 如果不在同一个点,绘制线段,按次序传递这两个点:
if(Lx!=Rx)
VID_HLine(MIN(Lx,Rx),MAX(Lx,Rx),i,c);
}
现在我们重新计算第一个增量,而且计算第二条边:
xd1=p3d.x-p2d.x;
yd1=p3d.y-p2d.y;
if(yd1)
for(i = p2d.y; i <= p3d.y; i++)
{
Lx = p1d.x + ((i - p1d.y) * xd2) / yd2;
Rx = p2d.x + ((i - p2d.y) * xd1) / yd1;
if(Lx!=Rx)
VID_HLine(MIN(Lx,Rx),MAX(Lx,Rx),i,c);
}
}
以上我们已经得到多边形填充公式,对于平面填充更加简单:
void VID_HLine(int x1, int x2, int y, char c)
{
int x;
for(x=x1; x<=x2; x++)
putpixel(x, y, c);
}
回目录
--------------------------------------------------------------------------------
4、Sutherland-Hodgman剪贴
4.1 概述
一般地,我们更愿意剪贴我们的多边形。必须靠着屏幕的边缘剪贴,但也必须在观察的前方(我们不需要绘制观察者后面的事物,当z左边非常小时)。当我们剪贴一个多边形,并不考虑是否每一个点在限制以内,而我们更愿意增加必须的顶点,所以我们需要一个第三个多边形结构:
typedef struct {
int Count;
_3D Vertex[20];
} CPolygon_t;
由于我们有附加的顶点来投影,我们不再投影顶点,而是投影剪贴的3D多边形到2D多边形。
void M3D_Project(CPolygon_t *Polygon,Polygon2D_t *Clipped,int focaldistance)