advtreegenerator.cpp

来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 829 行 · 第 1/2 页

CPP
829
字号
// DrawTree.cpp: implementation of the CAdvTreeGenerator class.
//
//////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "AdvTreeGenerator.h"
#include "Rendering/GL/myGL.h"
#include "Rendering/GL/VertexArray.h"
#include "Game/Camera.h"
#include "Rendering/Textures/Bitmap.h"
#include "Map/ReadMap.h"
#include "Rendering/ShadowHandler.h"
#include "mmgr.h"

using namespace std;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CAdvTreeGenerator* treeGen;

//namespace std{
//void _Xlen(){};
//}

CAdvTreeGenerator::CAdvTreeGenerator()
{
	PrintLoadMsg("Generating trees");
	unsigned char(* tree)[2048][4]=SAFE_NEW unsigned char[256][2048][4];
	memset(tree[0][0],128,256*2048*4);

	TdfParser resources("gamedata/resources.tdf");

	CBitmap bm;
	std::string fn("bitmaps/"+resources.SGetValueDef("Bark.bmp","resources\\graphics\\trees\\bark"));
	if (!bm.Load(fn) || bm.xsize != 256 || bm.ysize != 256)
		throw content_error("Could not load tree texture from file " + fn);
	for(int y=0;y<256;y++){
		for(int x=0;x<256;x++){
			tree[y][x][0]=bm.mem[(y*256+x)*4];
			tree[y][x][1]=bm.mem[(y*256+x)*4+1];
			tree[y][x][2]=bm.mem[(y*256+x)*4+2];
			tree[y][x][3]=255;
		}
	}
	fn = "bitmaps/"+resources.SGetValueDef("bleaf.bmp","resources\\graphics\\trees\\leaf");
	if (!bm.Load(fn))
		throw content_error("Could not load tree texture from file " + fn);
	bm.CreateAlpha(0,0,0);
	//bm.Save("baseleaf.bmp");
	bm.Renormalize(float3(0.22f,0.43f,0.18f)*1.0f);
//	bm.Save("baseleaf2.bmp");
	GLuint leafTex;
	glGenTextures(1, &leafTex);
	glBindTexture(GL_TEXTURE_2D, leafTex);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,bm.xsize, bm.ysize, GL_RGBA, GL_UNSIGNED_BYTE, bm.mem);

	CreateLeafTex(leafTex,256,0,tree);
	CreateLeafTex(leafTex,512,0,tree);
	CreateLeafTex(leafTex,768,0,tree);

	glDeleteTextures (1, &leafTex);

	fn = "bitmaps/"+resources.SGetValueDef("Bark.bmp","resources\\graphics\\trees\\bark");
	if (!bm.Load(fn) || bm.xsize != 256 || bm.ysize != 256)
		throw content_error("Could not load tree texture from file " + fn);
	for(int y=0;y<256;y++){
		for(int x=0;x<256;x++){
			tree[y][x+1024][0]=(unsigned char)(bm.mem[(y*256+x)*4]*0.6f);
			tree[y][x+1024][1]=(unsigned char)(bm.mem[(y*256+x)*4+1]*0.6f);
			tree[y][x+1024][2]=(unsigned char)(bm.mem[(y*256+x)*4+2]*0.6f);
			tree[y][x+1024][3]=255;
		}
	}

	unsigned char* data=tree[0][0];
	CreateGranTex(data,1024+768,0,2048);
	CreateGranTex(data,1280,0,2048);
	CreateGranTex(data,1536,0,2048);
//	CBitmap b(data,2048,256);
//	b.Save("PartTex.bmp");

	glGenTextures(1, &barkTex);
	CreateTex(data,barkTex,2048,256,false,10);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST);

	delete[] tree;


	treeNSVP=LoadVertexProgram("treeNS.vp");

	leafDL=glGenLists(8);
	srand((unsigned int)15);
	for(int a=0;a<8;++a){
		va=GetVertexArray();
		va->Initialize();
		barkva=GetVertexArray();
		barkva->Initialize();

		glNewList(leafDL+a,GL_COMPILE);
		float size=0.65f+fRand(0.2f);
		MainTrunk(10,size*MAX_TREE_HEIGHT,size*0.05f*MAX_TREE_HEIGHT);
		va->DrawArrayTN(GL_QUADS);
		barkva->DrawArrayTN(GL_TRIANGLE_STRIP);

		glEndList();
	}

	pineDL=glGenLists(8);
	srand((unsigned int)15);
	for(int a=0;a<8;++a){
		va=GetVertexArray();
		va->Initialize();

		glNewList(pineDL+a,GL_COMPILE);
		float size=0.7f+fRand(0.2f);
		PineTree((int)(20+fRand(10)),MAX_TREE_HEIGHT*size);
		va->DrawArrayTN(GL_TRIANGLES);

		glEndList();
	}
	CreateFarTex();

	if(shadowHandler->canUseShadows){
		treeVP=LoadVertexProgram("tree.vp");
		treeFarVP=LoadVertexProgram("treeFar.vp");
		treeShadowVP=LoadVertexProgram("treeShadow.vp");
		treeFarShadowVP=LoadVertexProgram("treeFarShadow.vp");
		if(shadowHandler->useFPShadows){
			treeFPShadow=LoadFragmentProgram("treeFPshadow.fp");
		}
	}
}

CAdvTreeGenerator::~CAdvTreeGenerator()
{
	glDeleteTextures (1, &barkTex);
	glDeleteTextures (2, farTex);
	glDeleteLists(leafDL,8);
	glDeleteLists(pineDL,8);
//	delete[] grassCol;
	glSafeDeleteProgram( treeNSVP );
	if(shadowHandler->canUseShadows){
		glSafeDeleteProgram( treeVP );
		glSafeDeleteProgram( treeFarVP );
		glSafeDeleteProgram( treeShadowVP );
		glSafeDeleteProgram( treeFarShadowVP );
		if(shadowHandler->useFPShadows){
			glSafeDeleteProgram( treeFPShadow );
		}
	}
}

void CAdvTreeGenerator::Draw()
{
}

void CAdvTreeGenerator::DrawTrunk(const float3 &start, const float3 &end,const float3& orto1,const float3& orto2, float size)
{
	float3 flatSun=gs->sunVector;
	flatSun.y=0;

	int numIter=(int)max(3.0f,size*10);
	for(int a=0;a<=numIter;a++){
		float angle=a/(float)numIter*2*PI;
		float col=0.4f+(((orto1*sin(angle)+orto2*cos(angle)).dot(flatSun)))*0.3f;
		barkva->AddVertexTN(start+orto1*sin(angle)*size+orto2*cos(angle)*size,angle/PI*0.125f*0.5f,0,float3(0,0,col));
		barkva->AddVertexTN(end+orto1*sin(angle)*size*0.2f+orto2*cos(angle)*size*0.2f,angle/PI*0.125f*0.5f,3,float3(0,0,col));
	}
	barkva->EndStrip();
}

void CAdvTreeGenerator::MainTrunk(int numBranch,float height,float width)
{
	float3 orto1(1,0,0);
	float3 orto2(0,0,1);

	DrawTrunk(ZeroVector,float3(0,height,0),orto1,orto2,width);

	float baseAngle=fRand(2*PI);
	for(int a=0;a<numBranch;++a){
		float angle=baseAngle+a*3.88f+fRand(0.5f);
		float3 dir=orto1*sin(angle)+orto2*cos(angle);
		dir.y=0.3f+fRand(0.4f);
		dir.Normalize();
		float3 start(0,(a+5)*height/(numBranch+5),0);
		float length=(height*(0.4f+fRand(0.1f)))*sqrt(float(numBranch-a)/numBranch);
		TrunkIterator(start,dir,length,length*0.05f,1);
	}
	for(int a=0;a<3;++a){
		float angle=a*3.88f+fRand(0.5f);
		float3 dir=orto1*sin(angle)+orto2*cos(angle);
		dir.y=0.8f;
		dir.Normalize();
		float3 start(0,height-0.3f,0);
		float length=MAX_TREE_HEIGHT*0.1f;
		TrunkIterator(start,dir,length,length*0.05f,0);
	}
}

void CAdvTreeGenerator::TrunkIterator(float3 &start, float3 &dir, float length, float size, int depth)
{
	float3 orto1;
	if(dir.dot(UpVector)<0.9f)
		orto1=dir.cross(UpVector);
	else
		orto1=dir.cross(float3(1,0,0));
	orto1.Normalize();
	float3 orto2=dir.cross(orto1);
	orto2.Normalize();

	DrawTrunk(start,start+dir*length,orto1,orto2,size);

	if(depth<=1)
		CreateLeaves(start,dir,length,orto1,orto2);

	if(depth==0)
		return;

	float dirDif=fRand(0.8f)+1.0f;
	int numTrunks=(int)length*5/MAX_TREE_HEIGHT;
	for(int a=0;a<numTrunks;a++){
		float angle=PI+float(a)*PI+fRand(0.3f);
		float3 newbase=start+dir*length*(float(a+1)/(numTrunks+1));
		float3 newDir=dir+orto1*cos(angle)*dirDif+orto2*sin(angle)*dirDif;
		newDir.Normalize();
		float newLength=length*(float(numTrunks-a)/(numTrunks+1));
		TrunkIterator(newbase,newDir,newLength,newLength*0.05f,depth-1);
	}
}

void CAdvTreeGenerator::CreateLeaves(float3 &start, float3 &dir, float length,float3& orto1,float3& orto2)
{
	float baseRot=fRand(2*PI);
	int numLeaves=(int)length*10/MAX_TREE_HEIGHT;

	float3 flatSun=gs->sunVector;
	flatSun.y=0;

	for(int a=0;a<numLeaves+1;a++){
		float3 pos=start+dir*length*(0.7f+fRand(0.3f));
		float angle=baseRot+a*0.618f*2*PI;
		pos+=(orto1*sin(angle)+orto2*cos(angle))*(sqrt((float)a+1)*0.6f+fRand(0.4f))*0.1f*MAX_TREE_HEIGHT;
		if(pos.y<0.2f*MAX_TREE_HEIGHT)
			pos.y=0.2f*MAX_TREE_HEIGHT;

		float tex=float(int(rand()*3/RAND_MAX))*0.125f;
		float flipTex=float(int(rand()*2/RAND_MAX))*0.123f;

		float3 npos=pos;
		npos.y=0;
		npos.Normalize();
		float col=0.5f+npos.dot(flatSun)*0.3f+fRand(0.1f);
		va->AddVertexTN(pos,0.126f+tex+flipTex,0.98f,float3(0.09f*MAX_TREE_HEIGHT,-0.09f*MAX_TREE_HEIGHT,col));
		va->AddVertexTN(pos,0.249f+tex-flipTex,0.98f,float3(-0.09f*MAX_TREE_HEIGHT,-0.09f*MAX_TREE_HEIGHT,col));
		va->AddVertexTN(pos,0.249f+tex-flipTex,0.02f,float3(-0.09f*MAX_TREE_HEIGHT,0.09f*MAX_TREE_HEIGHT,col));
		va->AddVertexTN(pos,0.126f+tex+flipTex,0.02f,float3(0.09f*MAX_TREE_HEIGHT,0.09f*MAX_TREE_HEIGHT,col));
	}
	float3 pos=start+dir*length*1.03f;

	float tex=float(int(rand()*3/RAND_MAX))*0.125f;
	float flipTex=float(int(rand()*2/RAND_MAX))*0.123f;

	float3 npos=pos;
	npos.y=0;
	npos.Normalize();
	float col=0.5f+npos.dot(flatSun)*0.3f+fRand(0.1f);
	va->AddVertexTN(pos,0.126f+tex+flipTex,0.98f,float3(0.09f*MAX_TREE_HEIGHT,-0.09f*MAX_TREE_HEIGHT,col));
	va->AddVertexTN(pos,0.249f+tex-flipTex,0.98f,float3(-0.09f*MAX_TREE_HEIGHT,-0.09f*MAX_TREE_HEIGHT,col));
	va->AddVertexTN(pos,0.249f+tex-flipTex,0.02f,float3(-0.09f*MAX_TREE_HEIGHT,0.09f*MAX_TREE_HEIGHT,col));
	va->AddVertexTN(pos,0.126f+tex+flipTex,0.02f,float3(0.09f*MAX_TREE_HEIGHT,0.09f*MAX_TREE_HEIGHT,col));
}

void CAdvTreeGenerator::CreateFarTex()
{
	unsigned char* data=SAFE_NEW unsigned char[512*512*4];
	unsigned char* data2=SAFE_NEW unsigned char[512*512*4];
	for(int y=0;y<512;++y){
		for(int x=0;x<512;++x){
				data[((y)*512+x)*4+0]=60;
				data[((y)*512+x)*4+1]=90;
				data[((y)*512+x)*4+2]=40;
				data[((y)*512+x)*4+3]=0;
		}
	}

	glPushMatrix();
	glLoadIdentity();
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glBindTexture(GL_TEXTURE_2D, barkTex);
	glEnable(GL_TEXTURE_2D);
	glBindProgramARB( GL_VERTEX_PROGRAM_ARB, treeNSVP );
	glEnable( GL_VERTEX_PROGRAM_ARB );
//	glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0,  GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV);
	glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,13, 1,0,0,0);	//camera side
	glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,9, 0,1,0,0);	//camera up
	glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,10,0,0,0,0);	//position delta
	glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,11, readmap->sunColor.x,readmap->sunColor.y,readmap->sunColor.z,0.85f);
	glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,14, readmap->ambientColor.x,readmap->ambientColor.y,readmap->ambientColor.z,0.85f);
	glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,12,0,0,0,0.02f);	//w=alpha/height modifier
	glAlphaFunc(GL_GREATER,0.5f);
	glDisable(GL_FOG);
	glDisable(GL_BLEND);
	glColor4f(1,1,1,1);
	glViewport(0,0,64,64);
	glAlphaFunc(GL_GREATER,0.5f);
	glEnable(GL_ALPHA_TEST);

	for(int a=0;a<8;++a){
		glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,13,  1,0,0,0);	//camera side
		glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,9,  0,1,0,0);	//camera up
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glScalef(-1,1,1);
		glOrtho(-MAX_TREE_HEIGHT*0.5f,MAX_TREE_HEIGHT*0.5f,0,MAX_TREE_HEIGHT,-MAX_TREE_HEIGHT*0.5f,MAX_TREE_HEIGHT*0.5f);
		CreateFarView(data,a*64,0,leafDL+a);
		CreateFarView(data,a*64,256,pineDL+a);
		glScalef(-1,1,1);

		glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,13,  0,0,1,0);
		glMatrixMode(GL_MODELVIEW);
		glRotatef(-90,0,1,0);
		CreateFarView(data,a*64,64,leafDL+a);
		CreateFarView(data,a*64,64+256,pineDL+a);

		glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,13,  -1,0,0,0);
		glMatrixMode(GL_MODELVIEW);
		glRotatef(-90,0,1,0);
		CreateFarView(data2,a*64,0,leafDL+a);
		CreateFarView(data2,a*64,256,pineDL+a);

		glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,13,  0,0,1,0);
		glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,9,  1,0,0,0);
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glRotatef(90,1,0,0);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(-MAX_TREE_HEIGHT*0.5f,MAX_TREE_HEIGHT*0.5f,-MAX_TREE_HEIGHT*0.5f,MAX_TREE_HEIGHT*0.5f,-MAX_TREE_HEIGHT,MAX_TREE_HEIGHT);
		CreateFarView(data,a*64,128,leafDL+a);
		CreateFarView(data,a*64,128+256,pineDL+a);
	}
	glDisable( GL_VERTEX_PROGRAM_ARB );
	glDisable(GL_ALPHA_TEST);

	glViewport(gu->viewPosX,0,gu->viewSizeX,gu->viewSizeY);
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();

	memcpy(&data[512*192*4],&data[512*64*4],512*64*4);		//far away trees
	memcpy(&data[512*(192+256)*4],&data[512*(64+256)*4],512*64*4);		//pine far away trees

	memcpy(&data2[512*64*4],&data[512*64*4],512*192*4);
	memcpy(&data2[512*(64+256)*4],&data[512*(64+256)*4],512*192*4);
//	memcpy(data2,&data2[512*256*4],512*64*4);		//darker trees

//	CBitmap bm(data,512,512);
//	bm.Save("fartex.bmp");

//	FixAlpha(data);
//	FixAlpha(data2);

	glGenTextures(2, farTex);

	CreateTex(data,farTex[0],512,512,true,4);
	CreateTex(data2,farTex[1],512,512,true,4);

	delete[] data;
	delete[] data2;
}

void CAdvTreeGenerator::CreateFarView(unsigned char* mem,int dx,int dy,unsigned int displist)
{
	unsigned char* buf=SAFE_NEW unsigned char[64*64*4];
	glClearColor(0.0f,0.0f,0.0f,0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glCallList(displist);

	glReadPixels(0,0,64,64,GL_RGBA,GL_UNSIGNED_BYTE,buf);

	for(int y=0;y<64;++y){
		for(int x=0;x<64;++x){
			if(buf[(y*64+x)*4]==0 && buf[(y*64+x)*4+1]==0 && buf[(y*64+x)*4+2]==0){
				mem[((y+dy)*512+x+dx)*4+0]=60;
				mem[((y+dy)*512+x+dx)*4+1]=90;
				mem[((y+dy)*512+x+dx)*4+2]=40;
				mem[((y+dy)*512+x+dx)*4+3]=0;
			} else {
				mem[((y+dy)*512+x+dx)*4+0]=buf[(y*64+x)*4];
				mem[((y+dy)*512+x+dx)*4+1]=buf[(y*64+x)*4+1];
				mem[((y+dy)*512+x+dx)*4+2]=buf[(y*64+x)*4+2];
				mem[((y+dy)*512+x+dx)*4+3]=255;
			}
		}
	}

	delete[] buf;
}

void CAdvTreeGenerator::FixAlpha(unsigned char* data)
{
	for(int y=0;y<63;++y){
		for(int x=0;x<512;++x){
			if(data[((y)*512+x)*4+3]==0){
				data[((y)*512+x)*4+3]=y*2;
			} else {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?