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