⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fluid.cpp

📁 游戏编程精粹6的光盘源代码
💻 CPP
字号:
//=============================================================================
// Fluid.cpp by Frank Luna (C) 2005 All Rights Reserved.
//=============================================================================

#include "Fluid.h"
#include "Vertex.h"


Fluid::Fluid(int m, int n, float dx, float dt, float speed, float damping)
{
	mRows = m;
	mCols = n;
	mDX   = dx;

	mPhysics = new FluidPhysics(m, dx, dt, speed, damping);

	buildGridMesh();
	buildRenderingFX();

	HR(D3DXCreateTextureFromFile(gd3dDevice, "wave1.dds", &mNormMap0));
	HR(D3DXCreateTextureFromFile(gd3dDevice, "wave0.dds", &mNormMap1));

	// Texture offsets for scrolling normal maps.  Coords x, y control
	// the first normal map, and coords z, w control the second normal map.
	mTexOffsets = D3DXVECTOR4(0.0f, 0.0f, 0.2f, 0.3f);
}

Fluid::~Fluid()
{
	delete mPhysics;
	ReleaseCOM(mGridMesh);
	ReleaseCOM(mRenderingFX);
	ReleaseCOM(mNormMap0);
	ReleaseCOM(mNormMap1);
}

int Fluid::numRows()const
{
	return mRows;
}

int Fluid::numCols()const
{
	return mCols;
}

int Fluid::numVertices()const
{
	return mGridMesh->GetNumVertices();
}

int Fluid::numTriangles()const
{
	return mGridMesh->GetNumFaces();
}

float Fluid::width()const
{
	return mCols*mDX;
}

float Fluid::depth()const
{
	return mRows*mDX;
}

void Fluid::onLostDevice()
{
	mPhysics->onLostDevice();
	HR(mRenderingFX->OnLostDevice());
}

void Fluid::onResetDevice()
{
	mPhysics->onResetDevice();
	HR(mRenderingFX->OnResetDevice());
}

void Fluid::disturb(float x, float y, float radius, float height)
{
	mPhysics->disturb(x, y, radius, height);
}

void Fluid::update(float dt)
{
	mPhysics->update(dt);

	// Scroll normal maps.
	mTexOffsets += (D3DXVECTOR4(0.02f, 0.06f, -0.01f, 0.03f)*dt);

	if(mTexOffsets.x >= 1.0f) mTexOffsets.x -= 1.0f;
	if(mTexOffsets.y >= 1.0f) mTexOffsets.y -= 1.0f;
	if(mTexOffsets.z >= 1.0f) mTexOffsets.z -= 1.0f;
	if(mTexOffsets.w >= 1.0f) mTexOffsets.w -= 1.0f;

	if(mTexOffsets.x <= -1.0f) mTexOffsets.x += 1.0f;
	if(mTexOffsets.y <= -1.0f) mTexOffsets.y += 1.0f;
	if(mTexOffsets.z <= -1.0f) mTexOffsets.z += 1.0f;
	if(mTexOffsets.w <= -1.0f) mTexOffsets.w += 1.0f;
}

void Fluid::draw(const D3DXMATRIX& W, const D3DXMATRIX& V, const D3DXMATRIX& P, const D3DXVECTOR3& eyePosW,
				 IDirect3DTexture9* refractMap, IDirect3DTexture9* reflectMap)
{
	D3DXMATRIX fluidWorldInv;
	D3DXMatrixInverse(&fluidWorldInv, 0, &W);

	HR(mRenderingFX->SetTechnique(mfxhFluidRenderingTech));
	HR(mRenderingFX->SetMatrix(mfxhWorld, &W));
	HR(mRenderingFX->SetMatrix(mfxhWorldInv, &fluidWorldInv));
	HR(mRenderingFX->SetMatrix(mfxhWVP, &(W*V*P)));
	HR(mRenderingFX->SetValue(mfxhEyePosW, &eyePosW, sizeof(D3DXVECTOR3)));
	HR(mRenderingFX->SetTexture(mfxhDispMap, mPhysics->getHeightMap()));
	HR(mRenderingFX->SetTexture(mfxhRefractMap, refractMap));
	HR(mRenderingFX->SetTexture(mfxhReflectMap, reflectMap));
	HR(mRenderingFX->SetTexture(mfxhNormMap0, mNormMap0));
	HR(mRenderingFX->SetTexture(mfxhNormMap1, mNormMap1));
	HR(mRenderingFX->SetVector(mfxhTexOffsets, &mTexOffsets));

	UINT numPasses = 0;
	HR(mRenderingFX->Begin(&numPasses, 0));
	HR(mRenderingFX->BeginPass(0));	
	HR(mGridMesh->DrawSubset(0));
	HR(mRenderingFX->EndPass());
	HR(mRenderingFX->End());
}

void Fluid::buildGridMesh()
{
	std::vector<D3DXVECTOR3> verts;
	std::vector<DWORD> indices;
	GenTriGrid(mRows, mCols, mDX, mDX, D3DXVECTOR3(0.0f, 0.0f, 0.0f), verts, indices);

	int numVerts = mRows*mCols;
	int numTris  = (mRows-1)*(mCols-1)*2;

	D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
	UINT numElems = 0;
	HR(VertexPT::Decl->GetDeclaration(elems, &numElems));
	HR(D3DXCreateMesh(numTris, numVerts, 
		D3DXMESH_MANAGED|D3DXMESH_32BIT, elems, gd3dDevice, &mGridMesh));

	VertexPT* v = 0;
	HR(mGridMesh->LockVertexBuffer(0,(void**)&v));

	// grid width/depth
	float w = (mRows-1) * mDX; 
	float d = (mCols-1) * mDX;
	for(int i = 0; i < mRows; ++i)
	{
		for(int j = 0; j < mCols; ++j)
		{
			DWORD index = i * mCols + j;
			v[index].pos    = verts[index];
			v[index].tex0.x = (v[index].pos.x + (0.5f*w)) / w;
			v[index].tex0.y = (v[index].pos.z - (0.5f*d)) / -d;
		}
	}

	HR(mGridMesh->UnlockVertexBuffer());


	DWORD* k = 0;
	HR(mGridMesh->LockIndexBuffer(0, (void**)&k));
	DWORD* attBuffer = 0;
	HR(mGridMesh->LockAttributeBuffer(0, &attBuffer));

	for(int i = 0; i < numTris; ++i)
	{
		k[i*3+0] = (DWORD)indices[i*3+0];
		k[i*3+1] = (DWORD)indices[i*3+1];
		k[i*3+2] = (DWORD)indices[i*3+2];

		attBuffer[i] = 0; // Always subset 0
	}

	HR(mGridMesh->UnlockIndexBuffer());
	HR(mGridMesh->UnlockAttributeBuffer());


	DWORD* adj = new DWORD[mGridMesh->GetNumFaces()*3];
	HR(mGridMesh->GenerateAdjacency(EPSILON, adj));
	HR(mGridMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE|D3DXMESHOPT_ATTRSORT,
		adj, 0, 0, 0));
	delete[] adj;
}

void Fluid::buildRenderingFX()
{
	HRESULT hr = 0;
	ID3DXBuffer* errors = 0;
	hr = D3DXCreateEffectFromFileEx(gd3dDevice, "fluidRendering.fx", 0, 0, 0, 
		D3DXSHADER_DEBUG, 0, &mRenderingFX, &errors);
	if( errors )
	{
		MessageBox(0, (char*)errors->GetBufferPointer(), 0, 0);
		HR(hr);
	}

	mfxhFluidRenderingTech = mRenderingFX->GetTechniqueByName("GPUFluidRenderingTech");
	mfxhWorld    = mRenderingFX->GetParameterByName(0, "gWorld");
	mfxhWorldInv = mRenderingFX->GetParameterByName(0, "gWorldInv");
	mfxhEyePosW  = mRenderingFX->GetParameterByName(0, "gEyePosW");
	mfxhWVP      = mRenderingFX->GetParameterByName(0, "gWVP");
	mfxhDispMap  = mRenderingFX->GetParameterByName(0, "gDispMap");
	mfxhRefractMap = mRenderingFX->GetParameterByName(0, "gRefractMap");
	mfxhReflectMap = mRenderingFX->GetParameterByName(0, "gReflectMap");
	mfxhNormMap0   = mRenderingFX->GetParameterByName(0, "gNormMap0");
	mfxhNormMap1   = mRenderingFX->GetParameterByName(0, "gNormMap1");
	mfxhTexOffsets = mRenderingFX->GetParameterByName(0, "gTexOffsets");
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -