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: