• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天行健 君子當(dāng)自強(qiáng)而不息

            D3D中的網(wǎng)格模型(5)

            11.2.4 產(chǎn)生頂點(diǎn)法線(xiàn)

            一個(gè)X文件不包含頂點(diǎn)法線(xiàn)數(shù)據(jù),這是很有可能的。假如是這種情況,那么手動(dòng)計(jì)算頂點(diǎn)法線(xiàn)以便我們能夠使用燈光這是很有必要的。現(xiàn)在知道了ID3DXMesh接口和它的父接口ID3DXBaseMesh,我們能夠使用下面的函數(shù)來(lái)產(chǎn)生任何mesh的頂點(diǎn)法線(xiàn):

            Computes unit normals for each vertex in a mesh. Provided to support legacy applications. Use D3DXComputeTangentFrameEx for better results.

            HRESULT D3DXComputeNormals(
            LPD3DXBASEMESH pMesh,
            CONST DWORD * pAdjacency
            );

            Parameters

            pMesh
            [in, out] Pointer to an ID3DXBaseMesh interface, representing the normalized mesh object. This function may not take an ID3DXPMesh progressive mesh as input.
            pAdjacency
            [in] Pointer to an array of three DWORDs per face that specify the three neighbors for each face in the created progressive mesh. This parameter is optional and should be set to NULL if it is unused.

            Return Values

            If the function succeeds, the return value is S_OK. If the function fails, the return value can be one of the following: D3DERR_INVALIDCALL, D3DXERR_INVALIDDATA, E_OUTOFMEMORY.

            Remarks

            The input mesh must have the D3DFVF_NORMAL flag specified in its flexible vertex format (FVF).

            A normal for a vertex is generated by averaging the normals of all faces that share that vertex.

            If adjacency is provided, replicated vertices are ignored and "smoothed" over. If adjacency is not provided, replicated vertices will have normals averaged in from only the faces explicitly referencing them.

            This function simply calls D3DXComputeTangentFrameEx with the following input parameters:

            D3DXComputeTangentFrameEx( pMesh,
            D3DX_DEFAULT,
            0,
            D3DX_DEFAULT,
            0,
            D3DX_DEFAULT,
            0,
            D3DDECLUSAGE_NORMAL,
            0,
            D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
            pAdjacency,
            -1.01f,
            -0.01f,
            -1.01f,
            NULL,
            NULL);

            這個(gè)函數(shù)通過(guò)使用平均法線(xiàn)的方法來(lái)產(chǎn)生頂點(diǎn)法線(xiàn)。假如有鄰接信息,那么重復(fù)的頂點(diǎn)是被忽略的。假如沒(méi)有鄰接信息,那么重復(fù)的頂點(diǎn)也會(huì)被重復(fù)計(jì)算。了解這些是很重要的,我們檢查pMash必須有一個(gè)包含D3DFVF_NORMAL標(biāo)記的頂點(diǎn)格式。

            注意假如X文件不包含頂點(diǎn)法線(xiàn)數(shù)據(jù),那么通過(guò)D3DXLoadMeshFromX創(chuàng)建的ID3DXMesh對(duì)象在它的頂點(diǎn)格式中沒(méi)有指定的D3DFVF_NORMAL標(biāo)記。因此,在我們能夠使用D3DXComputeNormals之前,我們必須克隆mesh并且為其指定包含D3DFVF_NORMAL的頂點(diǎn)格式。下面就是相應(yīng)的代碼:

            // does the mesh have a D3DFVF_NORMAL in its vertex format?

            if ( !(pMesh->GetFVF() & D3DFVF_NORMAL) )

            {

                   // no, so clone a new mesh and add D3DFVF_NORMAL to its format:

                   ID3DXMesh* pTempMesh = 0;

                   pMesh->CloneMeshFVF(

                          D3DXMESH_MANAGED,

                          pMesh->GetFVF() | D3DFVF_NORMAL, // add it here

                          Device,

                          &pTempMesh );

             

                   // compute the normals:

                   D3DXComputeNormals( pTempMesh, NULL );

             

                   pMesh->Release(); // get rid of the old mesh

                   pMesh = pTempMesh; // save the new mesh with normals

            }

            11.3漸進(jìn)網(wǎng)格(Progressive Meshes)

            漸進(jìn)網(wǎng)格,它通過(guò)ID3DXPMesh接口來(lái)表現(xiàn),允許我們通過(guò)邊縮減轉(zhuǎn)換(edge collapse transformations,ECT)來(lái)簡(jiǎn)化mesh。每執(zhí)行一次ECT就移除一個(gè)頂點(diǎn)和一或2個(gè)面。因?yàn)槊總€(gè)ECT是可逆的(它的逆過(guò)程叫頂點(diǎn)分裂),我們能夠逆轉(zhuǎn)簡(jiǎn)化過(guò)程并且恢復(fù)mesh為它的原始狀態(tài)。當(dāng)然,我們不可能得到比原始情況還要精細(xì)的網(wǎng)格。我們僅僅只能簡(jiǎn)化然后恢復(fù)簡(jiǎn)化操作。圖11.2顯示了同一個(gè)mesh的三種不同精細(xì)級(jí)別(levels of detail,LOD):高,中,低。

            漸進(jìn)網(wǎng)格和mipmaps紋理非常相似。當(dāng)使用紋理時(shí),我們已經(jīng)注意到在一個(gè)小或遠(yuǎn)的圖元上使用高分辨率的紋理簡(jiǎn)直就是浪費(fèi)。對(duì)于mesh也是同樣的道理,一個(gè)小或遠(yuǎn)的mesh不需要太多三角形,多了也是浪費(fèi)。因此,我們不會(huì)花費(fèi)渲染高三角形模型的時(shí)間來(lái)渲染一個(gè)只需要表現(xiàn)小的低三角形模型。

            我們可以使用漸進(jìn)網(wǎng)格來(lái)根據(jù)模型距離攝象機(jī)的距離來(lái)調(diào)整模型的LOD。也就是說(shuō),當(dāng)距離減少時(shí),我們?cè)黾觤esh的細(xì)節(jié),當(dāng)距離增加時(shí)我們減少mesh的細(xì)節(jié)。

            11.3.1 產(chǎn)生一個(gè)漸進(jìn)網(wǎng)格

            我們能夠使用下面的函數(shù)來(lái)創(chuàng)建一個(gè)ID3DXPMesh對(duì)象:

            HRESULT D3DXGeneratePMesh(

                   LPD3DXMESH pMesh,

                   CONST DWORD *pAdjacency,

                   CONST LPD3DXATTRIBUTEWEIGHTS pVertexAttributeWeights,

                   CONST FLOAT *pVertexWeights,

                   DWORD MinValue,

                   DWORD Options,

                   LPD3DXPMESH *ppPMesh

            );

            pMesh— 輸入原始mesh,它包含了我們想要生成的漸進(jìn)網(wǎng)格的mesh數(shù)據(jù)。

            pAdjacency — 指向一個(gè)包含pMesh鄰接信息的DWORD數(shù)組。

            pVertexAttributeWeights — 指向一個(gè)D3DXATTRIBUTEWEIGHTS數(shù)組,它的大小是pMesh->GetNumVertices()。它的第i項(xiàng)與pMesh中的第i個(gè)頂點(diǎn)相對(duì)應(yīng)并且指定的是它的品質(zhì)權(quán)重。品質(zhì)權(quán)重被用來(lái)確定一個(gè)頂點(diǎn)被刪除的可能性大小。你能夠?qū)⒋藚?shù)設(shè)置為null,對(duì)于每個(gè)頂點(diǎn)一個(gè)默認(rèn)的頂點(diǎn)品質(zhì)權(quán)重將被設(shè)置。

            pVertexWeights — 指向一個(gè)float數(shù)組,它的大小是pMesh->GetNumVertices(),它的第i項(xiàng)與pMesh中的第i個(gè)頂點(diǎn)相對(duì)應(yīng)并且指定的是它的頂點(diǎn)權(quán)重。頂點(diǎn)權(quán)重越高被刪除的可能性越小。你能夠?qū)⒋藚?shù)設(shè)置為null,對(duì)于每個(gè)頂點(diǎn)一個(gè)默認(rèn)的頂點(diǎn)品質(zhì)權(quán)重1.0將被設(shè)置。

            MinValue — 我們想要簡(jiǎn)化到的最小頂點(diǎn)或面數(shù)。注意該值是必須的,而且與頂點(diǎn)/品質(zhì)權(quán)重有關(guān),最終可能達(dá)不到該值。

            Options — 只能取D3DXMESHSIMP枚舉類(lèi)型中的一個(gè)值:

                     D3DXMESHSIMP_VERTEX — 指定在上一個(gè)參數(shù)MinValue中提到的數(shù)為頂點(diǎn)數(shù)。

                     D3DXMESHSIMP_FACE —指定在上一個(gè)參數(shù)MinValue中提到的數(shù)為面數(shù)。

            ppPMesh — 返回生成好的漸進(jìn)網(wǎng)格。

            11.3.2 頂點(diǎn)品質(zhì)權(quán)重

            Specifies mesh weight attributes.

            typedef struct D3DXATTRIBUTEWEIGHTS {
            FLOAT Position;
            FLOAT Boundary;
            FLOAT Normal;
            FLOAT Diffuse;
            FLOAT Specular;
            FLOAT Texcoord[8];
            FLOAT Tangent;
            FLOAT Binormal;
            } D3DXATTRIBUTEWEIGHTS, *LPD3DXATTRIBUTEWEIGHTS;

            Members

            Position
            Position.
            Boundary
            Blend weight.
            Normal
            Normal.
            Diffuse
            Diffuse lighting value.
            Specular
            Specular lighting value.
            Texcoord
            Eight texture coordinates.
            Tangent
            Tangent.
            Binormal
            Binormal.

            Remarks

            This structure describes how a simplification operation will consider vertex data when calculating relative costs between collapsing edges. For example, if the Normal field is 0.0, the simplification operation will ignore the vertex normal component when calculating the error for the collapse. However, if the Normal field is 1.0, the simplification operation will use the vertex normal component. If the Normal field is 2.0, double the amount of errors; if the Normal field is 4.0, then quadruple the number of errors, and so on.

            The LPD3DXATTRIBUTEWEIGHTS type is defined as a pointer to the D3DXATTRIBUTEWEIGHTS structure.

                
            typedef D3DXATTRIBUTEWEIGHTS* LPD3DXATTRIBUTEWEIGHTS;

            頂點(diǎn)權(quán)重結(jié)構(gòu)允許我們?yōu)槊總€(gè)頂點(diǎn)屬性指定一個(gè)權(quán)值。0.0表示該屬性沒(méi)有權(quán)重。頂點(diǎn)屬性的權(quán)重越高在簡(jiǎn)化過(guò)程中被移除的可能性越小。默認(rèn)的權(quán)值如下:

            D3DXATTRIBUTEWEIGHTS AttributeWeights;

            AttributeWeights.Position = 1.0;

            AttributeWeights.Boundary = 1.0;

            AttributeWeights.Normal = 1.0;

            AttributeWeights.Diffuse = 0.0;

            AttributeWeights.Specular = 0.0;

            AttributeWeights.Tex[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};

            默認(rèn)的權(quán)值是被推薦的,除非你的應(yīng)用程序有一個(gè)重要的理由而不使用它。

            11.3.3 ID3DXPMesh方法

            ID3DXPMesh接口是繼承自ID3DXBaseMesh接口,下面是一些方法:

            DWORD GetMaxFaces(VOID)——返回漸進(jìn)網(wǎng)格能夠被設(shè)置的最大面數(shù)。

            DWORD GetMaxVertices(VOID)——返回漸進(jìn)網(wǎng)格能夠被設(shè)置的最大頂點(diǎn)數(shù)。

            DWORD GetMinFaces(VOID)——返回漸進(jìn)網(wǎng)格能夠被設(shè)置的最小面數(shù)。

            DWORD GetMinVertices(VOID)——返回漸進(jìn)網(wǎng)格能夠被設(shè)置的最小頂點(diǎn)數(shù)。

            HRESULT SetNumFaces(DWORD Faces)——這個(gè)方法允許我們?cè)O(shè)置面的個(gè)數(shù),以便讓mesh簡(jiǎn)化/復(fù)雜化。例如,假設(shè)mesh目前有50個(gè)面,我們現(xiàn)在想將它簡(jiǎn)化到30個(gè)面;我們將寫(xiě)成:

            pmesh->SetNumFaces(30);

            注意調(diào)整后的面數(shù)可能并不是我們?cè)O(shè)定的面數(shù)。假如面數(shù)小于了GetMinFaces(),那么面數(shù)將為GetMinFaces()。同樣的,假如面數(shù)大于了GetMaxFaces(),那么面數(shù)將為GetMaxFaces()。

            HRESULT SetNumVertices(DWORD Vertices)——這個(gè)方法允許我們?cè)O(shè)置頂點(diǎn)的個(gè)數(shù),以便讓mesh簡(jiǎn)化/復(fù)雜化。例如,假設(shè)mesh目前有20個(gè)頂點(diǎn),我們現(xiàn)在想將它增加到40個(gè);我們將寫(xiě)成:

            pmesh->SetNumVertices(40);

            注意調(diào)整后的頂點(diǎn)數(shù)可能并不是我們?cè)O(shè)定的數(shù)。假如頂點(diǎn)數(shù)小于了GetMinVertices(),那么頂點(diǎn)數(shù)將為GetMinVertices()。同樣的,假如頂點(diǎn)數(shù)大于了GetMaxVertices(),那么頂點(diǎn)數(shù)將為GetMaxVertices()。

            HRESULT TrimByFaces(

            DWORD NewFacesMin,

            DWORD NewFacesMax,

            DWORD *rgiFaceRemap, // Face remap info.

            DWORD *rgiVertRemap // Vertex remap info.

            );

            這個(gè)方法允許我們?cè)O(shè)置新的最小和最大面數(shù),分別通過(guò)NewFacesMin和NewFacesMax指定。注意新的最小和最大值必須在現(xiàn)有最小和最大面數(shù)之間;也就是說(shuō),必須在[GetMinFaces(),GetMaxFaces()]之中。該函數(shù)也返回面和頂點(diǎn)的重影射信息。

            HRESULT TrimByVertices(

            DWORD NewVerticesMin,

            DWORD NewVerticesMax,

            DWORD *rgiFaceRemap, // Face remap info.

            DWORD *rgiVertRemap // Vertex remap info.

            );

            這個(gè)方法允許我們?cè)O(shè)置新的最小和最大頂點(diǎn)數(shù),分別通過(guò)NewVerticesMin和NewVerticesMax指定。注意新的最小和最大值必須在現(xiàn)有最小和最大頂點(diǎn)數(shù)之間;也就是說(shuō),必須在[GetMinVertices(),GetMaxVertices()]之中。

            11.3.4實(shí)例程序:漸進(jìn)網(wǎng)格

            漸進(jìn)網(wǎng)格例子與X文件例子很相似,除了實(shí)際上我們創(chuàng)建和渲染的是一個(gè)漸進(jìn)網(wǎng)格,通過(guò)ID3DXPMesh接口來(lái)表現(xiàn)。我們?cè)试S用戶(hù)通過(guò)鍵盤(pán)輸入進(jìn)行交互式地改變漸進(jìn)網(wǎng)格。你能通過(guò)按A鍵來(lái)增加mesh的面數(shù),按S鍵來(lái)減少mesh的面數(shù)。

            運(yùn)行截圖:
            主程序:

            /**************************************************************************************
              Demonstrates how to use the progressive mesh interface (ID3DXPMesh).  
              Use the 'A' key to add triangles, use the 'S' key to remove triangles.  
              Note that we outline the triangles in yellow so that you can see them get
              removed and added. 
             *************************************************************************************
            */

            #include 
            <vector>
            #include 
            "d3dUtility.h"

            #pragma warning(disable : 
            4100)

            using namespace std;

            const int WIDTH  = 640;
            const int HEIGHT = 480;

            IDirect3DDevice9
            *            g_device;
            ID3DXMesh
            *                    g_source_mesh;
            ID3DXPMesh
            *                    g_pmesh;
            vector
            <D3DMATERIAL9>        g_materials;
            vector
            <IDirect3DTexture9*>    g_textures;

            ////////////////////////////////////////////////////////////////////////////////////////////////////

            bool setup()
            {    
                
            // load the XFile data

                ID3DXBuffer
            *    adjacency_buffer = NULL;
                ID3DXBuffer
            *    material_buffer  = NULL;
                DWORD            num_material     
            = 0;

                HRESULT hr 
            = D3DXLoadMeshFromX("bigship1.x", D3DXMESH_MANAGED, g_device, &adjacency_buffer, &material_buffer,
                                               NULL, 
            &num_material, &g_source_mesh);

                
            if(FAILED(hr))
                {
                    MessageBox(NULL, 
            "D3DXLoadMeshFromX() - FAILED""ERROR", MB_OK);
                    
            return false;
                }

                
            // extract the materials, and load textures.
                if(material_buffer != NULL && num_material != 0)
                {
                    D3DXMATERIAL
            * materials = (D3DXMATERIAL*) material_buffer->GetBufferPointer();

                    
            for(DWORD i = 0; i < num_material; i++)
                    {
                        
            // the MatD3D property doesn't have an ambient value set when it load, so set it now.
                        materials[i].MatD3D.Ambient = materials[i].MatD3D.Diffuse;

                        
            // save the ith material
                        g_materials.push_back(materials[i].MatD3D);

                        
            // check if the ith material has an associative texture
                        if(materials[i].pTextureFilename != NULL)
                        {
                            
            // yes, load the texture for the ith subset.
                            IDirect3DTexture9* texture;
                            D3DXCreateTextureFromFile(g_device, materials[i].pTextureFilename, 
            &texture);

                            
            // save the loaded texture
                            g_textures.push_back(texture);
                        }
                        
            else
                        {
                            
            // no texture for the ith subset
                            g_textures.push_back(NULL);
                        }
                    }
                }

                safe_release
            <ID3DXBuffer*>(material_buffer);
                
                
            // optimize the mesh    
                hr = g_source_mesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE,
                    (DWORD
            *) adjacency_buffer->GetBufferPointer(), 
                    (DWORD
            *) adjacency_buffer->GetBufferPointer(), // new adjacency info
                    NULL, NULL);    

                
            if(FAILED(hr))
                {
                    MessageBox(NULL, 
            "OptimizeInplace() - FAILED""ERROR", MB_OK);
                    safe_release
            <ID3DXBuffer*>(adjacency_buffer);
                    
            return false;
                }

                
            // generate the progressive mesh
                hr = D3DXGeneratePMesh(
                    g_source_mesh,
                    (DWORD
            *) adjacency_buffer->GetBufferPointer(),
                    NULL,                
            // default vertex attribute weights
                    NULL,                // default vertex weights
                    1,                    // simply as low as possible
                    D3DXMESHSIMP_FACE,    // simplify by face count
                    &g_pmesh);

                safe_release
            <ID3DXMesh*>(g_source_mesh);
                safe_release
            <ID3DXBuffer*>(adjacency_buffer);

                
            if(FAILED(hr))
                {
                    MessageBox(NULL, 
            "D3DXGeneratePMesh() - FAILED""ERROR", MB_OK);
                    
            return false;
                }

                
            // set to original detail
                DWORD max_faces = g_pmesh->GetMaxFaces();
                g_pmesh
            ->SetNumFaces(max_faces);

                
            // set texture filters
                g_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
                g_device
            ->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
                g_device
            ->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

                
            // set lights

                D3DXVECTOR3 dir(
            1.0f-1.0f1.0f);
                D3DXCOLOR color(
            1.0f1.0f1.0f1.0f);
                D3DLIGHT9 light 
            = init_directional_light(&dir, &color);

                g_device
            ->SetLight(0&light);
                g_device
            ->LightEnable(0, TRUE);
                g_device
            ->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);
                g_device
            ->SetRenderState(D3DRS_SPECULARENABLE, TRUE);

                
            // set camera

                D3DXVECTOR3 pos(
            -8.0f4.0f-12.0f);
                D3DXVECTOR3 target(
            0.0f0.0f0.0f);
                D3DXVECTOR3 up(
            0.0f1.0f0.0f);

                D3DXMATRIX view_matrix;
                D3DXMatrixLookAtLH(
            &view_matrix, &pos, &target, &up);
                g_device
            ->SetTransform(D3DTS_VIEW, &view_matrix);

                
            // set the projection matrix
                D3DXMATRIX proj;
                D3DXMatrixPerspectiveFovLH(
            &proj, D3DX_PI * 0.5f, (float)WIDTH/HEIGHT, 1.0f1000.0f);
                g_device
            ->SetTransform(D3DTS_PROJECTION, &proj);
                
                
            return true;
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////////////

            void cleanup()
            {    
                safe_release
            <ID3DXPMesh*>(g_pmesh);
                
                
            for(DWORD i = 0; i < g_textures.size(); i++)
                    safe_release
            <IDirect3DTexture9*>(g_textures[i]);
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////////////

            bool display(float time_delta)
            {
                
            // update: rotate the mesh

                
            // get the current number of faces the pmesh has
                DWORD num_faces = g_pmesh->GetNumFaces();

                
            // Add a face, note the SetNumFaces() will automatically clamp the specified value
                
            // if it goes out of bounds.
                if(GetAsyncKeyState('A'& 0x8000f)
                {
                    
            // Sometimes we must add more than one face to invert an edge collaps transformation
                    
            // because of the internal implementation details of the ID3DXPMesh interface.
                    
            // In other words, adding one face may possibly result in a mesh with the same number
                    
            // of faces as before. Thus to increase the face count we may some times have to add
                    
            // two faces at once.

                    g_pmesh
            ->SetNumFaces(num_faces + 1);

                    
            if(g_pmesh->GetNumFaces() == num_faces)
                        g_pmesh
            ->SetNumFaces(num_faces + 2);
                }

                 
            // Remove a face, note the SetNumFaces() will automatically clamp the specified value
                
            // if it goes out of bounds.
                if(GetAsyncKeyState('S'& 0x8000f)
                    g_pmesh
            ->SetNumFaces(num_faces - 1);

                
            // render now

                g_device
            ->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000001.0f0);

                g_device
            ->BeginScene();

                
            for(DWORD i = 0; i < g_materials.size(); i++)
                {
                    
            // draw pmesh
                    g_device->SetMaterial(&g_materials[i]);
                    g_device
            ->SetTexture(0, g_textures[i]);
                    g_pmesh
            ->DrawSubset(i);

                    
            // draw wireframe outline
                    g_device->SetMaterial(&YELLOW_MATERIAL);
                    g_device
            ->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
                    g_pmesh
            ->DrawSubset(i);

                    
            // restore solid mode
                    g_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
                }

                g_device
            ->EndScene();

                g_device
            ->Present(NULL, NULL, NULL, NULL);

                
            return true;
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////////////

            LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM word_param, LPARAM long_param)
            {
                
            switch(msg)
                {
                
            case WM_DESTROY:
                    PostQuitMessage(
            0);
                    
            break;

                
            case WM_KEYDOWN:
                    
            if(word_param == VK_ESCAPE)
                        DestroyWindow(hwnd);
                    
            break;
                }

                
            return DefWindowProc(hwnd, msg, word_param, long_param);
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////////////

            int WINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line, int cmd_show)
            {
                
            if(! init_d3d(inst, WIDTH, HEIGHT, true, D3DDEVTYPE_HAL, &g_device))
                {
                    MessageBox(NULL, 
            "init_d3d() - failed."0, MB_OK);
                    
            return 0;
                }

                
            if(! setup())
                {
                    MessageBox(NULL, 
            "Steup() - failed."0, MB_OK);
                    
            return 0;
                }

                enter_msg_loop(display);

                cleanup();
                g_device
            ->Release();

                
            return 0;
            }

            下載源程序


            posted on 2008-03-29 17:05 lovedday 閱讀(1957) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            公告

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            隨筆分類(lèi)(178)

            3D游戲編程相關(guān)鏈接

            搜索

            最新評(píng)論

            久久综合精品国产二区无码| 国产精品狼人久久久久影院| 一本一道久久a久久精品综合| 久久久久久国产a免费观看黄色大片| 中文精品99久久国产| 天天爽天天狠久久久综合麻豆| 人妻无码中文久久久久专区| 日韩一区二区久久久久久| 久久午夜夜伦鲁鲁片免费无码影视 | 国产成人精品久久| 久久久久亚洲AV成人网人人网站 | 国产69精品久久久久777| 国产精品免费久久久久电影网| 蜜桃麻豆WWW久久囤产精品| 亚洲国产精品久久66| 久久热这里只有精品在线观看| 亚洲伊人久久大香线蕉苏妲己| 久久SE精品一区二区| 久久久久久亚洲精品无码| 99re久久精品国产首页2020| 一级女性全黄久久生活片免费 | 国产精品9999久久久久| 少妇无套内谢久久久久| 久久这里有精品视频| 99久久婷婷免费国产综合精品| 区久久AAA片69亚洲| 亚洲人成网站999久久久综合 | 国产精品99久久精品| 久久精品国产色蜜蜜麻豆| 欧美午夜A∨大片久久| 国产午夜福利精品久久| 久久99中文字幕久久| 99999久久久久久亚洲| 久久综合香蕉国产蜜臀AV| 日韩久久久久久中文人妻| 狠狠色噜噜色狠狠狠综合久久| 色播久久人人爽人人爽人人片aV| 狠狠人妻久久久久久综合| 精品久久久久久无码中文字幕| 久久精品国产亚洲AV不卡| 久久99精品久久久久久噜噜|