📄 water.cpp
字号:
{
*pwIndex++ = uX + uZ * WATER_SIZE;
*pwIndex++ = uX + uZ * WATER_SIZE - 1;
uZ++;
}
uZ--;
uX--;
// Bottom
for(u = 1; u < uSize; u++)
{
*pwIndex++ = uX + uZ * WATER_SIZE;
*pwIndex++ = uX + uZ * WATER_SIZE - WATER_SIZE;
uX--;
}
uX++;
uZ--;
// Left
for(u = 2; u < uSize; u++)
{
*pwIndex++ = uX + uZ * WATER_SIZE;
*pwIndex++ = uX + uZ * WATER_SIZE + 1;
uZ--;
}
uZ++;
uX++;
}
for(pwIndex = pwIndices; pwIndex < pwIndices + m_uIndices; pwIndex++)
{
if(*pwIndex >= m_uVertices)
*pwIndex = 0;
}
m_pibIndices->Unlock();
}
// Create vertices
if(!m_pvbVertices)
{
if(FAILED(hr = m_pDevice->CreateVertexBuffer(m_uVertices * sizeof(WATER_VERTEX),
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, WATER_VERTEX::FVF, D3DPOOL_DEFAULT, &m_pvbVertices, NULL)))
{
return hr;
}
}
// Create caustics
if(!m_pvbCaustics)
{
if(FAILED(hr = m_pDevice->CreateVertexBuffer(m_uVertices * sizeof(CAUSTICS_VERTEX),
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, CAUSTICS_VERTEX::FVF, D3DPOOL_DEFAULT, &m_pvbCaustics, NULL)))
{
return hr;
}
}
return S_OK;
}
HRESULT CWater::OnLostDevice()
{
SAFE_RELEASE( m_pibIndices );
SAFE_RELEASE( m_pvbVertices );
SAFE_RELEASE( m_pvbCaustics );
return S_OK;
}
HRESULT CWater::OnDestroyDevice()
{
m_pDevice = NULL;
return S_OK;
}
HRESULT CWater::Drop()
{
UINT uX = rand();
UINT uY = rand();
m_pSurface[WATER_INDEX_WRAP(uX, uY)].fVelocity -= 0.25f;
m_pSurface[WATER_INDEX_WRAP(uX - 1, uY)].fVelocity -= 0.125f;
m_pSurface[WATER_INDEX_WRAP(uX + 1, uY)].fVelocity -= 0.125f;
m_pSurface[WATER_INDEX_WRAP(uX, uY - 1)].fVelocity -= 0.125f;
m_pSurface[WATER_INDEX_WRAP(uX, uY + 1)].fVelocity -= 0.125f;
m_pSurface[WATER_INDEX_WRAP(uX - 1, uY - 1)].fVelocity -= 0.0625f;
m_pSurface[WATER_INDEX_WRAP(uX + 1, uY + 1)].fVelocity -= 0.0625f;
m_pSurface[WATER_INDEX_WRAP(uX + 1, uY - 1)].fVelocity -= 0.0625f;
m_pSurface[WATER_INDEX_WRAP(uX - 1, uY + 1)].fVelocity -= 0.0625f;
return S_OK;
}
HRESULT CWater::Update(D3DXVECTOR3 &vecPos, D3DXVECTOR3 &vecLight, BOOL bCalcCaustics)
{
HRESULT hr;
UINT uXN, uX, uXP, uY, uYN, uY0, uYP;
// Compute desired height
m_fAvgHeight = 0.0f;
WATER_SURFACE *pSurface = m_pSurface;
uYN = WATER_AREA - WATER_SIZE;
uY0 = 0;
uYP = WATER_SIZE;
do
{
uXN = WATER_SIZE - 1;
uX = 0;
uXP = 1;
do
{
// Bowl
float fX = (float) uX - (WATER_SIZE >> 1);
float fZ = (float) (uY0 >> WATER_SHIFT) - (WATER_SIZE >> 1);
float fDesire;
if((fX * fX + fZ * fZ) < (WATER_SPHERE_RADIUS2 - WATER_SPHERE_HEIGHT * WATER_SPHERE_HEIGHT))
{
fDesire =
(m_pSurface[uXN + uYN].fHeight +
m_pSurface[uXP + uYN].fHeight +
m_pSurface[uXN + uYP].fHeight +
m_pSurface[uXP + uYP].fHeight) * (1.0f / 12.0f)
+
(m_pSurface[uX + uYN].fHeight +
m_pSurface[uXN + uY0].fHeight +
m_pSurface[uXP + uY0].fHeight +
m_pSurface[uX + uYP].fHeight) * (2.0f / 12.0f);
}
else
{
fDesire = 0.0f;
pSurface->fHeight = 0.0f;
pSurface->fVelocity = 0.0f;
}
// Update velocity
if(pSurface->fVelocity > 0.01f || pSurface->fVelocity < -0.01f)
pSurface->fVelocity *= 0.99f;
pSurface->fVelocity += 0.25f * (fDesire - pSurface->fHeight);
m_fAvgHeight += pSurface->fHeight + pSurface->fVelocity;
pSurface++;
uXN = uX;
uX = uXP;
uXP = (uXP + 1) & WATER_MASK;
}
while(uX);
uYN = uY0;
uY0 = uYP;
uYP = (uYP + WATER_SIZE) & (WATER_MASK << WATER_SHIFT);
}
while(uY0);
m_fAvgHeight /= (float) m_uVertices;
// Calculate surface normals
WATER_VERTEX *pVertices, *pVertex, *pVertexLim;
D3DXVECTOR3 vec;
D3DXVECTOR3 vecP, vecN;
if(FAILED(hr = m_pvbVertices->Lock(0, m_uVertices * sizeof(WATER_VERTEX), (void**) &pVertices, D3DLOCK_DISCARD)))
return hr;
pVertex = pVertices;
pVertexLim = pVertex + m_uVertices;
pSurface = m_pSurface;
float fInc = m_fSize / (float) (WATER_SIZE - 1);
float fZ = m_fSize * -0.5f;
uYN = WATER_AREA - WATER_SIZE;
uY0 = 0;
uYP = WATER_SIZE;
do
{
float fX = m_fSize * -0.5f;
uXN = WATER_SIZE - 1;
uX = 0;
uXP = 1;
do
{
// Update position and normal
vecP.x = fX;
vecP.y = pSurface->fHeight = pSurface->fHeight + pSurface->fVelocity - m_fAvgHeight;
vecP.z = fZ;
float f;
f = m_pSurface[uXN + uYN].fHeight - m_pSurface[uXP + uYP].fHeight; vecN.x = vecN.z = f;
f = m_pSurface[uX + uYN].fHeight - m_pSurface[uX + uYP].fHeight; vecN.z += f;
f = m_pSurface[uXP + uYN].fHeight - m_pSurface[uXN + uYP].fHeight; vecN.x -= f; vecN.z += f;
f = m_pSurface[uXN + uY0].fHeight - m_pSurface[uXP + uY0].fHeight; vecN.x += f;
vecN.y = 1.0f;
D3DXVec3Normalize(&vecN, &vecN);
pSurface++;
// Update texture coords and diffuse based upon refraction
D3DXVec3Subtract(&vec, &vecPos, &vecP);
D3DXVec3Normalize(&vec, &vec);
WATER_REFRACT *pRefract;
pRefract = m_pRefract + f2i(D3DXVec3Dot(&vec, &vecN) * 255.0f);
pVertex->m_vecPos = vecP;
pVertex->m_vecNormal = vecN;
pVertex->m_dwDiffuse = pRefract->dwDiffuse;
// Bowl
D3DXVECTOR3 vecD;
vecD = (vecN * pRefract->fRefract + vec) * pRefract->fRefractNorm;
vecP.y -= WATER_SPHERE_HEIGHT;
float fC = D3DXVec3Dot(&vecP, &vecP) - WATER_SPHERE_RADIUS2;
if(fC < 0.0f)
{
float fB = D3DXVec3Dot(&vecD, &vecP) * 2.0f;
float fD = fB * fB - 4.0f * fC;
float fScale = (-fB + sqrtf(fD)) * 0.5f;
pVertex->m_vecTex.x = (vecD.x * fScale + vecP.x) * m_fScaleTex + 0.5f;
pVertex->m_vecTex.y = (vecD.z * fScale + vecP.z) * m_fScaleTex + 0.5f;
}
else
{
pVertex->m_vecTex.x = vecP.x * m_fScaleTex + 0.5f;
pVertex->m_vecTex.y = vecP.z * m_fScaleTex + 0.5f;
}
pVertex++;
fX += fInc;
uXN = uX;
uX = uXP;
uXP = (uXP + 1) & WATER_MASK;
}
while(uX);
fZ += fInc;
uYN = uY0;
uY0 = uYP;
uYP = (uYP + WATER_SIZE) & (WATER_MASK << WATER_SHIFT);
}
while(uY0);
// Calculate caustics
if(bCalcCaustics)
{
CAUSTICS_VERTEX *pCaustics, *pCaustic;
if(FAILED(hr = m_pvbCaustics->Lock(0, m_uVertices * sizeof(CAUSTICS_VERTEX), (void**) &pCaustics, D3DLOCK_DISCARD)))
return hr;
#define TABLE_SIZE 8
static DWORD Table[TABLE_SIZE];
if(!Table[0])
{
for(UINT u = 0; u < TABLE_SIZE; u++)
Table[u] = (0x40 / (u + 1)) * 0x00010101;
}
pVertex = pVertices;
pCaustic = pCaustics;
for(uY = 0; uY < WATER_SIZE; uY++)
{
for(uX = 0; uX < WATER_SIZE; uX++)
{
WATER_REFRACT *pRefract;
pRefract = m_pRefract + f2i(pVertex->m_vecNormal.y * 255.0f);
// Bowl
D3DXVECTOR3 vecD, vecP;
vecD = (pVertex->m_vecNormal * pRefract->fRefract + vecLight) * pRefract->fRefractNorm;
vecP = pVertex->m_vecPos;
vecP.y -= WATER_SPHERE_HEIGHT;
float fC = D3DXVec3Dot(&vecP, &vecP) - WATER_SPHERE_RADIUS2;
if(fC < 0.0f)
{
float fB = D3DXVec3Dot(&vecD, &vecP) * 2.0f;
float fD = fB * fB - 4.0f * fC;
float fScale = (-fB + sqrtf(fD)) * 0.5f;
pCaustic->m_vecPos.x = vecD.x * fScale + vecP.x;
pCaustic->m_vecPos.y = 0.0f;
pCaustic->m_vecPos.z = vecD.z * fScale + vecP.z;
}
else
{
pCaustic->m_vecPos.x = vecP.x;
pCaustic->m_vecPos.y = 0.0f;
pCaustic->m_vecPos.z = vecP.z;
}
if(uX && uY)
{
float fArea;
fArea = (pCaustic[-WATER_SIZE - 1].m_vecPos.x - pCaustic->m_vecPos.x) *
(pCaustic[-WATER_SIZE ].m_vecPos.z - pCaustic->m_vecPos.z) -
(pCaustic[-WATER_SIZE - 1].m_vecPos.z - pCaustic->m_vecPos.z) *
(pCaustic[-WATER_SIZE ].m_vecPos.x - pCaustic->m_vecPos.x);
if(fArea < 0.0f)
fArea = -fArea;
UINT u = f2i(fArea * fArea * 4.0f);
pCaustic->m_dwDiffuse = u < TABLE_SIZE ? Table[u] : 0;
}
pCaustic++;
pVertex++;
}
pCaustic[-WATER_SIZE].m_dwDiffuse = pCaustic[-1].m_dwDiffuse;
}
for(uX = 0; uX < WATER_SIZE; uX++)
{
pCaustics[uX].m_dwDiffuse = pCaustics[uX + (WATER_AREA - WATER_SIZE)].m_dwDiffuse;
}
m_pvbCaustics->Unlock();
}
m_pvbVertices->Unlock();
return S_OK;
}
HRESULT CWater::DrawCaustics()
{
HRESULT hr;
if(FAILED(hr = m_pDevice->SetFVF(CAUSTICS_VERTEX::FVF)))
return hr;
if(FAILED(hr = m_pDevice->SetStreamSource(0, m_pvbCaustics, 0, sizeof(CAUSTICS_VERTEX))))
return hr;
if(FAILED(hr = m_pDevice->SetIndices(m_pibIndices)))
return hr;
if(FAILED(hr = m_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, 0, m_uVertices, 0, m_uIndices - 2)))
return hr;
return S_OK;
}
HRESULT CWater::DrawSurface()
{
HRESULT hr;
if(FAILED(hr = m_pDevice->SetFVF(WATER_VERTEX::FVF)))
return hr;
if(FAILED(hr = m_pDevice->SetStreamSource(0, m_pvbVertices, 0, sizeof(WATER_VERTEX))))
return hr;
if(FAILED(hr = m_pDevice->SetIndices(m_pibIndices)))
return hr;
if(FAILED(hr = m_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, 0, m_uVertices, 0, m_uIndices - 2)))
return hr;
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -