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: