source: GTP/branches/IllumWPdeliver2008dec/IlluminationWP/demos/Standalone/RayTraceEffects [DirectX]/Common/DXUTMesh.cpp @ 3255

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