source: GTP/trunk/App/Demos/Illum/Envmap/Common/DXUTMesh.cpp @ 843

Revision 843, 34.0 KB checked in by szirmay, 19 years ago (diff)
Line 
1//-----------------------------------------------------------------------------
2// File: DXUTMesh.cpp
3//
4// Desc: Support code for loading DirectX .X files.
5//
6// Copyright (c) Microsoft Corporation. All rights reserved.
7//-----------------------------------------------------------------------------
8#include "dxstdafx.h"
9#include <dxfile.h>
10#include <rmxfguid.h>
11#include <rmxftmpl.h>
12#include "DXUTMesh.h"
13#undef min // use __min instead
14#undef max // use __max instead
15
16
17
18
19//-----------------------------------------------------------------------------
20CDXUTMesh::CDXUTMesh( LPCWSTR strName )
21{
22    StringCchCopy( m_strName, 512, strName );
23    m_pMesh              = NULL;
24    m_dwNumMaterials     = 0L;
25    m_pMaterials         = NULL;
26    m_pTextures          = NULL;
27    m_bUseMaterials      = TRUE;
28}
29
30
31
32
33//-----------------------------------------------------------------------------
34CDXUTMesh::~CDXUTMesh()
35{
36    Destroy();
37}
38
39
40
41
42//-----------------------------------------------------------------------------
43HRESULT CDXUTMesh::Create( LPDIRECT3DDEVICE9 pd3dDevice, LPCWSTR strFilename )
44{
45    WCHAR        strPath[MAX_PATH];
46    LPD3DXBUFFER pAdjacencyBuffer = NULL;
47    LPD3DXBUFFER pMtrlBuffer = NULL;
48    HRESULT      hr;
49
50    // Cleanup previous mesh if any
51    Destroy();
52
53    // Find the path for the file, and convert it to ANSI (for the D3DX API)
54    DXUTFindDXSDKMediaFileCch( strPath, sizeof(strPath) / sizeof(WCHAR), strFilename );
55
56    // Load the mesh
57    if( FAILED( hr = D3DXLoadMeshFromX( strPath, D3DXMESH_MANAGED, pd3dDevice,
58                                        &pAdjacencyBuffer, &pMtrlBuffer, NULL,
59                                        &m_dwNumMaterials, &m_pMesh ) ) )
60    {
61        return hr;
62    }
63
64    // Optimize the mesh for performance
65    if( FAILED( hr = m_pMesh->OptimizeInplace(
66                        D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
67                        (DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL ) ) )
68    {
69        SAFE_RELEASE( pAdjacencyBuffer );
70        SAFE_RELEASE( pMtrlBuffer );
71        return hr;
72    }
73
74    // Set strPath to the path of the mesh file
75    WCHAR *pLastBSlash = wcsrchr( strPath, L'\\' );
76    if( pLastBSlash )
77        *(pLastBSlash + 1) = L'\0';
78    else
79        *strPath = L'\0';
80
81    D3DXMATERIAL* d3dxMtrls = (D3DXMATERIAL*)pMtrlBuffer->GetBufferPointer();
82    hr = CreateMaterials( strPath, pd3dDevice, d3dxMtrls, m_dwNumMaterials );
83
84    SAFE_RELEASE( pAdjacencyBuffer );
85    SAFE_RELEASE( pMtrlBuffer );
86
87    // Extract data from m_pMesh for easy access
88    D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
89    m_dwNumVertices    = m_pMesh->GetNumVertices();
90    m_dwNumFaces       = m_pMesh->GetNumFaces();
91    m_dwBytesPerVertex = m_pMesh->GetNumBytesPerVertex();
92    m_pMesh->GetIndexBuffer( &m_pIB );
93    m_pMesh->GetVertexBuffer( &m_pVB );
94    m_pMesh->GetDeclaration( decl );
95    pd3dDevice->CreateVertexDeclaration( decl, &m_pDecl );
96
97    return hr;
98}
99
100
101//-----------------------------------------------------------------------------
102HRESULT CDXUTMesh::Create( LPDIRECT3DDEVICE9 pd3dDevice,
103                           LPD3DXFILEDATA pFileData )
104{
105    LPD3DXBUFFER pMtrlBuffer = NULL;
106    LPD3DXBUFFER pAdjacencyBuffer = NULL;
107    HRESULT      hr;
108
109    // Cleanup previous mesh if any
110    Destroy();
111
112    // Load the mesh from the DXFILEDATA object
113    if( FAILED( hr = D3DXLoadMeshFromXof( pFileData, D3DXMESH_MANAGED, pd3dDevice,
114                                          &pAdjacencyBuffer, &pMtrlBuffer, NULL,
115                                          &m_dwNumMaterials, &m_pMesh ) ) )
116    {
117        return hr;
118    }
119
120    // Optimize the mesh for performance
121    if( FAILED( hr = m_pMesh->OptimizeInplace(
122                        D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
123                        (DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL ) ) )
124    {
125        SAFE_RELEASE( pAdjacencyBuffer );
126        SAFE_RELEASE( pMtrlBuffer );
127        return hr;
128    }
129
130    D3DXMATERIAL* d3dxMtrls = (D3DXMATERIAL*)pMtrlBuffer->GetBufferPointer();
131    hr = CreateMaterials( L"", pd3dDevice, d3dxMtrls, m_dwNumMaterials );
132
133    SAFE_RELEASE( pAdjacencyBuffer );
134    SAFE_RELEASE( pMtrlBuffer );
135
136    // Extract data from m_pMesh for easy access
137    D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
138    m_dwNumVertices    = m_pMesh->GetNumVertices();
139    m_dwNumFaces       = m_pMesh->GetNumFaces();
140    m_dwBytesPerVertex = m_pMesh->GetNumBytesPerVertex();
141    m_pMesh->GetIndexBuffer( &m_pIB );
142    m_pMesh->GetVertexBuffer( &m_pVB );
143    m_pMesh->GetDeclaration( decl );
144    pd3dDevice->CreateVertexDeclaration( decl, &m_pDecl );
145
146    return hr;
147}
148
149
150//-----------------------------------------------------------------------------
151HRESULT CDXUTMesh::Create( LPDIRECT3DDEVICE9 pd3dDevice, ID3DXMesh* pInMesh,
152                           D3DXMATERIAL* pd3dxMaterials, DWORD dwMaterials )
153{
154    // Cleanup previous mesh if any
155    Destroy();
156
157    // Optimize the mesh for performance
158    DWORD *rgdwAdjacency = NULL;
159    rgdwAdjacency = new DWORD[pInMesh->GetNumFaces() * 3];
160    if( rgdwAdjacency == NULL )
161        return E_OUTOFMEMORY;
162    pInMesh->GenerateAdjacency(1e-6f,rgdwAdjacency);
163
164    D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
165    pInMesh->GetDeclaration( decl );
166
167    DWORD dwOptions = pInMesh->GetOptions();
168    dwOptions &= ~(D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM | D3DXMESH_WRITEONLY);
169    dwOptions |= D3DXMESH_MANAGED;
170    dwOptions |= D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE;
171
172    ID3DXMesh* pTempMesh = NULL;
173    if( FAILED( pInMesh->Optimize( dwOptions, rgdwAdjacency, NULL, NULL, NULL, &pTempMesh ) ) )
174    {
175        SAFE_DELETE_ARRAY( rgdwAdjacency );
176        return E_FAIL;
177    }
178
179    SAFE_DELETE_ARRAY( rgdwAdjacency );
180    SAFE_RELEASE( m_pMesh );
181    m_pMesh = pTempMesh;
182
183    HRESULT hr;
184    hr = CreateMaterials( L"", pd3dDevice, pd3dxMaterials, dwMaterials );
185
186    // Extract data from m_pMesh for easy access
187    m_dwNumVertices    = m_pMesh->GetNumVertices();
188    m_dwNumFaces       = m_pMesh->GetNumFaces();
189    m_dwBytesPerVertex = m_pMesh->GetNumBytesPerVertex();
190    m_pMesh->GetIndexBuffer( &m_pIB );
191    m_pMesh->GetVertexBuffer( &m_pVB );
192    m_pMesh->GetDeclaration( decl );
193    pd3dDevice->CreateVertexDeclaration( decl, &m_pDecl );
194
195    return hr;
196}
197
198
199//-----------------------------------------------------------------------------
200HRESULT CDXUTMesh::CreateMaterials( LPCWSTR strPath, IDirect3DDevice9 *pd3dDevice, D3DXMATERIAL* d3dxMtrls, DWORD dwNumMaterials )
201{
202    // Get material info for the mesh
203    // Get the array of materials out of the buffer
204    m_dwNumMaterials = dwNumMaterials;
205    if( d3dxMtrls && m_dwNumMaterials > 0 )
206    {
207        // Allocate memory for the materials and textures
208        m_pMaterials = new D3DMATERIAL9[m_dwNumMaterials];
209        if( m_pMaterials == NULL )
210            return E_OUTOFMEMORY;
211        m_pTextures = new LPDIRECT3DBASETEXTURE9[m_dwNumMaterials];
212        if( m_pTextures == NULL )
213            return E_OUTOFMEMORY;
214        m_strMaterials = new CHAR[m_dwNumMaterials][MAX_PATH];
215        if( m_strMaterials == NULL )
216            return E_OUTOFMEMORY;
217
218        // Copy each material and create its texture
219        for( DWORD i=0; i<m_dwNumMaterials; i++ )
220        {
221            // Copy the material
222            m_pMaterials[i]         = d3dxMtrls[i].MatD3D;
223            m_pTextures[i]          = NULL;
224
225            // Create a texture
226            if( d3dxMtrls[i].pTextureFilename )
227            {
228                StringCchCopyA( m_strMaterials[i], MAX_PATH, d3dxMtrls[i].pTextureFilename );
229
230                WCHAR strTexture[MAX_PATH];
231                WCHAR strTextureTemp[MAX_PATH];
232                D3DXIMAGE_INFO ImgInfo;
233
234                // First attempt to look for texture in the same folder as the input folder.
235                MultiByteToWideChar( CP_ACP, 0, d3dxMtrls[i].pTextureFilename, -1, strTextureTemp, MAX_PATH );
236                strTextureTemp[MAX_PATH-1] = 0;
237
238                StringCchCopy( strTexture, MAX_PATH, strPath );
239                StringCchCat( strTexture, MAX_PATH, strTextureTemp );
240
241                // Inspect the texture file to determine the texture type.
242                if( FAILED( D3DXGetImageInfoFromFile( strTexture, &ImgInfo ) ) )
243                {
244                    // Search the media folder
245                    if( FAILED( DXUTFindDXSDKMediaFileCch( strTexture, MAX_PATH, strTextureTemp ) ) )
246                        continue;  // Can't find. Skip.
247
248                    D3DXGetImageInfoFromFile( strTexture, &ImgInfo );
249                }
250
251                // Call the appropriate loader according to the texture type.
252                switch( ImgInfo.ResourceType )
253                {
254                    case D3DRTYPE_TEXTURE:
255                    {
256                        IDirect3DTexture9 *pTex;
257                        if( SUCCEEDED( D3DXCreateTextureFromFile( pd3dDevice, strTexture, &pTex ) ) )
258                        {
259                            // Obtain the base texture interface
260                            pTex->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i] );
261                            // Release the specialized instance
262                            pTex->Release();
263                        }
264                        break;
265                    }
266                    case D3DRTYPE_CUBETEXTURE:
267                    {
268                        IDirect3DCubeTexture9 *pTex;
269                        if( SUCCEEDED( D3DXCreateCubeTextureFromFile( pd3dDevice, strTexture, &pTex ) ) )
270                        {
271                            // Obtain the base texture interface
272                            pTex->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i] );
273                            // Release the specialized instance
274                            pTex->Release();
275                        }
276                        break;
277                    }
278                    case D3DRTYPE_VOLUMETEXTURE:
279                    {
280                        IDirect3DVolumeTexture9 *pTex;
281                        if( SUCCEEDED( D3DXCreateVolumeTextureFromFile( pd3dDevice, strTexture, &pTex ) ) )
282                        {
283                            // Obtain the base texture interface
284                            pTex->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i] );
285                            // Release the specialized instance
286                            pTex->Release();
287                        }
288                        break;
289                    }
290                }
291            }
292        }
293    }
294    return S_OK;
295}
296
297
298//-----------------------------------------------------------------------------
299HRESULT CDXUTMesh::SetFVF( LPDIRECT3DDEVICE9 pd3dDevice, DWORD dwFVF )
300{
301    LPD3DXMESH pTempMesh = NULL;
302
303    if( m_pMesh )
304    {
305        if( FAILED( m_pMesh->CloneMeshFVF( m_pMesh->GetOptions(), dwFVF,
306                                           pd3dDevice, &pTempMesh ) ) )
307        {
308            SAFE_RELEASE( pTempMesh );
309            return E_FAIL;
310        }
311
312        DWORD dwOldFVF = 0;
313        dwOldFVF = m_pMesh->GetFVF();
314        SAFE_RELEASE( m_pMesh );
315        m_pMesh = pTempMesh;
316
317        // Compute normals if they are being requested and
318        // the old mesh does not have them.
319        if( !(dwOldFVF & D3DFVF_NORMAL) && dwFVF & D3DFVF_NORMAL )
320        {
321            D3DXComputeNormals( m_pMesh, NULL );
322        }
323    }
324
325    return S_OK;
326}
327
328
329
330
331//-----------------------------------------------------------------------------
332// Convert the mesh to the format specified by the given vertex declarations.
333//-----------------------------------------------------------------------------
334HRESULT CDXUTMesh::SetVertexDecl( LPDIRECT3DDEVICE9 pd3dDevice, const D3DVERTEXELEMENT9 *pDecl,
335                                  bool bAutoComputeNormals, bool bAutoComputeTangents,
336                                  bool bSplitVertexForOptimalTangents )
337{
338    LPD3DXMESH pTempMesh = NULL;
339
340    if( m_pMesh )
341    {
342        if( FAILED( m_pMesh->CloneMesh( m_pMesh->GetOptions(), pDecl,
343                                        pd3dDevice, &pTempMesh ) ) )
344        {
345            SAFE_RELEASE( pTempMesh );
346            return E_FAIL;
347        }
348    }
349
350
351    // Check if the old declaration contains a normal.
352    bool bHadNormal = false;
353    bool bHadTangent = false;
354    D3DVERTEXELEMENT9 aOldDecl[MAX_FVF_DECL_SIZE];
355    if( m_pMesh && SUCCEEDED( m_pMesh->GetDeclaration( aOldDecl ) ) )
356    {
357        for( UINT index = 0; index < D3DXGetDeclLength( aOldDecl ); ++index )
358        {
359            if( aOldDecl[index].Usage == D3DDECLUSAGE_NORMAL )
360            {
361                bHadNormal = true;
362            }
363            if( aOldDecl[index].Usage == D3DDECLUSAGE_TANGENT )
364            {
365                bHadTangent = true;
366            }
367        }
368    }
369
370    // Check if the new declaration contains a normal.
371    bool bHaveNormalNow = false;
372    bool bHaveTangentNow = false;
373    D3DVERTEXELEMENT9 aNewDecl[MAX_FVF_DECL_SIZE];
374    if( pTempMesh && SUCCEEDED( pTempMesh->GetDeclaration( aNewDecl ) ) )
375    {
376        for( UINT index = 0; index < D3DXGetDeclLength( aNewDecl ); ++index )
377        {
378            if( aNewDecl[index].Usage == D3DDECLUSAGE_NORMAL )
379            {
380                bHaveNormalNow = true;
381            }
382            if( aNewDecl[index].Usage == D3DDECLUSAGE_TANGENT )
383            {
384                bHaveTangentNow = true;
385            }
386        }
387    }
388
389    SAFE_RELEASE( m_pMesh );
390
391    if( pTempMesh )
392    {
393        m_pMesh = pTempMesh;
394
395        if( !bHadNormal && bHaveNormalNow && bAutoComputeNormals )
396        {
397            // Compute normals in case the meshes have them
398            D3DXComputeNormals( m_pMesh, NULL );
399        }
400
401        if( bHaveNormalNow && !bHadTangent && bHaveTangentNow && bAutoComputeTangents )
402        {
403            ID3DXMesh* pNewMesh;
404            HRESULT hr;
405
406            DWORD *rgdwAdjacency = NULL;
407            rgdwAdjacency = new DWORD[m_pMesh->GetNumFaces() * 3];
408            if( rgdwAdjacency == NULL )
409                return E_OUTOFMEMORY;
410            V( m_pMesh->GenerateAdjacency(1e-6f,rgdwAdjacency) );
411
412            float fPartialEdgeThreshold;
413            float fSingularPointThreshold;
414            float fNormalEdgeThreshold;
415            if( bSplitVertexForOptimalTangents )
416            {
417                fPartialEdgeThreshold = 0.01f;
418                fSingularPointThreshold = 0.25f;
419                fNormalEdgeThreshold = 0.01f;
420            }
421            else
422            {
423                fPartialEdgeThreshold = -1.01f;
424                fSingularPointThreshold = 0.01f;
425                fNormalEdgeThreshold = -1.01f;
426            }
427
428            // Compute tangents, which are required for normal mapping
429            hr = D3DXComputeTangentFrameEx( m_pMesh,
430                                            D3DDECLUSAGE_TEXCOORD, 0,
431                                            D3DDECLUSAGE_TANGENT, 0,
432                                            D3DX_DEFAULT, 0,
433                                            D3DDECLUSAGE_NORMAL, 0,
434                                            0, rgdwAdjacency,
435                                            fPartialEdgeThreshold, fSingularPointThreshold, fNormalEdgeThreshold,
436                                            &pNewMesh, NULL );
437
438            SAFE_DELETE_ARRAY( rgdwAdjacency );
439            if( FAILED(hr) )
440                return hr;
441
442            SAFE_RELEASE( m_pMesh );
443            m_pMesh = pNewMesh;
444        }
445    }
446
447    return S_OK;
448}
449
450
451
452
453//-----------------------------------------------------------------------------
454HRESULT CDXUTMesh::RestoreDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice )
455{
456    return S_OK;
457}
458
459
460
461
462//-----------------------------------------------------------------------------
463HRESULT CDXUTMesh::InvalidateDeviceObjects()
464{
465    SAFE_RELEASE( m_pIB );
466    SAFE_RELEASE( m_pVB );
467    SAFE_RELEASE( m_pDecl );
468
469    return S_OK;
470}
471
472
473
474
475//-----------------------------------------------------------------------------
476HRESULT CDXUTMesh::Destroy()
477{
478    InvalidateDeviceObjects();
479    for( UINT i=0; i<m_dwNumMaterials; i++ )
480        SAFE_RELEASE( m_pTextures[i] );
481    SAFE_DELETE_ARRAY( m_pTextures );
482    SAFE_DELETE_ARRAY( m_pMaterials );
483    SAFE_DELETE_ARRAY( m_strMaterials );
484
485    SAFE_RELEASE( m_pMesh );
486
487    m_dwNumMaterials = 0L;
488
489    return S_OK;
490}
491
492
493
494
495//-----------------------------------------------------------------------------
496HRESULT CDXUTMesh::Render( LPDIRECT3DDEVICE9 pd3dDevice, bool bDrawOpaqueSubsets,
497                          bool bDrawAlphaSubsets )
498{
499    if( NULL == m_pMesh )
500        return E_FAIL;
501
502    // Frist, draw the subsets without alpha
503    if( bDrawOpaqueSubsets )
504    {
505        for( DWORD i=0; i<m_dwNumMaterials; i++ )
506        {
507            if( m_bUseMaterials )
508            {
509                if( m_pMaterials[i].Diffuse.a < 1.0f )
510                    continue;
511                pd3dDevice->SetMaterial( &m_pMaterials[i] );
512                pd3dDevice->SetTexture( 0, m_pTextures[i] );
513            }
514            m_pMesh->DrawSubset( i );
515        }
516    }
517
518    // Then, draw the subsets with alpha
519    if( bDrawAlphaSubsets && m_bUseMaterials )
520    {
521        for( DWORD i=0; i<m_dwNumMaterials; i++ )
522        {
523            if( m_pMaterials[i].Diffuse.a == 1.0f )
524                continue;
525
526            // Set the material and texture
527            pd3dDevice->SetMaterial( &m_pMaterials[i] );
528            pd3dDevice->SetTexture( 0, m_pTextures[i] );
529            m_pMesh->DrawSubset( i );
530        }
531    }
532
533    return S_OK;
534}
535
536
537
538
539//-----------------------------------------------------------------------------
540HRESULT CDXUTMesh::Render( ID3DXEffect *pEffect,
541                           D3DXHANDLE hTexture,
542                           D3DXHANDLE hDiffuse,
543                           D3DXHANDLE hAmbient,
544                           D3DXHANDLE hSpecular,
545                           D3DXHANDLE hEmissive,
546                           D3DXHANDLE hPower,
547                           bool bDrawOpaqueSubsets,
548                           bool bDrawAlphaSubsets )
549{
550    if( NULL == m_pMesh )
551        return E_FAIL;
552
553    UINT cPasses;
554    // Frist, draw the subsets without alpha
555    if( bDrawOpaqueSubsets )
556    {
557        pEffect->Begin( &cPasses, 0 );
558        for( UINT p = 0; p < cPasses; ++p )
559        {
560            pEffect->BeginPass( p );
561            for( DWORD i=0; i<m_dwNumMaterials; i++ )
562            {
563                if( m_bUseMaterials )
564                {
565                    if( m_pMaterials[i].Diffuse.a < 1.0f )
566                        continue;
567                    if( hTexture )
568                        pEffect->SetTexture( hTexture, m_pTextures[i] );
569                    // D3DCOLORVALUE and D3DXVECTOR4 are data-wise identical.
570                    // No conversion is needed.
571                    if( hDiffuse )
572                        pEffect->SetVector( hDiffuse, (D3DXVECTOR4*)&m_pMaterials[i].Diffuse );
573                    if( hAmbient )
574                        pEffect->SetVector( hAmbient, (D3DXVECTOR4*)&m_pMaterials[i].Ambient );
575                    if( hSpecular )
576                        pEffect->SetVector( hSpecular, (D3DXVECTOR4*)&m_pMaterials[i].Specular );
577                    if( hEmissive )
578                        pEffect->SetVector( hEmissive, (D3DXVECTOR4*)&m_pMaterials[i].Emissive );
579                    if( hPower )
580                        pEffect->SetFloat( hPower, m_pMaterials[i].Power );
581                    pEffect->CommitChanges();
582                }
583                m_pMesh->DrawSubset( i );
584            }
585            pEffect->EndPass();
586        }
587        pEffect->End();
588    }
589
590    // Then, draw the subsets with alpha
591    if( bDrawAlphaSubsets && m_bUseMaterials )
592    {
593        pEffect->Begin( &cPasses, 0 );
594        for( UINT p = 0; p < cPasses; ++p )
595        {
596            pEffect->BeginPass( p );
597            for( DWORD i=0; i<m_dwNumMaterials; i++ )
598            {
599                if( m_bUseMaterials )
600                {
601                    if( m_pMaterials[i].Diffuse.a == 1.0f )
602                        continue;
603                    if( hTexture )
604                        pEffect->SetTexture( hTexture, m_pTextures[i] );
605                    // D3DCOLORVALUE and D3DXVECTOR4 are data-wise identical.
606                    // No conversion is needed.
607                    if( hDiffuse )
608                        pEffect->SetVector( hDiffuse, (D3DXVECTOR4*)&m_pMaterials[i].Diffuse );
609                    if( hAmbient )
610                        pEffect->SetVector( hAmbient, (D3DXVECTOR4*)&m_pMaterials[i].Ambient );
611                    if( hSpecular )
612                        pEffect->SetVector( hSpecular, (D3DXVECTOR4*)&m_pMaterials[i].Specular );
613                    if( hEmissive )
614                        pEffect->SetVector( hEmissive, (D3DXVECTOR4*)&m_pMaterials[i].Emissive );
615                    if( hPower )
616                        pEffect->SetFloat( hPower, m_pMaterials[i].Power );
617                    pEffect->CommitChanges();
618                }
619                m_pMesh->DrawSubset( i );
620            }
621            pEffect->EndPass();
622        }
623        pEffect->End();
624    }
625
626    return S_OK;
627}
628
629
630
631
632//-----------------------------------------------------------------------------
633CDXUTMeshFrame::CDXUTMeshFrame( LPCWSTR strName )
634{
635    StringCchCopy( m_strName, 512, strName );
636    D3DXMatrixIdentity( &m_mat );
637    m_pMesh  = NULL;
638
639    m_pChild = NULL;
640    m_pNext  = NULL;
641}
642
643
644
645
646//-----------------------------------------------------------------------------
647CDXUTMeshFrame::~CDXUTMeshFrame()
648{
649    SAFE_DELETE( m_pChild );
650    SAFE_DELETE( m_pNext );
651}
652
653
654
655
656//-----------------------------------------------------------------------------
657bool CDXUTMeshFrame::EnumMeshes( bool (*EnumMeshCB)(CDXUTMesh*,void*),
658                            void* pContext )
659{
660    if( m_pMesh )
661        EnumMeshCB( m_pMesh, pContext );
662    if( m_pChild )
663        m_pChild->EnumMeshes( EnumMeshCB, pContext );
664    if( m_pNext )
665        m_pNext->EnumMeshes( EnumMeshCB, pContext );
666
667    return TRUE;
668}
669
670
671
672
673//-----------------------------------------------------------------------------
674CDXUTMesh* CDXUTMeshFrame::FindMesh( LPCWSTR strMeshName )
675{
676    CDXUTMesh* pMesh;
677
678    if( m_pMesh )
679        if( !lstrcmpi( m_pMesh->m_strName, strMeshName ) )
680            return m_pMesh;
681
682    if( m_pChild )
683        if( NULL != ( pMesh = m_pChild->FindMesh( strMeshName ) ) )
684            return pMesh;
685
686    if( m_pNext )
687        if( NULL != ( pMesh = m_pNext->FindMesh( strMeshName ) ) )
688            return pMesh;
689
690    return NULL;
691}
692
693
694
695
696//-----------------------------------------------------------------------------
697CDXUTMeshFrame* CDXUTMeshFrame::FindFrame( LPCWSTR strFrameName )
698{
699    CDXUTMeshFrame* pFrame;
700
701    if( !lstrcmpi( m_strName, strFrameName ) )
702        return this;
703
704    if( m_pChild )
705        if( NULL != ( pFrame = m_pChild->FindFrame( strFrameName ) ) )
706            return pFrame;
707
708    if( m_pNext )
709        if( NULL != ( pFrame = m_pNext->FindFrame( strFrameName ) ) )
710            return pFrame;
711
712    return NULL;
713}
714
715
716
717
718//-----------------------------------------------------------------------------
719HRESULT CDXUTMeshFrame::Destroy()
720{
721    if( m_pMesh )  m_pMesh->Destroy();
722    if( m_pChild ) m_pChild->Destroy();
723    if( m_pNext )  m_pNext->Destroy();
724
725    SAFE_DELETE( m_pMesh );
726    SAFE_DELETE( m_pNext );
727    SAFE_DELETE( m_pChild );
728
729    return S_OK;
730}
731
732
733
734
735//-----------------------------------------------------------------------------
736HRESULT CDXUTMeshFrame::RestoreDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice )
737{
738    if( m_pMesh )  m_pMesh->RestoreDeviceObjects( pd3dDevice );
739    if( m_pChild ) m_pChild->RestoreDeviceObjects( pd3dDevice );
740    if( m_pNext )  m_pNext->RestoreDeviceObjects( pd3dDevice );
741    return S_OK;
742}
743
744
745
746
747//-----------------------------------------------------------------------------
748HRESULT CDXUTMeshFrame::InvalidateDeviceObjects()
749{
750    if( m_pMesh )  m_pMesh->InvalidateDeviceObjects();
751    if( m_pChild ) m_pChild->InvalidateDeviceObjects();
752    if( m_pNext )  m_pNext->InvalidateDeviceObjects();
753    return S_OK;
754}
755
756
757
758
759//-----------------------------------------------------------------------------
760HRESULT CDXUTMeshFrame::Render( LPDIRECT3DDEVICE9 pd3dDevice, bool bDrawOpaqueSubsets,
761                           bool bDrawAlphaSubsets, D3DXMATRIX* pmatWorldMatrix )
762{
763    // For pure devices, specify the world transform. If the world transform is not
764    // specified on pure devices, this function will fail.
765
766    D3DXMATRIX matSavedWorld, matWorld;
767
768    if ( NULL == pmatWorldMatrix )
769        pd3dDevice->GetTransform( D3DTS_WORLD, &matSavedWorld );
770    else
771        matSavedWorld = *pmatWorldMatrix;
772
773    D3DXMatrixMultiply( &matWorld, &m_mat, &matSavedWorld );
774    pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
775
776    if( m_pMesh )
777        m_pMesh->Render( pd3dDevice, bDrawOpaqueSubsets, bDrawAlphaSubsets );
778
779    if( m_pChild )
780        m_pChild->Render( pd3dDevice, bDrawOpaqueSubsets, bDrawAlphaSubsets, &matWorld );
781
782    pd3dDevice->SetTransform( D3DTS_WORLD, &matSavedWorld );
783
784    if( m_pNext )
785        m_pNext->Render( pd3dDevice, bDrawOpaqueSubsets, bDrawAlphaSubsets, &matSavedWorld );
786
787    return S_OK;
788}
789
790
791
792
793//-----------------------------------------------------------------------------
794HRESULT CDXUTMeshFile::LoadFrame( LPDIRECT3DDEVICE9 pd3dDevice,
795                             LPD3DXFILEDATA pFileData,
796                             CDXUTMeshFrame* pParentFrame )
797{
798    LPD3DXFILEDATA   pChildData = NULL;
799    GUID Guid;
800    SIZE_T      cbSize;
801    CDXUTMeshFrame*  pCurrentFrame;
802    HRESULT     hr;
803
804    // Get the type of the object
805    if( FAILED( hr = pFileData->GetType( &Guid ) ) )
806        return hr;
807
808    if( Guid == TID_D3DRMMesh )
809    {
810        hr = LoadMesh( pd3dDevice, pFileData, pParentFrame );
811        if( FAILED(hr) )
812            return hr;
813    }
814    if( Guid == TID_D3DRMFrameTransformMatrix )
815    {
816        D3DXMATRIX* pmatMatrix;
817        hr = pFileData->Lock(&cbSize, (LPCVOID*)&pmatMatrix );
818        if( FAILED(hr) )
819            return hr;
820
821        // Update the parent's matrix with the new one
822        pParentFrame->SetMatrix( pmatMatrix );
823    }
824    if( Guid == TID_D3DRMFrame )
825    {
826        // Get the frame name
827        CHAR  strAnsiName[512] = "";
828        WCHAR strName[512];
829        SIZE_T dwNameLength = 512;
830        SIZE_T cChildren;
831        if( FAILED( hr = pFileData->GetName( strAnsiName, &dwNameLength ) ) )
832            return hr;
833
834        WideCharToMultiByte( CP_ACP, 0, strName, -1, strAnsiName, 512, NULL, NULL );
835        strName[511] = 0;
836
837        // Create the frame
838        pCurrentFrame = new CDXUTMeshFrame( strName );
839        if( pCurrentFrame == NULL )
840            return E_OUTOFMEMORY;
841
842        pCurrentFrame->m_pNext = pParentFrame->m_pChild;
843        pParentFrame->m_pChild = pCurrentFrame;
844
845        // Enumerate child objects
846        pFileData->GetChildren(&cChildren);
847        for (UINT iChild = 0; iChild < cChildren; iChild++)
848        {
849            // Query the child for its FileData
850            hr = pFileData->GetChild(iChild, &pChildData );
851            if( SUCCEEDED(hr) )
852            {
853                hr = LoadFrame( pd3dDevice, pChildData, pCurrentFrame );
854                SAFE_RELEASE( pChildData );
855            }
856
857            if( FAILED(hr) )
858                return hr;
859        }
860    }
861
862    return S_OK;
863}
864
865
866
867
868//-----------------------------------------------------------------------------
869HRESULT CDXUTMeshFile::LoadMesh( LPDIRECT3DDEVICE9 pd3dDevice,
870                            LPD3DXFILEDATA pFileData,
871                            CDXUTMeshFrame* pParentFrame )
872{
873    // Currently only allowing one mesh per frame
874    if( pParentFrame->m_pMesh )
875        return E_FAIL;
876
877    // Get the mesh name
878    CHAR  strAnsiName[512] = {0};
879    WCHAR strName[512];
880    SIZE_T dwNameLength = 512;
881    HRESULT hr;
882    if( FAILED( hr = pFileData->GetName( strAnsiName, &dwNameLength ) ) )
883        return hr;
884
885    MultiByteToWideChar( CP_ACP, 0, strAnsiName, -1, strName, 512 );
886    strName[511] = 0;
887
888    // Create the mesh
889    pParentFrame->m_pMesh = new CDXUTMesh( strName );
890    if( pParentFrame->m_pMesh == NULL )
891        return E_OUTOFMEMORY;
892    pParentFrame->m_pMesh->Create( pd3dDevice, pFileData );
893
894    return S_OK;
895}
896
897
898
899
900//-----------------------------------------------------------------------------
901HRESULT CDXUTMeshFile::CreateFromResource( LPDIRECT3DDEVICE9 pd3dDevice, LPCWSTR strResource, LPCWSTR strType )
902{
903    LPD3DXFILE           pDXFile   = NULL;
904    LPD3DXFILEENUMOBJECT pEnumObj  = NULL;
905    LPD3DXFILEDATA       pFileData = NULL;
906    HRESULT hr;
907    SIZE_T cChildren;
908
909    // Create a x file object
910    if( FAILED( hr = D3DXFileCreate( &pDXFile ) ) )
911        return E_FAIL;
912
913    // Register templates for d3drm and patch extensions.
914    if( FAILED( hr = pDXFile->RegisterTemplates( (void*)D3DRM_XTEMPLATES,
915                                                 D3DRM_XTEMPLATE_BYTES ) ) )
916    {
917        SAFE_RELEASE( pDXFile );
918        return E_FAIL;
919    }
920   
921    CHAR strTypeAnsi[MAX_PATH];
922    CHAR strResourceAnsi[MAX_PATH];
923
924    WideCharToMultiByte( CP_ACP, 0, strType, -1, strTypeAnsi, MAX_PATH, NULL, NULL );
925    strTypeAnsi[MAX_PATH-1] = 0;
926
927    WideCharToMultiByte( CP_ACP, 0, strResource, -1, strResourceAnsi, MAX_PATH, NULL, NULL );
928    strResourceAnsi[MAX_PATH-1] = 0;
929
930    D3DXF_FILELOADRESOURCE dxlr;
931    dxlr.hModule = NULL;
932    dxlr.lpName = strResourceAnsi;
933    dxlr.lpType = strTypeAnsi;
934
935    // Create enum object
936    hr = pDXFile->CreateEnumObject( (void*)&dxlr, D3DXF_FILELOAD_FROMRESOURCE,
937                                    &pEnumObj );
938    if( FAILED(hr) )
939    {
940        SAFE_RELEASE( pDXFile );
941        return hr;
942    }
943
944    // Enumerate top level objects (which are always frames)
945    pEnumObj->GetChildren(&cChildren);
946    for (UINT iChild = 0; iChild < cChildren; iChild++)
947    {
948        hr = pEnumObj->GetChild(iChild, &pFileData);
949        if (FAILED(hr))
950            return hr;
951
952        hr = LoadFrame( pd3dDevice, pFileData, this );
953        SAFE_RELEASE( pFileData );
954        if( FAILED(hr) )
955        {
956            SAFE_RELEASE( pEnumObj );
957            SAFE_RELEASE( pDXFile );
958            return E_FAIL;
959        }
960    }
961
962    SAFE_RELEASE( pFileData );
963    SAFE_RELEASE( pEnumObj );
964    SAFE_RELEASE( pDXFile );
965
966    return S_OK;
967}
968
969
970
971
972//-----------------------------------------------------------------------------
973HRESULT CDXUTMeshFile::Create( LPDIRECT3DDEVICE9 pd3dDevice, LPCWSTR strFilename )
974{
975    LPD3DXFILE           pDXFile   = NULL;
976    LPD3DXFILEENUMOBJECT pEnumObj  = NULL;
977    LPD3DXFILEDATA       pFileData = NULL;
978    HRESULT hr;
979    SIZE_T cChildren;
980
981    // Create a x file object
982    if( FAILED( hr = D3DXFileCreate( &pDXFile ) ) )
983        return E_FAIL;
984
985    // Register templates for d3drm and patch extensions.
986    if( FAILED( hr = pDXFile->RegisterTemplates( (void*)D3DRM_XTEMPLATES,
987                                                 D3DRM_XTEMPLATE_BYTES ) ) )
988    {
989        SAFE_RELEASE( pDXFile );
990        return E_FAIL;
991    }
992
993    // Find the path to the file, and convert it to ANSI (for the D3DXOF API)
994    WCHAR strPath[MAX_PATH];
995    CHAR  strPathANSI[MAX_PATH];
996    DXUTFindDXSDKMediaFileCch( strPath, sizeof(strPath) / sizeof(WCHAR), strFilename );
997   
998   
999    WideCharToMultiByte( CP_ACP, 0, strPath, -1, strPathANSI, MAX_PATH, NULL, NULL );
1000    strPathANSI[MAX_PATH-1] = 0;
1001
1002   
1003    // Create enum object
1004    hr = pDXFile->CreateEnumObject( (void*)strPathANSI, D3DXF_FILELOAD_FROMFILE,
1005                                    &pEnumObj );
1006    if( FAILED(hr) )
1007    {
1008        SAFE_RELEASE( pDXFile );
1009        return hr;
1010    }
1011
1012    // Enumerate top level objects (which are always frames)
1013    pEnumObj->GetChildren(&cChildren);
1014    for (UINT iChild = 0; iChild < cChildren; iChild++)
1015    {
1016        hr = pEnumObj->GetChild(iChild, &pFileData);
1017        if (FAILED(hr))
1018            return hr;
1019
1020        hr = LoadFrame( pd3dDevice, pFileData, this );
1021        SAFE_RELEASE( pFileData );
1022        if( FAILED(hr) )
1023        {
1024            SAFE_RELEASE( pEnumObj );
1025            SAFE_RELEASE( pDXFile );
1026            return E_FAIL;
1027        }
1028    }
1029
1030    SAFE_RELEASE( pFileData );
1031    SAFE_RELEASE( pEnumObj );
1032    SAFE_RELEASE( pDXFile );
1033
1034    return S_OK;
1035}
1036
1037
1038
1039
1040//-----------------------------------------------------------------------------
1041HRESULT CDXUTMeshFile::Render( LPDIRECT3DDEVICE9 pd3dDevice, D3DXMATRIX* pmatWorldMatrix )
1042{
1043
1044    // For pure devices, specify the world transform. If the world transform is not
1045    // specified on pure devices, this function will fail.
1046
1047    // Set up the world transformation
1048    D3DXMATRIX matSavedWorld, matWorld;
1049
1050    if ( NULL == pmatWorldMatrix )
1051        pd3dDevice->GetTransform( D3DTS_WORLD, &matSavedWorld );
1052    else
1053        matSavedWorld = *pmatWorldMatrix;
1054
1055    D3DXMatrixMultiply( &matWorld, &matSavedWorld, &m_mat );
1056    pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
1057
1058    // Render opaque subsets in the meshes
1059    if( m_pChild )
1060        m_pChild->Render( pd3dDevice, TRUE, FALSE, &matWorld );
1061
1062    // Enable alpha blending
1063    pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
1064    pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
1065    pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
1066
1067    // Render alpha subsets in the meshes
1068    if( m_pChild )
1069        m_pChild->Render( pd3dDevice, FALSE, TRUE, &matWorld );
1070
1071    // Restore state
1072    pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
1073    pd3dDevice->SetTransform( D3DTS_WORLD, &matSavedWorld );
1074
1075    return S_OK;
1076}
1077
1078
1079
1080
Note: See TracBrowser for help on using the repository browser.