Files
Client/GameTools/Zallad3D SceneClass/WBLightMapBuild.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

529 lines
11 KiB
C++
Raw Blame History

// WBLightMapBuild.cpp: implementation of the WBLightMapBuild class.
//
//////////////////////////////////////////////////////////////////////
#include "WBLightMapBuild.h"
#include "WBLightMapGenerator.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
unsigned char expose(float light,float exposure)
{
float e=(float)exp(-light*exposure);
return (unsigned char)((1.0f-e)*255.0f);
}
WBLightMapBuild::~WBLightMapBuild()
{
delete[] rad;
delete[] emm;
}
void WBLightMapBuild::set_base(int flag)
{
alloc_data(flag);
totalenergy = D3DXVECTOR3(0.0f,0.0f,0.0f);
if (m_iFaceId != -1)
{
float facearea=WBLightMapGenerator::m_lstFaces[m_iFaceId]->area();
pixelarea=facearea/(sizex*sizey);
}
else
pixelarea=0;
}
void WBLightMapBuild::compute_bgshadow()
{
int x,y;
float fi=1.0f/sizex,fj=1.0f/sizey,fu,fv;
D3DXVECTOR3 p,n;
float *r=rad,bgs;
fv=fj*0.5f;
for( y=0;y<sizey;y++,fv+=fj )
{
fu=fi*0.5f;
for( x=0;x<sizex;x++,fu+=fi )
{
map_point_local(fu,fv,p,n);
// world point, normal
bgs=WBLightMapGenerator::compute_bgshadow(p,n);
r[0]*=bgs;
r[1]*=bgs;
r[2]*=bgs;
r+=3;
}
}
}
void WBLightMapBuild::Blurring()
{
int i,j,k;
float *r=rad;
for( i = 0; i < sizey; i++ )
{
for( j = 0; j < sizex; j++ )
{
float *pCurrent1 = &(r[(i * bytesx) + (j * bytespixel)]);
float *pCurrent2 = &(r[(i * bytesx) + (j * bytespixel) + 1]);
float *pCurrent3 = &(r[(i * bytesx) + (j * bytespixel) + 2]);
float ucSum[3];
ucSum[0] = (*pCurrent1);
ucSum[1] = (*pCurrent2);
ucSum[2] = (*pCurrent3);
int iLegal = 0;
if(i > 0) // Up Pixel
{
ucSum[0] += r[( (i - 1) * bytesx ) + (j * bytespixel)] / 2.0f;
ucSum[1] += r[( (i - 1) * bytesx ) + (j * bytespixel) + 1]/ 2.0f;
ucSum[2] += r[( (i - 1) * bytesx ) + (j * bytespixel) + 2]/ 2.0f;
iLegal++;
}
if(i < (sizey - 1)) // Down Pixel
{
ucSum[0] += r[( (i + 1) * bytesx ) + (j * bytespixel)]/ 2.0f;
ucSum[1] += r[( (i + 1) * bytesx ) + (j * bytespixel) + 1]/ 2.0f;
ucSum[2] += r[( (i + 1) * bytesx ) + (j * bytespixel) + 2]/ 2.0f;
iLegal++;
}
if(j > 0) // Left
{
ucSum[0] += r[( i * bytesx ) + ((j - 1) * bytespixel)]/ 2.0f;
ucSum[1] += r[( i * bytesx ) + ((j - 1) * bytespixel) + 1]/ 2.0f;
ucSum[2] += r[( i * bytesx ) + ((j - 1) * bytespixel) + 2]/ 2.0f;
iLegal++;
}
if( j < (sizex - 1)) // Right
{
ucSum[0] += r[( i * bytesx ) + ((j + 1) * bytespixel)]/ 2.0f;
ucSum[1] += r[( i * bytesx ) + ((j + 1) * bytespixel) + 1]/ 2.0f;
ucSum[2] += r[( i * bytesx ) + ((j + 1) * bytespixel) + 2]/ 2.0f;
iLegal++;
}
if((i > 0) && (j > 0)) // Up Left
{
ucSum[0] += r[( (i - 1)* bytesx ) + ((j - 1) * bytespixel)]/ 2.0f;
ucSum[1] += r[( (i - 1)* bytesx ) + ((j - 1) * bytespixel) + 1]/ 2.0f;
ucSum[2] += r[( (i - 1)* bytesx ) + ((j - 1) * bytespixel) + 2]/ 2.0f;
iLegal++;
}
if((i < (sizey -1)) && (j > 0)) // Down Left
{
ucSum[0] += r[( (i + 1) * bytesx ) + ((j - 1) * bytespixel)]/ 2.0f;
ucSum[1] += r[( (i + 1) * bytesx ) + ((j - 1) * bytespixel) + 1]/ 2.0f;
ucSum[2] += r[( (i + 1) * bytesx ) + ((j - 1) * bytespixel) + 2]/ 2.0f;
iLegal++;
}
if((i > 0) && (j < (sizex - 1))) //Up Right
{
ucSum[0] += r[( (i - 1) * bytesx ) + ((j + 1) * bytespixel)]/ 2.0f;
ucSum[1] += r[( (i - 1) * bytesx ) + ((j + 1)* bytespixel) + 1]/ 2.0f;
ucSum[2] += r[( (i - 1) * bytesx ) + ((j + 1)* bytespixel) + 2]/ 2.0f;
iLegal++;
}
if( (i < (sizey - 1)) && ( j < (sizex - 1))) //Down Right
{
ucSum[0] += r[( (i + 1) * bytesx ) + ((j + 1) * bytespixel)]/ 2.0f;
ucSum[1] += r[( (i + 1) * bytesx ) + ((j + 1) * bytespixel) + 1]/ 2.0f;
ucSum[2] += r[( (i + 1) * bytesx ) + ((j + 1) * bytespixel) + 2]/ 2.0f;
iLegal++;
}
for(k = 0; k < 3; k++ )
{
float iSum = (float)ucSum[k];
iSum = (float)(iSum / (float)iLegal);
ucSum[k] = (float)iSum;
}
(*pCurrent1) = ucSum[0];
(*pCurrent2) = ucSum[1];
(*pCurrent3) = ucSum[2];
}
}
}
void WBLightMapBuild::alloc_data(int flag)
{
int i,j=sizex*sizey;
float ambient=WBLightMapGenerator::m_iLightMapAmb/255.0f;
delete[] rad;
j*=3;
rad=new float[j];
for( i=0;i<j;i++ )
rad[i]=ambient;
if (flag)
{
delete[] emm;
j*=3;
emm=new float[j];
for( i=0;i<j;i++ )
emm[i]=ambient;
}
}
void WBLightMapBuild::set_data(int flag,int x,int y,float *f)
{
int p=(x+y*sizex)*3;
if (flag)
{
rad[p]=f[0];
rad[p+1]=f[1];
rad[p+2]=f[2];
}
else
{
emm[p]=f[0];
emm[p+1]=f[1];
emm[p+2]=f[2];
}
}
void WBLightMapBuild::save_to_lightmap(float exposure)
{
int i,j,k;
float *f=rad;
unsigned char *uc=bmp;
if (exposure==0)
{
for( j=0;j<sizey;j++ )
for( i=0;i<sizex;i++ )
for( k=0;k<3;k++,f++ )
{
int z=(int)(*f*255);
*(uc++)=z<0?0:z>255?255:z;
}
}
else
{
for( j=0;j<sizey;j++ )
{
for( i=0;i<sizex;i++ ) {
int iNum = 0;
for( k=0;k<3;k++,f++ ) {
*(uc)=expose(*f,exposure);
if(*(uc) < (WBLightMapGenerator::m_iLightMapAmb))
iNum++;
uc++;
}
}
}
}
}
// pos : Light Pos, color : Light Color radius : light rad
void WBLightMapBuild::illum(D3DXVECTOR3& pos,D3DXVECTOR3& color,float radius,int shadows)
{
int i,j;
float dist,dot,r=radius*radius;
float fi=1.0f/sizex,fj=1.0f/sizey,fu,fv;
D3DXVECTOR3 p,dir,n;
float *data=rad;
fv=fj*0.5f;
for( j=0;j<sizey;j++,fv+=fj )
{
fu=fi*0.5f;
for( i=0;i<sizex;i++,fu+=fi )
{
map_point_local(fu,fv,p,n);
dir.x=(p.x)-(pos.x);
dir.y=(p.y)-(pos.y);
dir.z=(p.z)-(pos.z);
dist = (dir.x * dir.x) + (dir.y * dir.y) + (dir.z * dir.z);
if (dist>r)
data+=3;
else
{
dist=(float)sqrt(dist);
dir*=(1.0f/dist);
dot=D3DXVec3Dot(&dir,&n);
if ((shadows&4) && dot>0)
{
data+=3;
continue;
}
if (shadows&8 &&
!WBLightMapGenerator::collision_test(pos+n+dir,p-dir))
{
data+=3;
continue;
}
if(WBLightMapGenerator::collision_test(pos+n+dir,p-dir,m_iFaceId,1))
{
data+=3;
continue;
}
dist=(1.0f - (dist/radius));
if (shadows&2)
dist*=dist;
if (shadows&4)
dist*=-dot;
// 0.0 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>°<EFBFBD> <20><><EFBFBD><EFBFBD>
*(data)+=color.x*dist;
if(*(data) < 0.0f)
*(data) = 0.0f;
data++;
*(data)+=color.y*dist;
if(*(data) < 0.0f)
*(data) = 0.0f;
data++;
*(data)+=color.z*dist;
if(*(data) < 0.0f)
*(data) = 0.0f;
data++;
}
}
}
}
D3DXVECTOR3 WBLightMapBuild::tri_receive_light(WBLightMapFace *f,D3DXVECTOR3& P,D3DXVECTOR3& N,D3DXVECTOR3& E,int flag)
{
D3DXVECTOR3 receivedenergy = D3DXVECTOR3(0.0f,0.0f,0.0f);
D3DXVECTOR3 p,n,dir,e;
//float l2,dot1,dot2;
float *r1=&(WBLightMapGenerator::emm[f->m_iStartIndex*3]);
float *r2=&(WBLightMapGenerator::rad[f->m_iStartIndex*3]);
D3DXVECTOR3 reflectance;
/* if (f->sh!=-1)
reflectance=g_flyengine->shaders[f->sh]->color;
else
reflectance.vec(1);
int i;
for( i=0;i<f->nvert;i++,r1+=3,r2+=3 )
{
p=f->vert[i+f->vertindx];
n=f->vert[i+f->vertindx].normal;
dir=P-p;
l2=dir.length2();
if (l2<10.0f)
continue;
dir*=1.0f/(float)sqrt(l2);
dot1=FLY_VECDOT(dir,n);
if (dot1<=0.01f)
continue;
if (l2<1000)
dot1*=l2/1000.0f;
if (flag==0)
{
dot2=-FLY_VECDOT(dir,N);
if (dot2<=0.01f)
continue;
e=(E*reflectance)*((dot1*dot2)/(l2*FLY_2PI));
}
else
e=(E*reflectance)*(dot1/(l2*2.0f*FLY_2PI));
if ((lmshadows&8) &&
g_flyengine->collision_test(P+N+dir,p+dir,FLY_TYPE_STATICMESH))
continue;
r1[0]+=e.x;
r1[1]+=e.y;
r1[2]+=e.z;
r2[0]+=e.x;
r2[1]+=e.y;
r2[2]+=e.z;
receivedenergy+=e;
}
*/
return receivedenergy;
}
D3DXVECTOR3 WBLightMapBuild::receive_light(D3DXVECTOR3& P,D3DXVECTOR3& N,D3DXVECTOR3& E,int flag)
{
/* if (lastupdate==-1)
return flyVector(0);
int x,y;
float fi=1.0f/sizex,fj=1.0f/sizey,fu,fv;
float *f=emm,*r=rad;
flyVector p,n,dir,e;
float l2,dot1,dot2;
flyVector receivedenergy(0);
((flyEngineBuild *)g_flyengine)->unshotenergy-=totalenergy;
fv=fj*0.5f;
for( y=0;y<sizey;y++,fv+=fj )
{
fu=fi*0.5f;
for( x=0;x<sizex;x++,fu+=fi,receivedenergy+=flyVector(f[0]*pixelarea,f[1]*pixelarea,f[2]*pixelarea),f+=3,r+=3 )
{
map_point_local(fu,fv,p,n);
dir=P-p;
l2=dir.length2();
if (l2<10.0f)
continue;
dir*=1.0f/(float)sqrt(l2);
dot1=FLY_VECDOT(dir,n);
if (dot1<=0.01f)
continue;
if (l2<1000)
dot1*=l2/1000.0f;
if (flag==0)
{
dot2=-FLY_VECDOT(dir,N);
if (dot2<=0.01f)
continue;
e=(E*reflectance)*((dot1*dot2)/(l2*FLY_2PI));
}
else
e=(E*reflectance)*(dot1/(l2*2.0f*FLY_2PI));
if ((lmshadows&8) &&
g_flyengine->collision_test(P+N+dir,p+dir,FLY_TYPE_STATICMESH))
continue;
f[0]+=e.x;
f[1]+=e.y;
f[2]+=e.z;
r[0]+=e.x;
r[1]+=e.y;
r[2]+=e.z;
}
}
e.vec(receivedenergy.x-totalenergy.x,receivedenergy.y-totalenergy.y,receivedenergy.z-totalenergy.z);
totalenergy=receivedenergy;
((flyEngineBuild *)g_flyengine)->unshotenergy+=totalenergy;
return e;*/
return D3DXVECTOR3(0.0f,0.0f,0.0f);
}
int WBLightMapBuild::emmit_light()
{
/* if (lastupdate==-1)
{
((flyEngineBuild *)g_flyengine)->unshotenergy-=totalenergy;
totalenergy.vec(0,0,0);
return 1;
}
int x,y,i,j,k;
flyVector p,n,energy;
float fi=1.0f/sizex,fj=1.0f/sizey,fu,fv;
flyBspNode *node;
flyMesh *mesh;
flyFace **face;
float *f=emm;
flyLightMapBuild *lmb;
flyVector transferedenergy(0);
fv=fj*0.5f;
for( y=0;y<sizey;y++,fv+=fj )
{
fu=fi*0.5f;
for( x=0;x<sizex;x++,fu+=fi,f[0]=f[1]=f[2]=0,f+=3,cur_emm++ )
{
if (_kbhit())
if (_getch()==27)
return 0;
map_point_local(fu,fv,p,n);
energy.vec(pixelarea*f[0],pixelarea*f[1],pixelarea*f[2]);
node=g_flyengine->find_node(p);
if (node==0)
continue;
j=node->leaf;
for( i=0;i<g_flyengine->nleaf;i++ )
if (FLY_GLOBAL_PVS_TEST(j,i) &&
g_flyengine->leaf[i]->elem.num &&
g_flyengine->leaf[i]->elem[0]->type==FLY_TYPE_STATICMESH)
{
mesh=((flyStaticMesh *)g_flyengine->leaf[i]->elem[0])->objmesh;
if (mesh)
{
face=mesh->faces;
for( k=0;k<mesh->nf;k++ )
if (face[k]->lastupdate!=cur_emm)
if (face[k]->lm!=-1)
{
face[k]->lastupdate=cur_emm;
lmb=(flyLightMapBuild *)g_flyengine->lm[face[k]->lm];
if (this!=lmb)
transferedenergy+=lmb->receive_light(p,n,energy);
}
else
if (face[k]->facetype==FLY_FACETYPE_TRIANGLE_MESH)
{
face[k]->lastupdate=cur_emm;
transferedenergy+=tri_receive_light(face[k],p,n,energy);
}
}
}
}
}
float t=Intensity(transferedenergy)/Intensity(totalenergy)*100.0f;
if (t>100)
printf("Warning! energy generation %f%%!\n",t);
((flyEngineBuild *)g_flyengine)->unshotenergy-=totalenergy;
totalenergy.vec(0,0,0);
return 1;
*/
return 1;
}