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: const DWORD WIN_W       = 400;
0016: const DWORD WIN_H       =  80;
0017: const DWORD WIN_X       = (WIDTH - WIN_W)/2;
0018: const DWORD WIN_Y       = 30;
0019: 
0020: LPDIRECT3DVERTEXBUFFER8 pMeshVB = NULL;
0021: LPDIRECT3DINDEXBUFFER8  pMeshIndex = NULL;
0022: D3DXATTRIBUTERANGE      *pSubsetTable = NULL;
0023: DWORD                   nMeshFaces = 0;
0024: DWORD                   nMeshVertices = 0;
0025: D3DMATERIAL8            *pMeshMaterials = NULL;     // メッシュの質感
0026: LPDIRECT3DTEXTURE8      *pMeshTextures  = NULL;     // メッシュのテクスチャー
0027: DWORD                   dwNumMaterials = 0L;        // マテリアルの数
0028: 
0029: DWORD                   hVertexShader=~0;
0030: 
0031: // ----------------------------------------------------------------------------
0032: // 頂点の定義
0033: 
0034: typedef struct {
0035:     float x,y,z;
0036:     float nx,ny,nz;
0037:     float tu0,tv0;
0038: }D3DVERTEX;
0039: #define D3DFVF_VERTEX       (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
0040: 
0041: typedef struct {
0042:     float x,y,z;
0043:     float nx,ny,nz,nw;
0044:     float tu0,tv0;
0045: }D3D_CUSTOMVERTEX;
0046: #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
0047: 
0048: DWORD dwDecl[] = {
0049:     D3DVSD_STREAM(0),
0050:     D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3 ),          //D3DVSDE_POSITION,  0
0051:     D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_FLOAT4 ),          //D3DVSDE_NORMAL,    3
0052:     D3DVSD_REG(D3DVSDE_TEXCOORD0,D3DVSDT_FLOAT2 ),          //D3DVSDE_TEXCOORD0, 7  
0053:     D3DVSD_END()
0054: };
0055: 
0056: 
0057: // ----------------------------------------------------------------------------
0058: // Name: LoadXFile(char* filename, LPDIRECT3DDEVICE8 lpD3DDEV)
0059: // Desc: X-Fileの読み込み
0060: //-----------------------------------------------------------------------------
0061: HRESULT LoadXFile(char* filename, LPDIRECT3DDEVICE8 lpD3DDEV)
0062: {
0063:     LPD3DXMESH pMesh, pMeshOpt;
0064:     LPD3DXBUFFER pD3DXMtrlBuffer = NULL;
0065:     DWORD i;
0066:     HRESULT hr;
0067: 
0068:     hr = D3DXLoadMeshFromX(filename, D3DXMESH_MANAGED,
0069:                                 lpD3DDEV, NULL,
0070:                                 &pD3DXMtrlBuffer, &dwNumMaterials,
0071:                                 &pMesh);
0072:     if(FAILED(hr)) return E_FAIL;
0073: 
0074:     //並び替えておく
0075:     pMesh->Optimize(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL, &pMeshOpt);
0076:     RELEASE(pMesh);
0077: 
0078:     //アトリビュートテーブル
0079:     pMeshOpt->GetAttributeTable(NULL,&dwNumMaterials);
0080:     pSubsetTable = new D3DXATTRIBUTERANGE[dwNumMaterials];
0081:     pMeshOpt->GetAttributeTable(pSubsetTable, &dwNumMaterials);
0082: 
0083:     // FVF変換
0084:     hr = pMeshOpt->CloneMeshFVF(pMeshOpt->GetOptions(), D3DFVF_VERTEX, lpD3DDEV, &pMesh);
0085:     if(FAILED(hr)) return E_FAIL;
0086:     RELEASE(pMeshOpt);
0087:     D3DXComputeNormals(pMesh);
0088: 
0089:     //Vertex Bufferにコピーする
0090:     D3DVERTEX* pSrc;
0091:     D3D_CUSTOMVERTEX* pDest;
0092:     LPDIRECT3DINDEXBUFFER8 pSrcIndex;
0093:     WORD* pISrc;
0094:     WORD* pIDest;
0095: 
0096:     DWORD nMeshVertices = pMesh->GetNumVertices();
0097:     DWORD nMeshFaces = pMesh->GetNumFaces();
0098:     lpD3DDEV->CreateVertexBuffer(nMeshVertices * sizeof(D3D_CUSTOMVERTEX),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_MANAGED,&pMeshVB);
0099:     lpD3DDEV->CreateIndexBuffer(nMeshFaces * 3 * sizeof(WORD),0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&pMeshIndex);
0100: 
0101:     LPDIRECT3DVERTEXBUFFER8 pVB;
0102:     pMesh->GetVertexBuffer(&pVB);
0103:     pVB->Lock(0,0,(BYTE**)&pSrc,0);
0104:     pMeshVB->Lock(0,0,(BYTE**)&pDest,0);
0105:     for(i=0;i<nMeshVertices;i++){
0106:         pDest->x = pSrc->x;
0107:         pDest->y = pSrc->y;
0108:         pDest->z = pSrc->z;
0109:         pDest->nx = pSrc->nx;
0110:         pDest->ny = pSrc->ny;
0111:         pDest->nz = pSrc->nz;
0112:         pDest->nw = 1.0f;
0113:         pDest->tu0 = pSrc->tu0;
0114:         pDest->tu0 = pSrc->tu0;
0115:         pSrc += 1;
0116:         pDest += 1;
0117:     }
0118:     pVB->Unlock();
0119:     pVB->Release();
0120:     pMeshVB->Unlock();
0121: 
0122:     //インデックスのコピー
0123:     pMesh->GetIndexBuffer(&pSrcIndex);
0124:     pSrcIndex->Lock(0,0,(BYTE**)&pISrc,0);
0125:     pMeshIndex->Lock(0,0,(BYTE**)&pIDest,0);
0126:     CopyMemory(pIDest,pISrc,nMeshFaces * 3 * sizeof(WORD));
0127:     pSrcIndex->Unlock();
0128:     pMeshIndex->Unlock();
0129:     pSrcIndex->Release();
0130: 
0131:     // pD3DXMtrlBuffer から、質感やテクスチャーの情報を読み取る
0132:     D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
0133:     pMeshTextures = new LPDIRECT3DTEXTURE8[dwNumMaterials];
0134:     pMeshMaterials = new D3DMATERIAL8[dwNumMaterials];
0135: 
0136:     for(i = 0; i < dwNumMaterials; i++){
0137:         pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
0138:         pMeshMaterials[i].Ambient = pMeshMaterials[i].Diffuse;
0139:         hr = D3DXCreateTextureFromFile( lpD3DDEV, 
0140:                                         d3dxMaterials[i].pTextureFilename, 
0141:                                         &pMeshTextures[i] );
0142:         if(FAILED(hr)) pMeshTextures[i] = NULL;
0143:     }
0144:     RELEASE(pD3DXMtrlBuffer);
0145:     
0146:     RELEASE(pMesh);
0147: 
0148:     return S_OK;
0149: }
0150: // ----------------------------------------------------------------------------
0151: // Name: LoadXFile(char* filename, LPDIRECT3DDEVICE8 lpD3DDEV)
0152: // Desc: 頂点シェーダープログラムの読み込み
0153: //-----------------------------------------------------------------------------
0154: HRESULT LoadVertexShader(char* filename, LPDIRECT3DDEVICE8 lpD3DDEV, DWORD *phVertexShader, const DWORD *dwDecl)
0155: {
0156:     HRESULT hr;
0157:     ID3DXBuffer *pshader;
0158:     
0159:     if ( FAILED(hr = D3DXAssembleShaderFromFile(filename, 0,NULL,&pshader,NULL)) ) return hr;
0160:     
0161:     hr = lpD3DDEV->CreateVertexShader( dwDecl, (DWORD*)pshader->GetBufferPointer(), phVertexShader, 0 );
0162:     RELEASE(pshader);
0163:     if ( FAILED(hr) ) return hr;
0164:     
0165:     return S_OK;
0166: }
0167: // ----------------------------------------------------------------------------
0168: // Name: Render()
0169: // Desc: ポリゴンの初期化
0170: //-----------------------------------------------------------------------------
0171: HRESULT InitRender(LPDIRECT3DDEVICE8 lpD3DDEV)
0172: {
0173:     HRESULT hr;
0174: 
0175:     // モデルの読み込み
0176:     if ( FAILED(hr = LoadXFile("nsx.x", lpD3DDEV)) ) return hr;
0177:  
0178:     // バーテックスシェーダーを作成する
0179:     if ( FAILED(hr = LoadVertexShader("vs.vsh", lpD3DDEV, &hVertexShader, dwDecl)) ) return hr;
0180:     
0181:     // レンダリングの状態の設定
0182:     lpD3DDEV->SetRenderState( D3DRS_ZENABLE, TRUE);
0183:     
0184:     return S_OK;
0185: }
0186: // ----------------------------------------------------------------------------
0187: // Name: Render()
0188: // Desc: ポリゴンの描画
0189: //-----------------------------------------------------------------------------
0190: void Render(LPDIRECT3DDEVICE8 lpD3DDEV)
0191: {
0192:     if(NULL == pMeshVB) return;
0193:     
0194:     D3DVIEWPORT8 viewport={WIN_X, WIN_Y, WIN_W, WIN_H, 0.0f, 1.0f};
0195:     D3DVIEWPORT8 viewport_bak;
0196:     lpD3DDEV->GetViewport(&viewport_bak);       //  元のビューポート矩形を取っておく
0197: 
0198:     for(int n = 0; n < 2; n++){
0199:         D3DXMATRIX mWorld, mView, mProj, m;
0200: 
0201:         D3DXVECTOR3 eye    = D3DXVECTOR3(0.0f, 10.0f, 30.0f);
0202:         D3DXVECTOR3 lookAt = D3DXVECTOR3(0.0f,  3.0f,  0.0f);
0203:         D3DXVECTOR3 up     = D3DXVECTOR3(0.0f,  1.0f,  0.0f);
0204:         if(0 == n){
0205:             // 通常表示
0206:             D3DXMatrixLookAtLH(&mView, &eye, &lookAt, &up);
0207:             D3DXMatrixPerspectiveFovLH(&mProj
0208:                 ,60.0f*PI/180.0f                        // 視野角
0209:                 ,(float)WIDTH/(float)HEIGHT             // アスペクト比
0210:                 ,0.01f,100.0f                           // 最近接距離,最遠方距離
0211:                 );
0212:         }else{
0213:             //  バックミラー表示
0214:             lpD3DDEV->SetViewport(&viewport);
0215:             lpD3DDEV->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0x40, 0x40),1.0f,0);
0216:             lpD3DDEV->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
0217:             
0218:             eye.z   = -30.0f;                           // 窓で表示するときは、反対から見る
0219:             D3DXMatrixLookAtLH(&mView, &eye, &lookAt, &up);
0220:             D3DXMatrixIdentity(&m);
0221:             m(0,0)=-1.0f;                               // x軸に関して鏡像を取る
0222:             mView = m * mView;
0223:             D3DXMatrixPerspectiveFovLH(&mProj
0224:                 ,20.0f*PI/180.0f                        // 視野角
0225:                 ,(float)WIN_W/(float)WIN_H              // アスペクト比
0226:                 ,0.01f,100.0f                           // 最近接距離,最遠方距離
0227:                 );
0228:         }
0229:         D3DXMatrixRotationY( &mWorld, timeGetTime()/1000.0f );
0230: 
0231:         m = mWorld * mView * mProj;
0232:         D3DXMatrixTranspose( &m ,  &m);
0233:         lpD3DDEV->SetVertexShaderConstant(0,&m, 4);
0234: 
0235:         D3DXVECTOR4 lightDir(1.0f, 1.0f, 0.5f, 0.0f);
0236:         D3DXVec4Normalize(&lightDir, &lightDir);
0237:         D3DXMatrixInverse( &m,  NULL, &mWorld);
0238:         D3DXVec4Transform(&lightDir, &lightDir, &m);
0239:         lightDir[3] = 0.3f;// 環境光の強さ
0240:         lpD3DDEV->SetVertexShaderConstant(13, &lightDir, 1);
0241:         lpD3DDEV->SetVertexShaderConstant(12, D3DXVECTOR4(0.0f, 0.5f, 1.0f, 2.0f), 1);
0242: 
0243:         lpD3DDEV->SetRenderState(D3DRS_WRAP0,D3DWRAP_U | D3DWRAP_V);
0244:         lpD3DDEV->SetRenderState(D3DRS_WRAP1,D3DWRAP_U | D3DWRAP_V);
0245:         lpD3DDEV->SetTextureStageState(0,D3DTSS_MAGFILTER,  D3DTEXF_LINEAR);
0246:         lpD3DDEV->SetTextureStageState(0,D3DTSS_MINFILTER,  D3DTEXF_LINEAR);
0247:         lpD3DDEV->SetTextureStageState(0,D3DTSS_ADDRESSU,   D3DTADDRESS_CLAMP);
0248:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLOROP,    D3DTOP_MODULATE);
0249:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG1,  D3DTA_TEXTURE);
0250:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG2,  D3DTA_DIFFUSE);
0251:         lpD3DDEV->SetVertexShader(hVertexShader);
0252: 
0253:         //メッシュの描画
0254:         lpD3DDEV->SetStreamSource(0, pMeshVB, sizeof(D3D_CUSTOMVERTEX));
0255:         lpD3DDEV->SetIndices(pMeshIndex,0);
0256:         for(DWORD i=0;i<dwNumMaterials;i++){
0257:             //色をセット
0258:             D3DXVECTOR4 vl;
0259:             vl.x = pMeshMaterials[i].Diffuse.r;
0260:             vl.y = pMeshMaterials[i].Diffuse.g;
0261:             vl.z = pMeshMaterials[i].Diffuse.b;
0262:             lpD3DDEV->SetVertexShaderConstant(14, &vl, 1);
0263: 
0264:             lpD3DDEV->SetTexture(0,pMeshTextures[i]);
0265:             lpD3DDEV->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 
0266:                                             pSubsetTable[i].VertexStart,
0267:                                             pSubsetTable[i].VertexCount,
0268:                                             pSubsetTable[i].FaceStart * 3,
0269:                                             pSubsetTable[i].FaceCount);
0270:         }
0271:     }
0272:     
0273:     lpD3DDEV->SetViewport(&viewport_bak);           // ビューポート矩形を戻す
0274:     lpD3DDEV->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
0275:     lpD3DDEV->SetTexture(0, NULL);
0276: }
0277: //-----------------------------------------------------------------------------
0278: // メッシュオブジェクト削除
0279: //-----------------------------------------------------------------------------
0280: void DeleteMeshObject(void)
0281: {
0282:     DWORD i;
0283: 
0284:     if(pMeshVB == NULL) return;
0285: 
0286:     for(i=0; i<dwNumMaterials; i++){
0287:         RELEASE(pMeshTextures[i]);
0288:     }
0289:     delete[] pMeshTextures;
0290:     delete[] pMeshMaterials;
0291:     delete[] pSubsetTable;
0292: 
0293:     RELEASE(pMeshVB);
0294:     RELEASE(pMeshIndex);
0295: }
0296: //-----------------------------------------------------------------------------
0297: // Name: CleanRender()
0298: // Desc: 後始末
0299: //-----------------------------------------------------------------------------
0300: void CleanRender(LPDIRECT3DDEVICE8 lpD3DDEV)
0301: {
0302:     DeleteMeshObject();
0303:     
0304:     if ( hVertexShader != ~0 ){
0305:         lpD3DDEV->DeleteVertexShader( hVertexShader );
0306:         hVertexShader = ~0;
0307:     }
0308: }
0309: