DirectX图形处理(6)

D3DMATRIX matWorld = mat;

    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matWorld );

 

    // 视图矩阵定义了照相机的位置和方向,这里只是将其沿z轴向后移动了10

    // 个单位

    D3DMATRIX matView = mat;

    matView._43 = 10.0f;

    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &matView );

 

    // 投影矩阵定义了怎样将3-D场景投影到2-D绘制目标表面上

 

    // 设置一个非常简单的投影,x和y的单位为2,用 -1.0来翻译z

    D3DMATRIX matProj = mat;

    matProj._11 =  2.0f;

    matProj._22 =  2.0f;

    matProj._34 =  1.0f;

    matProj._43 = -1.0f;

    matProj._44 =  0.0f;

    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matProj );

   当设置了转换之后,Triangle就完成了设置场景的任务。应用程序定义的App_InitDeviceObjects函数向调用者返回S_OK。然后,Initialize3DEnvironment函数向WinMain返回该值,WinMain继续处理系统消息。

4. 监视系统消息
   在创建了应用程序窗口以后创建了DirectX对象,然后初始化了场景,接着就可以绘制场景了。在大多数情况下,Windows应用程序在其消息循环中监视系统消息,并在消息队列为空时绘制帧。Triangle例子程序没有不同,它在其消息循环中使用了下列代码:

    BOOL bGotMsg;

    MSG  msg;

    PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );

    g_bReady = TRUE;

 

    while( WM_QUIT != msg.message  )

    {

        // 在应用程序处于活动状态时使用函数Use PeekMessage(),因此可以使用

        // 空闲时间来绘制场景。另外,用函数GetMessage()来避免消耗CPU时间

        if( g_bActive )

            bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );

        else

            bGotMsg = GetMessage( &msg, NULL, 0U, 0U );

 

        if( bGotMsg )

        {

                TranslateMessage( &msg );

                DispatchMessage( &msg );

        }

        else

        {

            // 在空闲时间内绘制一帧(没有消息在等待)

            if( g_bActive && g_bReady )

                Render3DEnvironment();

        }

    }

   上面的代码使用了一个全局标志变量g_bActive来跟踪应用程序是否处于活动状态,另一个变量g_bReady用于表明所有的系统对象是否准备好绘制场景。应用程序在窗口不可见时将g_bActive设置为 FALSE,在需要重建用于绘制场景的对象时将g_bReady变量设置为FALSE。

   如果应用程序处于活动状态,就会检查消息队列是否存在未决消息。如果在该队列中有消息,代码就像任何其他Windows应用程序那样将它们分发出去。否则,就调用应用程序定义的Render3DEnvironment函数来绘制一帧场景。

5. 绘制与显示场景
   在应用程序没有处理系统消息时,可以绘制一幅场景的框架。当消息队列为空时,Triangle例子程序在WinMain中调用应用程序定义的Render3DEnvironment函数来绘制场景。Render3DEnvironment函数将绘制任务分为三个子步骤。

(1)更新场景

   Triangle例子程序中在调用Render3DEnvironment函数后,立即调用App_ FrameMove(另一个应用程序定义的函数)。App_FrameMove函数简单地更新Direct3D用于几何图形的世界矩阵,以便反映沿y轴方向的基于一个内部计数值的旋转,该计数值以fTimeKey参数的形式传递给函数。因为旋转对每一帧都要执行一次,最终结果看起来好像模型被实地旋转一样。代码如下:

HRESULT App_FrameMove( LPDIRECT3DDEVICE7 pd3dDevice, FLOAT fTimeKey )

{

    // 在这个例子中沿y轴方向旋转三角形。设置一个4×4矩阵来定义旋转并将它

    // 设置为新的世界转换

    D3DMATRIX matSpin;

    matSpin._11 = matSpin._22 = matSpin._33 = matSpin._44 = 1.0f;

    matSpin._12 = matSpin._13 = matSpin._14 = matSpin._41 = 0.0f;

    matSpin._21 = matSpin._23 = matSpin._24 = matSpin._42 = 0.0f;

    matSpin._31 = matSpin._32 = matSpin._34 = matSpin._43 = 0.0f;

   

    matSpin._11 = (FLOAT)cos( fTimeKey );

    matSpin._33 = (FLOAT)cos( fTimeKey );

    matSpin._13 = -(FLOAT)sin( fTimeKey );

    matSpin._31 = (FLOAT)sin( fTimeKey );

 

    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matSpin );

 

    return S_OK;

}

   当然,在现实世界中,应用程序将执行比对一个三角形实施一次简单的旋转更多的任务。

(2)绘制场景

   一旦几何图形更新后反映出所需要的动画,就可以绘制场景了。Triangle例子程序采用了一种典型的方法。在例子程序的Render3DEnvironment函数中调用的应用程序定义的App_Render函数通过清除视口开始:

HRESULT App_Render(LPDIRECT3DDEVICE7 pd3dDevice, D3DRECT* prcViewRect )

{

    // 将视口清除为蓝色

    pd3dDevice->Clear( 1UL, prcViewRect, D3DCLEAR_TARGET, Ox000000FF,

                       0L, 0L );

   上面的代码调用IDirect3DDevice7::Clear方法来清除视口。Clear方法接收的前两个参数为:一个用于描述绘制目标表面上要清除的区域的矩形数组的地址;另一个用于通知该方法应当清除多少个来自数组的矩形的值。在大多数情况下会使用一个覆盖了整个绘制目标的矩形。第三个参数决定了该方法的行为。可以清除一个绘制目标表面、一个相关深度缓冲区、模板缓冲区,或者这三者的任意组合。这个例子没有使用深度缓冲区,D3DCLEAR _TARGET是所使用的惟一标志。最后三个参数用于为绘制目标、深度缓冲区和模板缓冲区反映清除值。Triangle例子程序将绘制目标表面的清除颜色设置为蓝色。因为剩下的参数在例子程序中没有使用,代码将它们设置为零。Clear方法在相应的标志没有出现时会忽略它们。

   在清除了视口之后,Triangle例子程序通知Direct3D绘制将要开始,然后绘制场景,最后发出信号表明绘制已经完成,如下所示:

    // 开始场景

    if( FAILED( pd3dDevice->BeginScene() ) )

        return E_FAIL;

 

    // 调用函数DrawPrimitive()来绘制三角形,接着例子程序将进入更多的调用各

    // 种绘制多边形的函数的细节

    pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX,

                             g_pvTriangleVertices, 6, NULL );

 

    // 结束场景

    pd3dDevice->EndScene();

 

    return S_OK;

}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值