Files
Client/GameTools/Zallad3D SceneClass/WaterW.cpp
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

553 lines
15 KiB
C++

#include "WaterW.h"
#include "SceneManager.h"
CWaterW ::CWaterW() {
m_pWaterSpace = NULL;
m_pWaterChangeValue = NULL;
m_pWaterCoord = NULL;
m_nWidthSize = WATERWWIDTH;
m_nHeightSize = WATERWHEIGHT;
m_fLimitHeight = 0.0;
m_nDriftCount = 0;
m_Device = NULL;
m_nChopPower = WATERWCHOP;
m_IndexNum = 0;
m_ZeroPos.x = m_ZeroPos.y = m_ZeroPos.z = 0.0f;
m_QuadSize = 1.0f;
CreateWaterWSpace();
}
CWaterW ::CWaterW(int size,double lh,float chop,float x,float z,float quadsize,LPDIRECT3DDEVICE8 device) {
m_pWaterSpace = NULL;
m_pWaterChangeValue = NULL;
m_pWaterCoord = NULL;
m_nWidthSize = size;
m_nHeightSize = size;
m_fLimitHeight = lh;
m_nDriftCount = 0;
m_nChopPower = chop;
m_Device = device;
m_IndexNum = 0;
m_ZeroPos.x = x;
m_ZeroPos.z = z;
m_QuadSize = quadsize;
CreateWaterWSpace();
CreateTexture();
CreateVertexBuffer();
}
CWaterW ::CWaterW(int w,int h,double lh,float chop,float x,float z,float quadsize,LPDIRECT3DDEVICE8 device){
m_pWaterSpace = NULL;
m_pWaterChangeValue = NULL;
m_pWaterCoord = NULL;
m_nWidthSize = w;
m_nHeightSize = h;
m_fLimitHeight = lh;
m_nDriftCount = 0;
m_nChopPower = chop;
m_Device = device;
m_IndexNum = 0;
m_ZeroPos.x = x;
m_ZeroPos.z = z;
m_QuadSize = quadsize;
CreateWaterWSpace();
CreateTexture();
CreateVertexBuffer();
}
void CWaterW ::SetLimitHeight(double h) {
m_fLimitHeight = h;
}
bool CWaterW ::CreateWaterWSpace() {
int i;
if(!m_nWidthSize || !m_nHeightSize) {
return false;
}
////// mem clear //////
if(m_pWaterSpace != NULL) {
for(i=0;i<m_nWidthSize;i++) {
delete[] m_pWaterSpace[i];
m_pWaterSpace[i] = NULL;
}
delete[] m_pWaterSpace;
m_pWaterSpace = NULL;
}
if(m_pWaterChangeValue != NULL) {
for(i=0;i<m_nWidthSize;i++) {
delete[] m_pWaterChangeValue[i];
m_pWaterChangeValue[i] = NULL;
}
delete[] m_pWaterChangeValue;
m_pWaterChangeValue = NULL;
}
if(m_pWaterCoord != NULL) {
for(i=0;i<m_nWidthSize;i++) {
delete[] m_pWaterCoord[i];
m_pWaterCoord[i] = NULL;
}
delete[] m_pWaterCoord;
m_pWaterCoord = NULL;
}
//////////////////////////////////////////
m_pWaterSpace = new double*[m_nWidthSize];
m_pWaterChangeValue = new double*[m_nWidthSize];
m_pWaterCoord = new double*[m_nWidthSize];
for(i=0;i<m_nWidthSize;i++) {
m_pWaterSpace[i] = new double[m_nHeightSize];
m_pWaterChangeValue[i] = new double[m_nHeightSize];
m_pWaterCoord[i] = new double[m_nHeightSize];
}
// water 공간 세팅
InitWaterW();
return true;
}
void CWaterW ::InitWaterW() {
int i,j;
for(i=0;i<m_nWidthSize;i++)
for(j=0;j<m_nHeightSize;j++){
m_pWaterSpace[i][j] = 0.0f;
m_pWaterChangeValue[i][j] = 0.0f;//((double)rand()/(double)RAND_MAX-.2)*1;
}
}
void CWaterW ::UpdateWaterW() {
int i,j;
float h;
for(i=1;i<m_nWidthSize-1;i++) {
for(j=1;j<m_nHeightSize-1;j++) {
h = (m_pWaterSpace[j-1][i] + m_pWaterSpace[j+1][i] + m_pWaterSpace[j][i-1] + m_pWaterSpace[j][i+1])/2.0f - m_pWaterChangeValue[j][i];
h -= h/32.0f;
m_pWaterChangeValue[j][i] = h;
}
}
for(i=0;i<m_nWidthSize;i++) {
for(j=0;j<m_nHeightSize;j++) {
float t;
t = m_pWaterSpace[j][i];
m_pWaterSpace[j][i] = m_pWaterChangeValue[j][i];
m_pWaterChangeValue[j][i] = t;
}
}
/*
// 상호 작용 구현
// 각 버텍스별 영향치 계산
for(i=1;i<m_nWidthSize - 1;i++) {
for(j=1;j<m_nHeightSize - 1;j++) {
m_pWaterChangeValue[i][j] = m_pWaterChangeValue[i][j] -
(m_pWaterSpace[i][j] -
(m_pWaterSpace[i][j-1] +
m_pWaterSpace[i][j+1] +
m_pWaterSpace[i-1][j-1] +
m_pWaterSpace[i-1][j] +
m_pWaterSpace[i+1][j] +
m_pWaterSpace[i+1][j+1])/6 ) * m_nChopPower;
}
}*/
/*
// 영향치 적용
for(i=0;i<m_nWidthSize;i++) {
for(j=0;j<m_nHeightSize;j++) {
m_pWaterChangeValue[i][j]=m_pWaterChangeValue[i][j]-_copysign(.01,m_pWaterSpace[i][j]);
m_pWaterChangeValue[i][j]=m_pWaterChangeValue[i][j]*0.99;
m_pWaterSpace[i][j]=m_pWaterSpace[i][j]+m_pWaterChangeValue[i][j];
}
}
*/
}
void CWaterW ::SetHeight(int x,int y,float height) {
m_pWaterSpace[y][x] = height;
}
void CWaterW ::ComputeWaterW() {
int unitnum = m_DriftUnit.size();
int i;
// water영역안에 들어와 있는 unit 의 갯수 만큼 업데이트
for(i=0;i<unitnum;i++) {
int x,y;
x = (int)m_DriftUnit[i].m_UnitPos.x;
y = (int)m_DriftUnit[i].m_UnitPos.y;
int unitrange = m_DriftUnit[i].m_nUnitRange;
m_pWaterSpace[y][x] = -0.4f;
DeleteDriftUnit(m_DriftUnit[i]);
//m_DriftUnit[i].m_UnitPos.x += m_DriftUnit[i].m_UnitFwd.x;
//m_DriftUnit[i].m_UnitPos.y += m_DriftUnit[i].m_UnitFwd.y;
/* int unitrange = m_DriftUnit[i].m_nUnitRange;
D3DXVECTOR3 pos = m_DriftUnit[i].m_UnitPos;
// 영향의 범위가 water을 벗어났을 때에 영향 영역 수정
int xcenter=(int)(pos.x);
int ycenter=(int)(pos.y)+xcenter/2;
if((xcenter-unitrange)<0)
xcenter=unitrange;
if((xcenter+unitrange)>=m_nWidthSize)
xcenter=m_nWidthSize-unitrange;
if((ycenter-unitrange)<0)
ycenter=unitrange;
if((ycenter+unitrange)>m_nHeightSize)
ycenter=m_nHeightSize-unitrange;
// 영향 주기
int b=ycenter-unitrange;int e=ycenter;
for(i=xcenter-unitrange;i<xcenter+unitrange;i++) {
for(j=b;j<e;j++) {
double force;
D3DXVECTOR3 is(pos.x,pos.y,pos.z);
if(m_pWaterSpace[i][j]>is.y) {
force=(m_pWaterSpace[i][j]-is.y)+m_pWaterChangeValue[i][j];
m_pWaterSpace[i][j]=is.y;
m_pWaterChangeValue[i][j]=m_pWaterChangeValue[i][j]-force*.5;
}
}
if(i<xcenter)
e++;
else
b++;
} */// for(i=xcenter-unitrange;i<xcenter+unitrange;i++)
} //for(i=0;i<unitnum;i++)
unitnum = m_DriftUnit.size();
for(i=0;i<unitnum;i++) {
if(((int)m_DriftUnit[i].m_UnitPos.x >=m_nWidthSize) || ((int)m_DriftUnit[i].m_UnitPos.x <0)) {
DeleteDriftUnit(m_DriftUnit[i]);
}
if(((int)m_DriftUnit[i].m_UnitPos.y >=m_nHeightSize) || ((int)m_DriftUnit[i].m_UnitPos.y <0)) {
DeleteDriftUnit(m_DriftUnit[i]);
}
}
}
void CWaterW ::AddDriftUnit(CDriftUnit tmp_u) {
tmp_u.SetUnitIndex(m_nDriftCount++);
m_DriftUnit.push_back(tmp_u);
}
void CWaterW ::DeleteDriftUnit(CDriftUnit tmp_u) {
int i;
for(i=0;i<m_DriftUnit.size();i++) {
if(m_DriftUnit[i].m_nIndex == tmp_u.m_nIndex) {
m_DriftUnit.erase(&m_DriftUnit[i]);
break;
}
}
}
CWaterW ::~CWaterW() {
int i;
////// mem clear //////
if(m_pWaterSpace != NULL) {
for(i=0;i<m_nWidthSize;i++) {
delete[] m_pWaterSpace[i];
m_pWaterSpace[i] = NULL;
}
delete[] m_pWaterSpace;
m_pWaterSpace = NULL;
}
if(m_pWaterChangeValue != NULL) {
for(i=0;i<m_nWidthSize;i++) {
delete[] m_pWaterChangeValue[i];
m_pWaterChangeValue[i] = NULL;
}
delete[] m_pWaterChangeValue;
m_pWaterChangeValue = NULL;
}
if(m_pWaterCoord != NULL) {
for(i=0;i<m_nWidthSize;i++) {
delete[] m_pWaterCoord[i];
m_pWaterCoord[i] = NULL;
}
delete[] m_pWaterCoord;
m_pWaterCoord = NULL;
}
m_WaterVertexBuffer->Release();
m_WaterIndexBuffer->Release();
m_DriftUnit.clear();
}
int CWaterW::CDriftUnit::SetUnitIndex(int n) {
m_nIndex = n;
return m_nIndex;
}
void CWaterW::Render() {
ChangeVertexBuffer();
DWORD zmode,alphamode,cullmode;
D3DXMATRIX view,world,project;
D3DXMATRIX beforeworld;
D3DXMatrixIdentity(&beforeworld);
m_Device->GetTransform(D3DTS_WORLD,&world);
m_Device->SetTransform(D3DTS_WORLD,&beforeworld);
m_Device->GetTransform(D3DTS_VIEW,&view);
m_Device->GetTransform(D3DTS_PROJECTION,&project);
m_Device->GetRenderState(D3DRS_ZWRITEENABLE,&zmode);
m_Device->GetRenderState(D3DRS_ALPHABLENDENABLE,&alphamode);
m_Device->GetRenderState(D3DRS_CULLMODE,&cullmode);
//////////////////
m_Device->SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
m_Device->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
m_Device->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
m_Device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
m_Device->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
m_Device->SetRenderState(D3DRS_LIGHTING,TRUE);
m_Device->SetRenderState(D3DRS_ZWRITEENABLE,FALSE);
m_Device->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
m_Device->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
m_Device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
m_Device->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
///0//////
//m_Device->SetTextureStageState(0,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
//m_Device->SetTextureStageState(0,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
m_Device->SetTextureStageState(0,D3DTSS_MAGFILTER,D3DTEXF_LINEAR);
m_Device->SetTextureStageState(0,D3DTSS_MINFILTER,D3DTEXF_LINEAR);
m_Device->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
m_Device->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
m_Device->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_MODULATE);
DWORD env_alpha;
env_alpha = D3DCOLOR_COLORVALUE(1.0f,1.0f,1.0f,1.0f);
m_Device->SetRenderState(D3DRS_TEXTUREFACTOR,env_alpha);
m_Device->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TFACTOR);
m_Device->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_TEXTURE);
m_Device->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_MODULATE);
/////////
// Turn on texture-coord generation for cubemapping
m_Device->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR );
m_Device->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3 );
// Render the object with the environment-mapped body
m_Device->SetTexture( 0, m_pSkyCubeTex);
//////////////
m_Device->SetStreamSource(0,m_WaterVertexBuffer,sizeof(CWaterVertex));
m_Device->SetIndices(m_WaterIndexBuffer,0);
m_Device->SetVertexShader(D3DFVF_XYZ | D3DFVF_NORMAL);
m_Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,m_nWidthSize * m_nHeightSize,0,(m_IndexNum / 3));
m_Device->SetRenderState(D3DRS_ZWRITEENABLE,zmode);
m_Device->SetRenderState(D3DRS_ALPHABLENDENABLE,alphamode);
m_Device->SetRenderState(D3DRS_CULLMODE,cullmode);
// Restore the render states
m_Device->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU );
m_Device->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
m_Device->SetTransform(D3DTS_WORLD,&world);
}
void CWaterW::CreateVertexBuffer() {
WORD *VertIndex;
int i,j;
int count = 0;
m_Device->CreateVertexBuffer((m_nWidthSize) * (m_nHeightSize) * sizeof(CWaterVertex),0,
D3DFVF_XYZ | D3DFVF_NORMAL,D3DPOOL_DEFAULT,&(m_WaterVertexBuffer));
VertIndex = new WORD[(m_nWidthSize-2) * (m_nHeightSize-2) * 6];
for(i=1;i<(m_nWidthSize -1);i++) {
for(j=1;j<(m_nHeightSize-1);j++) {
VertIndex[count++] = (m_nWidthSize * (i)) + j-1;
VertIndex[count++] = (m_nWidthSize * (i-1)) + j-1;
VertIndex[count++] = (m_nWidthSize * (i)) + j;
VertIndex[count++] = (m_nWidthSize * (i)) + j;
VertIndex[count++] = (m_nWidthSize * (i-1)) + j-1;
VertIndex[count++] = (m_nWidthSize * (i-1)) + j;
//vertIndex[count++] = 1,0 (i,j-1)
//vertIndex[count++] = 0,0 (i-1,j-1)
//vertIndex[count++] = 1,1 (i,j)
//vertIndex[count++] = 1,1 (i,j)
//vertIndex[count++] = 0,0 (i-1,j-1)
//vertIndex[count++] = 0,1 (i-1,j)
}
}
m_IndexNum = count;
m_Device->CreateIndexBuffer((m_nWidthSize-2) * (m_nHeightSize-2) * 6 * sizeof(WORD),0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&(m_WaterIndexBuffer));
VOID *tmp_buffer;
m_WaterIndexBuffer->Lock(0,(m_nWidthSize-2) * (m_nHeightSize-2) * 6 * sizeof(WORD),(BYTE **)&tmp_buffer,0);
memcpy(tmp_buffer,VertIndex,(m_nWidthSize-2) * (m_nHeightSize-2) * 6 * sizeof(WORD));
m_WaterIndexBuffer->Unlock();
delete[] VertIndex;
}
void CWaterW::ChangeVertexBuffer() {
int i,j;
int count = 0;
CWaterVertex *m_WaterV = new CWaterVertex[(m_nHeightSize) * (m_nWidthSize)];
for(i=0;i<(m_nWidthSize);i++) {
for(j=0;j<(m_nHeightSize);j++) {
//quad setting
//left triangle
m_WaterV[count].x = m_ZeroPos.x + ((float)(j) * m_QuadSize);
m_WaterV[count].y = m_fLimitHeight + m_pWaterSpace[j][i];
m_WaterV[count].z = m_ZeroPos.z + ((float)(i)* m_QuadSize);
//normal
D3DXVECTOR3 tmp1;
D3DXVECTOR3 tmp2;
if((i-1 >=0) && (j-1 >=0)) {
tmp1.x = 0;
tmp1.y = m_pWaterSpace[j][i-1] - m_pWaterSpace[j][i];
tmp1.z = (i-1) - i;
D3DXVec3Normalize(&tmp1,&tmp1);
tmp2.x = (j-1) -j;
tmp2.y = m_pWaterSpace[j-1][i] - m_pWaterSpace[j][i];
tmp2.z = 0;
D3DXVec3Normalize(&tmp2,&tmp2);
D3DXVECTOR3 normal;
D3DXVec3Cross(&normal,&tmp1,&tmp2);
D3DXVec3Normalize(&normal,&normal);
m_WaterV[count].nx = normal.x;
m_WaterV[count].ny = normal.y;
m_WaterV[count].nz = normal.z;
}
else {
m_WaterV[count].nx = 0.0f;
m_WaterV[count].ny = 1.0f;
m_WaterV[count].nz = 0.0f;
}
count++;
}
}
VOID *tmp_buffer;
m_WaterVertexBuffer->Lock(0,(m_nHeightSize)*(m_nWidthSize)*sizeof(CWaterVertex),(BYTE **)&tmp_buffer,0);
memcpy(tmp_buffer,m_WaterV,((m_nHeightSize) * (m_nWidthSize) * sizeof(CWaterVertex)));
m_WaterVertexBuffer->Unlock();
delete[] m_WaterV;
}
bool CWaterW::SetTexture(char *filename,char *envfilename) {
CTexture::SetPath(EFFECTTEXTUREPATH);
if(strlen(filename) >0) {
m_WaterTexture.Load(filename);
}
if(strlen(envfilename) >0) {
m_WaterEnv.Load(envfilename);
return true;
}
return false;
}
// Water Scene 전체 업데이트
void CWaterW ::Update(float x,float y,float z) {
int x_index = (int)( (x - m_ZeroPos.x)/m_QuadSize);
int y_index = (int) ((z - m_ZeroPos.z)/m_QuadSize);
int flag = 0;
if(!(x == 0 && y == 0 && z==0))
if(x_index>= 0 && y_index >=0)
if(x_index <m_nWidthSize && y_index <m_nHeightSize) {
SetHeight(y_index,x_index,m_nChopPower);
flag = 1;
}
if(!flag) {
InitWaterW();
}
UpdateWaterW();
// ComputeWaterW();
}
void CWaterW ::CreateTexture() {
char* szSkyTex[6] = {
"c:\\lobbyxpos.bmp","c:\\lobbyxneg.bmp","c:\\lobbyypos.bmp","c:\\lobbyyneg.bmp","c:\\lobbyzneg.bmp","c:\\lobbyzpos.bmp"
};
for(int i = 0; i < 6; i++) {
D3DXCreateTextureFromFileEx(m_Device,szSkyTex[i], D3DX_DEFAULT, D3DX_DEFAULT,
1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT,
0, NULL, NULL, &m_pSkyTex[i]);
}
D3DXCreateCubeTexture(m_Device, 128, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, &m_pSkyCubeTex);
for(i = 0; i < 6; i++) {
if(m_pSkyTex[i]) {
IDirect3DSurface8 *pSrc;
IDirect3DSurface8 *pDest;
m_pSkyTex[i]->GetSurfaceLevel(0, &pSrc);
m_pSkyCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES) i, 0, &pDest);
if(pSrc && pDest)
D3DXLoadSurfaceFromSurface(pDest, NULL, NULL, pSrc, NULL, NULL, D3DX_DEFAULT, 0);
pDest->Release();
pSrc->Release();
}
}
D3DXFilterCubeTexture(m_pSkyCubeTex, NULL, 0, D3DX_DEFAULT);
}