advtreegenerator.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 829 行 · 第 1/2 页
CPP
829 行
data[((y)*512+x)*4+3]=255-y*2;
}
}
}
for(int y=0;y<63;++y){
for(int x=0;x<512;++x){
if(data[((y+64)*512+x)*4+3]==0){
data[((y+64)*512+x)*4+3]=y*2;
} else {
data[((y+64)*512+x)*4+3]=255-y*2;
}
}
}
for(int y=0;y<63;++y){
for(int x=0;x<512;++x){
if(data[((y+128)*512+x)*4+3]==0){
data[((y+128)*512+x)*4+3]=y*2;
} else {
data[((y+128)*512+x)*4+3]=255-y*2;
}
}
}
}
void CAdvTreeGenerator::FixAlpha2(unsigned char* data)
{
for(int y=0;y<31;++y){
for(int x=0;x<256;++x){
if(data[((y)*256+x)*4+3]==0){
data[((y)*256+x)*4+3]=y*4;
} else {
data[((y)*256+x)*4+3]=255-y*4;
}
}
}
for(int y=0;y<31;++y){
for(int x=0;x<256;++x){
if(data[((y+32)*256+x)*4+3]==0){
data[((y+32)*256+x)*4+3]=y*4;
} else {
data[((y+32)*256+x)*4+3]=255-y*4;
}
}
}
for(int y=0;y<31;++y){
for(int x=0;x<256;++x){
if(data[((y+64)*256+x)*4+3]==0){
data[((y+64)*256+x)*4+3]=y*4;
} else {
data[((y+64)*256+x)*4+3]=255-y*4;
}
}
}
}
void CAdvTreeGenerator::CreateTex(unsigned char* data, unsigned int tex,int xsize,int ysize,bool fixAlpha,int maxMipLevel)
{
unsigned char* mipmaps[12];
mipmaps[0]=data;
int mipnum=0;
int xs=xsize;
int ys=ysize;
while(xsize!=1 || ysize!=1){
if(xsize!=1)
xsize/=2;
if(ysize!=1)
ysize/=2;
mipnum++;
mipmaps[mipnum]=SAFE_NEW unsigned char[max(2,xsize)*max(2,ysize)*4];
memset(mipmaps[mipnum],0,max(2,xsize)*max(2,ysize)*4);
for(int y=0;y<ysize;++y){
for(int x=0;x<xsize;++x){
int r=0,g=0,b=0,a=0;
for(int y2=0;y2<2;++y2){
for(int x2=0;x2<2;++x2){
int alpha=mipmaps[mipnum-1][((y*2+y2)*xsize*2+x*2+x2)*4+3];
r+=mipmaps[mipnum-1][((y*2+y2)*xsize*2+x*2+x2)*4+0]*alpha;
g+=mipmaps[mipnum-1][((y*2+y2)*xsize*2+x*2+x2)*4+1]*alpha;
b+=mipmaps[mipnum-1][((y*2+y2)*xsize*2+x*2+x2)*4+2]*alpha;
a+=alpha;
}
}
if(a!=0){
mipmaps[mipnum][((y)*xsize+x)*4+0]=(unsigned char)( (r+a*0.5f)/a );
mipmaps[mipnum][((y)*xsize+x)*4+1]=(unsigned char)( (g+a*0.5f)/a );
mipmaps[mipnum][((y)*xsize+x)*4+2]=(unsigned char)( (b+a*0.5f)/a );
} else {
mipmaps[mipnum][((y)*xsize+x)*4+0]=40;
mipmaps[mipnum][((y)*xsize+x)*4+1]=80;
mipmaps[mipnum][((y)*xsize+x)*4+2]=20;
}
mipmaps[mipnum][((y)*xsize+x)*4+3]=(unsigned char)( (a+2.0f)/4 );
}
}
}
xsize=xs*2;
ysize=ys*2;
mipnum=-1;
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
while(xsize!=1 || ysize!=1){
if(xsize!=1)
xsize/=2;
if(ysize!=1)
ysize/=2;
mipnum++;
if(mipnum>0){
for(int y=0;y<ysize;++y){
int cumError=0;
for(int x=0;x<xsize;++x){
if(mipmaps[mipnum][(y*xsize+x)*4+3]+cumError>126){
cumError+=int(mipmaps[mipnum][(y*xsize+x)*4+3])-255;
mipmaps[mipnum][(y*xsize+x)*4+3]=255;
} else {
cumError+=mipmaps[mipnum][(y*xsize+x)*4+3];
mipmaps[mipnum][(y*xsize+x)*4+3]=0;
for(int c=0;c<3;++c){
int alpha=0,col=0;
for(int y2=max(0,y-1);y2<min(ysize,y+2);++y2){
for(int x2=max(0,x-1);x2<min(xsize,x+2);++x2){
if(abs(x2-x)+abs(y2-y)==1){
if(mipmaps[mipnum][(y2*xsize+x2)*4+3]>126){
col+=mipmaps[mipnum][(y2*xsize+x2)*4+c];
alpha+=1;
}
}
}
}
if(alpha!=0)
mipmaps[mipnum][(y*xsize+x)*4+c]=(unsigned char)( (col+alpha*0.5f)/alpha ); // !
}
}
}
}
}
if(mipnum>maxMipLevel){
for(int y=0;y<ysize;++y){
for(int x=0;x<xsize;++x){
mipmaps[mipnum][(y*xsize+x)*4+3]=0;
}
}
}
if(fixAlpha && mipnum==0)
FixAlpha(mipmaps[0]);
if(fixAlpha && mipnum==1)
FixAlpha2(mipmaps[1]);
glTexImage2D(GL_TEXTURE_2D,mipnum,GL_RGBA8 ,xsize, ysize,0, GL_RGBA, GL_UNSIGNED_BYTE, mipmaps[mipnum]);
if(mipnum!=0)
delete[] mipmaps[mipnum];
}
}
void CAdvTreeGenerator::CreateGranTex(unsigned char* data, int xpos, int ypos, int xsize)
{
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glOrtho(-1,1,-1,1,-4,4);
glDisable(GL_TEXTURE_2D);
glDisable(GL_FOG);
glDisable(GL_BLEND);
glColor4f(1,1,1,1);
glViewport(0,0,256,256);
glAlphaFunc(GL_GREATER,0.5f);
glEnable(GL_ALPHA_TEST);
glDisable(GL_DEPTH_TEST);
glClearColor(0.0f,0.0f,0.0f,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
CreateGranTexBranch(ZeroVector,float3(0.93f,0.93f,0));
unsigned char* buf=SAFE_NEW unsigned char[256*256*4];
glReadPixels(0,0,256,256,GL_RGBA,GL_UNSIGNED_BYTE,buf);
for(int y=0;y<256;++y){
for(int x=0;x<256;++x){
if(buf[(y*256+x)*4]==0 && buf[(y*256+x)*4+1]==0 && buf[(y*256+x)*4+2]==0){
data[((y+ypos)*xsize+x+xpos)*4+0]=60;
data[((y+ypos)*xsize+x+xpos)*4+1]=90;
data[((y+ypos)*xsize+x+xpos)*4+2]=40;
data[((y+ypos)*xsize+x+xpos)*4+3]=0;
} else {
data[((y+ypos)*xsize+x+xpos)*4+0]=buf[(y*256+x)*4];
data[((y+ypos)*xsize+x+xpos)*4+1]=buf[(y*256+x)*4+1];
data[((y+ypos)*xsize+x+xpos)*4+2]=buf[(y*256+x)*4+2];
data[((y+ypos)*xsize+x+xpos)*4+3]=255;
}
}
}
delete[] buf;
glEnable(GL_DEPTH_TEST);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
void CAdvTreeGenerator::CreateGranTexBranch(const float3& start, const float3& end)
{
float3 dir=end-start;
float length=dir.Length();
dir.Normalize();
float3 orto=dir.cross(float3(0,0,1));
glBegin(GL_QUADS);
glColor3f(0.05f+fRand(0.02f),0.21f+fRand(0.05f),0.04f+fRand(0.01f));
glVertexf3(start+dir*0.006f+orto*0.007f);
glVertexf3(start+dir*0.006f-orto*0.007f);
glVertexf3(end-orto*0.007f);
glVertexf3(end+orto*0.007f);
glColor3f(0.18f,0.18f,0.07f);
glVertexf3(start+orto*length*0.01f);
glVertexf3(start-orto*length*0.01f);
glVertexf3(end-orto*0.001f);
glVertexf3(end+orto*0.001f);
glEnd();
float tipDist=0.025f;
float delta=0.013f;
int side=(rand()&1)*2-1;
while(tipDist<length*(0.83f+fRand(0.15f))){
float3 bstart=start+dir*(length-tipDist);
float3 bdir=dir+orto*side*(1.0f+fRand(0.7f));
bdir.Normalize();
float3 bend=bstart+bdir*tipDist*((6-tipDist)*(0.10f+fRand(0.05f)));
CreateGranTexBranch(bstart,bend);
side*=-1;
tipDist+=delta;
delta+=0.005f;
}
}
void CAdvTreeGenerator::PineTree(int numBranch, float height)
{
DrawPineTrunk(ZeroVector,float3(0,height,0),height*0.025f);
float3 orto1(1,0,0);
float3 orto2(0,0,1);
float baseAngle=fRand(2*PI);
for(int a=0;a<numBranch;++a){
float sh=0.2f+fRand(0.2f);
float h=pow(sh+float(a)/numBranch*(1-sh),(float)0.7f)*height;
float angle=baseAngle+(a*0.618f+fRand(0.1f))*2*PI;
float3 dir(orto1*sin(angle)+orto2*cos(angle));
dir.y=(a-numBranch)*0.01f-fRand(0.2f)-0.2f;
dir.Normalize();
float size=sqrt((float)numBranch-a+5)*0.08f*MAX_TREE_HEIGHT;
DrawPineBranch(float3(0,h,0),dir,size);
}
//create the top
float col=0.55f+fRand(0.2f);
va->AddVertexTN(float3(0,height-0.09f*MAX_TREE_HEIGHT,0), 0.126f+0.5f,0.02f,float3(0,0,col));
va->AddVertexTN(float3(0,height-0.03f*MAX_TREE_HEIGHT,0), 0.249f+0.5f,0.02f,float3(0.05f*MAX_TREE_HEIGHT,0,col));
va->AddVertexTN(float3(0,height-0.03f*MAX_TREE_HEIGHT,0), 0.126f+0.5f,0.98f,float3(-0.05f*MAX_TREE_HEIGHT,0,col));
va->AddVertexTN(float3(0,height-0.03f*MAX_TREE_HEIGHT,0), 0.249f+0.5f,0.02f,float3(0.05f*MAX_TREE_HEIGHT,0,col));
va->AddVertexTN(float3(0,height-0.03f*MAX_TREE_HEIGHT,0), 0.126f+0.5f,0.98f,float3(-0.05f*MAX_TREE_HEIGHT,0,col));
va->AddVertexTN(float3(0,height+0.03f*MAX_TREE_HEIGHT,0), 0.249f+0.5f,0.98f,float3(0,0,col));
}
void CAdvTreeGenerator::DrawPineTrunk(const float3 &start, const float3 &end, float size)
{
float3 orto1(1,0,0);
float3 orto2(0,0,1);
float3 flatSun=gs->sunVector;
flatSun.y=0;
int numIter=8;
for(int a=0;a<numIter;a++){
float angle=a/(float)numIter*2*PI;
float angle2=(a+1)/(float)numIter*2*PI;
float col=0.45f+(((orto1*sin(angle)+orto2*cos(angle)).dot(flatSun)))*0.3f;
float col2=0.45f+(((orto1*sin(angle2)+orto2*cos(angle2)).dot(flatSun)))*0.3f;
va->AddVertexTN(start+orto1*sin(angle)*size+orto2*cos(angle)*size, angle/PI*0.125f*0.5f+0.5f,0,float3(0,0,col));
va->AddVertexTN(end+orto1*sin(angle)*size*0.1f+orto2*cos(angle)*size*0.1f, angle/PI*0.125f*0.5f+0.5f,3,float3(0,0,col));
va->AddVertexTN(start+orto1*sin(angle2)*size+orto2*cos(angle2)*size, angle2/PI*0.125f*0.5f+0.5f,0,float3(0,0,col2));
va->AddVertexTN(start+orto1*sin(angle2)*size+orto2*cos(angle2)*size, angle2/PI*0.125f*0.5f+0.5f,0,float3(0,0,col2));
va->AddVertexTN(end+orto1*sin(angle)*size*0.1f+orto2*cos(angle)*size*0.1f, angle/PI*0.125f*0.5f+0.5f,3,float3(0,0,col));
va->AddVertexTN(end+orto1*sin(angle2)*size*0.1f+orto2*cos(angle2)*size*0.1f, angle2/PI*0.125f*0.5f+0.5f,3,float3(0,0,col2));
}
}
void CAdvTreeGenerator::DrawPineBranch(const float3 &start, const float3 &dir, float size)
{
float3 flatSun=gs->sunVector;
flatSun.y=0;
float3 orto1=dir.cross(UpVector);
orto1.Normalize();
float3 orto2=dir.cross(orto1);
float tex=float(int(rand()*3.0f/(float)RAND_MAX))*0.125f;
float baseCol=0.4f+dir.dot(flatSun)*0.3f+fRand(0.1f);
float col1=baseCol+fRand(0.2f);
float col2=baseCol+fRand(0.2f);
float col3=baseCol+fRand(0.2f);
float col4=baseCol+fRand(0.2f);
float col5=baseCol+fRand(0.2f);
va->AddVertexTN(start, 0.126f+tex+0.5f,0.02f,float3(0,0,col1));
va->AddVertexTN(start+dir*size*0.5f+orto1*size*0.5f+orto2*size*0.2f, 0.249f+tex+0.5f,0.02f,float3(0,0,col2));
va->AddVertexTN(start+dir*size*0.5f, 0.1875f+tex+0.5f,0.50f,float3(0,0,col4));
va->AddVertexTN(start, 0.126f+tex+0.5f,0.02f,float3(0,0,col1));
va->AddVertexTN(start+dir*size*0.5f-orto1*size*0.5f+orto2*size*0.2f, 0.126f+tex+0.5f,0.98f,float3(0,0,col3));
va->AddVertexTN(start+dir*size*0.5f, 0.1875f+tex+0.5f,0.50f,float3(0,0,col4));
va->AddVertexTN(start+dir*size*0.5f, 0.1875f+tex+0.5f,0.50f,float3(0,0,col4));
va->AddVertexTN(start+dir*size*0.5f+orto1*size*0.5f+orto2*size*0.2f, 0.249f+tex+0.5f,0.02f,float3(0,0,col2));
va->AddVertexTN(start+dir*size+orto2*size*0.1f, 0.249f+tex+0.5f,0.98f,float3(0,0,col5));
va->AddVertexTN(start+dir*size*0.5f, 0.1875f+tex+0.5f,0.50f,float3(0,0,col4));
va->AddVertexTN(start+dir*size*0.5f-orto1*size*0.5f+orto2*size*0.2f, 0.126f+tex+0.5f,0.98f,float3(0,0,col3));
va->AddVertexTN(start+dir*size+orto2*size*0.1f, 0.249f+tex+0.5f,0.98f,float3(0,0,col5));
}
float CAdvTreeGenerator::fRand(float size)
{
return float(rand())/RAND_MAX*size;
}
void CAdvTreeGenerator::CreateLeafTex(unsigned int baseTex, int xpos, int ypos,unsigned char buf[256][2048][4])
{
unsigned char* buf2=SAFE_NEW unsigned char[256*256*4];
glViewport(0,0,256,256);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -5, 5);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER,0.5f);
glBindTexture(GL_TEXTURE_2D, baseTex);
glEnable(GL_TEXTURE_2D);
glDisable(GL_FOG);
glDisable(GL_BLEND);
glColor4f(1,1,1,1);
glClearColor(0.0f,0.0f,0.0f,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float baseCol=0.8f+fRand(0.2f);
for(int a=0;a<84;++a){
float xp=0.9f-fRand(1.8f);
float yp=0.9f-fRand(1.8f);
float rot=fRand(360);
float rCol=0.7f+fRand(0.3f);
float gCol=0.7f+fRand(0.3f);
float bCol=0.7f+fRand(0.3f);
glPushMatrix();
glLoadIdentity();
glColor3f(baseCol*rCol,baseCol*gCol,baseCol*bCol);
glTranslatef(xp,yp,0);
glRotatef(rot,0,0,1);
glRotatef(fRand(360),1,0,0);
glRotatef(fRand(360),0,1,0);
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex3f(-0.1f,-0.2f,0);
glTexCoord2f(0,1); glVertex3f(-0.1f,0.2f,0);
glTexCoord2f(1,1); glVertex3f(0.1f,0.2f,0);
glTexCoord2f(1,0); glVertex3f(0.1f,-0.2f,0);
glEnd();
glPopMatrix();
}
glReadPixels(0,0,256,256,GL_RGBA,GL_UNSIGNED_BYTE,buf2);
// CBitmap bm(buf2,256,256);
// bm.Save("leaf.bmp");
for(int y=0;y<256;++y){
for(int x=0;x<256;++x){
if(buf2[(y*256+x)*4+1]!=0){
buf[y+ypos][x+xpos][0]=buf2[(y*256+x)*4+0];
buf[y+ypos][x+xpos][1]=buf2[(y*256+x)*4+1];
buf[y+ypos][x+xpos][2]=buf2[(y*256+x)*4+2];
buf[y+ypos][x+xpos][3]=255;
} else {
buf[y+ypos][x+xpos][0]=(unsigned char)(0.24f*1.2f*255);
buf[y+ypos][x+xpos][1]=(unsigned char)(0.40f*1.2f*255);
buf[y+ypos][x+xpos][2]=(unsigned char)(0.23f*1.2f*255);
buf[y+ypos][x+xpos][3]=0;
}
}
}
glViewport(gu->viewPosX,0,gu->viewSizeX,gu->viewSizeY);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
delete[] buf2;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?