0001: //-----------------------------------------------------------------------------
0002: // File: D3DFile.cpp
0003: //
0004: // Desc: Support code for loading DirectX .X files.
0005: //-----------------------------------------------------------------------------
0006: #define STRICT
0007: #include <tchar.h>
0008: #include <stdio.h>
0009: #include <d3d9.h>
0010: #include <d3dx9.h>
0011: #include <dxfile.h>
0012: #include <rmxfguid.h>
0013: #include <rmxftmpl.h>
0014: #include "D3DFile.h"
0015: #include "DXUtil.h"
0016: 
0017: 
0018: 
0019: 
0020: //-----------------------------------------------------------------------------
0021: // Name:
0022: // Desc:
0023: //-----------------------------------------------------------------------------
0024: CD3DMesh::CD3DMesh( TCHAR* strName )
0025: {
0026:     _tcsncpy( m_strName, strName, sizeof(m_strName) / sizeof(TCHAR) );
0027:     m_strName[sizeof(m_strName) / sizeof(TCHAR) - 1] = _T('\0');
0028:     m_pSysMemMesh        = NULL;
0029:     m_pLocalMesh         = NULL;
0030:     m_dwNumMaterials     = 0L;
0031:     m_pMaterials         = NULL;
0032:     m_pTextures          = NULL;
0033:     m_bUseMaterials      = TRUE;
0034: }
0035: 
0036: 
0037: 
0038: 
0039: //-----------------------------------------------------------------------------
0040: // Name:
0041: // Desc:
0042: //-----------------------------------------------------------------------------
0043: CD3DMesh::~CD3DMesh()
0044: {
0045:     Destroy();
0046: }
0047: 
0048: 
0049: 
0050: 
0051: //-----------------------------------------------------------------------------
0052: // Name:
0053: // Desc:
0054: //-----------------------------------------------------------------------------
0055: HRESULT CD3DMesh::Create( LPDIRECT3DDEVICE9 pd3dDevice, TCHAR* strFilename )
0056: {
0057:     TCHAR        strPath[MAX_PATH];
0058:     LPD3DXBUFFER pAdjacencyBuffer = NULL;
0059:     LPD3DXBUFFER pMtrlBuffer = NULL;
0060:     HRESULT      hr;
0061: 
0062:     // Find the path for the file, and convert it to ANSI (for the D3DX API)
0063:     DXUtil_FindMediaFileCb( strPath, sizeof(strPath), strFilename );
0064: 
0065:     // Load the mesh
0066:     if( FAILED( hr = D3DXLoadMeshFromX( strPath, D3DXMESH_SYSTEMMEM, pd3dDevice, 
0067:                                         &pAdjacencyBuffer, &pMtrlBuffer, NULL,
0068:                                         &m_dwNumMaterials, &m_pSysMemMesh ) ) )
0069:     {
0070:         return hr;
0071:     }
0072: 
0073:     // Optimize the mesh for performance
0074:     if( FAILED( hr = m_pSysMemMesh->OptimizeInplace(
0075:                         D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
0076:                         (DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL ) ) )
0077:     {
0078:         SAFE_RELEASE( pAdjacencyBuffer );
0079:         SAFE_RELEASE( pMtrlBuffer );
0080:         return hr;
0081:     }
0082: 
0083:     // Get material info for the mesh
0084:     // Get the array of materials out of the buffer
0085:     if( pMtrlBuffer && m_dwNumMaterials > 0 )
0086:     {
0087:         // Allocate memory for the materials and textures
0088:         D3DXMATERIAL* d3dxMtrls = (D3DXMATERIAL*)pMtrlBuffer->GetBufferPointer();
0089:         m_pMaterials = new D3DMATERIAL9[m_dwNumMaterials];
0090:         if( m_pMaterials == NULL )
0091:         {
0092:             hr = E_OUTOFMEMORY;
0093:             goto LEnd;
0094:         }
0095:         m_pTextures  = new LPDIRECT3DTEXTURE9[m_dwNumMaterials];
0096:         if( m_pTextures == NULL )
0097:         {
0098:             hr = E_OUTOFMEMORY;
0099:             goto LEnd;
0100:         }
0101: 
0102:         // Copy each material and create its texture
0103:         for( DWORD i=0; i<m_dwNumMaterials; i++ )
0104:         {
0105:             // Copy the material
0106:             m_pMaterials[i]         = d3dxMtrls[i].MatD3D;
0107:             m_pTextures[i]          = NULL;
0108: 
0109:             // Create a texture
0110:             if( d3dxMtrls[i].pTextureFilename )
0111:             {
0112:                 TCHAR strTexture[MAX_PATH];
0113:                 TCHAR strTextureTemp[MAX_PATH];
0114:                 DXUtil_ConvertAnsiStringToGenericCb( strTextureTemp, d3dxMtrls[i].pTextureFilename, sizeof(strTextureTemp) );
0115:                 DXUtil_FindMediaFileCb( strTexture, sizeof(strTexture), strTextureTemp );
0116: 
0117:                 if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, strTexture, 
0118:                                                        &m_pTextures[i] ) ) )
0119:                     m_pTextures[i] = NULL;
0120:             }
0121:         }
0122:     }
0123:     hr = S_OK;
0124: 
0125: LEnd:
0126:     SAFE_RELEASE( pAdjacencyBuffer );
0127:     SAFE_RELEASE( pMtrlBuffer );
0128: 
0129:     return hr;
0130: }
0131: 
0132: 
0133: 
0134: 
0135: //-----------------------------------------------------------------------------
0136: // Name:
0137: // Desc:
0138: //-----------------------------------------------------------------------------
0139: HRESULT CD3DMesh::Create( LPDIRECT3DDEVICE9 pd3dDevice,
0140:                           LPDIRECTXFILEDATA pFileData )
0141: {
0142:     LPD3DXBUFFER pMtrlBuffer = NULL;
0143:     LPD3DXBUFFER pAdjacencyBuffer = NULL;
0144:     HRESULT      hr;
0145: 
0146:     // Load the mesh from the DXFILEDATA object
0147:     if( FAILED( hr = D3DXLoadMeshFromXof( pFileData, D3DXMESH_SYSTEMMEM, pd3dDevice,
0148:                                           &pAdjacencyBuffer, &pMtrlBuffer, NULL,
0149:                                           &m_dwNumMaterials, &m_pSysMemMesh ) ) )
0150:     {
0151:         return hr;
0152:     }
0153: 
0154:     // Optimize the mesh for performance
0155:     if( FAILED( hr = m_pSysMemMesh->OptimizeInplace(
0156:                         D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
0157:                         (DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL ) ) )
0158:     {
0159:         SAFE_RELEASE( pAdjacencyBuffer );
0160:         SAFE_RELEASE( pMtrlBuffer );
0161:         return hr;
0162:     }
0163: 
0164:     // Get material info for the mesh
0165:     // Get the array of materials out of the buffer
0166:     if( pMtrlBuffer && m_dwNumMaterials > 0 )
0167:     {
0168:         // Allocate memory for the materials and textures
0169:         D3DXMATERIAL* d3dxMtrls = (D3DXMATERIAL*)pMtrlBuffer->GetBufferPointer();
0170:         m_pMaterials = new D3DMATERIAL9[m_dwNumMaterials];
0171:         if( m_pMaterials == NULL )
0172:         {
0173:             hr = E_OUTOFMEMORY;
0174:             goto LEnd;
0175:         }
0176:         m_pTextures  = new LPDIRECT3DTEXTURE9[m_dwNumMaterials];
0177:         if( m_pTextures == NULL )
0178:         {
0179:             hr = E_OUTOFMEMORY;
0180:             goto LEnd;
0181:         }
0182: 
0183:         // Copy each material and create its texture
0184:         for( DWORD i=0; i<m_dwNumMaterials; i++ )
0185:         {
0186:             // Copy the material
0187:             m_pMaterials[i]         = d3dxMtrls[i].MatD3D;
0188:             m_pTextures[i]          = NULL;
0189: 
0190:             // Create a texture
0191:             if( d3dxMtrls[i].pTextureFilename )
0192:             {
0193:                 TCHAR strTexture[MAX_PATH];
0194:                 TCHAR strTextureTemp[MAX_PATH];
0195:                 DXUtil_ConvertAnsiStringToGenericCb( strTextureTemp, d3dxMtrls[i].pTextureFilename, sizeof(strTextureTemp) );
0196:                 DXUtil_FindMediaFileCb( strTexture, sizeof(strTexture), strTextureTemp );
0197: 
0198:                 if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, strTexture, 
0199:                                                        &m_pTextures[i] ) ) )
0200:                     m_pTextures[i] = NULL;
0201:             }
0202:         }
0203:     }
0204:     hr = S_OK;
0205: 
0206: LEnd:
0207:     SAFE_RELEASE( pAdjacencyBuffer );
0208:     SAFE_RELEASE( pMtrlBuffer );
0209: 
0210:     return hr;
0211: }
0212: 
0213: 
0214: 
0215: 
0216: //-----------------------------------------------------------------------------
0217: // Name:
0218: // Desc:
0219: //-----------------------------------------------------------------------------
0220: HRESULT CD3DMesh::SetFVF( LPDIRECT3DDEVICE9 pd3dDevice, DWORD dwFVF )
0221: {
0222:     LPD3DXMESH pTempSysMemMesh = NULL;
0223:     LPD3DXMESH pTempLocalMesh  = NULL;
0224: 
0225:     if( m_pSysMemMesh )
0226:     {
0227:         if( FAILED( m_pSysMemMesh->CloneMeshFVF( D3DXMESH_SYSTEMMEM, dwFVF,
0228:                                                  pd3dDevice, &pTempSysMemMesh ) ) )
0229:             return E_FAIL;
0230:     }
0231:     if( m_pLocalMesh )
0232:     {
0233:         if( FAILED( m_pLocalMesh->CloneMeshFVF( 0L, dwFVF, pd3dDevice,
0234:                                                 &pTempLocalMesh ) ) )
0235:         {
0236:             SAFE_RELEASE( pTempSysMemMesh );
0237:             return E_FAIL;
0238:         }
0239:     }
0240: 
0241:     SAFE_RELEASE( m_pSysMemMesh );
0242:     SAFE_RELEASE( m_pLocalMesh );
0243: 
0244:     if( pTempSysMemMesh ) m_pSysMemMesh = pTempSysMemMesh;
0245:     if( pTempLocalMesh )  m_pLocalMesh  = pTempLocalMesh;
0246: 
0247:     // Compute normals in case the meshes have them
0248:     if( m_pSysMemMesh )
0249:         D3DXComputeNormals( m_pSysMemMesh, NULL );
0250:     if( m_pLocalMesh )
0251:         D3DXComputeNormals( m_pLocalMesh, NULL );
0252: 
0253:     return S_OK;
0254: }
0255: 
0256: 
0257: 
0258: 
0259: //-----------------------------------------------------------------------------
0260: // Name:
0261: // Desc:
0262: //-----------------------------------------------------------------------------
0263: HRESULT CD3DMesh::RestoreDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice )
0264: {
0265:     if( NULL == m_pSysMemMesh )
0266:         return E_FAIL;
0267: 
0268:     // Make a local memory version of the mesh. Note: because we are passing in
0269:     // no flags, the default behavior is to clone into local memory.
0270:     if( FAILED( m_pSysMemMesh->CloneMeshFVF( 0L, m_pSysMemMesh->GetFVF(),
0271:                                              pd3dDevice, &m_pLocalMesh ) ) )
0272:         return E_FAIL;
0273: 
0274:     return S_OK;
0275: 
0276: }
0277: 
0278: 
0279: 
0280: 
0281: //-----------------------------------------------------------------------------
0282: // Name:
0283: // Desc:
0284: //-----------------------------------------------------------------------------
0285: HRESULT CD3DMesh::InvalidateDeviceObjects()
0286: {
0287:     SAFE_RELEASE( m_pLocalMesh );
0288: 
0289:     return S_OK;
0290: }
0291: 
0292: 
0293: 
0294: 
0295: //-----------------------------------------------------------------------------
0296: // Name:
0297: // Desc:
0298: //-----------------------------------------------------------------------------
0299: HRESULT CD3DMesh::Destroy()
0300: {
0301:     InvalidateDeviceObjects();
0302:     for( UINT i=0; i<m_dwNumMaterials; i++ )
0303:         SAFE_RELEASE( m_pTextures[i] );
0304:     SAFE_DELETE_ARRAY( m_pTextures );
0305:     SAFE_DELETE_ARRAY( m_pMaterials );
0306: 
0307:     SAFE_RELEASE( m_pSysMemMesh );
0308: 
0309:     m_dwNumMaterials = 0L;
0310: 
0311:     return S_OK;
0312: }
0313: 
0314: 
0315: 
0316: 
0317: //-----------------------------------------------------------------------------
0318: // Name:
0319: // Desc:
0320: //-----------------------------------------------------------------------------
0321: HRESULT CD3DMesh::Render( LPDIRECT3DDEVICE9 pd3dDevice, bool bDrawOpaqueSubsets,
0322:                           bool bDrawAlphaSubsets )
0323: {
0324:     if( NULL == m_pLocalMesh )
0325:         return E_FAIL;
0326: 
0327:     // Frist, draw the subsets without alpha
0328:     if( bDrawOpaqueSubsets )
0329:     {
0330:         for( DWORD i=0; i<m_dwNumMaterials; i++ )
0331:         {
0332:             if( m_bUseMaterials )
0333:             {
0334:                 if( m_pMaterials[i].Diffuse.a < 1.0f )
0335:                     continue;
0336:                 pd3dDevice->SetMaterial( &m_pMaterials[i] );
0337:                 pd3dDevice->SetTexture( 0, m_pTextures[i] );
0338:             }
0339:             m_pLocalMesh->DrawSubset( i );
0340:         }
0341:     }
0342: 
0343:     // Then, draw the subsets with alpha
0344:     if( bDrawAlphaSubsets && m_bUseMaterials )
0345:     {
0346:         for( DWORD i=0; i<m_dwNumMaterials; i++ )
0347:         {
0348:             if( m_pMaterials[i].Diffuse.a == 1.0f )
0349:                 continue;
0350: 
0351:             // Set the material and texture
0352:             pd3dDevice->SetMaterial( &m_pMaterials[i] );
0353:             pd3dDevice->SetTexture( 0, m_pTextures[i] );
0354:             m_pLocalMesh->DrawSubset( i );
0355:         }
0356:     }
0357: 
0358:     return S_OK;
0359: }
0360: 
0361: 
0362: 
0363: 
0364: //-----------------------------------------------------------------------------
0365: // Name:
0366: // Desc:
0367: //-----------------------------------------------------------------------------
0368: CD3DFrame::CD3DFrame( TCHAR* strName )
0369: {
0370:     _tcsncpy( m_strName, strName, sizeof(m_strName) / sizeof(TCHAR) );
0371:     m_strName[sizeof(m_strName) / sizeof(TCHAR) - 1] = _T('\0');
0372:     D3DXMatrixIdentity( &m_mat );
0373:     m_pMesh  = NULL;
0374: 
0375:     m_pChild = NULL;
0376:     m_pNext  = NULL;
0377: }
0378: 
0379: 
0380: 
0381: 
0382: //-----------------------------------------------------------------------------
0383: // Name:
0384: // Desc:
0385: //-----------------------------------------------------------------------------
0386: CD3DFrame::~CD3DFrame()
0387: {
0388:     SAFE_DELETE( m_pChild );
0389:     SAFE_DELETE( m_pNext );
0390: }
0391: 
0392: 
0393: 
0394: 
0395: //-----------------------------------------------------------------------------
0396: // Name:
0397: // Desc:
0398: //-----------------------------------------------------------------------------
0399: bool CD3DFrame::EnumMeshes( bool (*EnumMeshCB)(CD3DMesh*,void*),
0400:                             void* pContext )
0401: {
0402:     if( m_pMesh )
0403:         EnumMeshCB( m_pMesh, pContext );
0404:     if( m_pChild )
0405:         m_pChild->EnumMeshes( EnumMeshCB, pContext );
0406:     if( m_pNext )
0407:         m_pNext->EnumMeshes( EnumMeshCB, pContext );
0408: 
0409:     return TRUE;
0410: }
0411: 
0412: 
0413: 
0414: 
0415: //-----------------------------------------------------------------------------
0416: // Name:
0417: // Desc:
0418: //-----------------------------------------------------------------------------
0419: CD3DMesh* CD3DFrame::FindMesh( TCHAR* strMeshName )
0420: {
0421:     CD3DMesh* pMesh;
0422: 
0423:     if( m_pMesh )
0424:         if( !lstrcmpi( m_pMesh->m_strName, strMeshName ) )
0425:             return m_pMesh;
0426: 
0427:     if( m_pChild )
0428:         if( NULL != ( pMesh = m_pChild->FindMesh( strMeshName ) ) )
0429:             return pMesh;
0430: 
0431:     if( m_pNext )
0432:         if( NULL != ( pMesh = m_pNext->FindMesh( strMeshName ) ) )
0433:             return pMesh;
0434: 
0435:     return NULL;
0436: }
0437: 
0438: 
0439: 
0440: 
0441: //-----------------------------------------------------------------------------
0442: // Name:
0443: // Desc:
0444: //-----------------------------------------------------------------------------
0445: CD3DFrame* CD3DFrame::FindFrame( TCHAR* strFrameName )
0446: {
0447:     CD3DFrame* pFrame;
0448: 
0449:     if( !lstrcmpi( m_strName, strFrameName ) )
0450:         return this;
0451: 
0452:     if( m_pChild )
0453:         if( NULL != ( pFrame = m_pChild->FindFrame( strFrameName ) ) )
0454:             return pFrame;
0455: 
0456:     if( m_pNext )
0457:         if( NULL != ( pFrame = m_pNext->FindFrame( strFrameName ) ) )
0458:             return pFrame;
0459: 
0460:     return NULL;
0461: }
0462: 
0463: 
0464: 
0465: 
0466: //-----------------------------------------------------------------------------
0467: // Name:
0468: // Desc:
0469: //-----------------------------------------------------------------------------
0470: HRESULT CD3DFrame::Destroy()
0471: {
0472:     if( m_pMesh )  m_pMesh->Destroy();
0473:     if( m_pChild ) m_pChild->Destroy();
0474:     if( m_pNext )  m_pNext->Destroy();
0475: 
0476:     SAFE_DELETE( m_pMesh );
0477:     SAFE_DELETE( m_pNext );
0478:     SAFE_DELETE( m_pChild );
0479: 
0480:     return S_OK;
0481: }
0482: 
0483: 
0484: 
0485: 
0486: //-----------------------------------------------------------------------------
0487: // Name:
0488: // Desc:
0489: //-----------------------------------------------------------------------------
0490: HRESULT CD3DFrame::RestoreDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice )
0491: {
0492:     if( m_pMesh )  m_pMesh->RestoreDeviceObjects( pd3dDevice );
0493:     if( m_pChild ) m_pChild->RestoreDeviceObjects( pd3dDevice );
0494:     if( m_pNext )  m_pNext->RestoreDeviceObjects( pd3dDevice );
0495:     return S_OK;
0496: }
0497: 
0498: 
0499: 
0500: 
0501: //-----------------------------------------------------------------------------
0502: // Name:
0503: // Desc:
0504: //-----------------------------------------------------------------------------
0505: HRESULT CD3DFrame::InvalidateDeviceObjects()
0506: {
0507:     if( m_pMesh )  m_pMesh->InvalidateDeviceObjects();
0508:     if( m_pChild ) m_pChild->InvalidateDeviceObjects();
0509:     if( m_pNext )  m_pNext->InvalidateDeviceObjects();
0510:     return S_OK;
0511: }
0512: 
0513: 
0514: 
0515: 
0516: //-----------------------------------------------------------------------------
0517: // Name:
0518: // Desc:
0519: //-----------------------------------------------------------------------------
0520: HRESULT CD3DFrame::Render( LPDIRECT3DDEVICE9 pd3dDevice, bool bDrawOpaqueSubsets,
0521:                            bool bDrawAlphaSubsets, D3DXMATRIX* pmatWorldMatrix )
0522: {
0523:     // For pure devices, specify the world transform. If the world transform is not
0524:     // specified on pure devices, this function will fail.
0525: 
0526:     D3DXMATRIXA16 matSavedWorld, matWorld;
0527: 
0528:     if ( NULL == pmatWorldMatrix )
0529:         pd3dDevice->GetTransform( D3DTS_WORLD, &matSavedWorld );
0530:     else
0531:         matSavedWorld = *pmatWorldMatrix;
0532: 
0533:     D3DXMatrixMultiply( &matWorld, &m_mat, &matSavedWorld );
0534:     pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
0535: 
0536:     if( m_pMesh )
0537:         m_pMesh->Render( pd3dDevice, bDrawOpaqueSubsets, bDrawAlphaSubsets );
0538: 
0539:     if( m_pChild )
0540:         m_pChild->Render( pd3dDevice, bDrawOpaqueSubsets, bDrawAlphaSubsets, &matWorld );
0541: 
0542:     pd3dDevice->SetTransform( D3DTS_WORLD, &matSavedWorld );
0543: 
0544:     if( m_pNext )
0545:         m_pNext->Render( pd3dDevice, bDrawOpaqueSubsets, bDrawAlphaSubsets, &matSavedWorld );
0546: 
0547:     return S_OK;
0548: }
0549: 
0550: 
0551: 
0552: 
0553: //-----------------------------------------------------------------------------
0554: // Name:
0555: // Desc:
0556: //-----------------------------------------------------------------------------
0557: HRESULT CD3DFile::LoadFrame( LPDIRECT3DDEVICE9 pd3dDevice,
0558:                              LPDIRECTXFILEDATA pFileData,
0559:                              CD3DFrame* pParentFrame )
0560: {
0561:     LPDIRECTXFILEDATA   pChildData = NULL;
0562:     LPDIRECTXFILEOBJECT pChildObj = NULL;
0563:     const GUID* pGUID;
0564:     DWORD       cbSize;
0565:     CD3DFrame*  pCurrentFrame;
0566:     HRESULT     hr;
0567: 
0568:     // Get the type of the object
0569:     if( FAILED( hr = pFileData->GetType( &pGUID ) ) )
0570:         return hr;
0571: 
0572:     if( *pGUID == TID_D3DRMMesh )
0573:     {
0574:         hr = LoadMesh( pd3dDevice, pFileData, pParentFrame );
0575:         if( FAILED(hr) )
0576:             return hr;
0577:     }
0578:     if( *pGUID == TID_D3DRMFrameTransformMatrix )
0579:     {
0580:         D3DXMATRIX* pmatMatrix;
0581:         hr = pFileData->GetData( NULL, &cbSize, (void**)&pmatMatrix );
0582:         if( FAILED(hr) )
0583:             return hr;
0584: 
0585:         // Update the parent's matrix with the new one
0586:         pParentFrame->SetMatrix( pmatMatrix );
0587:     }
0588:     if( *pGUID == TID_D3DRMFrame )
0589:     {
0590:         // Get the frame name
0591:         CHAR  strAnsiName[512] = "";
0592:         TCHAR strName[512];
0593:         DWORD dwNameLength = 512;
0594:         if( FAILED( hr = pFileData->GetName( strAnsiName, &dwNameLength ) ) )
0595:             return hr;
0596:         DXUtil_ConvertAnsiStringToGenericCb( strName, strAnsiName, sizeof(strName) );
0597: 
0598:         // Create the frame
0599:         pCurrentFrame = new CD3DFrame( strName );
0600:         if( pCurrentFrame == NULL )
0601:             return E_OUTOFMEMORY;
0602: 
0603:         pCurrentFrame->m_pNext = pParentFrame->m_pChild;
0604:         pParentFrame->m_pChild = pCurrentFrame;
0605: 
0606:         // Enumerate child objects
0607:         while( SUCCEEDED( pFileData->GetNextObject( &pChildObj ) ) )
0608:         {
0609:             // Query the child for its FileData
0610:             hr = pChildObj->QueryInterface( IID_IDirectXFileData,
0611:                                             (void**)&pChildData );
0612:             if( SUCCEEDED(hr) )
0613:             {
0614:                 hr = LoadFrame( pd3dDevice, pChildData, pCurrentFrame );
0615:                 pChildData->Release();
0616:             }
0617: 
0618:             pChildObj->Release();
0619: 
0620:             if( FAILED(hr) )
0621:                 return hr;
0622:         }
0623:     }
0624: 
0625:     return S_OK;
0626: }
0627: 
0628: 
0629: 
0630: 
0631: //-----------------------------------------------------------------------------
0632: // Name:
0633: // Desc:
0634: //-----------------------------------------------------------------------------
0635: HRESULT CD3DFile::LoadMesh( LPDIRECT3DDEVICE9 pd3dDevice,
0636:                             LPDIRECTXFILEDATA pFileData,
0637:                             CD3DFrame* pParentFrame )
0638: {
0639:     // Currently only allowing one mesh per frame
0640:     if( pParentFrame->m_pMesh )
0641:         return E_FAIL;
0642: 
0643:     // Get the mesh name
0644:     CHAR  strAnsiName[512] = {0};
0645:     TCHAR strName[512];
0646:     DWORD dwNameLength = 512;
0647:     HRESULT hr;
0648:     if( FAILED( hr = pFileData->GetName( strAnsiName, &dwNameLength ) ) )
0649:         return hr;
0650:     DXUtil_ConvertAnsiStringToGenericCb( strName, strAnsiName, sizeof(strName) );
0651: 
0652:     // Create the mesh
0653:     pParentFrame->m_pMesh = new CD3DMesh( strName );
0654:     if( pParentFrame->m_pMesh == NULL )
0655:         return E_OUTOFMEMORY;
0656:     pParentFrame->m_pMesh->Create( pd3dDevice, pFileData );
0657: 
0658:     return S_OK;
0659: }
0660: 
0661: 
0662: 
0663: 
0664: //-----------------------------------------------------------------------------
0665: // Name:
0666: // Desc:
0667: //-----------------------------------------------------------------------------
0668: HRESULT CD3DFile::CreateFromResource( LPDIRECT3DDEVICE9 pd3dDevice, TCHAR* strResource, TCHAR* strType )
0669: {
0670:     LPDIRECTXFILE           pDXFile   = NULL;
0671:     LPDIRECTXFILEENUMOBJECT pEnumObj  = NULL;
0672:     LPDIRECTXFILEDATA       pFileData = NULL;
0673:     HRESULT hr;
0674: 
0675:     // Create a x file object
0676:     if( FAILED( hr = DirectXFileCreate( &pDXFile ) ) )
0677:         return E_FAIL;
0678: 
0679:     // Register templates for d3drm and patch extensions.
0680:     if( FAILED( hr = pDXFile->RegisterTemplates( (void*)D3DRM_XTEMPLATES,
0681:                                                  D3DRM_XTEMPLATE_BYTES ) ) )
0682:     {
0683:         pDXFile->Release();
0684:         return E_FAIL;
0685:     }
0686:     
0687:     CHAR strTypeAnsi[MAX_PATH];
0688:     DXUtil_ConvertGenericStringToAnsiCb( strTypeAnsi, strType, sizeof(strTypeAnsi) );
0689: 
0690:     DXFILELOADRESOURCE dxlr;
0691:     dxlr.hModule = NULL;
0692:     dxlr.lpName = strResource;
0693:     dxlr.lpType = (TCHAR*) strTypeAnsi;
0694: 
0695:     // Create enum object
0696:     hr = pDXFile->CreateEnumObject( (void*)&dxlr, DXFILELOAD_FROMRESOURCE, 
0697:                                     &pEnumObj );
0698:     if( FAILED(hr) )
0699:     {
0700:         pDXFile->Release();
0701:         return hr;
0702:     }
0703: 
0704:     // Enumerate top level objects (which are always frames)
0705:     while( SUCCEEDED( pEnumObj->GetNextDataObject( &pFileData ) ) )
0706:     {
0707:         hr = LoadFrame( pd3dDevice, pFileData, this );
0708:         pFileData->Release();
0709:         if( FAILED(hr) )
0710:         {
0711:             pEnumObj->Release();
0712:             pDXFile->Release();
0713:             return E_FAIL;
0714:         }
0715:     }
0716: 
0717:     SAFE_RELEASE( pFileData );
0718:     SAFE_RELEASE( pEnumObj );
0719:     SAFE_RELEASE( pDXFile );
0720: 
0721:     return S_OK;
0722: }
0723: 
0724: 
0725: 
0726: 
0727: //-----------------------------------------------------------------------------
0728: // Name:
0729: // Desc:
0730: //-----------------------------------------------------------------------------
0731: HRESULT CD3DFile::Create( LPDIRECT3DDEVICE9 pd3dDevice, TCHAR* strFilename )
0732: {
0733:     LPDIRECTXFILE           pDXFile   = NULL;
0734:     LPDIRECTXFILEENUMOBJECT pEnumObj  = NULL;
0735:     LPDIRECTXFILEDATA       pFileData = NULL;
0736:     HRESULT hr;
0737: 
0738:     // Create a x file object
0739:     if( FAILED( hr = DirectXFileCreate( &pDXFile ) ) )
0740:         return E_FAIL;
0741: 
0742:     // Register templates for d3drm and patch extensions.
0743:     if( FAILED( hr = pDXFile->RegisterTemplates( (void*)D3DRM_XTEMPLATES,
0744:                                                  D3DRM_XTEMPLATE_BYTES ) ) )
0745:     {
0746:         pDXFile->Release();
0747:         return E_FAIL;
0748:     }
0749: 
0750:     // Find the path to the file, and convert it to ANSI (for the D3DXOF API)
0751:     TCHAR strPath[MAX_PATH];
0752:     CHAR  strPathANSI[MAX_PATH];
0753:     DXUtil_FindMediaFileCb( strPath, sizeof(strPath), strFilename );
0754:     DXUtil_ConvertGenericStringToAnsiCb( strPathANSI, strPath, sizeof(strPathANSI) );
0755:     
0756:     // Create enum object
0757:     hr = pDXFile->CreateEnumObject( (void*)strPathANSI, DXFILELOAD_FROMFILE, 
0758:                                     &pEnumObj );
0759:     if( FAILED(hr) )
0760:     {
0761:         pDXFile->Release();
0762:         return hr;
0763:     }
0764: 
0765:     // Enumerate top level objects (which are always frames)
0766:     while( SUCCEEDED( pEnumObj->GetNextDataObject( &pFileData ) ) )
0767:     {
0768:         hr = LoadFrame( pd3dDevice, pFileData, this );
0769:         pFileData->Release();
0770:         if( FAILED(hr) )
0771:         {
0772:             pEnumObj->Release();
0773:             pDXFile->Release();
0774:             return E_FAIL;
0775:         }
0776:     }
0777: 
0778:     SAFE_RELEASE( pFileData );
0779:     SAFE_RELEASE( pEnumObj );
0780:     SAFE_RELEASE( pDXFile );
0781: 
0782:     return S_OK;
0783: }
0784: 
0785: 
0786: 
0787: 
0788: //-----------------------------------------------------------------------------
0789: // Name:
0790: // Desc:
0791: //-----------------------------------------------------------------------------
0792: HRESULT CD3DFile::Render( LPDIRECT3DDEVICE9 pd3dDevice, D3DXMATRIX* pmatWorldMatrix )
0793: {
0794: 
0795:     // For pure devices, specify the world transform. If the world transform is not
0796:     // specified on pure devices, this function will fail.
0797: 
0798:     // Set up the world transformation
0799:     D3DXMATRIX matSavedWorld, matWorld;
0800: 
0801:     if ( NULL == pmatWorldMatrix )
0802:         pd3dDevice->GetTransform( D3DTS_WORLD, &matSavedWorld );
0803:     else
0804:         matSavedWorld = *pmatWorldMatrix;
0805: 
0806:     D3DXMatrixMultiply( &matWorld, &matSavedWorld, &m_mat );
0807:     pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
0808: 
0809:     // Render opaque subsets in the meshes
0810:     if( m_pChild )
0811:         m_pChild->Render( pd3dDevice, TRUE, FALSE, &matWorld );
0812: 
0813:     // Enable alpha blending
0814:     pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
0815:     pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
0816:     pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
0817: 
0818:     // Render alpha subsets in the meshes
0819:     if( m_pChild )
0820:         m_pChild->Render( pd3dDevice, FALSE, TRUE, &matWorld );
0821: 
0822:     // Restore state
0823:     pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
0824:     pd3dDevice->SetTransform( D3DTS_WORLD, &matSavedWorld );
0825: 
0826:     return S_OK;
0827: }
0828: 
0829: 
0830: 
0831: 
0832: