2014年2月7日星期五(7-3,消除了背面的3D线框立方体)

好久没进行了,看看吧,与DEMO7-2的区别,只看不同的地方,相机类型不同,归一化平面改为2*2/ar,视口为640*480,执行了背面消除,(就是判断面元向量与面元到视点向量的点乘,>0,则可见,否则,消除)

这一步是在物体剔除后和世界坐标到相机坐标变换之前进行背面消除,

先建立4D向量,两点确定一个向量,SO  EASY如下。

void ddraw_math::VECTOR4D_Build( VECTOR4D_PTR init, VECTOR4D_PTR term, VECTOR4D_PTR result )

{

    result->x                      = term->x -init->x;

    result->y                      = term->y - init->y;

    result->z                      = term->z - init->z;

    result->w                      = 1;

}

 

再做个准备工作,4元数之间的叉乘

void ddraw_math::VECTOR4D_CROSS( VECTOR4D_PTR va, VECTOR4D_PTR vb, VECTOR4D_PTR vn )

{

    vn->x                                  = (( va->y * vb->z) - ( va->z * vb->y));

    vn->y                                  = - ( ( va->x * vb->z) - ( va->z * vb->x ));

    vn->z                                  = ( ( va->x * vb->y ) - ( va->y * vb->x));

    vn->w                                  = 1;

 

 

}

 

四元数之间的点乘

float ddraw_math::VECTOR4D_DOT( VECTOR4D_PTR va, VECTOR4D_PTR vb )

{

    return ( ( va->x * vb->x ) + ( va->y * vb->y ) + ( va->z + vb->z ) );

}

 

背面消除函数如下

 

void ddraw_liushuixian::Remove_Backfaces_OBJECT4DV1(OBJECT4DV1_PTR obj, CAM4DV1_PTR cam, ddraw_math math)

{

    //检查物体是否已经被剔除

    //在执行物体提出之后和世界坐标到相机坐标变换之前进行背面消除

    if ( obj->state & OBJECT4DV1_STATE_CULLED )

    {

         return;

    }

    //处理物体的每个多边形

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

    {

         //获取多边形

         POLY4DV1_PTR              curr_poly         = & obj->plist[poly];

         //该多边形是否有效?

         //判断该多边形是否没被裁剪掉,没有被剔除,处于活动状态,可见且不是双面的

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

             ( curr_poly->state & POLY4DV1_STATE_CLIPPED) ||

             ( curr_poly->state & POLY4DV1_ATTR_2SIDED) ||

             ( curr_poly->state & POLY4DV1_STATE_BACKFACE))

            

         {

             continue;

         }

 

         //获取顶点列表中的顶点索引

         int                            vindex_0     = curr_poly->vert[0];

         int                            vindex_1     = curr_poly->vert[1];

         int                            vindex_2     = curr_poly->vert[2];

 

         //计算多边形的面法线,

         //顶点是按照顺时针方向排列的,u=p0->p1,v=p0->p2,n=UXV;

         VECTOR4D                  u, v, n;

         //计算u和v

         math.VECTOR4D_Build( & obj->vlist_trans[vindex_0], & obj->vlist_trans[vindex_1], & u );

         math.VECTOR4D_Build( & obj->vlist_trans[vindex_0], & obj->vlist_trans[vindex_2], & v );

         //计算叉积

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

 

         //创建指向视点的向量

         VECTOR4D                  view;

         math.VECTOR4D_Build( & obj->vlist_trans[vindex_0], & cam->pos, & view );

 

         //计算点积

         float                          dp                = math.VECTOR4D_DOT( &n, &view );

         if ( dp<= 0)

         {

             SET_BIT( curr_poly->state, POLY4DV1_STATE_BACKFACE );

         }

        

        

    }

}

 

现在看看在主函数中怎么改动,首先,在GAME_INIT()中,加载cube2.plg,

             WINDOW_HEIGHT);

//加载模型

liushuixian.Load_OBJECT4DV1_PLG( & obj, "cube2.plg", & vscale, & vpos, & vrot );

在Game_Main()中加上背面消除

。。。。。。

    liushuixian.Build_CAM4DV1_Matrix_Euler( *math, & cam, CAM_ROT_SEQ_ZYX );

    //Build_CAM4DV1_Matrix_Euler( & cam, CAM_ROT_SEQ_ZYX );

    liushuixian.Remove_Backfaces_OBJECT4DV1( & obj, &cam, * math );

    liushuixian.World_To_Camera_OBJECT4DV1(  *math, &obj, & cam );

。。。。。。

如下图所示

 

说明背面消除没有起作用,将

    if ( dp>0 )

         {

             SET_BIT( curr_poly->state, POLY4DV1_STATE_BACKFACE );

         }

发现也是整个显示,说明没起作用。

输出到文件的方法

void Remove_Backfaces_OBJECT4DV1(OBJECT4DV1_PTR obj, CAM4DV1_PTR cam)

{

         FILE * fp = fopen( "test.txt", "w");

         fprintf( fp, "removebackface函数起效果了\n" );

         ;

    //检查物体是否已经被剔除

    //在执行物体提出之后和世界坐标到相机坐标变换之前进行背面消除

    if ( obj->state & OBJECT4DV1_STATE_CULLED )

    {

         return;

    }

    fprintf(fp, "有不是OBJECT4DV1_STATE_CULLED的点\n");

 

    //处理物体的每个多边形

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

    {

         //获取多边形

         POLY4DV1_PTR              curr_poly         = & obj->plist[poly];

         //该多边形是否有效?

         //判断该多边形是否没被裁剪掉,没有被剔除,处于活动状态,可见且不是双面的

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

             ( curr_poly->state & POLY4DV1_STATE_CLIPPED) ||

             ( curr_poly->state & POLY4DV1_ATTR_2SIDED) ||

             ( curr_poly->state & POLY4DV1_STATE_BACKFACE))

 

         {

             fprintf(fp, "第%d个顶点没经过计算\n",poly);

 

             continue;

         }

         fprintf(fp, "有进行计算的点\n");

 

 

         //获取顶点列表中的顶点索引

         int                            vindex_0     = curr_poly->vert[0];

         int                            vindex_1     = curr_poly->vert[1];

         int                            vindex_2     = curr_poly->vert[2];

 

         //计算多边形的面法线,

         //顶点是按照顺时针方向排列的,u=p0->p1,v=p0->p2,n=UXV;

         VECTOR4D                  u, v, n;

         //计算u和v

         VECTOR4D_Build( & obj->vlist_trans[vindex_0], & obj->vlist_trans[vindex_1], & u );

         VECTOR4D_Build( & obj->vlist_trans[vindex_0], & obj->vlist_trans[vindex_2], & v );

         //计算叉积

         VECTOR4D_Cross( & u, &v, &n );

 

         //创建指向视点的向量

         VECTOR4D                  view;

         VECTOR4D_Build( & obj->vlist_trans[vindex_0], & cam->pos, & view );

 

   

         //计算点积

         float                          dp                =VECTOR4D_Dot( &n, &view );

         if ( dp<0 )

         {

             SET_BIT( curr_poly->state, POLY4DV1_STATE_BACKFACE );

 

         }

         ;   fprintf(fp, "第%d个面法线与视线点积为%f", poly, dp );

 

   

 

    }

         fclose( fp);

}

发现test.txt的显示内容是

removebackface函数起效果了

有不是OBJECT4DV1_STATE_CULLED的点

第0个顶点没经过计算,共12个顶点

第1个顶点没经过计算,共12个顶点

第2个顶点没经过计算,共12个顶点

第3个顶点没经过计算,共12个顶点

第4个顶点没经过计算,共12个顶点

第5个顶点没经过计算,共12个顶点

第6个顶点没经过计算,共12个顶点

第7个顶点没经过计算,共12个顶点

第8个顶点没经过计算,共12个顶点

第9个顶点没经过计算,共12个顶点

第10个顶点没经过计算,共12个顶点

第11个顶点没经过计算,共12个顶点

说明全continue了,再往前看状态。

 

结果发现太马虎了,应该是

curr_poly->attr & POLY4DV1_ATTR_2SIDED

而不是

curr_poly->state & POLY4DV1_ATTR_2SIDED

 

另外点乘最后一项应该是×而不是+,即原来是

float ddraw_math::VECTOR4D_DOT( VECTOR4D_PTR va, VECTOR4D_PTR vb )

{

    return ( ( va->x * vb->x ) + ( va->y * vb->y ) + ( va->z + vb->z ) );

}

应改为

float ddraw_math::VECTOR4D_DOT( VECTOR4D_PTR va, VECTOR4D_PTR vb )

{

    return ( ( va->x * vb->x ) + ( va->y * vb->y ) + ( va->z * vb->z ) );

}

修正后结果如下所示,OK了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值