0001: // ----------------------------------------------------------------------------
0002: //
0003: // draw.cpp - 描画部分
0004: // 
0005: // Copyright (c) 2001 if (if@edokko.com)
0006: // All Rights Reserved.
0007: //
0008: // ----------------------------------------------------------------------------
0009: #define STRICT
0010: 
0011: #include <windows.h>
0012: #include "main.h"
0013: #include "draw.h"
0014: #include "load.h"
0015: 
0016: static const int SHADOWMAP_HEIGHT = 512;
0017: static const int SHADOWMAP_WIDTH = 512;
0018: 
0019: LPDIRECT3DVERTEXBUFFER8 pMeshVB = NULL;
0020: LPDIRECT3DINDEXBUFFER8  pMeshIndex = NULL;
0021: D3DXATTRIBUTERANGE      *pSubsetTable = NULL;
0022: DWORD                   nMeshFaces = 0;
0023: DWORD                   nMeshVertices = 0;
0024: D3DMATERIAL8            *pMeshMaterials = NULL;     // メッシュの質感
0025: LPDIRECT3DTEXTURE8      *pMeshTextures  = NULL;     // メッシュのテクスチャー
0026: DWORD                   dwNumMaterials = 0L;        // マテリアルの数
0027: FLOAT                   MeshRadius;                 // メッシュの大きさ
0028: 
0029: DWORD                   hVertexShader=~0;           // モデルの描画
0030: DWORD                   hPixelShader=~0;            // モデルの描画
0031: 
0032: 
0033: // ----------------------------------------------------------------------------
0034: // 外部関数
0035: void InitBg(LPDIRECT3DDEVICE8 lpD3DDev);
0036: void DrawBg(LPDIRECT3DDEVICE8 lpD3DDev);
0037: void CleanBg(LPDIRECT3DDEVICE8 lpD3DDev);
0038: 
0039: 
0040: 
0041: // ----------------------------------------------------------------------------
0042: // Name: LoadXFile(char* filename, LPDIRECT3DDEVICE8 lpD3DDev)
0043: // Desc: X-Fileの読み込み
0044: //-----------------------------------------------------------------------------
0045: HRESULT LoadXFile(char* filename, LPDIRECT3DDEVICE8 lpD3DDev)
0046: {
0047:     LPD3DXMESH pMesh, pMeshOpt;
0048:     LPD3DXBUFFER pD3DXMtrlBuffer = NULL;
0049:     DWORD i;
0050:     HRESULT hr;
0051: 
0052:     hr = D3DXLoadMeshFromX(filename, D3DXMESH_MANAGED,
0053:                                 lpD3DDev, NULL,
0054:                                 &pD3DXMtrlBuffer, &dwNumMaterials,
0055:                                 &pMesh);
0056:     if(FAILED(hr)) return E_FAIL;
0057: 
0058:     //並び替えておく
0059:     pMesh->Optimize(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL, &pMeshOpt);
0060:     RELEASE(pMesh);
0061: 
0062:     //アトリビュートテーブル
0063:     pMeshOpt->GetAttributeTable(NULL,&dwNumMaterials);
0064:     pSubsetTable = new D3DXATTRIBUTERANGE[dwNumMaterials];
0065:     pMeshOpt->GetAttributeTable(pSubsetTable, &dwNumMaterials);
0066: 
0067:     // FVF変換
0068:     hr = pMeshOpt->CloneMeshFVF(pMeshOpt->GetOptions(), D3DFVF_VERTEX, lpD3DDev, &pMesh);
0069:     if(FAILED(hr)) return E_FAIL;
0070:     RELEASE(pMeshOpt);
0071:     D3DXComputeNormals(pMesh, NULL);
0072: 
0073:     //Vertex Bufferにコピーする
0074:     D3DVERTEX* pSrc;
0075:     D3D_CUSTOMVERTEX* pDest;
0076:     LPDIRECT3DINDEXBUFFER8 pSrcIndex;
0077:     WORD* pISrc;
0078:     WORD* pIDest;
0079: 
0080:     DWORD nMeshVertices = pMesh->GetNumVertices();
0081:     DWORD nMeshFaces = pMesh->GetNumFaces();
0082:     lpD3DDev->CreateVertexBuffer(nMeshVertices * sizeof(D3D_CUSTOMVERTEX),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_MANAGED,&pMeshVB);
0083:     lpD3DDev->CreateIndexBuffer(nMeshFaces * 3 * sizeof(WORD),0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&pMeshIndex);
0084: 
0085:     LPDIRECT3DVERTEXBUFFER8 pVB;
0086:     pMesh->GetVertexBuffer(&pVB);
0087:     pVB->Lock(0,0,(BYTE**)&pSrc,0);
0088:     pMeshVB->Lock(0,0,(BYTE**)&pDest,0);
0089:     MeshRadius = 0.0f;
0090:     for(i=0;i<nMeshVertices;i++){
0091:         pDest->x = pSrc->x;
0092:         pDest->y = pSrc->y;
0093:         pDest->z = pSrc->z;
0094:         pDest->nx = pSrc->nx;
0095:         pDest->ny = pSrc->ny;
0096:         pDest->nz = pSrc->nz;
0097:         pDest->tu0 = pSrc->tu0;
0098:         pDest->tu0 = pSrc->tu0;
0099:         // サイズの計算
0100:         FLOAT radius = sqrtf( pSrc->x*pSrc->x + pSrc->y*pSrc->y + pSrc->z*pSrc->z );
0101:         if (MeshRadius < radius) MeshRadius = radius;
0102:         
0103:         pSrc += 1;
0104:         pDest += 1;
0105:     }
0106:     pVB->Unlock();
0107:     pVB->Release();
0108:     pMeshVB->Unlock();
0109: 
0110:     //インデックスのコピー
0111:     pMesh->GetIndexBuffer(&pSrcIndex);
0112:     pSrcIndex->Lock(0,0,(BYTE**)&pISrc,0);
0113:     pMeshIndex->Lock(0,0,(BYTE**)&pIDest,0);
0114:     CopyMemory(pIDest,pISrc,nMeshFaces * 3 * sizeof(WORD));
0115:     pSrcIndex->Unlock();
0116:     pMeshIndex->Unlock();
0117:     pSrcIndex->Release();
0118: 
0119:     // pD3DXMtrlBuffer から、質感やテクスチャーの情報を読み取る
0120:     D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
0121:     pMeshTextures = new LPDIRECT3DTEXTURE8[dwNumMaterials];
0122:     pMeshMaterials = new D3DMATERIAL8[dwNumMaterials];
0123: 
0124:     for(i = 0; i < dwNumMaterials; i++){
0125:         pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
0126:         pMeshMaterials[i].Ambient = pMeshMaterials[i].Diffuse;
0127:         hr = D3DXCreateTextureFromFile( lpD3DDev, 
0128:                                         d3dxMaterials[i].pTextureFilename, 
0129:                                         &pMeshTextures[i] );
0130:         if(FAILED(hr)) pMeshTextures[i] = NULL;
0131:     }
0132:     RELEASE(pD3DXMtrlBuffer);
0133:     
0134:     RELEASE(pMesh);
0135: 
0136:     return S_OK;
0137: }
0138: 
0139: //-----------------------------------------------------------------------------
0140: // Name: InitRender()
0141: // Desc: Load the mesh and build the material and texture arrays
0142: //-----------------------------------------------------------------------------
0143: HRESULT InitRender(LPDIRECT3DDEVICE8 lpD3DDev)
0144: {
0145:     HRESULT hr;
0146: 
0147:     // モデルの読み込み
0148:     if ( FAILED(hr = LoadXFile("nsx.x", lpD3DDev)) ) return hr;
0149:     
0150:     // バーテックスシェーダーを作成する
0151:     if ( FAILED(CVertexShaderMgr::Load(lpD3DDev, "vs.vsh",     &hVertexShader, dwDecl)) ) return hr;
0152:     if ( FAILED( CPixelShaderMgr::Load(lpD3DDev, "ps.psh",      &hPixelShader)) ) return hr;
0153:     
0154:     // 背景部分の初期化
0155:     InitBg(lpD3DDev);
0156: 
0157:     // 不変なレジスタの設定
0158:     lpD3DDev->SetRenderState( D3DRS_ZENABLE, TRUE );
0159:     lpD3DDev->SetRenderState( D3DRS_LIGHTING,  FALSE );
0160:     lpD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE);
0161:     lpD3DDev->SetVertexShaderConstant(12, &D3DXVECTOR4(0.0f, 0.5f, 1.0f, 2.0f), 1);
0162: 
0163:     
0164:     return S_OK;
0165: }
0166: //-----------------------------------------------------------------------------
0167: // Name: Render()
0168: // Desc: Draws the scene
0169: //-----------------------------------------------------------------------------
0170: const float z_min =   0.5f;
0171: const float z_max =  100.0f;
0172: D3DXVECTOR4 lightDir(1.0f, 1.0f, 0.5f, 0.0f);
0173: 
0174: VOID DrawModel(LPDIRECT3DDEVICE8 lpD3DDev)
0175: {
0176:     D3DXMATRIX mWorld, mView,  mProj;
0177:     D3DXMATRIX  m;
0178:     D3DXVECTOR4 vl;
0179:     DWORD i;
0180:     
0181:     // 
0182:     // 通常レンダリング用の行列を作成
0183:     // 
0184:     // ビュー行列
0185:     D3DXVECTOR3 eye    = D3DXVECTOR3(0.0f,1.0f*MeshRadius,2.0f*MeshRadius);
0186:     D3DXVECTOR3 lookAt = D3DXVECTOR3(0.0f,  0.0f,  0.0f);
0187:     D3DXVECTOR3 up     = D3DXVECTOR3(0.0f,  1.0f,  0.0f);
0188:     D3DXMatrixLookAtLH(&mView, &eye, &lookAt, &up);
0189: 
0190:     // 射影行列(比較用)
0191:     D3DXMatrixPerspectiveFovLH(&mProj
0192:         , D3DXToRadian(60.0f)                       // 視野角
0193:         , (float)WIDTH/(float)HEIGHT                // アスペクト比
0194:         , 0.1f, 100.f                                   // 最近接距離,最遠方距離
0195:         );
0196:     D3DXMatrixTranspose( &mProj ,  &mProj);
0197:     lpD3DDev->SetVertexShaderConstant(4,&mProj, 4);
0198:     
0199:     lpD3DDev->SetVertexShaderConstant(15, &D3DXVECTOR4(z_max/(z_max-z_min), -z_max*z_min/(z_max-z_min), 0.0f, 0.0f), 1);
0200: 
0201: 
0202:     //
0203:     // 外側もでる描画
0204:     //
0205:     int t = timeGetTime()%314159;
0206:     D3DXMatrixTranslation(&m, 1.5f*MeshRadius, 0,0);
0207:     D3DXMatrixRotationY( &mWorld, t/1000.0f );
0208: //D3DXMatrixRotationY( &mWorld, -0.2*PI/2 ); // 撮影角度
0209:     mWorld = m * mWorld;
0210:     m = mWorld * mView;
0211:     D3DXMatrixTranspose( &m ,  &m);
0212:     lpD3DDev->SetVertexShaderConstant(0,&m, 4);
0213: 
0214:     D3DXMatrixInverse( &m,  NULL, &mWorld);
0215:     D3DXVec4Transform(&vl, &lightDir, &m);
0216:     D3DXVec4Normalize(&vl, &vl);
0217:     vl[3] = 0.1f;// w成分は環境色の強さ
0218:     lpD3DDev->SetVertexShaderConstant(13, &vl, 1);
0219:     
0220:     lpD3DDev->SetStreamSource(0, pMeshVB, sizeof(D3D_CUSTOMVERTEX));
0221:     lpD3DDev->SetIndices(pMeshIndex,0);
0222:     
0223:     for(i=0;i<dwNumMaterials;i++){
0224:         //色をセット
0225:         D3DXVECTOR4 vl;
0226:         vl.x = pMeshMaterials[i].Diffuse.r;
0227:         vl.y = pMeshMaterials[i].Diffuse.g;
0228:         vl.z = pMeshMaterials[i].Diffuse.b;
0229:         lpD3DDev->SetVertexShaderConstant(14, &vl, 1);
0230: 
0231:         lpD3DDev->SetTexture(0,pMeshTextures[i]);
0232:         lpD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 
0233:                                         pSubsetTable[i].VertexStart,
0234:                                         pSubsetTable[i].VertexCount,
0235:                                         pSubsetTable[i].FaceStart * 3,
0236:                                         pSubsetTable[i].FaceCount);
0237:     }
0238:     //
0239:     // モデル2
0240:     //
0241:     D3DXMatrixRotationY( &mWorld, -t/3000.0f );
0242: //D3DXMatrixRotationY( &mWorld, 1.4f*PI/2 ); // 撮影角度
0243:     m = mWorld * mView;
0244:     D3DXMatrixTranspose( &m ,  &m);
0245:     lpD3DDev->SetVertexShaderConstant(0,&m, 4);
0246: 
0247:     D3DXMatrixInverse( &m,  NULL, &mWorld);
0248:     D3DXVec4Transform(&vl, &lightDir, &m);
0249:     D3DXVec4Normalize(&vl, &vl);
0250:     vl[3] = 0.1f;// w成分は環境色の強さ
0251:     lpD3DDev->SetVertexShaderConstant(13, &vl, 1);
0252:     
0253:     for(i=0;i<dwNumMaterials;i++){
0254:         //色をセット
0255:         D3DXVECTOR4 vl;
0256:         vl.x = pMeshMaterials[i].Diffuse.r;
0257:         vl.y = pMeshMaterials[i].Diffuse.g;
0258:         vl.z = pMeshMaterials[i].Diffuse.b;
0259:         lpD3DDev->SetVertexShaderConstant(14, &vl, 1);
0260: 
0261:         lpD3DDev->SetTexture(0,pMeshTextures[i]);
0262:         lpD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 
0263:                                         pSubsetTable[i].VertexStart,
0264:                                         pSubsetTable[i].VertexCount,
0265:                                         pSubsetTable[i].FaceStart * 3,
0266:                                         pSubsetTable[i].FaceCount);
0267:     }
0268: 
0269:     //
0270:     // 背景描画
0271:     // 
0272:     D3DXMatrixScaling(&mWorld, 3.0f, 3.0f, 3.0f);
0273:     m = mWorld * mView;
0274:     D3DXMatrixTranspose( &m ,  &m);
0275:     lpD3DDev->SetVertexShaderConstant(0,&m, 4);
0276:     
0277:     lpD3DDev->SetVertexShaderConstant(13, &D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f), 1);
0278:     lpD3DDev->SetVertexShaderConstant(14, &D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f), 1);
0279:     DrawBg(lpD3DDev);
0280: }
0281: //-----------------------------------------------------------------------------
0282: // Name: Render()
0283: // Desc: Draws the scene
0284: //-----------------------------------------------------------------------------
0285: VOID Render(LPDIRECT3DDEVICE8 lpD3DDev)
0286: {
0287:     // シェーダーの設定
0288:     lpD3DDev->SetVertexShader(hVertexShader);
0289:     lpD3DDev->SetPixelShader(hPixelShader);
0290:     
0291:     DrawModel(lpD3DDev);
0292:     
0293:     // 念のため、他のレンダーでおかしくならないように
0294:     lpD3DDev->SetPixelShader(0);
0295: }
0296: //-----------------------------------------------------------------------------
0297: // メッシュオブジェクト削除
0298: //-----------------------------------------------------------------------------
0299: void DeleteMeshObject(void)
0300: {
0301:     DWORD i;
0302: 
0303:     if(pMeshVB == NULL) return;
0304: 
0305:     for(i=0; i<dwNumMaterials; i++){
0306:         RELEASE(pMeshTextures[i]);
0307:     }
0308:     delete[] pMeshTextures;
0309:     delete[] pMeshMaterials;
0310:     delete[] pSubsetTable;
0311: 
0312:     RELEASE(pMeshVB);
0313:     RELEASE(pMeshIndex);
0314: }
0315: //-----------------------------------------------------------------------------
0316: // Name: CleanRender()
0317: // Desc: 後始末
0318: //-----------------------------------------------------------------------------
0319: void CleanRender(LPDIRECT3DDEVICE8 lpD3DDev)
0320: {
0321:     CleanBg(lpD3DDev);
0322:     
0323:     CPixelShaderMgr::Release(lpD3DDev, &hPixelShader);
0324:     CVertexShaderMgr::Release(lpD3DDev, &hVertexShader);
0325: 
0326:     DeleteMeshObject();
0327: }
0328: