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: LPDIRECT3DTEXTURE8      pToonTexture  = NULL;           // エフェクト用のテクスチャー
0025: LPDIRECT3DTEXTURE8      pToneTexture  = NULL;           // エフェクト用のテクスチャー
0026: DWORD                   hVertexShader=~0;
0027: DWORD                   hPixelShader=~0;
0028: 
0029: // ----------------------------------------------------------------------------
0030: // 頂点の定義
0031: 
0032: typedef struct {
0033:     float x,y,z;
0034:     float nx,ny,nz;
0035:     float tu0,tv0;
0036: }D3DVERTEX;
0037: #define D3DFVF_VERTEX       (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
0038: 
0039: typedef struct {
0040:     float x,y,z;
0041:     float nx,ny,nz;
0042:     float tu0,tv0;
0043:     float tu1,tv1;
0044: }D3D_CUSTOMVERTEX;
0045: #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 | D3DFVF_TEX2)
0046: 
0047: DWORD dwDecl[] = {
0048:     D3DVSD_STREAM(0),
0049:     D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3 ),          //D3DVSDE_POSITION,  0
0050:     D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_FLOAT3 ),          //D3DVSDE_NORMAL,    3
0051:     D3DVSD_REG(D3DVSDE_TEXCOORD0,D3DVSDT_FLOAT2 ),          //D3DVSDE_TEXCOORD0, 7  
0052:     D3DVSD_REG(D3DVSDE_TEXCOORD1,D3DVSDT_FLOAT2 ),          //D3DVSDE_TEXCOORD1, 8  
0053:     D3DVSD_END()
0054: };
0055: /*---------------------------------------------
0056:     X-Fileの読み込み
0057: ---------------------------------------------*/
0058: HRESULT LoadXFile(char* filename, LPDIRECT3DDEVICE8 lpD3DDEV)
0059: {
0060:     LPD3DXMESH pMesh, pMeshOpt;
0061:     LPD3DXBUFFER pD3DXMtrlBuffer = NULL;
0062:     DWORD i;
0063:     HRESULT hr;
0064: 
0065:     hr = D3DXLoadMeshFromX(filename, D3DXMESH_MANAGED,
0066:                                 lpD3DDEV, NULL,
0067:                                 &pD3DXMtrlBuffer, &dwNumMaterials,
0068:                                 &pMesh);
0069:     if(FAILED(hr)) return E_FAIL;
0070: 
0071:     //並び替えておく
0072:     pMesh->Optimize(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL, &pMeshOpt);
0073:     RELEASE(pMesh);
0074: 
0075:     //アトリビュートテーブル
0076:     pMeshOpt->GetAttributeTable(NULL,&dwNumMaterials);
0077:     pSubsetTable = new D3DXATTRIBUTERANGE[dwNumMaterials];
0078:     pMeshOpt->GetAttributeTable(pSubsetTable, &dwNumMaterials);
0079: 
0080:     // FVF変換
0081:     hr = pMeshOpt->CloneMeshFVF(pMeshOpt->GetOptions(), D3DFVF_VERTEX, lpD3DDEV, &pMesh);
0082:     if(FAILED(hr)) return E_FAIL;
0083:     RELEASE(pMeshOpt);
0084:     D3DXComputeNormals(pMesh, NULL);
0085: 
0086:     //Vertex Bufferにコピーする
0087:     D3DVERTEX* pSrc;
0088:     D3D_CUSTOMVERTEX* pDest;
0089:     LPDIRECT3DINDEXBUFFER8 pSrcIndex;
0090:     WORD* pISrc;
0091:     WORD* pIDest;
0092: 
0093:     DWORD nMeshVertices = pMesh->GetNumVertices();
0094:     DWORD nMeshFaces = pMesh->GetNumFaces();
0095:     lpD3DDEV->CreateVertexBuffer(nMeshVertices * sizeof(D3D_CUSTOMVERTEX),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_MANAGED,&pMeshVB);
0096:     lpD3DDEV->CreateIndexBuffer(nMeshFaces * 3 * sizeof(WORD),0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&pMeshIndex);
0097: 
0098:     LPDIRECT3DVERTEXBUFFER8 pVB;
0099:     pMesh->GetVertexBuffer(&pVB);
0100:     pVB->Lock(0,0,(BYTE**)&pSrc,0);
0101:     pMeshVB->Lock(0,0,(BYTE**)&pDest,0);
0102:     for(i=0;i<nMeshVertices;i++){
0103:         pDest->x = pSrc->x;
0104:         pDest->y = pSrc->y;
0105:         pDest->z = pSrc->z;
0106:         pDest->nx = pSrc->nx;
0107:         pDest->ny = pSrc->ny;
0108:         pDest->nz = pSrc->nz;
0109: //      pDest->tu1 = pSrc->tu0;
0110: //      pDest->tv1 = pSrc->tv0;
0111:         pSrc += 1;
0112:         pDest += 1;
0113:     }
0114:     pVB->Unlock();
0115:     pVB->Release();
0116:     pMeshVB->Unlock();
0117: 
0118:     //インデックスのコピー
0119:     pMesh->GetIndexBuffer(&pSrcIndex);
0120:     pSrcIndex->Lock(0,0,(BYTE**)&pISrc,0);
0121:     pMeshIndex->Lock(0,0,(BYTE**)&pIDest,0);
0122:     CopyMemory(pIDest,pISrc,nMeshFaces * 3 * sizeof(WORD));
0123:     pSrcIndex->Unlock();
0124:     pMeshIndex->Unlock();
0125:     pSrcIndex->Release();
0126: 
0127:     // pD3DXMtrlBuffer から、質感やテクスチャーの情報を読み取る
0128:     D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
0129:     pMeshTextures = new LPDIRECT3DTEXTURE8[dwNumMaterials];
0130:     pMeshMaterials = new D3DMATERIAL8[dwNumMaterials];
0131: 
0132:     for(i = 0; i < dwNumMaterials; i++){
0133:         pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
0134:         pMeshMaterials[i].Ambient = pMeshMaterials[i].Diffuse;
0135:         hr = D3DXCreateTextureFromFile( lpD3DDEV, 
0136:                                         d3dxMaterials[i].pTextureFilename, 
0137:                                         &pMeshTextures[i] );
0138:         if(FAILED(hr)) pMeshTextures[i] = NULL;
0139:     }
0140:     RELEASE(pD3DXMtrlBuffer);
0141:     
0142:     RELEASE(pMesh);
0143: 
0144:     return S_OK;
0145: }
0146: 
0147: 
0148: // ----------------------------------------------------------------------------
0149: // Name: MakeTexture()
0150: // Desc: テクスチャーの生成
0151: //-----------------------------------------------------------------------------
0152: VOID MakeTexture(D3DXVECTOR4* pOut, D3DXVECTOR2 *pTexCoord, D3DXVECTOR2 *pTexelSize, LPVOID pData)
0153: {
0154:     const int num = 16; // 縦に並んだ円の個数
0155:     const float grid_size = 1.0f/((float)num);  // 円の直径
0156: 
0157:     float shade=1.0f;
0158:     float dx, dy, r2;
0159: 
0160:     dx = pTexCoord->x/(0.5f*grid_size) - 0.0f;
0161:     dy = pTexCoord->y/(0.5f*grid_size) - 0.0f;
0162:     while(    1.0f<dx) dx -= 2.0f;
0163:     while(dx<-1.0f   ) dx += 2.0f;
0164:     while(    1.0f<dy) dy -= 2.0f;
0165:     while(dy<-1.0f   ) dy += 2.0f;
0166:     r2 = 1.0f-2*(dx*dx+dy*dy);
0167:     if(0.0f< r2)shade -= (float)sqrt(r2);
0168: 
0169:     dx = pTexCoord->x/(0.5f*grid_size) - 1.0f;
0170:     dy = pTexCoord->y/(0.5f*grid_size) - 1.0f;
0171:     while(    1.0f<dx) dx -= 2.0f;
0172:     while(dx<-1.0f   ) dx += 2.0f;
0173:     while(    1.0f<dy) dy -= 2.0f;
0174:     while(dy<-1.0f   ) dy += 2.0f;
0175:     r2 = 1.0f-2*(dx*dx+dy*dy);
0176:     if(0.0f< r2)shade -= (float)sqrt(r2);
0177: 
0178:     if(shade < 0.0f)shade = 0.0f;
0179:     if(1.0f < shade)shade = 1.0f;
0180: 
0181:     pOut->x = shade;
0182:     pOut->y = shade;
0183:     pOut->z = shade;
0184:     pOut->w = 1.0f;
0185: }
0186: // ----------------------------------------------------------------------------
0187: // Name: InitRender()
0188: // Desc: ポリゴンの初期化
0189: //-----------------------------------------------------------------------------
0190: HRESULT InitRender(LPDIRECT3DDEVICE8 lpD3DDEV)
0191: {
0192:     HRESULT hr;
0193: 
0194:     hr = LoadXFile("nsx.x", lpD3DDEV);
0195:     if ( FAILED(hr) ) return hr;
0196:  
0197:     // ツゥーンテクスチャーの読み込み
0198:     D3DXCreateTextureFromFileEx(lpD3DDEV, "toon.bmp",0,0,0,0,D3DFMT_A8R8G8B8,
0199:                                 D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR,
0200:                                 0, NULL, NULL, &pToonTexture);
0201:     // トーンテクスチャーの生成
0202:     if( FAILED(hr = lpD3DDEV->CreateTexture(256, 256, 1 ,D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pToneTexture))) return hr;
0203:     if( FAILED(hr = D3DXFillTexture(pToneTexture, MakeTexture, NULL))) return hr;
0204: 
0205:     // バーテックスシェーダーを作成する
0206:     LPD3DXBUFFER    pshader;
0207:     hr = D3DXAssembleShaderFromFile("vs.vsh", 0,NULL,&pshader,NULL);
0208:     if ( FAILED(hr) ) return hr;
0209:     hr = lpD3DDEV->CreateVertexShader( dwDecl, (DWORD*)pshader->GetBufferPointer(), &hVertexShader, 0 );
0210:     RELEASE(pshader);
0211:     if ( FAILED(hr) ) return hr;
0212: 
0213:     // ピクセルシェーダーを作成する
0214:     hr = D3DXAssembleShaderFromFile("ps.psh", 0,NULL, &pshader, NULL);
0215:     if ( FAILED(hr) ) return hr;
0216:     hr = lpD3DDEV->CreatePixelShader( (DWORD*)pshader->GetBufferPointer(), &hPixelShader);
0217:     RELEASE(pshader);
0218:     if ( FAILED(hr) ) return hr;
0219: 
0220: 
0221:     
0222:     // レンダリングの状態の設定
0223:     lpD3DDEV->SetRenderState( D3DRS_ZENABLE, TRUE);
0224:     lpD3DDEV->SetRenderState( D3DRS_AMBIENT, 0xff808080);
0225:     
0226:     lpD3DDEV->SetTextureStageState(0,D3DTSS_COLOROP,    D3DTOP_MODULATE);
0227:     lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG1,  D3DTA_TEXTURE);
0228:     lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG2,  D3DTA_DIFFUSE);
0229:     lpD3DDEV->SetTextureStageState(0,D3DTSS_MAGFILTER,  D3DTEXF_LINEAR);
0230:     lpD3DDEV->SetTextureStageState(0,D3DTSS_MINFILTER,  D3DTEXF_LINEAR);
0231:     lpD3DDEV->SetTextureStageState(0,D3DTSS_ADDRESSU,   D3DTADDRESS_CLAMP);
0232: 
0233:     lpD3DDEV->SetRenderState(D3DRS_WRAP1, D3DWRAP_U | D3DWRAP_V);
0234:     lpD3DDEV->SetTextureStageState(1,D3DTSS_COLOROP,D3DTOP_MODULATE);
0235:     lpD3DDEV->SetTextureStageState(1,D3DTSS_COLORARG1,D3DTA_TEXTURE);
0236:     lpD3DDEV->SetTextureStageState(1,D3DTSS_COLORARG2,D3DTA_CURRENT);
0237:     lpD3DDEV->SetTextureStageState(1,D3DTSS_MAGFILTER,D3DTEXF_LINEAR);
0238:     lpD3DDEV->SetTextureStageState(1,D3DTSS_MINFILTER,D3DTEXF_LINEAR);
0239:     lpD3DDEV->SetTextureStageState(1,D3DTSS_ADDRESSU,   D3DTADDRESS_WRAP );
0240:     lpD3DDEV->SetTextureStageState(1,D3DTSS_ADDRESSV,   D3DTADDRESS_WRAP );
0241: 
0242:     return S_OK;
0243: }
0244: // ----------------------------------------------------------------------------
0245: // Name: Render()
0246: // Desc: ポリゴンの描画
0247: //-----------------------------------------------------------------------------
0248: void Render(LPDIRECT3DDEVICE8 lpD3DDEV)
0249: {
0250:     if(NULL == pMeshVB) return;
0251:     
0252:     D3DXMATRIX mWorld, mView, mProj;
0253: 
0254:     D3DXMatrixRotationY( &mWorld, timeGetTime()/1000.0f );
0255: //    D3DXMatrixRotationY( &mWorld, -D3DX_PI*4/5 );
0256:     
0257:     D3DXVECTOR3 eye, lookAt, up;
0258:     eye.x    = 0.0f; eye.y    = 10.00f; eye.z   = 28.0f;
0259:     lookAt.x = 0.0f; lookAt.y = 0.0f; lookAt.z = 0.0f;
0260:     up.x     = 0.0f; up.y     = 1.0f; up.z     = 0.0f;
0261:     D3DXMatrixLookAtLH(&mView, &eye, &lookAt, &up);
0262:     
0263:     D3DXMatrixPerspectiveFovLH(&mProj
0264:         ,60.0f*PI/180.0f                        // 視野角
0265:         ,(float)WIDTH/(float)HEIGHT             // アスペクト比
0266:         ,0.01f                                  // 最近接距離
0267:         ,100.0f                                 // 最遠方距離
0268:         );
0269:     D3DXMATRIX  m = mWorld * mView * mProj;
0270:     D3DXMatrixTranspose( &m ,  &m);
0271:     lpD3DDEV->SetVertexShaderConstant(0,&m, 4);
0272:     D3DXMatrixTranspose( &m ,  &mWorld);
0273:     lpD3DDEV->SetVertexShaderConstant(4, &m, 4);
0274:     D3DXMatrixInverse( &m,  NULL, &mWorld);
0275:     lpD3DDEV->SetVertexShaderConstant(8, &m, 4);
0276: 
0277:     lpD3DDEV->SetVertexShaderConstant(12, D3DXVECTOR4(0.0f, 0.5f, 1.0f, 3.0f), 1);
0278: 
0279:     D3DXVECTOR4 lightDir(1.0f, 1.0f, 0.5f, 0.0f);
0280:     D3DXVec4Normalize(&lightDir, &lightDir);
0281:     D3DXMatrixInverse( &m,  NULL, &mWorld);
0282:     D3DXVec4Transform(&lightDir, &lightDir, &m);
0283:     lightDir[3] = 0.1f;// 環境光の強さ
0284:     lpD3DDEV->SetVertexShaderConstant(13, &lightDir, 1);
0285: 
0286:     lpD3DDEV->SetVertexShader(hVertexShader);
0287:     lpD3DDEV->SetPixelShader ( hPixelShader);
0288:     lpD3DDEV->SetTexture(0,pToonTexture);
0289:     lpD3DDEV->SetTexture(1,pToneTexture);
0290: 
0291:     //メッシュの描画
0292:     lpD3DDEV->SetStreamSource(0, pMeshVB, sizeof(D3D_CUSTOMVERTEX));
0293:     lpD3DDEV->SetIndices(pMeshIndex,0);
0294:     
0295:     for(DWORD i=0;i<dwNumMaterials;i++){
0296:         //色をセット
0297:         D3DXVECTOR4 vl;
0298:         vl.x = pMeshMaterials[i].Diffuse.r;
0299:         vl.y = pMeshMaterials[i].Diffuse.g;
0300:         vl.z = pMeshMaterials[i].Diffuse.b;
0301:         lpD3DDEV->SetVertexShaderConstant(15,&vl,1);
0302: 
0303:         lpD3DDEV->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 
0304:                                         pSubsetTable[i].VertexStart,
0305:                                         pSubsetTable[i].VertexCount,
0306:                                         pSubsetTable[i].FaceStart * 3,
0307:                                         pSubsetTable[i].FaceCount);
0308:     }
0309:     
0310:     // 描画した画面をテクスチャーとして描く
0311:     {
0312:         struct TLVERTEX
0313:         {
0314:             float x,y,z,rhw;
0315:             D3DCOLOR color;
0316:             float tu,tv;
0317:         };
0318:         #define FVF_TLVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)
0319:         
0320:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLOROP,    D3DTOP_SELECTARG1);
0321:         lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG1,  D3DTA_TEXTURE);
0322:         lpD3DDEV->SetTextureStageState(1,D3DTSS_COLOROP,    D3DTOP_DISABLE );
0323:         TLVERTEX Vertex[4] = {
0324:             // x  y  z rhw           color                     tu tv
0325:             {  0,  0,0, 1, D3DCOLOR_ARGB( 255, 255, 255, 255 ), 0, 0,},
0326:             { 64,  0,0, 1, D3DCOLOR_ARGB( 255, 255, 255, 255 ), 0.25f, 0,},
0327:             { 64, 64,0, 1, D3DCOLOR_ARGB( 255, 255, 255, 255 ), 0.25f, 0.25f,},
0328:             {  0, 64,0, 1, D3DCOLOR_ARGB( 255, 255, 255, 255 ), 0, 0.25f,},
0329:         };
0330:         lpD3DDEV->SetPixelShader (0);
0331:         lpD3DDEV->SetVertexShader( FVF_TLVERTEX );
0332:         lpD3DDEV->SetTexture( 0, pToneTexture );
0333:         lpD3DDEV->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, Vertex, sizeof( TLVERTEX ) );
0334:     }
0335:     lpD3DDEV->SetTexture(0, NULL);
0336: }
0337: //-----------------------------------------------------------------------------
0338: // メッシュオブジェクト削除
0339: //-----------------------------------------------------------------------------
0340: void DeleteMeshObject(void)
0341: {
0342:     DWORD i;
0343: 
0344:     if(pMeshVB == NULL) return;
0345: 
0346:     for(i=0; i<dwNumMaterials; i++){
0347:         RELEASE(pMeshTextures[i]);
0348:     }
0349:     delete[] pMeshTextures;
0350:     delete[] pMeshMaterials;
0351:     delete[] pSubsetTable;
0352: 
0353:     RELEASE(pMeshVB);
0354:     RELEASE(pMeshIndex);
0355: }
0356: //-----------------------------------------------------------------------------
0357: // Name: CleanRender()
0358: // Desc: 後始末
0359: //-----------------------------------------------------------------------------
0360: void CleanRender(LPDIRECT3DDEVICE8 lpD3DDEV)
0361: {
0362:     DeleteMeshObject();
0363:     
0364:     if ( hPixelShader != ~0 ){
0365:         lpD3DDEV->DeleteVertexShader( hPixelShader );
0366:         hPixelShader = ~0;
0367:     }
0368:     if ( hVertexShader != ~0 ){
0369:         lpD3DDEV->DeleteVertexShader( hVertexShader );
0370:         hVertexShader = ~0;
0371:     }
0372:     
0373:     RELEASE(pToneTexture);
0374:     RELEASE(pToonTexture);
0375: }
0376: