一直以来,看directx的一些例子,都是将world, view, project三个变换分开,写的很清楚。但是跟opengl 中的model view, project很不一致,而且缺乏象opengl中的matrix stack操作,在opengl中,用glPushMatrix glPopMatrix用的很顺手。而在directx中没有看到这样的用法,还以为directx就不提供了呢。其实在directx 的文档中说得很清楚,之所以在例子中不采用model-view矩阵,是怕初学者困惑. 以下引自directx文档: Microsoft Direct3D uses the world and view matrices that you set to configure several internal data structures. Each time you set a new world or view matrix, the system recalculates the associated internal structures. Setting these matrices frequently—for example, thousands of times per frame—is computationally time-consuming. You can minimize the number of required calculations by concatenating your world and view matrices into a world-view matrix that you set as the world matrix, and then setting the view matrix to the identity. Keep cached copies of individual world and view matrices so that you can modify, concatenate, and reset the world matrix as needed. For clarity, in this documentation Direct3D samples rarely employ this optimization.
而且在directx中也提供了一个ID3DXMatrixStack类,用来描述matrix stack。看来我真是误会MS了。 一个描述太阳系统的例子(codesampler):
以下内容为程序代码:
void render( void ) { g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f), 1.0f, 0 );
g_pd3dDevice->BeginScene();
// // Have the view matrix move the view move us to a good vantage point so // we can see the Sun sitting at the origin while the Earth orbits it. //
D3DXMATRIX matView; D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3( 0.0f, 2.0f, -25.0f ), // Camera position &D3DXVECTOR3( 0.0f, 0.0f, 0.0f ), // Look-at point &D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) ); // Up vector
g_matrixStack->LoadIdentity(); g_matrixStack->LoadMatrix( &matView );
// // Cache rotational positions between frames... //
static float fSunSpin = 0.0f; static float fEarthSpin = 0.0f; static float fEarthOrbit = 0.0f; static float fMoonSpin = 0.0f; static float fMoonOrbit = 0.0f;
if( g_bOrbitOn == true ) { fSunSpin += g_fSpeedmodifier * (g_fElpasedTime * 10.0f);
fEarthSpin += g_fSpeedmodifier * (g_fElpasedTime * 100.0f); fEarthOrbit += g_fSpeedmodifier * (g_fElpasedTime * 20.0f);
fMoonSpin += g_fSpeedmodifier * (g_fElpasedTime * 50.0f); fMoonOrbit += g_fSpeedmodifier * (g_fElpasedTime * 200.0f); }
// // The Sun is easy because the mesh for it is initially created centered // at origin. All we have to do is spin it by rotating it about the Y axis // and scale it by 5.0f. //
D3DXMATRIX mSunScale; D3DXMATRIX mSunSpinRotation; D3DXMATRIX mSunMatrix; D3DXMatrixRotationY( &mSunSpinRotation, D3DXToRadian( fSunSpin ) ); D3DXMatrixScaling( &mSunScale, 5.0f, 5.0f, 5.0f ); // Now, concatenate them together...
mSunMatrix = mSunScale * // 1. Uniformaly scale the Sun up in size mSunSpinRotation; // 2. and then spin it on its axis.
g_matrixStack->ush(); { g_matrixStack->MultMatrixLocal( &mSunMatrix );
g_pd3dDevice->SetTransform( D3DTS_WORLD, g_matrixStack->GetTop() ); g_pSunMesh->DrawSubset(0); } g_matrixStack->op();
//other render task // //
g_pd3dDevice->EndScene(); g_pd3dDevice->resent( NULL, NULL, NULL, NULL );
} |