0001:
0002:
0003:
0004:
0005:
0006:
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: LPDIRECT3DTEXTURE8 pTexture = NULL;
0031:
0032:
0033:
0034:
0035: typedef struct {
0036: float x,y,z;
0037: float nx,ny,nz;
0038: float tu0,tv0;
0039: }D3DVERTEX;
0040: #define D3DFVF_VERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
0041:
0042: typedef struct {
0043: float x,y,z;
0044: float nx,ny,nz;
0045: float tu0,tv0;
0046: }D3D_CUSTOMVERTEX;
0047: #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
0048:
0049: DWORD dwDecl[] = {
0050: D3DVSD_STREAM(0),
0051: D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3 ),
0052: D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3 ),
0053: D3DVSD_REG(D3DVSDE_TEXCOORD0,D3DVSDT_FLOAT2 ),
0054: D3DVSD_END()
0055: };
0056:
0057:
0058: static void frame_back_init(LPDIRECT3DDEVICE8 lpD3DDEV);
0059: static void frame_back_draw(LPDIRECT3DDEVICE8 lpD3DDEV);
0060:
0061:
0062:
0063:
0064:
0065:
0066: HRESULT LoadXFile(char* filename, LPDIRECT3DDEVICE8 lpD3DDEV)
0067: {
0068: LPD3DXMESH pMesh, pMeshOpt;
0069: LPD3DXBUFFER pD3DXMtrlBuffer = NULL;
0070: DWORD i;
0071: HRESULT hr;
0072:
0073: hr = D3DXLoadMeshFromX(filename, D3DXMESH_MANAGED,
0074: lpD3DDEV, NULL,
0075: &pD3DXMtrlBuffer, &dwNumMaterials,
0076: &pMesh);
0077: if(FAILED(hr)) return E_FAIL;
0078:
0079:
0080: pMesh->Optimize(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL, &pMeshOpt);
0081: RELEASE(pMesh);
0082:
0083:
0084: pMeshOpt->GetAttributeTable(NULL,&dwNumMaterials);
0085: pSubsetTable = new D3DXATTRIBUTERANGE[dwNumMaterials];
0086: pMeshOpt->GetAttributeTable(pSubsetTable, &dwNumMaterials);
0087:
0088:
0089: hr = pMeshOpt->CloneMeshFVF(pMeshOpt->GetOptions(), D3DFVF_VERTEX, lpD3DDEV, &pMesh);
0090: if(FAILED(hr)) return E_FAIL;
0091: RELEASE(pMeshOpt);
0092: D3DXComputeNormals(pMesh);
0093:
0094:
0095: D3DVERTEX* pSrc;
0096: D3D_CUSTOMVERTEX* pDest;
0097: LPDIRECT3DINDEXBUFFER8 pSrcIndex;
0098: WORD* pISrc;
0099: WORD* pIDest;
0100:
0101: DWORD nMeshVertices = pMesh->GetNumVertices();
0102: DWORD nMeshFaces = pMesh->GetNumFaces();
0103: lpD3DDEV->CreateVertexBuffer(nMeshVertices * sizeof(D3D_CUSTOMVERTEX),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_MANAGED,&pMeshVB);
0104: lpD3DDEV->CreateIndexBuffer(nMeshFaces * 3 * sizeof(WORD),0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&pMeshIndex);
0105:
0106: LPDIRECT3DVERTEXBUFFER8 pVB;
0107: pMesh->GetVertexBuffer(&pVB);
0108: pVB->Lock(0,0,(BYTE**)&pSrc,0);
0109: pMeshVB->Lock(0,0,(BYTE**)&pDest,0);
0110: for(i=0;i<nMeshVertices;i++){
0111: pDest->x = pSrc->x;
0112: pDest->y = pSrc->y;
0113: pDest->z = pSrc->z;
0114: pDest->nx = pSrc->nx;
0115: pDest->ny = pSrc->ny;
0116: pDest->nz = pSrc->nz;
0117: pDest->tu0 = pSrc->tu0;
0118: pDest->tu0 = pSrc->tu0;
0119: pSrc += 1;
0120: pDest += 1;
0121: }
0122: pVB->Unlock();
0123: pVB->Release();
0124: pMeshVB->Unlock();
0125:
0126:
0127: pMesh->GetIndexBuffer(&pSrcIndex);
0128: pSrcIndex->Lock(0,0,(BYTE**)&pISrc,0);
0129: pMeshIndex->Lock(0,0,(BYTE**)&pIDest,0);
0130: CopyMemory(pIDest,pISrc,nMeshFaces * 3 * sizeof(WORD));
0131: pSrcIndex->Unlock();
0132: pMeshIndex->Unlock();
0133: pSrcIndex->Release();
0134:
0135:
0136: D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
0137: pMeshTextures = new LPDIRECT3DTEXTURE8[dwNumMaterials];
0138: pMeshMaterials = new D3DMATERIAL8[dwNumMaterials];
0139:
0140: for(i = 0; i < dwNumMaterials; i++){
0141: pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
0142: pMeshMaterials[i].Ambient = pMeshMaterials[i].Diffuse;
0143: hr = D3DXCreateTextureFromFile( lpD3DDEV,
0144: d3dxMaterials[i].pTextureFilename,
0145: &pMeshTextures[i] );
0146: if(FAILED(hr)) pMeshTextures[i] = NULL;
0147: }
0148: RELEASE(pD3DXMtrlBuffer);
0149:
0150: RELEASE(pMesh);
0151:
0152: return S_OK;
0153: }
0154:
0155:
0156:
0157:
0158: HRESULT LoadVertexShader(char* filename, LPDIRECT3DDEVICE8 lpD3DDEV, DWORD *phVertexShader, const DWORD *dwDecl)
0159: {
0160: HRESULT hr;
0161: ID3DXBuffer *pshader;
0162:
0163: if ( FAILED(hr = D3DXAssembleShaderFromFile(filename, 0,NULL,&pshader,NULL)) ) return hr;
0164:
0165: hr = lpD3DDEV->CreateVertexShader( dwDecl, (DWORD*)pshader->GetBufferPointer(), phVertexShader, 0 );
0166: RELEASE(pshader);
0167: if ( FAILED(hr) ) return hr;
0168:
0169: return S_OK;
0170: }
0171:
0172:
0173:
0174:
0175: HRESULT InitRender(LPDIRECT3DDEVICE8 lpD3DDEV)
0176: {
0177: HRESULT hr;
0178:
0179:
0180: if ( FAILED(hr = LoadXFile("nsx.x", lpD3DDEV)) ) return hr;
0181:
0182:
0183: D3DXCreateTextureFromFileEx(lpD3DDEV, "light.bmp",0,0,0,0,D3DFMT_A8R8G8B8,
0184: D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR,
0185: 0, NULL, NULL, &pTexture);
0186:
0187:
0188:
0189: if ( FAILED(hr = LoadVertexShader("vs.vsh", lpD3DDEV, &hVertexShader, dwDecl)) ) return hr;
0190:
0191:
0192: lpD3DDEV->SetRenderState( D3DRS_ZENABLE, TRUE);
0193:
0194: frame_back_init(lpD3DDEV);
0195: return S_OK;
0196: }
0197:
0198:
0199:
0200:
0201: void Render(LPDIRECT3DDEVICE8 lpD3DDEV)
0202: {
0203: if(NULL == pMeshVB) return;
0204:
0205: D3DVIEWPORT8 viewport={WIN_X, WIN_Y, WIN_W, WIN_H, 0.0f, 0.0f};
0206: D3DVIEWPORT8 viewport_bak;
0207: lpD3DDEV->GetViewport(&viewport_bak);
0208:
0209: lpD3DDEV->SetTextureStageState(0,D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
0210: lpD3DDEV->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
0211: lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE);
0212: lpD3DDEV->SetTextureStageState(0,D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
0213: lpD3DDEV->SetTextureStageState(0,D3DTSS_MINFILTER, D3DTEXF_LINEAR);
0214: lpD3DDEV->SetTextureStageState(1,D3DTSS_COLOROP,D3DTOP_MODULATE);
0215: lpD3DDEV->SetTextureStageState(1,D3DTSS_COLORARG1,D3DTA_TEXTURE);
0216: lpD3DDEV->SetTextureStageState(1,D3DTSS_COLORARG2,D3DTA_CURRENT);
0217: lpD3DDEV->SetTextureStageState(1,D3DTSS_MAGFILTER,D3DTEXF_LINEAR);
0218: lpD3DDEV->SetTextureStageState(1,D3DTSS_MINFILTER,D3DTEXF_LINEAR);
0219:
0220: for(int n = 0; n < 2; n++){
0221: D3DXMATRIX mWorld, mView, mProj, m;
0222:
0223: D3DXMatrixRotationY( &mWorld, timeGetTime()/1000.0f );
0224:
0225: D3DXVECTOR3 eye, lookAt, up;
0226: eye.x = 0.0f; eye.y = 10.0f; eye.z = 30.0f;
0227: lookAt.x = 0.0f; lookAt.y = 3.0f; lookAt.z = 0.0f;
0228: up.x = 0.0f; up.y = 1.0f; up.z = 0.0f;
0229: if(1 == n){
0230:
0231: eye.z = -30.0f;
0232: D3DXMatrixLookAtLH(&mView, &eye, &lookAt, &up);
0233: D3DXMatrixIdentity(&m);
0234: m(0,0)=-1.0f;
0235: mView = m * mView;
0236: D3DXMatrixPerspectiveFovLH(&mProj
0237: ,20.0f*PI/180.0f
0238: ,(float)WIN_W/(float)WIN_H
0239: ,0.01f
0240: ,100.0f
0241: );
0242: }else{
0243: D3DXMatrixLookAtLH(&mView, &eye, &lookAt, &up);
0244: D3DXMatrixPerspectiveFovLH(&mProj
0245: ,60.0f*PI/180.0f
0246: ,(float)WIDTH/(float)HEIGHT
0247: ,0.01f
0248: ,100.0f
0249: );
0250: }
0251: m = mWorld * mView * mProj;
0252: D3DXMatrixTranspose( &m , &m);
0253: lpD3DDEV->SetVertexShaderConstant(0,&m, 4);
0254:
0255: D3DXVECTOR4 lightDir(1.0f, 1.0f, 0.5f, 0.0f);
0256: D3DXVec4Normalize(&lightDir, &lightDir);
0257: D3DXMatrixInverse( &m, NULL, &mWorld);
0258: D3DXVec4Transform(&lightDir, &lightDir, &m);
0259: lpD3DDEV->SetVertexShaderConstant(13, &lightDir, 1);
0260: lpD3DDEV->SetVertexShaderConstant(12, D3DXVECTOR4(0.0f, 0.5f, 1.0f, 2.0f), 1);
0261:
0262: lpD3DDEV->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
0263: lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE);
0264: lpD3DDEV->SetVertexShader(hVertexShader);
0265: lpD3DDEV->SetTexture(0,pTexture);
0266:
0267:
0268: lpD3DDEV->SetStreamSource(0, pMeshVB, sizeof(D3D_CUSTOMVERTEX));
0269: lpD3DDEV->SetIndices(pMeshIndex,0);
0270: for(DWORD i=0;i<dwNumMaterials;i++){
0271: #if 0
0272:
0273: D3DXVECTOR4 vl;
0274: vl.x = pMeshMaterials[i].Diffuse.r;
0275: vl.y = pMeshMaterials[i].Diffuse.g;
0276: vl.z = pMeshMaterials[i].Diffuse.b;
0277: lpD3DDEV->SetVertexShaderConstant(14, &vl, 1);
0278: #endif
0279: lpD3DDEV->SetTexture(1,pMeshTextures[i]);
0280: lpD3DDEV->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
0281: pSubsetTable[i].VertexStart,
0282: pSubsetTable[i].VertexCount,
0283: pSubsetTable[i].FaceStart * 3,
0284: pSubsetTable[i].FaceCount);
0285: }
0286: if(n==0){
0287: frame_back_draw(lpD3DDEV);
0288: lpD3DDEV->SetViewport(&viewport);
0289: lpD3DDEV->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
0290: }else{
0291: lpD3DDEV->SetViewport(&viewport_bak);
0292: lpD3DDEV->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
0293: }
0294: }
0295:
0296: lpD3DDEV->SetTexture(0, NULL);
0297: lpD3DDEV->SetTexture(1, NULL);
0298: }
0299:
0300:
0301:
0302: LPDIRECT3DVERTEXBUFFER8 pFrameBackVB = NULL;
0303: typedef struct{
0304: FLOAT x, y, z, rhw;
0305: DWORD color;
0306: }FRAME_BACK_VERTEX;
0307: #define D3DFVF_FRAME_BACK_VERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
0308:
0309: static void frame_back_init(LPDIRECT3DDEVICE8 lpD3DDEV)
0310: {
0311: FRAME_BACK_VERTEX vertices[] = {
0312:
0313: {WIN_X -1, WIN_Y -1, 0.0f, 1.0f, D3DCOLOR_RGBA(0x00, 0xff, 0xff, 0xff), },
0314: {WIN_X+WIN_W+1, WIN_Y -1, 0.0f, 1.0f, D3DCOLOR_RGBA(0x00, 0xff, 0xff, 0xff), },
0315: {WIN_X -1, WIN_Y+WIN_H+1, 0.0f, 1.0f, D3DCOLOR_RGBA(0x00, 0xff, 0xff, 0xff), },
0316: {WIN_X+WIN_W+1, WIN_Y+WIN_H+1, 0.0f, 1.0f, D3DCOLOR_RGBA(0x00, 0xff, 0xff, 0xff), },
0317: };
0318: RELEASE(pFrameBackVB);
0319: if(FAILED(lpD3DDEV->CreateVertexBuffer( sizeof(vertices),0,
0320: D3DFVF_FRAME_BACK_VERTEX, D3DPOOL_DEFAULT, &pFrameBackVB))) return;
0321: VOID* pVertices;
0322: if(FAILED(pFrameBackVB->Lock( 0, sizeof(vertices), (BYTE**)&pVertices, 0))) return;
0323: memcpy( pVertices, vertices, sizeof(vertices) );
0324: pFrameBackVB->Unlock();
0325: }
0326:
0327: static void frame_back_draw(LPDIRECT3DDEVICE8 lpD3DDEV)
0328: {
0329: lpD3DDEV->SetRenderState( D3DRS_ZENABLE, FALSE);
0330:
0331: lpD3DDEV->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
0332: lpD3DDEV->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_DIFFUSE);
0333:
0334: lpD3DDEV->SetStreamSource( 0, pFrameBackVB, sizeof(FRAME_BACK_VERTEX) );
0335: lpD3DDEV->SetVertexShader( D3DFVF_FRAME_BACK_VERTEX );
0336: lpD3DDEV->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
0337:
0338: lpD3DDEV->SetRenderState( D3DRS_ZENABLE, TRUE);
0339: }
0340:
0341: static void frame_back_clean()
0342: {
0343: RELEASE(pFrameBackVB);
0344: }
0345:
0346:
0347:
0348: void DeleteMeshObject(void)
0349: {
0350: DWORD i;
0351:
0352: if(pMeshVB == NULL) return;
0353:
0354: for(i=0; i<dwNumMaterials; i++){
0355: RELEASE(pMeshTextures[i]);
0356: }
0357: delete[] pMeshTextures;
0358: delete[] pMeshMaterials;
0359: delete[] pSubsetTable;
0360:
0361: RELEASE(pMeshVB);
0362: RELEASE(pMeshIndex);
0363: }
0364:
0365:
0366:
0367:
0368: void CleanRender(LPDIRECT3DDEVICE8 lpD3DDEV)
0369: {
0370: DeleteMeshObject();
0371:
0372: if ( hVertexShader != ~0 ){
0373: lpD3DDEV->DeleteVertexShader( hVertexShader );
0374: hVertexShader = ~0;
0375: }
0376:
0377: RELEASE(pTexture);
0378: frame_back_clean();
0379: }
0380: