📄 blois.cpp
字号:
//-----------------------------------------------------------------------------
// File: bLois.cpp
//
// Desc: DirectX window application created by the DirectX AppWizard
//-----------------------------------------------------------------------------
#define STRICT
#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
#include <basetsd.h>
#include <direct.h>
#include <math.h>
#include <stdio.h>
#include <d3dx9.h>
#include <dxerr9.h>
#include <tchar.h>
#include "DXUtil.h"
#include "D3DEnumeration.h"
#include "D3DSettings.h"
#include "D3DApp.h"
#include "D3DFont.h"
#include "D3DFile.h"
#include "D3DUtil.h"
#include "resource.h"
#include "bLois.h"
#include <algorithm>
#include <functional>
static float RandMinusOneToOne()
{
return float( double(rand()) / double(RAND_MAX) * 2.0 - 1.0 );
}
static float RandZeroToOne()
{
return float( double(rand()) / double(RAND_MAX) );
}
static const float kGravConst = 30.f;
class ClearVert
{
public:
D3DXVECTOR3 m_Pos;
D3DXVECTOR2 m_Uv;
};
static const int kVSize = sizeof(ClearVert);
static const DWORD kClearVertFVF = D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0);
//-----------------------------------------------------------------------------
// Global access to the app (needed for the global WndProc())
//-----------------------------------------------------------------------------
CMyD3DApplication* g_pApp = NULL;
HINSTANCE g_hInst = NULL;
//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Entry point to the program. Initializes everything, and goes into a
// message-processing loop. Idle time is used to render the scene.
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
CMyD3DApplication d3dApp;
g_pApp = &d3dApp;
g_hInst = hInst;
InitCommonControls();
if( FAILED( d3dApp.Create( hInst ) ) )
return 0;
return d3dApp.Run();
}
//-----------------------------------------------------------------------------
// Name: CMyD3DApplication()
// Desc: Application constructor. Paired with ~CMyD3DApplication()
// Member variables should be initialized to a known state here.
// The application window has not yet been created and no Direct3D device
// has been created, so any initialization that depends on a window or
// Direct3D should be deferred to a later stage.
//-----------------------------------------------------------------------------
CMyD3DApplication::CMyD3DApplication()
{
m_dwCreationWidth = 500;
m_dwCreationHeight = 375;
m_strWindowTitle = TEXT( "bLois" );
m_d3dEnumeration.AppUsesDepthBuffer = TRUE;
m_bStartFullscreen = false;
m_bShowCursorWhenFullscreen = false;
m_bShowHelp = false;
m_bSortWater = true;
m_bDrawBump = false;
m_LastToggle = 0.f;
// Create a D3D font using d3dfont.cpp
m_pFont = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
m_bLoadingApp = TRUE;
memset(m_bKey, 0x00, sizeof(m_bKey));
D3DXMatrixIdentity(&m_matView);
D3DXMatrixIdentity(&m_matPosition);
D3DXMatrixIdentity(&m_matProjection);
m_CompCosinesEff = NULL;
m_WaterEff = NULL;
m_WaterMesh = NULL;
m_LandMesh = NULL;
m_PillarsMesh = NULL;
m_EnvMap = NULL;
m_LandTex = NULL;
m_CosineLUT = NULL;
m_BiasNoiseMap = NULL;
m_BumpTex = NULL;
m_BumpSurf = NULL;
m_BumpRender = NULL;
m_BumpVBuffer = NULL;
m_WaterIndices = NULL;
m_WaterFacePos = NULL;
m_WaterSortData = NULL;
ResetWater();
}
//-----------------------------------------------------------------------------
// Name: ~CMyD3DApplication()
// Desc: Application destructor. Paired with CMyD3DApplication()
//-----------------------------------------------------------------------------
CMyD3DApplication::~CMyD3DApplication()
{
delete [] m_WaterIndices;
delete [] m_WaterFacePos;
delete [] m_WaterSortData;
}
//-----------------------------------------------------------------------------
// Name: OneTimeSceneInit()
// Desc: Paired with FinalCleanup().
// The window has been created and the IDirect3D9 interface has been
// created, but the device has not been created yet. Here you can
// perform application-related initialization and cleanup that does
// not depend on a device.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::OneTimeSceneInit()
{
// TODO: perform one time initialization
// Drawing loading status message until app finishes loading
SendMessage( m_hWnd, WM_PAINT, 0, 0 );
m_bLoadingApp = FALSE;
// Misc stuff
D3DXMatrixLookAtLH(&m_matView,
&D3DXVECTOR3(0.f, -150.f, 50.f),
&D3DXVECTOR3(0.f, 0.f, 0.f),
&D3DXVECTOR3(0.f, 0.f, 1.f));
D3DXMatrixInverse(&m_matPosition, NULL, &m_matView);
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: ConfirmDevice()
// Desc: Called during device initialization, this code checks the display device
// for some minimum set of capabilities
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior,
D3DFORMAT Format )
{
UNREFERENCED_PARAMETER( Format );
UNREFERENCED_PARAMETER( dwBehavior );
UNREFERENCED_PARAMETER( pCaps );
BOOL bCapsAcceptable;
// TODO: Perform checks to see if these display caps are acceptable.
bCapsAcceptable = TRUE;
if( bCapsAcceptable )
return S_OK;
else
return E_FAIL;
}
//-----------------------------------------------------------------------------
// Name: InitDeviceObjects()
// Desc: Paired with DeleteDeviceObjects()
// The device has been created. Resources that are not lost on
// Reset() can be created here -- resources in D3DPOOL_MANAGED,
// D3DPOOL_SCRATCH, or D3DPOOL_SYSTEMMEM. Image surfaces created via
// CreateImageSurface are never lost and can be created here. Vertex
// shaders and pixel shaders can also be created here as they are not
// lost on Reset().
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::InitDeviceObjects()
{
// TODO: create device objects
HRESULT hr;
// Init the font
m_pFont->InitDeviceObjects( m_pd3dDevice );
if( FAILED(hr = CreateCosineLUT()) )
return hr;
if( FAILED(hr = CreateBiasNoiseMap()) )
return hr;
if( FAILED(hr = D3DXCreateCubeTextureFromFile( m_pd3dDevice, TEXT("nvlobby_new_cube_mipmap.dds"), &m_EnvMap)) )
return DXTRACE_ERR( "EnvMap load", hr );
if( FAILED(hr = D3DXCreateTextureFromFile( m_pd3dDevice, "Sandy.dds", &m_LandTex)) )
return hr;
if( FAILED(hr = D3DXLoadMeshFromX(TEXT("LandMesh.x"), D3DXMESH_MANAGED, m_pd3dDevice, NULL, NULL, NULL, NULL, &m_LandMesh)) )
return hr;
if( FAILED(hr = D3DXLoadMeshFromX(TEXT("pillars.x"), D3DXMESH_MANAGED, m_pd3dDevice, NULL, NULL, NULL, NULL, &m_PillarsMesh)) )
return hr;
ID3DXMesh* waterMesh = NULL;
if( FAILED(hr = D3DXLoadMeshFromX(TEXT("WaterMesh.x"), D3DXMESH_MANAGED, m_pd3dDevice, NULL, NULL, NULL, NULL, &waterMesh)) )
return hr;
if( FAILED( hr = CreateWaterMesh(waterMesh)) )
return hr;
if( FAILED(hr = CreateClearBuffer()) )
return hr;
LPD3DXBUFFER pBufferErrors = NULL;
if( FAILED( hr = D3DXCreateEffectFromFile( m_pd3dDevice, "CompCosines.fx", NULL, NULL,
0, NULL, &m_CompCosinesEff, &pBufferErrors) ) )
{
char* errStr = (char*)pBufferErrors->GetBufferPointer();
OutputDebugString(errStr);
return hr;
}
GetCompCosineEffParams();
if( FAILED(hr = D3DXCreateEffectFromFile( m_pd3dDevice, "WaterRip.fx", NULL, NULL,
0, NULL, &m_WaterEff, &pBufferErrors) ) )
{
char* errStr = (char*)pBufferErrors->GetBufferPointer();
OutputDebugString(errStr);
return hr;
}
GetWaterParams();
return S_OK;
}
HRESULT CMyD3DApplication::CreateWaterMesh(ID3DXMesh* waterMesh)
{
// All this should happen off line. In particular, note the assumption of even
// spacing in calculating the edge lengths, which defeats the whole purpose.
// Still, it's a demo, not a game.
struct OutVert
{
D3DXVECTOR3 m_Pos;
DWORD m_Color;
};
const DWORD kWaterFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
HRESULT hr = waterMesh->CloneMeshFVF(D3DXMESH_MANAGED,
kWaterFVF,
m_pd3dDevice,
&m_WaterMesh);
SAFE_RELEASE(waterMesh);
if( FAILED(hr) )
return hr;
const int nVerts = m_WaterMesh->GetNumVertices();
OutVert* oVert;
if( FAILED(hr = m_WaterMesh->LockVertexBuffer(0, (void**)&oVert)) )
return hr;
OutVert* origVert = oVert;
D3DXVECTOR3 del = oVert[0].m_Pos - oVert[1].m_Pos;
float dist = D3DXVec3Length(&del);
if( dist < 1.f )
dist = 1.f;
UINT alpha = UINT(255.9f / dist);
int i;
for( i = 0; i < nVerts; i++ )
{
oVert->m_Color = alpha << 24 | 0x00ffffff;
oVert++;
}
oVert = origVert;
const int nFaces = m_WaterMesh->GetNumFaces();
m_WaterIndices = new FaceIndices[nFaces];
m_WaterFacePos = new D3DXVECTOR3[nFaces];
m_WaterSortData = new FaceSortData[nFaces];
DWORD* oIdx;
if( FAILED(hr = m_WaterMesh->LockIndexBuffer(0, (void**)&oIdx)) )
{
m_WaterMesh->UnlockVertexBuffer();
return hr;
}
memcpy(m_WaterIndices, oIdx, nFaces * sizeof(*m_WaterIndices));
for( i = 0; i < nFaces; i++ )
{
D3DXVECTOR3 pos = oVert[m_WaterIndices[i].m_Idx[0]].m_Pos;
pos += oVert[m_WaterIndices[i].m_Idx[1]].m_Pos;
pos += oVert[m_WaterIndices[i].m_Idx[2]].m_Pos;
pos.z = 0;
pos /= 3.f;
m_WaterFacePos[i] = pos;
}
m_WaterMesh->UnlockIndexBuffer();
m_WaterMesh->UnlockVertexBuffer();
return hr;
}
struct CompSortFace : public std::binary_function<FaceSortData, FaceSortData, bool>
{
bool operator()( const FaceSortData& lhs, const FaceSortData& rhs) const
{
return lhs.m_Dist < rhs.m_Dist;
}
};
void CMyD3DApplication::SortWaterMesh()
{
const D3DXVECTOR3 eyePos(m_matPosition._41, m_matPosition._42, 0.f);
const int nFaces = m_WaterMesh->GetNumFaces();
int i;
for( i = 0; i < nFaces; i++ )
{
D3DXVECTOR3 del(eyePos - m_WaterFacePos[i]);
m_WaterSortData[i].m_Dist = D3DXVec3LengthSq(&del);
m_WaterSortData[i].m_Idx = i;
}
FaceSortData* begin = m_WaterSortData;
FaceSortData* end = begin + nFaces;
std::sort(begin, end, CompSortFace());
FaceIndices* oIdx;
if( FAILED(m_WaterMesh->LockIndexBuffer(0, (void**)&oIdx)) )
{
m_WaterMesh->UnlockVertexBuffer();
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -