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

📄 fluidphysics.cpp

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

#include "FluidPhysics.h"

struct FluidVertex
{
	D3DXVECTOR3 pos;
	D3DXVECTOR2 uv;
};

FluidPhysics::FluidPhysics(int m, float dx, float dt, float speed, float damping)
{
	mNumVertRows = m;
	mNumVertCols = m;
	mSpatialStep = dx;
	mTimeStep    = dt;

	// Compute finite difference scheme constants.
	float d      = damping*dt+2.0f;
	float e      = (speed*speed)*(dt*dt)/(dx*dx);
	mK1          = (damping*dt-2.0f)/ d;
	mK2          = (4.0f-8.0f*e) / d;
	mK3          = (2.0f*e) / d;
	mTexelSize   = 1.0f / (float)m;

	D3DVIEWPORT9 vp = {0, 0, m, m, 0.0f, 1.0f};
	mPrevStepMap = new DrawableTex2D(m, m, 1, D3DFMT_A16B16G16R16F, false, D3DFMT_UNKNOWN, vp);
	mCurrStepMap = new DrawableTex2D(m, m, 1, D3DFMT_A16B16G16R16F, false, D3DFMT_UNKNOWN, vp);
	mNextStepMap = new DrawableTex2D(m, m, 1, D3DFMT_A16B16G16R16F, false, D3DFMT_UNKNOWN, vp);
	mTangentMap  = new DrawableTex2D(m, m, 1, D3DFMT_G16R16F, false, D3DFMT_UNKNOWN, vp);
	mVertexDataMap = new DrawableTex2D(m, m, 1, D3DFMT_A32B32G32R32F, false, D3DFMT_UNKNOWN, vp);

	buildQuadVB();
	buildDisturbanceIB();
	buildPhysicsFX();
}

FluidPhysics::~FluidPhysics()
{
	delete mPrevStepMap;
	delete mCurrStepMap;
	delete mNextStepMap;
	delete mTangentMap;
	delete mVertexDataMap;

	ReleaseCOM(mPhysicsFX);
	ReleaseCOM(mQuadVB);
	ReleaseCOM(mDisturbanceVB);
	ReleaseCOM(mDisturbanceIB);
}

void FluidPhysics::onLostDevice()
{
	mPrevStepMap->onLostDevice();
	mCurrStepMap->onLostDevice();
	mNextStepMap->onLostDevice();
	mTangentMap->onLostDevice();
	mVertexDataMap->onLostDevice();
	HR(mPhysicsFX->OnLostDevice());

	ReleaseCOM(mDisturbanceVB);
}

void FluidPhysics::onResetDevice()
{
	mPrevStepMap->onResetDevice();
	mCurrStepMap->onResetDevice();
	mNextStepMap->onResetDevice();
	mTangentMap->onResetDevice();
	mVertexDataMap->onResetDevice();
	HR(mPhysicsFX->OnResetDevice());

	mPrevStepMap->clear(0x00000000);
	mCurrStepMap->clear(0x00000000);
	mNextStepMap->clear(0x00000000);
	mTangentMap->clear(0x00000000);
	mVertexDataMap->clear(0x00000000);

	HR(gd3dDevice->CreateVertexBuffer(9*sizeof(D3DXVECTOR3), D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, 
		D3DFVF_XYZ, D3DPOOL_DEFAULT, &mDisturbanceVB, 0));
}

IDirect3DTexture9* FluidPhysics::getHeightMap()
{
	return mVertexDataMap->d3dTex();
}

void FluidPhysics::disturb(float x, float y, float radius, float height)
{
	// We disturb the point (x, y) [center] and the points around it.
	// 0*-1*-2*
	//  |  |  |
	// 3*-4*-5*
	//  |  |  |
	// 6*-7*-8*

	D3DXVECTOR3* v = 0;
	HR(mDisturbanceVB->Lock(0, 0, (void**)&v, D3DLOCK_DISCARD));
	v[0] = D3DXVECTOR3(x-radius, y+radius, 0.1f*height);
	v[1] = D3DXVECTOR3(x, y+radius, 0.4f*height);
	v[2] = D3DXVECTOR3(x+radius, y+radius, 0.1f*height);
	v[3] = D3DXVECTOR3(x-radius, y, 0.4f*height);
	v[4] = D3DXVECTOR3(x, y, height);
	v[5] = D3DXVECTOR3(x+radius, y, 0.4f*height);
	v[6] = D3DXVECTOR3(x-radius, y-radius, 0.1f*height);
	v[7] = D3DXVECTOR3(x, y-radius, 0.4f*height);
	v[8] = D3DXVECTOR3(x+radius, y-radius, 0.1f*height);
	HR(mDisturbanceVB->Unlock());
	
	HR(mPhysicsFX->SetTechnique(mfxhDisturbTech));
	mPrevStepMap->beginScene();
	UINT numPasses = 0;
	HR(mPhysicsFX->Begin(&numPasses, 0));
	for(UINT i = 0; i < numPasses; ++i)
	{
		HR(mPhysicsFX->BeginPass(i));
		HR(gd3dDevice->SetStreamSource(0, mDisturbanceVB, 0, sizeof(D3DXVECTOR3)));
		HR(gd3dDevice->SetFVF(D3DFVF_XYZ));
		HR(gd3dDevice->SetIndices(mDisturbanceIB));
		HR(gd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 9, 0, 8));
		HR(mPhysicsFX->EndPass());
	}
	HR(mPhysicsFX->End());
	mPrevStepMap->endScene();
	 
	HR(mPhysicsFX->SetTechnique(mfxhDisturbTech));
	mCurrStepMap->beginScene();
	HR(mPhysicsFX->Begin(&numPasses, 0));
	for(UINT i = 0; i < numPasses; ++i)
	{
		HR(mPhysicsFX->BeginPass(i));
		HR(gd3dDevice->SetStreamSource(0, mDisturbanceVB, 0, sizeof(D3DXVECTOR3)));
		HR(gd3dDevice->SetFVF(D3DFVF_XYZ));
		HR(gd3dDevice->SetIndices(mDisturbanceIB));
		HR(gd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 9, 0, 8));
		HR(mPhysicsFX->EndPass());
	}
	HR(mPhysicsFX->End());
	mCurrStepMap->endScene();
}

void FluidPhysics::update(float dt)
{
	static float timeAccum = 0.0f;
	timeAccum += dt;
	if( timeAccum >= mTimeStep )
	{
		HR(mPhysicsFX->SetTechnique(mfxhPhysicsTech));
		HR(mPhysicsFX->SetFloat(mfxhStepSizeL, mSpatialStep));
		HR(mPhysicsFX->SetFloat(mfxhTexelSize, mTexelSize));
		HR(mPhysicsFX->SetFloat(mfxhK1, mK1));
		HR(mPhysicsFX->SetFloat(mfxhK2, mK2));
		HR(mPhysicsFX->SetFloat(mfxhK3, mK3));
		HR(mPhysicsFX->SetTexture(mfxhPrevStepMap, mPrevStepMap->d3dTex()));
		HR(mPhysicsFX->SetTexture(mfxhCurrStepMap, mCurrStepMap->d3dTex()));
		UINT numPasses = 0;
		mNextStepMap->beginScene();
		HR(mPhysicsFX->Begin(&numPasses, 0));
		for(UINT i = 0; i < numPasses; ++i)
		{
			HR(mPhysicsFX->BeginPass(i));
			HR(gd3dDevice->SetStreamSource(0, mQuadVB, 0, sizeof(D3DXVECTOR3)));
			HR(gd3dDevice->SetFVF(D3DFVF_XYZ));
			HR(gd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2));
			HR(mPhysicsFX->EndPass());
		}
		HR(mPhysicsFX->End());
		mNextStepMap->endScene();

		// Cycle the render targets for next iteration.
		DrawableTex2D* temp = mPrevStepMap;
		mPrevStepMap = mCurrStepMap;
		mCurrStepMap = mNextStepMap;
		mNextStepMap = temp;
	
		timeAccum = 0.0f;

		// Now generate tangent info.
		HR(mPhysicsFX->SetTechnique(mfxhCalcTangentsTech));
		HR(mPhysicsFX->SetTexture(mfxhCurrStepMap, mCurrStepMap->d3dTex()));
		mTangentMap->beginScene();
		HR(mPhysicsFX->Begin(&numPasses, 0));
		for(UINT i = 0; i < numPasses; ++i)
		{
			HR(mPhysicsFX->BeginPass(i));
			HR(gd3dDevice->SetStreamSource(0, mQuadVB, 0, sizeof(D3DXVECTOR3)));
			HR(gd3dDevice->SetFVF(D3DFVF_XYZ));
			HR(gd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2));
			HR(mPhysicsFX->EndPass());
		}
		HR(mPhysicsFX->End());
		mTangentMap->endScene();

		copy16To32();
	}
}

void FluidPhysics::buildQuadVB()
{
	HR(gd3dDevice->CreateVertexBuffer(6*sizeof(D3DXVECTOR3), D3DUSAGE_WRITEONLY, 
		D3DFVF_XYZ, D3DPOOL_MANAGED, &mQuadVB, 0));
	
	D3DXVECTOR3* v = 0;
	mQuadVB->Lock(0, 0, (void**)&v, 0);
	v[0] = D3DXVECTOR3(-1.0f, -1.0f, 0.0f);
	v[1] = D3DXVECTOR3(-1.0f,  1.0f, 0.0f);
	v[2] = D3DXVECTOR3( 1.0f,  1.0f, 0.0f);
	v[3] = D3DXVECTOR3(-1.0f, -1.0f, 0.0f);
	v[4] = D3DXVECTOR3( 1.0f,  1.0f, 0.0f);
	v[5] = D3DXVECTOR3( 1.0f, -1.0f, 0.0f);
	mQuadVB->Unlock();
}

void FluidPhysics::buildDisturbanceIB()
{
	HR(gd3dDevice->CreateIndexBuffer(sizeof(WORD)*24,
		D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &mDisturbanceIB, 0));

	// We disturb the ijth texel and its eight neighbors.
	// 0*-1*-2*
	//  |  |  |
	// 3*-4*-5*
	//  |  |  |
	// 6*-7*-8*

	WORD* indices = 0;
	mDisturbanceIB->Lock(0, 0, (void**)&indices, 0);
	indices[0]  = 0;  indices[1]  = 1;  indices[2]  = 3;
	indices[3]  = 1;  indices[4]  = 4;  indices[5]  = 3;
	indices[6]  = 1;  indices[7]  = 2;  indices[8]  = 4;
	indices[9]  = 2;  indices[10] = 5;  indices[11] = 4;
	indices[12] = 3;  indices[13] = 4;  indices[14] = 6;
	indices[15] = 4;  indices[16] = 7;  indices[17] = 6;
	indices[18] = 4;  indices[19] = 5;  indices[20] = 7;
	indices[21] = 5;  indices[22] = 8;  indices[23] = 7;
	mDisturbanceIB->Unlock();
}

void FluidPhysics::buildPhysicsFX()
{
	HRESULT hr = 0;
	ID3DXBuffer* errors = 0;
	hr = D3DXCreateEffectFromFileEx(gd3dDevice, "fluidphysics.fx", 0, 0, 0, 
		D3DXSHADER_DEBUG, 0, &mPhysicsFX, &errors);
	if( errors )
	{
		MessageBox(0, (char*)errors->GetBufferPointer(), 0, 0);
		HR(hr);
	}

	mfxhCopyTexTech      = mPhysicsFX->GetTechniqueByName("CopyTexTech");
	mfxhDisturbTech      = mPhysicsFX->GetTechniqueByName("DisturbTech");
	mfxhPhysicsTech      = mPhysicsFX->GetTechniqueByName("PhysicsTech");
	mfxhCalcTangentsTech = mPhysicsFX->GetTechniqueByName("CalcTangentsTech");
	mfxhHeightMap        = mPhysicsFX->GetParameterByName(0, "gHeightMap");
	mfxhTangentMap       = mPhysicsFX->GetParameterByName(0, "gTangentMap");
	mfxhStepSizeL        = mPhysicsFX->GetParameterByName(0, "gStepSizeL");
	mfxhTexelSize        = mPhysicsFX->GetParameterByName(0, "gTexelSize");
	mfxhPrevStepMap      = mPhysicsFX->GetParameterByName(0, "gPrevStepTex");
	mfxhCurrStepMap      = mPhysicsFX->GetParameterByName(0, "gCurrStepTex");
	mfxhK1               = mPhysicsFX->GetParameterByName(0, "gK1");
	mfxhK2               = mPhysicsFX->GetParameterByName(0, "gK2");
	mfxhK3               = mPhysicsFX->GetParameterByName(0, "gK3");
}

void FluidPhysics::copy16To32()
{
	HR(mPhysicsFX->SetTechnique(mfxhCopyTexTech));
	HR(mPhysicsFX->SetTexture(mfxhHeightMap, mCurrStepMap->d3dTex()));
	HR(mPhysicsFX->SetTexture(mfxhTangentMap, mTangentMap->d3dTex()));
	mVertexDataMap->beginScene();
	UINT numPasses = 0;
	HR(mPhysicsFX->Begin(&numPasses, 0));
	for(UINT i = 0; i < numPasses; ++i)
	{
		HR(mPhysicsFX->BeginPass(i));
		HR(gd3dDevice->SetStreamSource(0, mQuadVB, 0, sizeof(D3DXVECTOR3)));
		HR(gd3dDevice->SetFVF(D3DFVF_XYZ));
		HR(gd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2));
		HR(mPhysicsFX->EndPass());
	}
	HR(mPhysicsFX->End());
	mVertexDataMap->endScene();
}

⌨️ 快捷键说明

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