#include "dxstdafx.h" #include "OceanEffect.h" #include "waves.h" OceanEffect::OceanEffect(LPDIRECT3DDEVICE9 device) { this->device = device; D3DXCreateSprite( device, &g_pTextSprite ); DXUTGetGlobalResourceCache().CreateFont( device, 15, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial", &g_pFont ); nShips = 2; D3DXCreateTextureFromFile(device, L"waves2.dds", &waterTexture); D3DXCreateTextureFromFile(device, L"moonbase3.bmp", &elevationTexture); D3DXCreateCubeTextureFromFile(device, L"CloudyHillsCubemap2.dds", &environmentCube); camera = new CFirstPersonCamera(); camera->SetViewParams( &D3DXVECTOR3(0.0f, 0.0f, 4.0f), &D3DXVECTOR3(0.0f, 0.0f, 0.0f)); camera->SetProjParams(D3DX_PI/4, 1.0f, 0.1f, 1000.0f); device->CreateIndexBuffer(sizeof(short) * 3 * 2 * 127 * 127, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &oceanIndexBuffer, NULL); device->CreateVertexBuffer(sizeof(float) * 3 * 128 * 128, D3DUSAGE_WRITEONLY, D3DFVF_XYZ, D3DPOOL_DEFAULT, &oceanVertexBuffer, NULL); short* indexData; oceanIndexBuffer->Lock(0, sizeof(short) * 3 * 2 * 127 * 127, (void**)&indexData, 0); for(int i=0; i<127; i++) for(int j=0; j<127; j++) { indexData[ (i * 127 + j) * 6] = i * 128 + j; indexData[ (i * 127 + j) * 6 + 2] = i * 128 + j + 1; indexData[ (i * 127 + j) * 6 + 1] = (i + 1) * 128 + j; indexData[ (i * 127 + j) * 6 + 4] = i * 128 + j + 1; indexData[ (i * 127 + j) * 6 + 5] = (i + 1) * 128 + j; indexData[ (i * 127 + j) * 6 + 3] = (i + 1) * 128 + j + 1; } oceanIndexBuffer->Unlock(); float* vertexData; oceanVertexBuffer->Lock(0, sizeof(float) * 3 * 128 * 128, (void**)&vertexData, 0); for(int i=0; i<128; i++) for(int j=0; j<128; j++) { vertexData[ (i * 128 + j) * 3] = (float)j / 127; vertexData[ (i * 128 + j) * 3 + 1] = (float)0; vertexData[ (i * 128 + j) * 3 + 2] = (float)i/127; } oceanVertexBuffer->Unlock(); //creating the effect: LPD3DXBUFFER pBufferErrors = NULL; HRESULT hr = D3DXCreateEffectFromFile(device, L"ocean.fx", NULL, NULL, 0, NULL, &effect, &pBufferErrors); if( FAILED(hr)) { LPVOID pCompilErrors = pBufferErrors->GetBufferPointer(); MessageBoxA(NULL, (const char*)pCompilErrors, "Fx Compile Error", MB_OK|MB_ICONEXCLAMATION); exit(-1); return; } //loading the x file: hr = D3DXLoadMeshFromX( L"ship_model\\ketch.x", // L"ship_model\\unitsphere.x", D3DXMESH_MANAGED, device, &adjBuffer, &mtrlBuffer, 0, &numMtrls, &ship); LPD3DXMESH clonedShip; ship->CloneMeshFVF(ship->GetOptions(), D3DFVF_XYZ | D3DFVF_NORMAL, device, &clonedShip); ship->Release(); ship = clonedShip; if( mtrlBuffer != 0 && numMtrls != 0 ) { D3DXMATERIAL* mtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer(); for(int i = 0; i < numMtrls; i++) { mtrls[i].MatD3D.Ambient = mtrls[i].MatD3D.Diffuse; Mtrls.push_back( mtrls[i].MatD3D ); if( mtrls[i].pTextureFilename != 0 ) { IDirect3DTexture9* tex = 0; D3DXCreateTextureFromFile( device, //mtrls[i].pTextureFilename, NULL, &tex); textures.push_back( tex ); } else { textures.push_back( 0 ); } } } mtrlBuffer->Release(); /* hr = D3DXLoadMeshFromX(L"ship_model\\ketch.x", NULL, device, NULL, NULL, NULL, NULL, &ship); if( FAILED(hr)) { MessageBoxA(NULL, (const char*)"Can't load the ship container file", "Loading the Mesh has failed", MB_OK|MB_ICONEXCLAMATION); exit(-1); return; }*/ D3DVERTEXELEMENT9 shipElement[] = { {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1}, {1, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2}, D3DDECL_END()}; ships[0].direction = D3DXVECTOR2(1,0); ships[0].position = D3DXVECTOR2(0,0); ships[1].direction = D3DXVECTOR2(.7,0.7); ships[1].position = D3DXVECTOR2(50,15); HRESULT hrr = device->CreateVertexDeclaration(shipElement, &shipDeclaration); device->CreateVertexBuffer(MAXSHIPS * sizeof(float) * 3 * 3, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &instanceVertexBuffer, NULL); ship->GetVertexBuffer(&shipVertexBuffer); ship->GetIndexBuffer(&shipIndexBuffer); applyShip(); //optimizing the mesh: //ship->OptimizeInplace(D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE | D3DXMESHOPT_STRIPREORDER, NULL, NULL, NULL, NULL); D3DXMATRIX rotationMatrix, translationMatrix; D3DXMatrixRotationX(&rotationMatrix, 4.7123); //rotating 270 degrees D3DXMatrixTranslation(&translationMatrix, 0, 1, 0.0); //translating one unit up D3DXMatrixScaling(&downScale, .01,.01,.01); D3DXMatrixMultiply(&finalWorld, &rotationMatrix, &downScale); D3DXMatrixMultiply(&finalWorld, &finalWorld, &translationMatrix); //applying the model transformations /* D3DXMATRIX rotationMatrix, translationMatrix, ssm; D3DXMatrixIdentity(&finalWorld); D3DXMatrixTranslation(&translationMatrix, 0, 0.6, 0.0); //translating one unit up D3DXMatrixMultiply(&finalWorld, &finalWorld, &translationMatrix); double fp = 0.1, bp = 2.1; D3DXMATRIX sphereToShip(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, (bp + fp)/(bp-fp), 0.0f, 1.0f , 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, -2.0 * bp * fp / (bp-fp), 0.0f, 0.0f); D3DXMatrixMultiply(&finalWorld, &finalWorld, &sphereToShip); D3DXMatrixTranslation(&translationMatrix, 0, -1.0, 0.0); D3DXMatrixMultiply(&finalWorld, &finalWorld, &translationMatrix); D3DXMatrixScaling(&ssm, 8.0, 10.0, 1.0); D3DXMatrixMultiply(&finalWorld, &finalWorld, &ssm);*/ } OceanEffect::~OceanEffect(void) { if(effect != NULL) effect->Release(); if(shipVertexBuffer != NULL) shipVertexBuffer->Release(); if(shipIndexBuffer != NULL) shipIndexBuffer->Release(); if(oceanIndexBuffer != NULL)oceanIndexBuffer->Release(); if(oceanVertexBuffer != NULL) oceanVertexBuffer->Release(); if(environmentCube != NULL) environmentCube->Release(); if(waterTexture != NULL) waterTexture->Release(); if(elevationTexture != NULL) elevationTexture->Release(); if(ship != NULL) ship->Release(); if(shipDeclaration != NULL) shipDeclaration->Release(); if(instanceVertexBuffer != NULL) instanceVertexBuffer->Release(); if(camera != NULL) delete camera; if(adjBuffer != NULL) adjBuffer->Release(); g_pTextSprite->Release(); g_pFont->Release(); } void OceanEffect::render() { device->SetRenderState(D3DRS_CULLMODE, NULL); //device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DXCOLOR(0.0,.3,0.7,0), 1.0f, NULL); device->BeginScene(); //displaying the FPS CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 ); txtHelper.Begin(); txtHelper.SetInsertionPos( 5, 5 ); txtHelper.SetForegroundColor( D3DXCOLOR( 0.0f, 5.0f, 1.0f, 1.0f ) ); txtHelper.DrawTextLine( DXUTGetFrameStats(true) ); // Show FPS txtHelper.DrawTextLine( DXUTGetDeviceStats() ); txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) ); txtHelper.End(); effect->SetTechnique("ocean"); UINT nPasses; effect->Begin(&nPasses, 0); effect->BeginPass(0); device->SetIndices(oceanIndexBuffer); device->SetStreamSource(0, oceanVertexBuffer, 0, 3 * sizeof(float)); device->SetFVF(D3DFVF_XYZ); effect->SetFloat("time", time); const D3DXVECTOR3* ep = camera->GetEyePt(); HRESULT hr = effect->SetFloatArray("eyePosition", (float*)ep,3); effect->SetTexture("environmentCubeTexture", environmentCube); effect->SetTexture("waterTexture", waterTexture); D3DXMATRIX viewProjMatrix; D3DXMatrixMultiply(&viewProjMatrix, camera->GetViewMatrix(), camera->GetProjMatrix()); effect->SetMatrix("viewProjMatrix", &viewProjMatrix); D3DXVECTOR3 pushBack = *camera->GetWorldAhead(); float maxDistortion = 0.0; for(int iWave=0; iWaveSetFloatArray("eyePositionPushedBack", (float*)&epPushedBack,3); worldCornerCar0 = worldCornerCar0 - epPushedBack; D3DXVec3Normalize(&worldCornerCar0, &worldCornerCar0); worldCornerCar1 = worldCornerCar1 - epPushedBack; D3DXVec3Normalize(&worldCornerCar1, &worldCornerCar1); worldCornerCar2 = worldCornerCar2 - epPushedBack; D3DXVec3Normalize(&worldCornerCar2, &worldCornerCar2); worldCornerCar3 = worldCornerCar3 - epPushedBack; D3DXVec3Normalize(&worldCornerCar3, &worldCornerCar3); if(ep->y > 0) { if(worldCornerCar2.y > 0 && worldCornerCar0.y < 0) worldCornerCar2 += (worldCornerCar0 - worldCornerCar2) * (worldCornerCar2.y - worldCornerCar0.y / 40.0) / (-worldCornerCar0.y + worldCornerCar2.y); if(worldCornerCar3.y > 0 && worldCornerCar1.y < 0) worldCornerCar3 += (worldCornerCar1 - worldCornerCar3) * (worldCornerCar3.y - worldCornerCar1.y / 40.0) / (-worldCornerCar1.y + worldCornerCar3.y); // if(worldCornerCar2.y > 0 && worldCornerCar0.y < 0) worldCornerCar2.y = worldCornerCar0.y / 40.0; // if(worldCornerCar3.y > 0 && worldCornerCar1.y < 0) worldCornerCar3.y = worldCornerCar1.y / 40.0; } else { if(worldCornerCar2.y < 0 && worldCornerCar0.y > 0) worldCornerCar0.y = worldCornerCar2.y / 40.0; if(worldCornerCar3.y < 0 && worldCornerCar1.y > 0) worldCornerCar1.y = worldCornerCar3.y / 40.0; } /* if(worldCornerCar0.y > horizon) worldCornerCar0.y = horizon; if(worldCornerCar1.y > horizon) worldCornerCar1.y = horizon; if(worldCornerCar2.y > horizon) worldCornerCar2.y = horizon; if(worldCornerCar3.y > horizon) worldCornerCar3.y = horizon;*/ /* worldCornerCar0 = epPushedBack - (epPushedBack.y/worldCornerCar0.y) * worldCornerCar0; worldCornerCar1 = epPushedBack - (epPushedBack.y/worldCornerCar1.y) * worldCornerCar1; worldCornerCar2 = epPushedBack - (epPushedBack.y/worldCornerCar2.y) * worldCornerCar2; worldCornerCar3 = epPushedBack - (epPushedBack.y/worldCornerCar3.y) * worldCornerCar3;*/ effect->SetFloatArray("worldCornerCar0", (float*)&worldCornerCar0,3); effect->SetFloatArray("worldCornerCar1", (float*)&worldCornerCar1,3); effect->SetFloatArray("worldCornerCar2", (float*)&worldCornerCar2,3); effect->SetFloatArray("worldCornerCar3", (float*)&worldCornerCar3,3); //setting the scale parameter: D3DXMatrixMultiply(&shipWorldViewProjMatrix, &finalWorld, &viewProjMatrix); effect->SetMatrix("shipWorldMatrix", &finalWorld); effect->SetMatrix("shipViewProjMatrix", &viewProjMatrix); D3DXVECTOR4 lightPosition = D3DXVECTOR4(10,10,0,0); effect->SetVector("lightPosition", &lightPosition); //set ship positions for reflections for(int iShip=0; iShipSetMatrix(fxvarname, &worldToTangent); } effect->CommitChanges(); device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 128 * 128, 0, 127 * 127*2); effect->EndPass(); effect->End(); /* effect->SetTechnique("terrain"); effect->Begin(&nPasses, 0); effect->BeginPass(0); device->SetIndices(oceanIndexBuffer); device->SetStreamSource(0, oceanVertexBuffer, 0, 3 * sizeof(float)); device->SetFVF(D3DFVF_XYZ); effect->SetTexture("elevationTexture", elevationTexture); effect->SetFloatArray("eyeDirection", (float*)camera->GetWorldAhead(),3); effect->SetFloat("fp", 0.1f); effect->SetFloat("bp", 1000.0f); effect->CommitChanges(); device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 128 * 128, 0, 127 * 127*2); effect->EndPass(); effect->End();*/ hr = effect->SetTechnique("ship"); effect->Begin(&nPasses, 0); effect->BeginPass(0); device->SetStreamSourceFreq(0, D3DSTREAMSOURCE_INDEXEDDATA | nShips); int sss = ship->GetNumBytesPerVertex(); device->SetStreamSource(0, shipVertexBuffer, 0, ship->GetNumBytesPerVertex()); device->SetStreamSourceFreq(1, (unsigned)(D3DSTREAMSOURCE_INSTANCEDATA | 1)); device->SetStreamSource(1, instanceVertexBuffer, 0, sizeof(float) * 3 * 3); device->SetVertexDeclaration(shipDeclaration); device->SetIndices(shipIndexBuffer); device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, ship->GetNumVertices(), 0, ship->GetNumFaces()); effect->EndPass(); effect->End(); device->EndScene(); } void OceanEffect::move(double time, double elapsedTime) { camera->FrameMove(elapsedTime * 10.0); for(int i=0; i< nShips; i++) { ships[i].Move(elapsedTime); } this->time = (float)time; applyShip(); } void OceanEffect::message(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { camera->HandleMessages(hWnd, uMsg, wParam, lParam); if(uMsg == WM_KEYDOWN) { switch(wParam) { case 'U': ships[0].accelerate = true; ships[0].brake = false; break; case 'J': ships[0].accelerate = false; ships[0].brake = true; break; case 'H': ships[0].turnLeft = true; ships[0].turnRight = false; break; case 'K': ships[0].turnLeft = false; ships[0].turnRight = true; break; } } if(uMsg == WM_KEYUP) { switch(wParam) { case 'U' : ships[0].accelerate = false; break; case 'J': ships[0].brake = false; break; case 'H': ships[0].turnLeft = false; break; case 'K': ships[0].turnRight = false; break; } } } void OceanEffect::applyShip() { OceanEffect::ShipInstanceData* tempShips; instanceVertexBuffer->Lock(0, MAXSHIPS * sizeof(float) * 3 * 3, (void**) &tempShips, 0); for(int si=0; siUnlock(); }