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: 
0015: LPDIRECT3DVERTEXBUFFER8 pMeshVB = NULL;
0016: LPDIRECT3DINDEXBUFFER8  pMeshIndex = NULL;
0017: D3DXATTRIBUTERANGE      *pSubsetTable = NULL;
0018: DWORD                   nMeshFaces = 0;
0019: DWORD                   nMeshVertices = 0;
0020: D3DMATERIAL8            *pMeshMaterials = NULL;     // メッシュの質感
0021: LPDIRECT3DTEXTURE8      *pMeshTextures  = NULL;     // メッシュのテクスチャー
0022: DWORD                   dwNumMaterials = 0L;        // マテリアルの数
0023: 
0024: DWORD                   hVertexShader=~0;
0025: FLOAT                   MeshRadius;                 // メッシュの多さ(初登場)
0026: 
0027: // ----------------------------------------------------------------------------
0028: // 頂点の定義
0029: 
0030: typedef struct {
0031:     float x,y,z;
0032:     float nx,ny,nz;
0033:     float tu0,tv0;
0034: }D3DVERTEX;
0035: #define D3DFVF_VERTEX       (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
0036: 
0037: typedef struct {
0038:     float x,y,z;
0039:     float nx,ny,nz;
0040:     float tu0,tv0;
0041: }D3D_CUSTOMVERTEX;
0042: #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
0043: 
0044: DWORD dwDecl[] = {
0045:     D3DVSD_STREAM(0),
0046:     D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3 ),          //D3DVSDE_POSITION,  0
0047:     D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_FLOAT3 ),          //D3DVSDE_NORMAL,    3
0048:     D3DVSD_REG(D3DVSDE_TEXCOORD0,D3DVSDT_FLOAT2 ),          //D3DVSDE_TEXCOORD0, 7  
0049:     D3DVSD_END()
0050: };
0051: /*---------------------------------------------
0052:     X-Fileの読み込み
0053: ---------------------------------------------*/
0054: HRESULT LoadXFile(char* filename, LPDIRECT3DDEVICE8 lpD3DDEV)
0055: {
0056:     LPD3DXMESH pMesh, pMeshOpt;
0057:     LPD3DXBUFFER pD3DXMtrlBuffer = NULL;
0058:     DWORD i;
0059:     HRESULT hr;
0060: 
0061:     hr = D3DXLoadMeshFromX(filename, D3DXMESH_MANAGED,
0062:                                 lpD3DDEV, NULL,
0063:                                 &pD3DXMtrlBuffer, &dwNumMaterials,
0064:                                 &pMesh);
0065:     if(FAILED(hr)) return E_FAIL;
0066: 
0067:     //並び替えておく
0068:     pMesh->Optimize(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL, &pMeshOpt);
0069:     RELEASE(pMesh);
0070: 
0071:     //アトリビュートテーブル
0072:     pMeshOpt->GetAttributeTable(NULL,&dwNumMaterials);
0073:     pSubsetTable = new D3DXATTRIBUTERANGE[dwNumMaterials];
0074:     pMeshOpt->GetAttributeTable(pSubsetTable, &dwNumMaterials);
0075: 
0076:     // FVF変換
0077:     hr = pMeshOpt->CloneMeshFVF(pMeshOpt->GetOptions(), D3DFVF_VERTEX, lpD3DDEV, &pMesh);
0078:     if(FAILED(hr)) return E_FAIL;
0079:     RELEASE(pMeshOpt);
0080:     D3DXComputeNormals(pMesh);
0081: 
0082:     //Vertex Bufferにコピーする
0083:     D3DVERTEX* pSrc;
0084:     D3D_CUSTOMVERTEX* pDest;
0085:     LPDIRECT3DINDEXBUFFER8 pSrcIndex;
0086:     WORD* pISrc;
0087:     WORD* pIDest;
0088: 
0089:     DWORD nMeshVertices = pMesh->GetNumVertices();
0090:     DWORD nMeshFaces = pMesh->GetNumFaces();
0091:     lpD3DDEV->CreateVertexBuffer(nMeshVertices * sizeof(D3D_CUSTOMVERTEX),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_MANAGED,&pMeshVB);
0092:     lpD3DDEV->CreateIndexBuffer(nMeshFaces * 3 * sizeof(WORD),0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&pMeshIndex);
0093: 
0094:     LPDIRECT3DVERTEXBUFFER8 pVB;
0095:     pMesh->GetVertexBuffer(&pVB);
0096:     pVB->Lock(0,0,(BYTE**)&pSrc,0);
0097:     pMeshVB->Lock(0,0,(BYTE**)&pDest,0);
0098:     MeshRadius = 0.0f;
0099:     for(i=0;i<nMeshVertices;i++){
0100:         // サイズの計算
0101:         FLOAT radius = sqrtf( pSrc->x*pSrc->x + pSrc->y*pSrc->y + pSrc->z*pSrc->z );
0102:         if (MeshRadius < radius) MeshRadius = radius;
0103:         
0104:         pDest->x = pSrc->x;
0105:         pDest->y = pSrc->y;
0106:         pDest->z = pSrc->z;
0107:         pDest->nx = pSrc->nx;
0108:         pDest->ny = pSrc->ny;
0109:         pDest->nz = pSrc->nz;
0110:         pDest->tu0 = pSrc->tu0;
0111:         pDest->tv0 = pSrc->tv0;
0112:         pSrc += 1;
0113:         pDest += 1;
0114:     }
0115:     pVB->Unlock();
0116:     pVB->Release();
0117:     pMeshVB->Unlock();
0118: 
0119:     //インデックスのコピー
0120:     pMesh->GetIndexBuffer(&pSrcIndex);
0121:     pSrcIndex->Lock(0,0,(BYTE**)&pISrc,0);
0122:     pMeshIndex->Lock(0,0,(BYTE**)&pIDest,0);
0123:     CopyMemory(pIDest,pISrc,nMeshFaces * 3 * sizeof(WORD));
0124:     pSrcIndex->Unlock();
0125:     pMeshIndex->Unlock();
0126:     pSrcIndex->Release();
0127: 
0128:     // pD3DXMtrlBuffer から、質感やテクスチャーの情報を読み取る
0129:     D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
0130:     pMeshTextures = new LPDIRECT3DTEXTURE8[dwNumMaterials];
0131:     pMeshMaterials = new D3DMATERIAL8[dwNumMaterials];
0132: 
0133:     for(i = 0; i < dwNumMaterials; i++){
0134:         pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
0135:         pMeshMaterials[i].Ambient = pMeshMaterials[i].Diffuse;
0136:         hr = D3DXCreateTextureFromFile( lpD3DDEV, 
0137:                                         d3dxMaterials[i].pTextureFilename, 
0138:                                         &pMeshTextures[i] );
0139:         if(FAILED(hr)) pMeshTextures[i] = NULL;
0140:     }
0141:     RELEASE(pD3DXMtrlBuffer);
0142:     
0143:     RELEASE(pMesh);
0144: 
0145:     return S_OK;
0146: }
0147: 
0148: 
0149: // ----------------------------------------------------------------------------
0150: // Name: Render()
0151: // Desc: ポリゴンの初期化
0152: //-----------------------------------------------------------------------------
0153: HRESULT InitRender(LPDIRECT3DDEVICE8 lpD3DDev)
0154: {
0155:     HRESULT hr;
0156: 
0157:     // モデルの読み込み
0158:     hr = LoadXFile("nsx.x", lpD3DDev);
0159:     if ( FAILED(hr) ) return hr;
0160:  
0161:     // バーテックスシェーダーを作成する
0162:     ID3DXBuffer*    pshader;
0163:     hr = D3DXAssembleShaderFromFile("vs.vsh", 0,NULL,&pshader,NULL);
0164:     if ( FAILED(hr) ) return hr;
0165:     hr = lpD3DDev->CreateVertexShader( dwDecl, (DWORD*)pshader->GetBufferPointer(), &hVertexShader, 0 );
0166:     RELEASE(pshader);
0167:     if ( FAILED(hr) ) return hr;
0168:     
0169:     // レンダリングの状態の設定
0170:     lpD3DDev->SetRenderState( D3DRS_LIGHTING,        FALSE );
0171:     lpD3DDev->SetRenderState( D3DRS_CULLMODE,       D3DCULL_CCW ); 
0172:     lpD3DDev->SetRenderState( D3DRS_FOGENABLE,      FALSE);
0173: 
0174:     lpD3DDev->SetRenderState( D3DRS_DITHERENABLE,   FALSE );
0175:     lpD3DDev->SetRenderState( D3DRS_SPECULARENABLE, FALSE );
0176:     lpD3DDev->SetRenderState( D3DRS_ZENABLE,        TRUE );
0177:     
0178:     lpD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
0179:     lpD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
0180:     lpD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
0181: 
0182:     lpD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);
0183:     lpD3DDev->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
0184:     lpD3DDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
0185: 
0186:     lpD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
0187:     lpD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
0188:     lpD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
0189:     lpD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG2);
0190:     lpD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
0191:     
0192:     // 定数レジスタの設定
0193:     lpD3DDev->SetVertexShaderConstant(0, D3DXVECTOR4(0.0f,0.5f,1.0f,2.0f), 1);
0194:     
0195:     return S_OK;
0196: }
0197: // ----------------------------------------------------------------------------
0198: static set_transform(bool bWithBlur, LPDIRECT3DDEVICE8 lpD3DDev, D3DXMATRIX mWorld, D3DXMATRIX mView, D3DXMATRIX mProj)
0199: {
0200:     D3DXMATRIX m, mWV, mWV_IT;
0201:     static D3DXMATRIX mLastWV;
0202: 
0203:     D3DXMatrixMultiply(&mWV,   &mWorld, &mView);
0204:     D3DXMatrixInverse( &mWV_IT, NULL, &mWV);
0205:     
0206:     // 射影行列 
0207:     D3DXMatrixTranspose(&m, &mProj);
0208:     lpD3DDev->SetVertexShaderConstant(4, &m, 4);
0209: 
0210:     // ビュー行列
0211:     D3DXMatrixTranspose(&mWV, &mWV);
0212:     lpD3DDev->SetVertexShaderConstant(8, &mWV, 3);
0213:     if (bWithBlur){
0214:         lpD3DDev->SetVertexShaderConstant(12, &mLastWV, 3);
0215:         mLastWV = mWV;
0216:     }else{
0217:         // ブラーしないときは、現在のマトリックスを過去のものとして使用
0218:         lpD3DDev->SetVertexShaderConstant(12, &mWV, 3);
0219:     }
0220: 
0221:     // ビュー行列 の逆転置行列
0222:     lpD3DDev->SetVertexShaderConstant(16, &mWV_IT, 3);
0223: 
0224:     return S_OK;
0225: }
0226: // ----------------------------------------------------------------------------
0227: // Name: Render()
0228: // Desc: ポリゴンの描画
0229: //-----------------------------------------------------------------------------
0230: void Render(LPDIRECT3DDEVICE8 lpD3DDev)
0231: {
0232:     if(NULL == pMeshVB) return;
0233:     
0234:     D3DXMATRIX m, mWorld, mView, mProj;
0235:     DWORD i;
0236: 
0237:     // ワールド行列
0238:     D3DXMatrixTranslation(&m, MeshRadius, 0,0);
0239:     D3DXMatrixRotationY( &mWorld, timeGetTime()/1000.0f );
0240:     mWorld = m * mWorld;
0241:     
0242:     // ビュー行列
0243:     D3DXVECTOR3 eye   (0.0f,MeshRadius,2.5f*MeshRadius);
0244:     D3DXVECTOR3 lookAt(0.0f, 0.0f, 0.0f);
0245:     D3DXVECTOR3 up    (0.0f, 1.0f, 0.0f);
0246:     D3DXMatrixLookAtLH(&mView, &eye, &lookAt, &up);
0247:     // 射影行列 
0248:     D3DXMatrixPerspectiveFovLH(&mProj, PI/3.0f, (float)WIDTH/(float)HEIGHT, 0.01f, 100.0f);
0249:     
0250:     // ブラーパラメータの設定
0251:     lpD3DDev->SetVertexShaderConstant( 3, D3DXVECTOR4(
0252:         2.0f/MeshRadius,
0253:         3.0f,               // ブラーの長さ
0254:         1.0f,0.0f),  1 );
0255:     
0256:     lpD3DDev->SetVertexShader(hVertexShader);
0257:     lpD3DDev->SetStreamSource(0, pMeshVB, sizeof(D3D_CUSTOMVERTEX));
0258:     lpD3DDev->SetIndices(pMeshIndex,0);
0259:     
0260: 
0261:     //メッシュの描画(透明なブラー部分)
0262:     set_transform(1,lpD3DDev, mWorld, mView, mProj);
0263:     lpD3DDev->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
0264:     for(i=0;i<dwNumMaterials;i++){
0265:         //色をセット
0266:         D3DXVECTOR4 c(pMeshMaterials[i].Diffuse.r,
0267:                       pMeshMaterials[i].Diffuse.g,
0268:                       pMeshMaterials[i].Diffuse.b,
0269:                       1.0f);
0270:         FLOAT const kBlurAlpha = 0.0f;
0271: 
0272:         lpD3DDev->SetVertexShaderConstant( 1, &c,  1 );  // メッシュの色
0273:         c[3] = kBlurAlpha;
0274:         lpD3DDev->SetVertexShaderConstant( 2, &c,  1 );  // ブラーしたメッシュの色
0275: 
0276:         lpD3DDev->SetTexture(0, pMeshTextures[i]);
0277:         lpD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 
0278:                                         pSubsetTable[i].VertexStart,
0279:                                         pSubsetTable[i].VertexCount,
0280:                                         pSubsetTable[i].FaceStart * 3,
0281:                                         pSubsetTable[i].FaceCount);
0282:     }
0283:     
0284:     //メッシュの描画(2パス目:通常描画)
0285:     set_transform(0,lpD3DDev, mWorld, mView, mProj);
0286:     lpD3DDev->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
0287:     for(i=0;i<dwNumMaterials;i++){
0288:         //色をセット
0289:         D3DXVECTOR4 c(pMeshMaterials[i].Diffuse.r,
0290:                       pMeshMaterials[i].Diffuse.g,
0291:                       pMeshMaterials[i].Diffuse.b,
0292:                       1.0f);
0293:         lpD3DDev->SetVertexShaderConstant( 1, &c,  1 );  // メッシュの色
0294:         lpD3DDev->SetVertexShaderConstant( 2, &c,  1 );  // ブラーしたメッシュの色
0295: 
0296:         lpD3DDev->SetTexture(0, pMeshTextures[i]);
0297:         lpD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 
0298:                                         pSubsetTable[i].VertexStart,
0299:                                         pSubsetTable[i].VertexCount,
0300:                                         pSubsetTable[i].FaceStart * 3,
0301:                                         pSubsetTable[i].FaceCount);
0302:     }
0303:     
0304:     Sleep(100);
0305: }
0306: //-----------------------------------------------------------------------------
0307: // メッシュオブジェクト削除
0308: //-----------------------------------------------------------------------------
0309: void DeleteMeshObject(void)
0310: {
0311:     DWORD i;
0312: 
0313:     if(pMeshVB == NULL) return;
0314: 
0315:     for(i=0; i<dwNumMaterials; i++){
0316:         RELEASE(pMeshTextures[i]);
0317:     }
0318:     delete[] pMeshTextures;
0319:     delete[] pMeshMaterials;
0320:     delete[] pSubsetTable;
0321: 
0322:     RELEASE(pMeshVB);
0323:     RELEASE(pMeshIndex);
0324: }
0325: //-----------------------------------------------------------------------------
0326: // Name: CleanRender()
0327: // Desc: 後始末
0328: //-----------------------------------------------------------------------------
0329: void CleanRender(LPDIRECT3DDEVICE8 lpD3DDEV)
0330: {
0331:     DeleteMeshObject();
0332:     
0333:     if ( hVertexShader != ~0 ){
0334:         lpD3DDEV->DeleteVertexShader( hVertexShader );
0335:         hVertexShader = ~0;
0336:     }
0337: }
0338: