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 + -
显示快捷键?