0001: 
0002: #include <assert.h>
0003: #include "D3DFile.h"
0004: #include "DXUtil.h"
0005: #include "CShadowVolume.h"
0006: 
0007: // ---------------------------------------------------------------------------
0008: // 静的オブジェクト
0009: // ---------------------------------------------------------------------------
0010: const DWORD CShadowVolume::FVF = D3DFVF_XYZ | D3DFVF_NORMAL;
0011: 
0012: // ---------------------------------------------------------------------------
0013: CShadowVolume::CShadowVolume()
0014: {
0015:     m_pVertices = NULL;
0016:     m_dwNumFaces = 0;
0017: }
0018: // ---------------------------------------------------------------------------
0019: CShadowVolume::~CShadowVolume()
0020: {
0021: }
0022: // ---------------------------------------------------------------------------
0023: // 描画
0024: // ---------------------------------------------------------------------------
0025: VOID CShadowVolume::Render( LPDIRECT3DDEVICE9 pd3dDevice )
0026: {
0027:     pd3dDevice->SetFVF( CShadowVolume::FVF );
0028: 
0029:     pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, m_dwNumFaces,
0030:                                 m_pVertices, sizeof(SHADOW_VOLUME_VERTEX) );
0031: }
0032: // ---------------------------------------------------------------------------
0033: // 生成
0034: // ---------------------------------------------------------------------------
0035: HRESULT CShadowVolume::Create( LPDIRECT3DDEVICE9 pd3dDevice, LPD3DXMESH pSrcMesh )
0036: {
0037:     HRESULT ret = S_OK;
0038:     struct MESHVERTEX { D3DXVECTOR3 p, n; };
0039:     SHADOW_VOLUME_VERTEX* pVertices;
0040:     WORD*       pIndices;
0041:     DWORD i,j,k,l, face;
0042:     LPD3DXMESH pMesh;
0043: 
0044:     if( FAILED( pSrcMesh->CloneMeshFVF( D3DXMESH_SYSTEMMEM,
0045:                                         D3DFVF_XYZ | D3DFVF_NORMAL,
0046:                                         pd3dDevice, &pMesh ) ) )
0047:         return E_FAIL;
0048:     DWORD dwNumFaces    = pMesh->GetNumFaces();
0049: 
0050:     // 出力用のメモリの確保
0051:     m_dwNumFaces = 4*dwNumFaces;
0052:     m_pVertices = new SHADOW_VOLUME_VERTEX[3*m_dwNumFaces];
0053: 
0054:     // バッファを専有
0055:     pMesh->LockVertexBuffer( 0L, (LPVOID*)&pVertices );
0056:     pMesh->LockIndexBuffer ( 0L, (LPVOID*)&pIndices );
0057:     
0058:     // 法線保存用
0059:     D3DXVECTOR3 *vNormal = new D3DXVECTOR3[dwNumFaces];
0060:     if(NULL==vNormal){
0061:         m_dwNumFaces = 0;
0062:         ret = E_OUTOFMEMORY;
0063:         goto end;
0064:     }
0065:     // 通常データ製作
0066:     for( i=0; i<dwNumFaces; i++ )
0067:     {
0068:         D3DXVECTOR3 v0 = pVertices[pIndices[3*i+0]].p;
0069:         D3DXVECTOR3 v1 = pVertices[pIndices[3*i+1]].p;
0070:         D3DXVECTOR3 v2 = pVertices[pIndices[3*i+2]].p;
0071: 
0072:         D3DXVECTOR3 vCross1(v1-v0);
0073:         D3DXVECTOR3 vCross2(v2-v1);
0074:         D3DXVec3Cross( &vNormal[i], &vCross1, &vCross2 );
0075:         
0076:         m_pVertices[3*i+0].p = v0;
0077:         m_pVertices[3*i+1].p = v1;
0078:         m_pVertices[3*i+2].p = v2;
0079:         m_pVertices[3*i+0].n = vNormal[i];
0080:         m_pVertices[3*i+1].n = vNormal[i];
0081:         m_pVertices[3*i+2].n = vNormal[i];
0082:     }
0083:     
0084:     // 稜線に挟み込むデータ製作
0085:     face = dwNumFaces;
0086:     for( i=0  ; i<dwNumFaces; i++ ){
0087:     for( j=i+1; j<dwNumFaces; j++ ){
0088:         DWORD id[2][2];
0089:         DWORD cnt=0;
0090:         for(k=0;k<3;k++){
0091:         for(l=0;l<3;l++){
0092:             D3DXVECTOR3 dv;
0093:             D3DXVec3Subtract( &dv,  &pVertices[pIndices[3*i+k]].p,
0094:                                     &pVertices[pIndices[3*j+l]].p);
0095:             if( D3DXVec3LengthSq( &dv ) < 0.001f ){
0096:                 // 頂点の位置が同じデータを検索
0097:                 id[cnt][0] = 3*i+k;
0098:                 id[cnt][1] = 3*j+l;
0099:                 cnt++;
0100:             }
0101:         }
0102:         }
0103:         if(2==cnt){
0104:             // 共有稜線があった
0105:             if(id[1][0]-id[0][0]!=1){
0106:                 // ポリゴンの表向きを調整するための順番ずらし
0107:                 DWORD tmp = id[0][0];
0108:                 id[0][0] = id[1][0];
0109:                 id[1][0] = tmp;
0110:                 tmp = id[0][1];
0111:                 id[0][1] = id[1][1];
0112:                 id[1][1] = tmp;
0113:             }
0114:             // 稜線にポリゴンを埋め込む
0115:             m_pVertices[3*face+0].p = pVertices[pIndices[id[1][0]]].p;
0116:             m_pVertices[3*face+2].p = pVertices[pIndices[id[0][1]]].p;
0117:             m_pVertices[3*face+1].p = pVertices[pIndices[id[0][0]]].p;
0118:             m_pVertices[3*face+0].n = vNormal[i];
0119:             m_pVertices[3*face+2].n = vNormal[j];
0120:             m_pVertices[3*face+1].n = vNormal[i];
0121:             face++;
0122:             m_pVertices[3*face+0].p = pVertices[pIndices[id[1][0]]].p;
0123:             m_pVertices[3*face+2].p = pVertices[pIndices[id[1][1]]].p;
0124:             m_pVertices[3*face+1].p = pVertices[pIndices[id[0][1]]].p;
0125:             m_pVertices[3*face+0].n = vNormal[i];
0126:             m_pVertices[3*face+2].n = vNormal[j];
0127:             m_pVertices[3*face+1].n = vNormal[j];
0128:             face++;
0129:         }
0130:     }
0131:     }
0132:     assert(face == m_dwNumFaces);
0133: m_dwNumFaces=face;
0134: 
0135:     delete[] vNormal;
0136: end:
0137:     // バッファの専有を解除
0138:     pMesh->UnlockVertexBuffer();
0139:     pMesh->UnlockIndexBuffer();
0140:     
0141:     pMesh->Release();
0142: 
0143:     return ret;
0144: }
0145: // ---------------------------------------------------------------------------
0146: // 破棄
0147: // ---------------------------------------------------------------------------
0148: VOID CShadowVolume::Destroy()
0149: {
0150:     SAFE_DELETE_ARRAY( m_pVertices );
0151:     m_dwNumFaces = 0;
0152: }
0153: // ---------------------------------------------------------------------------
0154: