2014年11月4日星期二(DEMO10-1,3D裁剪)


本来应该进行9-4和那个RAISER3D的游戏,不过由于要进行的是软引擎,故先避免之 。直接开第十章,

本节的主要内容是3D裁剪,

裁剪就是尽可能少地将图元传给3D流水线的下一个阶段。

首先,介绍了物体空间裁剪。定义是:根据特定的裁剪区域对基本图元组成的几何体进行裁剪,是根据对象的数学表示进行的,然后把裁剪后的多边形(这里是三角形)传给下一个阶段。问题是有可能生成新的多边形,需要重构成新的三角形。

 

以前都是空间的2D裁剪,就是说将直线或者三角形投影到视平面上进后,根据矩形视平面对其进行裁剪。

在物理空间的3D裁剪,问题是多边形可能穿过近裁剪面或者Z=0平面。于是,采取如下方法:

1, 对所有物体进行提出操作

2, 执行背面消除

3, 根据视景体对所有多边形裁剪,只对近裁剪面对多边形进行完整的裁剪,并将裁剪后的多边形重新分割为三角形,其他裁剪面值执行剔除操作,

4, 将余下的多边形传递到3D流水线的下一个阶段,在光栅化阶段对超出视平面和屏幕空间边界的三角形进行2D裁剪。

接下来介绍了图像空间裁剪。也就是屏幕(或者视平面的2D裁剪),这样第一比较麻烦,第二会丢失Z缓存。

因此,用物理空间裁剪的方法。

 

下面介绍裁剪。点测试是基础,边测试只要判断两个端点即可。

1,2D点测试

点在矩形内:( xmin <= x <= xmax )且( ymin<= y <= ymax )

2,3D点测试:

(1) 裁剪区域长方体

(xmin<=x<=xmax )且(ymin<= y <=ymax)且(zmin<=z<=zmax)

(2) 视景体为棱锥台。对于平面ptop、pbotton、pright、pleft、pfar、pNear,需判断点是否在裁剪面内侧(即正半空间),即各个法线指向的一侧。+1表示正半空间,-1表示负半空间,0表示位于平面上,

判断方法是把点的坐标代入平面方程中。

方法如下:

对于平面方程a(x-x0)+b(y-y0)+c(z-z0) = 0,其中法线向量为<a,b,c>,(x0,y0,z0)为平面上的一个点。则对于

Hs=a*(x-x0)+b*(y-y0)+c*(z-z0),只需将点(x,y,z)代入。

若Hs=0,则该点位于平面上;

若Hs>0,则该点位于平面的正半空间中;

若Hs<0,则该点位于平面的负半空间中。

 

1, 线段裁剪分2D裁剪(用无限长直线裁剪线段)和3D裁剪(用平面裁剪线段)。多边形裁剪可简化为线段裁剪。

(1)2D线段裁剪只考虑X=XL和Y=YL两种情形,即,水平直线或垂直直线对三角形进行裁剪。

对于线段P=P0 + ( P1 – P0 ) * t,即

x=x0 + ( x1 – x0 ) * t

y = y0 + ( y1-y0 ) * t,

分别 代入X坐标(或者Y坐标),若(0<=t<=1 ),则相交,否则不相交。

当然,前提是端点P0和P1不重合,且两条直线不能平行。

(2)3D空间中的线段裁剪

对于点法式平面方程:

Nx * ( x – x0 ) + ny * ( y – y0 ) + nz * ( z – z0 ) = 0

其中,法线为(nx,ny,nz),平面上的点为(x0,y0,z0),

直线方程p1->p2:

P = p1 + ( p2 – p1 ) * t ( 0<=t<=1),

X=x1 + ( x2 –x1 ) * t;

Y=y1+(y2-y1) * t;

Z=z1+(z2-z1) * t;

则可以得到t的值,并以此计算出交点。

 

下面的几种裁剪算法:

1,Cohen-Sutherland裁剪算法

此算法主要用来排除完全在区域外和区域内。通过编码的方式,省却了很多if,else语句。

编码方式为b3b2b1b0,。为TRUE时的含义如下,

B3: y>ymax,位于上边缘上方

B2:y<ymin,位于下边缘下方

B1:x>xmax,位于右边缘右方

B0,x<xmin,.位于左边缘左方。

 

若未通过测试,则代表线段与裁剪区域边界有1个或2个交点,需要进行裁剪。可以采用的方法之一,就是使用线段穿过的裁剪区域边界对线段进行裁剪,浙江增加1条或2条线段,然后对这些线段应用该算法。

1, Cyrus-Back/梁友栋-Barksy裁剪算法

与第一个算法类似,不过使用的参数方程来代替X,Y变量。由于不实现该算法,故省略之。

2, Weiler-Anthon裁剪算法

由于是为了实现,而不是学术研究,故只介绍简化后的算法。

这个算法出发点:认为多边形是由顶点构成的。这里只考虑三角形。

按照一定顺序遍历各顶点,顶点或者在裁剪区域内,或者在裁剪区域外,如果第一个顶点在裁剪区域内,则输出它;否则,则遍历到下一个顶点,若三角形边的起点和终点状态不同(一个在裁剪区域内,一个在裁剪区域外),则计算这条边与边界的交点,并输出它。若起点在裁剪区域内,则计算在进入和离开裁剪区域的两个交点。

 

总之,裁剪只要找出多边形与裁剪边界交点即可。

这里,使用多边形级别的裁剪。,在相机变换后进行裁剪/剔除;剔除完全在视景体外的多边形,同时只对穿过近裁剪面的多边形进行裁剪。,对于上、下、左、右裁剪面的多边形,则不去管,因为光栅化函数将在图像空间对其进行裁剪。

 

理论比比叨叨地讲了半天,下面终于进行编程了。裁剪由于属于流水线部分,故写在DDRAW_LIUSHUIXIAN_TEXTURE类里。或许应该建立个子类。

(1)

先看左右裁剪面方程为,

Tan(theta/2) = |x| / z,

|x| = tan(theta/2) * z

若 |x| = tan( theta/2 )* z.则顶点在裁剪面上

若 |x| < tan( theta/2) * z.则顶点在裁剪面内侧

若 |x| > tan( theta/2) * z.则顶点在裁剪面外侧。

 

同样,上下平面,以y代替x,同样适用。

(2)    远近裁剪面:对于三角形面三个顶点vi(xi,yi,zi)(i=0,1,2)

完全在远裁剪面之外(v0.z>far_clip_z且v1.z>far_clip_z且v2.z>far_clip_z)

完全在近裁剪面之外(v0.z<near_clip_z且v1.z<near_clip_z且v2.z<far_clip_z)

穿过远裁剪面:不考虑

穿过近裁剪面

1)   一个顶点在视景体内,2个顶点在视景体外

对2条与近裁剪面相交的边进行裁剪,用新顶点覆盖原来的顶点即可。必要时重新计算纹理坐标和法线。

2)   两个顶点在视景体内,1个顶点在视景体内

裁剪后,将会成为一个四边形,必须分割为2个三角形,其中,两个顶点不变的三角形代替以前的三角形。1个顶点不变的三角形插入到渲染列表尾部。

(3)    计算纹理坐标

用插值的方式。

 

接下来就是裁剪函数的代码了,书上还是注释的比较详细的。

 

 

 

int DDRAW_LIUSHUIXIAN_TEXTURE::Insert_POLYF4DV2_RENDERLIST4DV2(RENDERLIST4DV2_PTR rend_list,POLYF4DV2_PTR poly,ddraw_math math)

{

    if(rend_list->num_polys>= RENDERLIST4DV2_MAX_POLYS )

         return( 0 );

 

    memcpy(( void * ) & rend_list->poly_data[rend_list->num_polys], ( void* ) poly, sizeof(POLYF4DV2 ) );

 

    if(rend_list->num_polys== 0 )

    {

         rend_list->poly_data[0].next                         = NULL;

         rend_list->poly_data[0].prev                         = NULL;

    }

    else

    {

         rend_list->poly_data[rend_list->num_polys].next      = NULL;

         rend_list->poly_data[rend_list->num_polys].prev      = & rend_list->poly_data[rend_list->num_polys-1];

         rend_list->poly_data[rend_list->num_polys-1].next    = & rend_list->poly_data[rend_list->num_polys];

 

    }

    rend_list->num_polys++;

 

    return( 1 );

}

裁剪代码如下:

 

void DDRAW_LIUSHUIXIAN_TEXTURE::Clip_Polys_RENDERLIST4DV2( ddraw_math * math2, RENDERLIST4DV2_PTR rend_list,CAM4DV1_PTR cam,int clip_flags)

{

 

    //内部裁剪码

#define  CLIP_CODE_GZ                   0x0001                //z> z_max

#define  CLIP_CODE_LZ                   0x0002                //z< z_min

#define CLIP_CODE_IZ                   0x0004                // z_min < z < z_max

 

#define  CLIP_CODE_GX                   0x0001                //x> x_max

#define  CLIP_CODE_LX                   0x0002                //x< x_min

#define CLIP_CODE_IX                   0x0004                // x_min < x < x_max

 

#define  CLIP_CODE_GY                   0x0001                //y> y_max

#define  CLIP_CODE_LY                   0x0002                //y< y_min

#define CLIP_CODE_IY                   0x0004                // y_min < y < y_max

 

#define  CLIP_CODE_NULL                     0x0000

 

    int                                    vertex_ccodes[3]; //用于存储裁剪标记

    int                                    num_verts_in;         //位于视景体内部的顶点数

    int                                    v0, v1, v2;           //顶点索引

 

    float                                  z_factor,             //用于裁剪计算                                 

                                            z_test;               //用于裁剪计算

 

    float                                  xi, yi, x01i, y01i, x02i, y02i,        //交点坐标

                                            t1, t2,               //参数化t

                                            ui, vi, u01i, v01i, u02i, v02i;        //交点纹理坐标

 

    int                                    last_poly_index//渲染列表中最后一个有效的多边形

                                            insert_poly_index;    //新多边形的插入位置

 

    VECTOR4D                           u, v, n;          //用于向量计算

 

    POLYF4DV2                              temp_poly;            //将多边形分割成个时,用于存储新增的多边形

 

    //设置last_poly_index和insert_poly_index,使其对英语渲染列表末尾,以免分割多边形次

    insert_poly_index                                        = last_poly_index     =rend_list->num_polys;

 

    //遍历渲染列表,对其中的多边形进行裁剪/剔除

    for(int poly =0; poly < last_poly_index;poly++ )

    {

         //获得当前多边形

         POLYF4DV2_PTR                      curr_poly             = rend_list->poly_ptrs[poly];

 

         //该多边形有效么?仅当多边形处于活动状态、为被

 

         if( curr_poly == NULL||

             ! ( curr_poly->state& POLY4DV2_STATE_ACTIVE) ||

             ( curr_poly->state& POLY4DV2_STATE_CLIPPED) ||

             ( curr_poly->state& POLY4DV2_STATE_BACKFACE ))

 

         {

             continue;

         }

 

         //根据左右裁剪面进行剔除

         if(clip_flags & CLIP_POLY_X_PLANE)

         {

             z_factor= ( 0.5 ) * cam->viewplane_width/ cam->view_dist;

 

             //顶点

             z_test                             = z_factor * curr_poly->tvlist[0].z;

 

             if(curr_poly->tvlist[0].x > z_test )

                  vertex_ccodes[0]          =CLIP_CODE_GX;

             elseif( curr_poly->tvlist[0].x< - z_test )

                  vertex_ccodes[0]          =CLIP_CODE_LX;

             else

                  vertex_ccodes[0]          =CLIP_CODE_IX;

            

             //顶点

 

             z_test                             = z_factor * curr_poly->tvlist[1].z;

 

             if(curr_poly->tvlist[1].x > z_test )

                  vertex_ccodes[1]          =CLIP_CODE_GX;

             elseif( curr_poly->tvlist[1].x< - z_test )

                  vertex_ccodes[1]          =CLIP_CODE_LX;

             else

                  vertex_ccodes[1]          =CLIP_CODE_IX;

 

             //顶点

 

             z_test                             = z_factor * curr_poly->tvlist[2].z;

 

             if(curr_poly->tvlist[2].x > z_test )

                  vertex_ccodes[2]          =CLIP_CODE_GX;

             elseif( curr_poly->tvlist[1].x< - z_test )

                  vertex_ccodes[2]          =CLIP_CODE_LX;

             else

                  vertex_ccodes[2]          =CLIP_CODE_IX;

 

            

             //进行简单拒绝测试,即多边形是否完全在左裁剪面或者右裁剪面外侧

             if(( ( vertex_ccodes[0] == CLIP_CODE_GX ) &&

                      ( vertex_ccodes[1] == CLIP_CODE_GX) &&

                      ( vertex_ccodes[2] == CLIP_CODE_GX) ) ||

                     

                  ( ( vertex_ccodes[0] == CLIP_CODE_LX) &&

                      ( vertex_ccodes[1] == CLIP_CODE_LX) &&

                      ( vertex_ccodes[2] == CLIP_CODE_LX) )  )

             {

                  //将完全在裁剪面外侧的多边形裁剪掉

                  SET_BIT( curr_poly->state, POLY4DV2_STATE_CLIPPED);

 

                  //进入下一个多边形

                  continue;

             }

         }

 

 

         //根据上下裁剪面进行剔除

         if(clip_flags & CLIP_POLY_X_PLANE)

         {

             z_factor= ( 0.5 ) * cam->viewplane_width/ cam->view_dist;

 

             //顶点

             z_test                             = z_factor * curr_poly->tvlist[0].z;

 

             if(curr_poly->tvlist[0].y > z_test )

                  vertex_ccodes[0]          =CLIP_CODE_GY;

             elseif( curr_poly->tvlist[0].y< - z_test )

                  vertex_ccodes[0]          =CLIP_CODE_LY;

             else

                  vertex_ccodes[0]          =CLIP_CODE_IY;

            

             //顶点

 

             z_test                             = z_factor * curr_poly->tvlist[1].z;

 

             if(curr_poly->tvlist[1].y > z_test )

                  vertex_ccodes[1]          =CLIP_CODE_GY;

             elseif( curr_poly->tvlist[1].y< - z_test )

                  vertex_ccodes[1]          =CLIP_CODE_LY;

             else

                  vertex_ccodes[1]          =CLIP_CODE_IY;

 

             //顶点

 

             z_test                             = z_factor * curr_poly->tvlist[2].z;

 

             if(curr_poly->tvlist[2].y > z_test )

                  vertex_ccodes[2]          =CLIP_CODE_GY;

             elseif( curr_poly->tvlist[1].y< - z_test )

                  vertex_ccodes[2]          =CLIP_CODE_LY;

             else

                  vertex_ccodes[2]          =CLIP_CODE_IY;

 

            

             //进行简单拒绝测试,即多边形是否完全在左裁剪面或者右裁剪面外侧

             if(( ( vertex_ccodes[0] == CLIP_CODE_GY ) &&

                      ( vertex_ccodes[1] == CLIP_CODE_GY) &&

                      ( vertex_ccodes[2] == CLIP_CODE_GY) ) ||

                     

                  ( ( vertex_ccodes[0] == CLIP_CODE_LY) &&

                      ( vertex_ccodes[1] == CLIP_CODE_LY) &&

                      ( vertex_ccodes[2] == CLIP_CODE_LY) )  )

             {

                  //将完全在裁剪面外侧的多边形裁剪掉

                  SET_BIT( curr_poly->state, POLY4DV2_STATE_CLIPPED);

 

                  //进入下一个多边形

                  continue;

             }

         }

 

 

         //根据远/近裁剪面进行裁剪/剔除

 

         if(clip_flags & CLIP_POLY_Z_PLANE)

         {

             //重置内部顶点计数器,该变量用于对最终的三角形分类

             num_verts_in                       = 0;

 

             //顶点

             if(curr_poly->tvlist[0].z > cam->far_clip_z )

             {

                  vertex_ccodes[0]                   =CLIP_CODE_GZ;

             }

             elseif( curr_poly->tvlist[0].z< cam->near_clip_z)

             {

                  vertex_ccodes[0]                   =CLIP_CODE_LZ;

             }

             else

             {

                  vertex_ccodes[0]                   =CLIP_CODE_IZ;

                  num_verts_in ++;

             }

 

             //顶点

 

             if(curr_poly->tvlist[1].z > cam->far_clip_z )

             {

                  vertex_ccodes[1]                   =CLIP_CODE_GZ;

             }

             elseif( curr_poly->tvlist[1].z< cam->near_clip_z)

             {

                  vertex_ccodes[1]                   =CLIP_CODE_LZ;

             }

             else

             {

                  vertex_ccodes[1]                   =CLIP_CODE_IZ;

                  num_verts_in ++;

             }

 

 

             //顶点

 

             if(curr_poly->tvlist[2].z > cam->far_clip_z )

             {

                  vertex_ccodes[2]                   =CLIP_CODE_GZ;

             }

             elseif( curr_poly->tvlist[2].z< cam->near_clip_z)

             {

                  vertex_ccodes[2]                   =CLIP_CODE_LZ;

             }

             else

             {

                  vertex_ccodes[2]                   =CLIP_CODE_IZ;

                  num_verts_in ++;

             }

 

   

             //进行简单拒绝测试,即多边形是否完全在左裁剪面或者右裁剪面外侧

             if(( ( vertex_ccodes[0] == CLIP_CODE_GZ ) &&

                      ( vertex_ccodes[1] == CLIP_CODE_GZ) &&

                      ( vertex_ccodes[2] == CLIP_CODE_GZ) ) ||

                     

                  ( ( vertex_ccodes[0] == CLIP_CODE_LZ) &&

                      ( vertex_ccodes[1] == CLIP_CODE_LZ) &&

                      ( vertex_ccodes[2] == CLIP_CODE_LZ) )  )

             {

                  //将完全在裁剪面外侧的多边形裁剪掉

                  SET_BIT( curr_poly->state, POLY4DV2_STATE_CLIPPED);

 

                  //进入下一个多边形

                  continue;

             }

         }

 

         //判断是否有顶点在近裁剪面外侧

         if(( ( vertex_ccodes[0] | vertex_ccodes[1] | vertex_ccodes[2]) & CLIP_CODE_LZ ) )

         {

             //2种情景:

             //1,三角形有个顶点在近裁剪面内部

             //2,或者个顶点在近裁剪面内部

 

             //第一步:根据内外侧顶点数对三角形进行分类

             //情形:简单情形:裁剪后的三角形覆盖原来的三角形

             if(num_verts_in == 1 )

             {

                  //第一步,找出位于内侧的顶点

                  if( vertex_ccodes[0]== CLIP_CODE_IZ )

                  {

                      v0 = 0;

                      v1 = 1;

                      v2 = 2;

                  }

                  else

                  if( vertex_ccodes[1]== CLIP_CODE_IZ )

                  {

                      v0 = 1;

                      v1 = 2;

                      v2 = 0;

                  }

                  else

                  {

                      v0 = 2;

                      v1 = 0;

                      v2 = 1;

                  }

 

                  //第步:对每条边进行裁剪

                  //创建参数化线段p = v0 + v01 * t

 

                  //对三角形边v0->v1,进行裁剪

                  math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v1].v, & v );

 

                  //交点的z坐标为near_clip_z,因此,t值如下

                  t1 = ( ( cam->near_clip_z - curr_poly->tvlist[v0].z ) / v.z );

 

                   //代入t,得到交点的x,y坐标

                  xi                             =curr_poly->tvlist[v0].x + v.x * t1;

                 yi                             =curr_poly->tvlist[v0].y + v.y * t1;

 

                   //用交点覆盖原来的原点

                  curr_poly->tvlist[v1].x        = xi;

                  curr_poly->tvlist[v1].y        = yi;

                  curr_poly->tvlist[v1].z        = cam->near_clip_z;

            

                 

                  //对三角形边v0->v2,进行裁剪

                  math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v2].v, & v );

 

                  //交点的z坐标为near_clip_z,因此,t值如下

                  t2 = ( ( cam->near_clip_z - curr_poly->tvlist[v0].z ) / v.z );

 

                   //代入t,得到交点的x,y坐标

                  xi                             =curr_poly->tvlist[v0].x + v.x * t2;

                  yi                             =curr_poly->tvlist[v0].y + v.y * t2;

 

                   //用交点覆盖原来的原点

                  curr_poly->tvlist[v2].x        = xi;

                  curr_poly->tvlist[v2].y        = yi;

                  curr_poly->tvlist[v2].z        = cam->near_clip_z;

                 

                  //检查多边形是否带纹理,

                  //如果带纹理,则对纹理坐标进行裁剪

                  if( curr_poly->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)

                  {

                      ui                        =curr_poly->tvlist[v0].u0 + ( curr_poly->tvlist[v1].u0 - curr_poly->tvlist[v0].u0 ) * t1;

                      vi                        =curr_poly->tvlist[v0].v0 + ( curr_poly->tvlist[v1].v0 - curr_poly->tvlist[v0].v0 ) * t1;

                      curr_poly->tvlist[v1].u0= ui;

                      curr_poly->tvlist[v1].v0= vi;

 

                      ui                        =curr_poly->tvlist[v0].u0 + ( curr_poly->tvlist[v2].u0 - curr_poly->tvlist[v0].u0 ) * t2;

                      vi                        =curr_poly->tvlist[v0].v0 + ( curr_poly->tvlist[v2].v0 - curr_poly->tvlist[v0].v0 ) * t2;

                      curr_poly->tvlist[v2].u0= ui;

                      curr_poly->tvlist[v2].v0= vi;

                  }

 

                  //最后,重新计算法线长度

                  //计算u

                  math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v1].v, & u );

                  math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v2].v, & v );

 

                  //计算叉积

                  math2->VECTOR4D_CROSS(& u, & v,& n );

 

                  //计算并存储法线长度

                  curr_poly->nlength= math2->VECTOR4D_length(& n );

             }

             else

             //情形:被裁减后三角形变为四边形,覆盖一个,插入渲染列表末尾个

             if(num_verts_in == 2 )

             {

                  //第步,复制多边形

                  memcpy( & temp_poly,curr_poly, sizeof(POLY4DV2 ) );

 

 

                  //第一步,找出位于外侧的顶点

                  if( vertex_ccodes[0]== CLIP_CODE_LZ )

                  {

                      v0 = 0;

                      v1 = 1;

                      v2 = 2;

                  }

                  else

                  if( vertex_ccodes[1]== CLIP_CODE_LZ )

                  {

                      v0 = 1;

                      v1 = 2;

                      v2 = 0;

                  }

                  else

                  {

                      v0 = 2;

                      v1 = 0;

                      v2 = 1;

                  }

 

                  //第步:对每条边进行裁剪

                  //创建参数化线段p = v0 + v01 * t

 

                  //对三角形边v0->v1,进行裁剪

                  math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v1].v, & v );

 

                  //交点的z坐标为near_clip_z,因此,t值如下

                  t1 = ( ( cam->near_clip_z - curr_poly->tvlist[v0].z ) / v.z );

 

                   //代入t,得到交点的x,y坐标

                  x01i                           =curr_poly->tvlist[v0].x + v.x * t1;

                  y01i                           =curr_poly->tvlist[v0].y + v.y * t1;

 

                 

                 

                  //对三角形边v0->v2,进行裁剪

                  math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v2].v, & v );

 

                  //交点的z坐标为near_clip_z,因此,t值如下

                  t2 = ( ( cam->near_clip_z - curr_poly->tvlist[v0].z ) / v.z );

 

                   //代入t,得到交点的x,y坐标

                  x02i                      =curr_poly->tvlist[v0].x + v.x * t2;

                  y02i                      = curr_poly->tvlist[v0].y + v.y * t2;

 

 

                   //用交点覆盖原来的三角形的顶点

                  curr_poly->tvlist[v0].x        = x01i;

                  curr_poly->tvlist[v0].y        = y01i;

                  curr_poly->tvlist[v0].z        = cam->near_clip_z;

            

             //使用原来的顶点和两个交点创建一个新三角形

             //该三角形被插入到渲染列表的末尾

                  temp_poly.tvlist[v1].x         = x01i;

                  temp_poly.tvlist[v1].y         = y01i;

                  temp_poly.tvlist[v1].z         = cam->near_clip_z;

 

                  temp_poly.tvlist[v0].x         = x02i;

                  temp_poly.tvlist[v0].y         = y02i;

                  temp_poly.tvlist[v0].z         = cam->near_clip_z;

 

 

                  //检查多边形是否带纹理,

                  //如果带纹理,则对纹理坐标进行裁剪

                  if( curr_poly->attr & POLY4DV2_ATTR_SHADE_MODE_TEXTURE)

                  {

                      //计算多边形的纹理坐标

                      u01i                  =curr_poly->tvlist[v0].u0 + ( curr_poly->tvlist[v1].u0 - curr_poly->tvlist[v0].u0 ) * t1;

                      v01i                  =curr_poly->tvlist[v0].v0 + ( curr_poly->tvlist[v1].v0 - curr_poly->tvlist[v0].v0 ) * t1;

 

                      //计算多边形的纹理坐标

                      u02i                  =curr_poly->tvlist[v0].u0 + ( curr_poly->tvlist[v2].u0 - curr_poly->tvlist[v0].u0 ) * t2;

                      v02i                  =curr_poly->tvlist[v0].v0 + ( curr_poly->tvlist[v2].v0 - curr_poly->tvlist[v0].v0 ) * t2;

 

                      //覆盖原来的纹理坐标

                      //多边形

                      curr_poly->tvlist[v1].u0= u01i;

                      curr_poly->tvlist[v1].v0= v01i;

 

                      //多边形

                      temp_poly.tvlist[v0].u0   = u02i;

                      temp_poly.tvlist[v0].u0   = v02i;

                      temp_poly.tvlist[v1].u0   = u01i;

                      temp_poly.tvlist[v1].u0   = v01i;

                     

                  }

 

                  //最后,重新计算法线长度

                  //计算u和v

                  math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v1].v, & u );

                  math2->VECTOR4D_Build(& curr_poly->tvlist[v0].v, & curr_poly->tvlist[v2].v, & v );

 

                  //计算叉积

                  math2->VECTOR4D_CROSS(& u, & v,& n );

 

                  //计算并存储法线长度

                  curr_poly->nlength= math2->VECTOR4D_length(& n );

 

                  //现在计算多边形(temp_poly)的法线长度

                  //计算u和v

                  math2->VECTOR4D_Build(& temp_poly.tvlist[v0].v, & temp_poly.tvlist[v1].v, & u );

                  math2->VECTOR4D_Build(& temp_poly.tvlist[v0].v, & temp_poly.tvlist[v2].v, & v );

 

                  //计算叉积

                  math2->VECTOR4D_CROSS(& u, & v,& n );

 

                  //计算并存储法线长度

                  temp_poly.nlength= math2->VECTOR4D_length(& n );

 

                  //现在将多边形插入到渲染列表末尾

                  Insert_POLYF4DV2_RENDERLIST4DV2( rend_list, & temp_poly,math2 );

             }

             }

             }

             }

 

 

现在看main.cpp了

定义个物体数量

 

#define  NUM_OBJECTS             6

位置变化了

vpos = {0,0,150,1},

物体

 

OBJECT4DV2_PTR    obj_work;

OBJECT4DV2_PTR    obj_array[NUM_OBJECTS];  

 

几个模型

 

// filenames of objects to load

char *object_filenames[NUM_OBJECTS] = { "cube_flat_01.cob",

                                       "cube_gouraud_01.cob",

                                       "cube_flat_textured_01.cob",

                                       "sphere02.cob",

                                        "sphere03.cob",

                                       "hammer03.cob",

                                     };

 

 

int curr_object                             = 0;

在初始化中

摄像机换了位置

    liushuixian.Init_CAM4DV1( * math,&cam,      // the camera object

         CAM_MODEL_EULER,// the euler model

         &cam_pos // initial camera position

         &cam_dir // initial camera angles

         &cam_target,      // no target

         100.0,      // near and farclipping planes

         1000.0,

         120.0,      // field ofview in degrees

         SCREEN_WIDTH,  // size offinal screen viewport

         SCREEN_HEIGHT);

                 

//放大扩大倍数

math->VECTOR4D_INITXYZ(&vscale,20.00,20.00,20.00);

物体数组

 

    for(int index_obj= 0; index_obj < NUM_OBJECTS;index_obj ++ )

    {

    liushuixian_texture.Load_OBJECT4DV2_COB( * math,matiGroup, & obj_array[index_obj],object_filenames[index_obj], 

         &vscale, &vpos, &vrot, VERTEX_FLAGS_SWAP_YZ|

         VERTEX_FLAGS_TRANSFORM_LOCAL  /*|

         VERTEX_FLAGS_TRANSFORM_LOCAL_WORLD*/ );

    }

 

    curr_object  = 0;

    obj_work= & obj_array[curr_object];

 

设置灯光时,引入新的灯光数据类型

 

 

#define  LIGHTV2_ATTR_AMBIENT               0x0001       //环境光源

#define  LIGHTV2_ATTR_DIRECTIONAL           0x0002      

#define  LIGHTV2_ATTR_INFINITE              0x0002       //无穷远光源

#define  LIGHTV2_ATTR_POINT                     0x0004       //点光源

#define  LIGHTV2_ATTR_SPOTLIGHT1                0x0008       //1类(简单)聚光灯

#define  LIGHTV2_ATTR_SPOTLIGHT2                0x0010       //2类(复杂)聚光灯

 

#define  LIGHTV2_STATE_ON                   1            //光源打开

#define  LIGHTV2_STATE_OFF                  0            //光源关闭

 

#define  TRANSFORM_COPY_LOCAL_TO_TRANS      3

 

typedef struct LIGHTV2_TYP

{

    int               state;            //光照状态

    int               id;               //光源ID

    int               attr;             //光源类型及其他属性

 

    RGBAV1            c_ambient;        //环境光强度

    RGBAV1            c_diffuse;        //散射光强度

    RGBAV1            c_specular;       //镜面反射光强度

 

    POINT4D           pos;         //光源位置

    POINT4D           tpos;

 

    VECTOR4D     dir;         //光源方向

    VECTOR4D     tdir;             //光源方向

 

    float             kc,kl,kq;         //衰减因子

    float             spot_inner;       //聚光灯内锥角

    float             spot_outer//聚光灯外锥角

    float             pf;               //聚光灯指数因子

    int               iaux1,iaux2; //auxiliary vars for future expansion

    float             faux1,faux2;

    void*            ptr;

}LIGHTV2, * LIGHTV2_PTR;

另外,重置灯光

 

int DDRAW_LIGHT::Reset_Lights_LIGHTV2(LIGHTV2_PTR lights,int max_lights,int num_lights)

{

    staticint            first_time                =1;

    memset(lights, 0, max_lights* sizeof( LIGHTV2));

 

    //重置光源数

    num_lights                                      = 0;

    first_time                                      = 0;

    return( 1 );

}

初始化灯光也随之更新。

int DDRAW_LIGHT::Init_Light_LIGHTV2(ddraw_math math2, LIGHTV2_PTRlight_gr, intindex, int _state, int _attr, RGBAV1 _c_ambient, RGBAV1_c_diffuse, RGBAV1_c_specular, POINT4D_PTR_pos, VECTOR4D_PTR_dir, float kc, float kl, float kq, float _spot_inner, float_spot_outer, float_pf )

{

 

 

if ( index < 0 || index >= MAX_LIGHTS)

    {

         return( 0 );

    }

 

    //初始化光源

    light_gr[index].state                           = _state;

    light_gr[index].id                                   = index;

    light_gr[index].attr                            = _attr;

    light_gr[index].c_ambient                       = _c_ambient;

    light_gr[index].c_diffuse                       = _c_diffuse;

    light_gr[index].c_specular                      = _c_specular;

    light_gr[index].kc                                   = kc;

    light_gr[index].kl                                   = kl;

    light_gr[index].kq                                   = kq;

    if( _pos )

    {

         math2.VECTOR4D_COPY(& light_gr[index].pos, _pos );       //光源位置

         math2.VECTOR4D_COPY(& light_gr[index].tpos, _pos );     

    }

    if( _dir )

    {

         math2.VECTOR4D_COPY( & light_gr[index].dir, _dir );      //光源方向

//       math2.VECTOR4D_COPY(& light_gr[index].dir, _dir );

         //归一化

         math2.VECTOR4D_Normalize( & light_gr[index].dir );

         math2.VECTOR4D_COPY( & light_gr[index].tdir,& light_gr[index].dir );

 

    }

 

    light_gr[index].spot_inner                  = _spot_inner;

    light_gr[index].spot_outer                  = _spot_outer;

    light_gr[index].pf                              = _pf;

 

    //返回光源索引

    returnindex;

}

 

与之对应的初始化

 

    light.Init_Light_LIGHTV2( * math,lightGroup,AMBIENT_LIGHT_INDEX,LIGHTV2_STATE_ON, LIGHTV2_ATTR_AMBIENT,gray, black,black, NULL,NULL, 0, 0, 0, 0, 0, 0 );

 

在Game_Main()中,

设定裁剪模式

 

    staticint x_clip_mode         = 1;

    staticint y_clip_mode         = 1;

    staticint z_clip_mode         = 1;

 

//重置物体

                   liushuixian_texture.Reset_OBJECT4DV2(obj_work);

 

    //generate rotation matrix around y axis

    math->Build_XYZ_Rotation_MATRIX4x4(x_ang, y_ang, z_ang, &mrot);

    //  Build_XYZ_Rotation_MATRIX4x4(x_ang, y_ang,z_ang, &mrot);

 

    //rotate the local coords of the object

    liushuixian_texture.Transform_OBJECT4DV2( obj_work,&mrot, TRANSFORM_LOCAL_TO_TRANS,1,* math );

 

    //perform world transform

    liushuixian_texture.Model_To_World_OBJECT4DV2(obj_work,* math, TRANSFORM_TRANS_ONLY);

 

    //insert the object into render list

liushuixian_texture.Insert_OBJECT4DV2_RENDERLIST4DV2(* math, &rend_list,obj_work,0);

 

光照代码如下

 

int DDRAW_LIUSHUIXIAN_TEXTURE::Light_RENDERLIST4DV2_World2_16( ddraw_math math,int rgb_format,RENDERLIST4DV2_PTR rend_list,CAM4DV1_PTR cam,LIGHTV2_PTR lights,int max_lights)

{

    unsigned     int               r_base,g_base, b_base,            //原来的颜色值

         r_sum,g_sum, b_sum,           //全部光源的总体光照效果

         r_sum0,g_sum0, b_sum0,  

         r_sum1,g_sum1, b_sum1,  

         r_sum2,g_sum2, b_sum2,  

         ri,gi, bi,

         shaded_color;                      //最后的颜色

    float                              dp,                                //点积

         dist,                              //表面和光源之间的距离

         dists,

         i,                                 //强度

         nl,                                //法线长度

         atten;                             //衰减计算结果

 

    VECTOR4D                       u,v, n, l, d, s;

 

    for( int poly =0; poly < rend_list->num_polys; poly++)

    {

         POLYF4DV2_PTR         curr_poly                 =  rend_list->poly_ptrs[poly];

         if( ! ( curr_poly->state& POLY4DV2_STATE_ACTIVE) ||

             ( curr_poly->state& POLY4DV2_STATE_CLIPPED) ||

             ( curr_poly->state& POLY4DV2_STATE_BACKFACE) ||

             ( curr_poly->state& POLY4DV2_STATE_LIT ))

 

         {

             continue;

         }

         SET_BIT(curr_poly->state,POLY4DV2_STATE_LIT );

 

 

         //检查多边形的着色模式

         if( curr_poly->attr& POLY4DV2_ATTR_SHADE_MODE_FLAT  )

         {

             //提取多边形颜色的RGB

 

             _RGB565FROM16BIT(curr_poly->color,& r_base, & g_base,& b_base );

             //转换成.8.8格式

             r_base                                 <<= 3;

             g_base                                 <<= 2;

             b_base                                 <<=3;

 

 

 

             //初始化总体光照颜色

             r_sum                                       = 0;

             g_sum                                       = 0;

             b_sum                                       = 0;

 

             n.z                                         =FLT_MAX;

 

             //遍历光照

             for( int curr_light= 0; curr_light < max_lights; curr_light ++)

             {

                  //光源是否被打开

                  if ( lights[curr_light].state==LIGHTV2_STATE_OFF)

                  {

                      continue;

                  }

 

                  //判断光源类型

                  if ( lights[curr_light].attr& LIGHTV2_ATTR_AMBIENT )

                  {

                      r_sum                              +=( ( lights[curr_light].c_ambient.r * r_base) / 256 );

                      g_sum                              +=( ( lights[curr_light].c_ambient.g * g_base) / 256 );

                      b_sum                              +=( ( lights[curr_light].c_ambient.b * b_base) / 256 );

 

                  }

                  else

                      if ( lights[curr_light].attr& LIGHTV2_ATTR_INFINITE )

                      {

                          if( n.z == FLT_MAX)

                          {

                               math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[1].v,& u );

                               math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[2].v,& v );

                               math.VECTOR4D_CROSS(& u, &v,&n );

 

                          }

 

                          nl                                 =curr_poly->nlength;

 

                          dp                                 =math.VECTOR4D_DOT(&n, & lights[curr_light].tdir);

 

                          if ( dp > 0 )

                          {

                               i                              =128 * dp / nl;

                               r_sum                          +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                               g_sum                          +=(  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                               b_sum                          +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                          }

 

 

                      }

                      else

                          if ( lights[curr_light].attr& LIGHTV2_ATTR_POINT )

                          {

                               if ( n.z == FLT_MAX)

                               {

                                   math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[1].v,& u );

                                   math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[2].v,& v );

 

                                   math.VECTOR4D_CROSS(& u, &v,&n );

                               }

 

 

                               nl                                 =curr_poly->nlength;

 

                               //计算从表面到光源的向量

                               math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & lights[curr_light].tpos,&l );

                               //计算距离和衰减

                               dist                           =math.VECTOR4D_length(&l);

 

 

                               dp                                 =math.VECTOR4D_DOT(&n, & l);

 

                               if ( dp > 0 )

                               {

                                   atten                          = ( lights[curr_light].kc + lights[curr_light].kl* dist + lights[curr_light].kq* dist * dist);

                                   i                              =128 * dp / ( nl* dist * atten);

                                   r_sum                          +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                   g_sum                          += (  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                   b_sum                          +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                               }

 

 

                          }

                          else

                               if ( lights[curr_light].attr& LIGHTV2_ATTR_SPOTLIGHT1 )

                               {

                                   if (n.z == FLT_MAX)

                                   {

                                       math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[1].v,& u );

                                       math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[2].v,& v );

                                       math.VECTOR4D_CROSS(& u, &v,&n );

 

                                   }

 

                                   nl                                 =curr_poly->nlength;

 

                                   //计算从表面到光源的向量

                                   math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & lights[curr_light].tpos,&l );

                                   //计算距离和衰减

                                   dist                           =math.VECTOR4D_length(&l);

 

 

                                   dp                                 =math.VECTOR4D_DOT(&n, & lights[curr_light].tdir);

 

                                   if ( dp > 0 )

                                   {

                                       atten                          =( lights[curr_light].kc + lights[curr_light].kl* dist + lights[curr_light].kq* dist * dist);

                                       i                              =128 * dp / ( nl* atten );

                                       r_sum                          +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                       g_sum                          +=(  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                       b_sum                          +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                                   }

 

 

                               }  

                               else

                                   if ( lights[curr_light].attr& LIGHTV2_ATTR_SPOTLIGHT2 )

                                   {

                                       if (n.z == FLT_MAX )

                                       {

                                            math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[1].v,& u );

                                            math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & curr_poly->tvlist[2].v,& v );

                                            math.VECTOR4D_CROSS(& u, &v,&n );

 

                                       }

 

                                       nl                                 =curr_poly->nlength;

                                       dp                                 =math.VECTOR4D_DOT(&n, & lights[curr_light].tdir);

 

                                       if ( dp > 0 )

                                       {

                                            //计算从表面到光源的向量

                                            math.VECTOR4D_Build(& lights[curr_light].tpos, & curr_poly->tvlist[0].v,  &s );

                                            dists                          =math.VECTOR4D_length(&s);

 

                                            float    dpsl              =math.VECTOR4D_DOT(& s, & lights[curr_light].tdir) / dists;

 

                                            if ( dpsl > 0)

                                            {

                                                atten                     =( lights[curr_light].kc + lights[curr_light].kl* dists + lights[curr_light].kq* dists * dists);

                                                float    dpsl_exp     =dpsl;

                                                for ( int e_index = 1; e_index< ( int ) lights[curr_light].pf;e_index++ )

                                                {

                                                     dpsl              *=dpsl;

                                                }

                                                i                         =128 * dp * dpsl_exp/ ( nl * atten);

                                                r_sum                     +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                                g_sum                     +=(  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                                b_sum                     +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

                                            }

 

 

                                       }

 

 

                                   }  

             }

             //确保颜色分量不溢出

             if( r_sum   >255 )

             {

                  r_sum                                                =255;

 

             }

             if( g_sum   >255 )

             {

                  g_sum                                                =255;

 

             }

             if( b_sum   >255 )

             {

                  b_sum                                                =255;

 

             }

 

             //写入颜色

 

 

             curr_poly->lit_color[0]                                  =_RGB16BIT565( r_sum,g_sum, b_sum);

 

         }

         else

             if( curr_poly->attr& POLY4DV2_ATTR_SHADE_MODE_GOURAUD  )

             {

                  //提取多边形颜色的RGB

 

                  _RGB565FROM16BIT( curr_poly->color, & r_base,& g_base, & b_base);

                  //转换成.8.8格式

                  r_base                                      <<=3;

                  g_base                                      <<=2;

                  b_base                                      <<= 3;

 

 

 

                  //初始化顶点的累积RGB

                  r_sum0                                      =0;

                  g_sum0                                      =0;

                  b_sum0                                      =0;

 

                  r_sum1                                      =0;

                  g_sum1                                      =0;

                  b_sum1                                      =0;

 

                  r_sum2                                      =0;

                  g_sum2                                      =0;

                  b_sum2                                      =0;

 

 

                  //遍历光照

                  for ( int curr_light = 0; curr_light< max_lights; curr_light++)

                  {

                      //光源是否被打开

                      if ( lights[curr_light].state==LIGHTV2_STATE_OFF)

                      {

                          continue;

                      }

 

                      //判断光源类型

                      if ( lights[curr_light].attr& LIGHTV2_ATTR_AMBIENT )

                      {

                          ri                             +=( ( lights[curr_light].c_ambient.r * r_base) / 256 );

                          gi                             +=( ( lights[curr_light].c_ambient.g * g_base) / 256 );

                          bi                             +=( ( lights[curr_light].c_ambient.b * b_base) / 256 );

 

                          //环境光源对每个顶点的影响相同

                           r_sum0                         += ri;

                          g_sum0                         +=gi;

                          b_sum0                         +=bi;

 

                          r_sum1                         +=ri;

                          g_sum1                         +=gi;

                          b_sum1                         +=bi;

 

                          r_sum2                         +=ri;

                          g_sum2                         +=gi;

                          b_sum2                         +=bi;

 

 

 

                      }

                      else

                          if ( lights[curr_light].attr& LIGHTV2_ATTR_INFINITE )

                          {

 

 

                               //顶点

                               dp                                 =math.VECTOR4D_DOT(& curr_poly->tvlist[0].n, & lights[curr_light].tdir);

 

                               if ( dp > 0 )

                               {

                                   i                              =128 * dp;

                                   r_sum0                         +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                   g_sum0                         +=(  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                   b_sum0                         +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                               }

                               //顶点

 

                               dp                                 =math.VECTOR4D_DOT(& curr_poly->tvlist[1].n, & lights[curr_light].tdir);

 

                               if ( dp > 0 )

                               {

                                   i                              =128 * dp;

                                   r_sum1                         +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                   g_sum1                         += (  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                   b_sum1                         +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                               }

                               //顶点

                               dp                                 =math.VECTOR4D_DOT(& curr_poly->tvlist[2].n, & lights[curr_light].tdir);

 

                               if ( dp > 0 )

                               {

                                   i                              =128 * dp ;

                                   r_sum2                         +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                   g_sum2                         +=(  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                   b_sum2                         +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                               }

                          }

                          else

                               if ( lights[curr_light].attr& LIGHTV2_ATTR_POINT )

                               {

 

 

 

                                   //计算从表面到光源的向量

                                   math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & lights[curr_light].tpos,&l );

                                   //计算距离和衰减

                                   dist                           =math.VECTOR4D_length(&l);

 

 

                                   //顶点

                                   dp                                 =math.VECTOR4D_DOT(&curr_poly->tvlist[0].n, & l);

 

                                   if ( dp > 0 )

                                   {

                                       atten                          =( lights[curr_light].kc + lights[curr_light].kl* dist + lights[curr_light].kq* dist * dist);

                                       i                              =128 * dp / ( dist* atten );

                                       r_sum0                         +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                       g_sum0                         +=(  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                       b_sum0                         +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                                   }

                                   //顶点

                                   dp                                 =math.VECTOR4D_DOT(&curr_poly->tvlist[1].n, & l);

 

                                   if ( dp > 0 )

                                   {

                                       atten                          =( lights[curr_light].kc + lights[curr_light].kl* dist + lights[curr_light].kq* dist * dist);

                                       i                              =128 * dp / ( dist* atten );

                                       r_sum1                         +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                       g_sum1                         +=(  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                       b_sum1                         +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                                   }

                                   //顶点

                                   dp                                 =math.VECTOR4D_DOT(&curr_poly->tvlist[2].n, & l);

 

                                   if ( dp > 0 )

                                   {

                                       atten                          =( lights[curr_light].kc + lights[curr_light].kl* dist + lights[curr_light].kq* dist * dist);

                                       i                              =128 * dp / ( dist* atten );

                                       r_sum2                         +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                       g_sum2                         +=(  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                       b_sum2                         +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                                   }

 

                               }

                               else

                                   if ( lights[curr_light].attr& LIGHTV2_ATTR_SPOTLIGHT1 )

                                   {

 

 

                                       //计算从表面到光源的向量

                                       math.VECTOR4D_Build(& curr_poly->tvlist[0].v, & lights[curr_light].tpos,&l );

                                       //计算距离和衰减

                                       dist                           =math.VECTOR4D_length(&l);

 

                                       //顶点

 

                                       dp                                 =math.VECTOR4D_DOT(&curr_poly->tvlist[0].n, & lights[curr_light].tdir);

 

                                       if ( dp > 0 )

                                       {

                                            atten                          =( lights[curr_light].kc + lights[curr_light].kl* dist + lights[curr_light].kq* dist * dist);

                                            i                              =128 * dp / ( atten);

                                            r_sum0                         +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                            g_sum0                         +=(  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                            b_sum0                         += (  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                                       }

 

                                       //顶点

 

                                       dp                                 =math.VECTOR4D_DOT(&curr_poly->tvlist[1].n, & lights[curr_light].tdir);

 

                                       if ( dp > 0 )

                                       {

                                            atten                          =( lights[curr_light].kc + lights[curr_light].kl* dist + lights[curr_light].kq* dist * dist);

                                            i                              =128 * dp / ( atten);

                                            r_sum1                         +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                            g_sum1                         += ( lights[curr_light].c_diffuse.g * g_base * i ) /( 256 * 128);

                                            b_sum1                         +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                                       }

                                       //顶点

 

                                       dp                                 =math.VECTOR4D_DOT(&curr_poly->tvlist[2].n, & lights[curr_light].tdir);

 

                                       if ( dp > 0 )

                                       {

                                            atten                          =( lights[curr_light].kc + lights[curr_light].kl* dist + lights[curr_light].kq* dist * dist);

                                            i                              =128 * dp / ( atten);

                                            r_sum2                         +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                            g_sum2                         +=(  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                            b_sum2                         +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

 

                                       }

                                   }  

                                   else

                                       if ( lights[curr_light].attr& LIGHTV2_ATTR_SPOTLIGHT2 )

                                       {

 

 

                                            //顶点

 

                                            dp                                 =math.VECTOR4D_DOT(&curr_poly->tvlist[0].n, & lights[curr_light].tdir);

 

                                            if ( dp > 0 )

                                            {

                                               math.VECTOR4D_Build(& lights[curr_light].tpos, & curr_poly->tvlist[0].v,& s );

                                                dists                          =math.VECTOR4D_length(& s );

                                                float        dpsl         =math.VECTOR4D_DOT(& s, & lights[curr_light].tdir) / dists;

 

                                                if ( dpsl > 0)

                                                {

                                                     atten                     =( lights[curr_light].kc + lights[curr_light].kl* dists + lights[curr_light].kq* dists * dists);

 

                                                     float    dpsl_exp     =dpsl;

                                                     for ( int e_index = 1; e_index< ( int ) lights[curr_light].pf;e_index ++ )

                                                     {

                                                         dpsl_exp          *=dpsl;

                                                     }

                                                     i                         =128 * dp * dpsl_exp/ ( atten );

                                                     r_sum0                         +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                                     g_sum0                         +=(  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                                     b_sum0                         +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

                                                }

 

 

                                            }

 

                                            //顶点

 

                                            dp                                 =math.VECTOR4D_DOT(&curr_poly->tvlist[1].n, & lights[curr_light].tdir);

 

                                            if ( dp > 0 )

                                            {

                                               math.VECTOR4D_Build(& lights[curr_light].tpos, & curr_poly->tvlist[1].v,& s );

                                                dists                          =math.VECTOR4D_length(& s );

                                                float        dpsl         =math.VECTOR4D_DOT(& s, & lights[curr_light].tdir) / dists;

 

                                                if ( dpsl > 0)

                                                {

                                                     atten                     =( lights[curr_light].kc + lights[curr_light].kl* dists + lights[curr_light].kq* dists * dists);

 

                                                     float    dpsl_exp     =dpsl;

                                                     for ( int e_index = 1; e_index< ( int ) lights[curr_light].pf;e_index ++ )

                                                     {

                                                         dpsl_exp          *=dpsl;

                                                     }

                                                     i                         =128 * dp * dpsl_exp/ ( atten );

                                                     r_sum1                         +=(  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                                     g_sum1                         +=(  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                                     b_sum1                         +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

                                                }

 

 

                                            }                                     

                                            //顶点

 

                                            dp                                 = math.VECTOR4D_DOT(&curr_poly->tvlist[2].n, & lights[curr_light].tdir);

 

                                            if ( dp > 0 )

                                            {

                                               math.VECTOR4D_Build(& lights[curr_light].tpos, & curr_poly->tvlist[2].v,& s );

                                                dists                          =math.VECTOR4D_length(& s );

                                                float        dpsl         =math.VECTOR4D_DOT(& s, & lights[curr_light].tdir) / dists;

 

                                                if ( dpsl > 0)

                                                {

                                                     atten                     =( lights[curr_light].kc + lights[curr_light].kl* dists + lights[curr_light].kq* dists * dists);

 

                                                     float    dpsl_exp     =dpsl;

                                                     for ( int e_index = 1; e_index< ( int ) lights[curr_light].pf;e_index ++ )

                                                     {

                                                         dpsl_exp          *=dpsl;

                                                     }

                                                     i                         =128 * dp * dpsl_exp/ ( atten );

                                                     r_sum2                         += (  lights[curr_light].c_diffuse.r * r_base * i ) / ( 256 * 128);

                                                     g_sum2                         +=(  lights[curr_light].c_diffuse.g * g_base * i ) / ( 256 * 128);

                                                     b_sum2                         +=(  lights[curr_light].c_diffuse.b * b_base * i ) / ( 256 * 128);

                                                }

 

 

                                            }

 

                                       }  

                  }

                  //确保颜色分量不溢出

                  if ( r_sum0  > 255 )

                  {

                      r_sum0                                               =255;

 

                  }

                  if ( g_sum0  > 255 )

                  {

                      g_sum0                                               =255;

 

                  }

                  if ( b_sum0  > 255 )

                  {

                      b_sum0                                              = 255;

 

                  }

                  if ( r_sum1  > 255 )

                  {

                      r_sum1                                               =255;

 

                  }

                  if ( g_sum1  > 255 )

                  {

                      g_sum1                                               =255;

 

                  }

                  if ( b_sum1  > 255 )

                  {

                      b_sum1                                               =255;

 

                  }

                  if ( r_sum2  > 255 )

                  {

                      r_sum2                                               =255;

 

                  }

                  if ( g_sum2  > 255 )

                  {

                      g_sum2                                               =255;

 

                  }

                  if ( b_sum2  > 255 )

                  {

                      b_sum2                                               =255;

 

                  }

 

                  //写入颜色

 

 

                  curr_poly->lit_color[0]                                  = _RGB16BIT565( r_sum0,g_sum0, b_sum0);

                  curr_poly->lit_color[1]                                  = _RGB16BIT565( r_sum1,g_sum1, b_sum1);

                  curr_poly->lit_color[2]                                  = _RGB16BIT565( r_sum2,g_sum2, b_sum2);

 

             }

             else

             {

                  curr_poly->lit_color[0]                                  = curr_poly->color;

             }

 

 

    }

    return( 1 );

}

 

 

 

 

运行结果如下图所示


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值