advtreedrawer.cpp

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

CPP
893
字号
// TreeDrawer.cpp: implementation of the CAdvTreeDrawer class.
//
//////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "AdvTreeDrawer.h"
#include "Map/BaseGroundDrawer.h"
#include "Map/Ground.h"
#include "Game/Camera.h"
#include "Rendering/GL/VertexArray.h"
#include "Map/ReadMap.h"
#include "Rendering/GL/myGL.h"
#include "AdvTreeGenerator.h"
#include "Rendering/Textures/Bitmap.h"
#include "LogOutput.h"
#include "GrassDrawer.h"
#include "Matrix44f.h"
#include "Rendering/ShadowHandler.h"
#include "mmgr.h"

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

static const float TEX_LEAF_START_Y1=0.001f;
static const float TEX_LEAF_END_Y1=0.124f;
static const float TEX_LEAF_START_Y2=0.126f;
static const float TEX_LEAF_END_Y2=0.249f;
static const float TEX_LEAF_START_Y3=0.251f;
static const float TEX_LEAF_END_Y3=0.374f;
static const float TEX_LEAF_START_Y4=0.376f;
static const float TEX_LEAF_END_Y4=0.499f;

static const float TEX_LEAF_START_X1=0.0f;
static const float TEX_LEAF_END_X1=0.125f;
static const float TEX_LEAF_START_X2=0.0f;
static const float TEX_LEAF_END_X2=0.125f;
static const float TEX_LEAF_START_X3=0.0f;
static const float TEX_LEAF_END_X3=0.125f;

CAdvTreeDrawer::CAdvTreeDrawer()
{
	oldTreeDistance=4;

	treeGen=SAFE_NEW CAdvTreeGenerator;
	grassDrawer=SAFE_NEW CGrassDrawer();
	lastListClean=0;
	treesX=gs->mapx/TREE_SQUARE_SIZE;
	treesY=gs->mapy/TREE_SQUARE_SIZE;
	trees=SAFE_NEW TreeSquareStruct[treesX*treesY];

	for(int y=0;y<treesY;y++){
		for(int x=0;x<treesX;x++){
			trees[y*treesX+x].lastSeen=0;
			trees[y*treesX+x].lastSeenFar=0;
			trees[y*treesX+x].viewVector=UpVector;
			trees[y*treesX+x].displist=0;
			trees[y*treesX+x].farDisplist=0;
		}
	}
}

CAdvTreeDrawer::~CAdvTreeDrawer()
{
	for(int y=0;y<treesY;y++){
		for(int x=0;x<treesX;x++){
			if(trees[y*treesX+x].displist)
				glDeleteLists(trees[y*treesX+x].displist,1);
			if(trees[y*treesX+x].farDisplist)
				glDeleteLists(trees[y*treesX+x].farDisplist,1);
		}
	}
	delete[] trees;
	delete treeGen;
	delete grassDrawer;
}

void CAdvTreeDrawer::Update()
{
	for(std::list<FallingTree>::iterator fti=fallingTrees.begin();fti!=fallingTrees.end();){
		fti->fallPos+=fti->speed*0.1f;
		if(fti->fallPos>1){		//remove the tree
			std::list<FallingTree>::iterator prev=fti++;
			fallingTrees.erase(prev);
		} else {
			fti->speed+=sin(fti->fallPos)*0.04f;
			++fti;
		}
	}

}

static CVertexArray *va;

static void inline SetArray(float t1,float t2,float3 v)
{
	va->AddVertexT(v,t1,t2);
}

struct CAdvTreeSquareDrawer : CReadMap::IQuadDrawer
{
	CAdvTreeSquareDrawer() {td=0;}

	void DrawQuad (int x,int y);

	CAdvTreeDrawer *td;
	int cx,cy;
	float treeDistance;
	bool drawDetailed;
};

void CAdvTreeSquareDrawer::DrawQuad (int x,int y)
{
	int treesX = td->treesX;
	CAdvTreeDrawer::TreeSquareStruct* tss=&td->trees[y*treesX+x];
	if(abs(cy-y)<=2 && abs(cx-x)<=2)	//skip the closest squares
		return;

	float3 dif;
	dif.x=camera->pos.x-(x*SQUARE_SIZE*TREE_SQUARE_SIZE + SQUARE_SIZE*TREE_SQUARE_SIZE/2);
	dif.y=0;
	dif.z=camera->pos.z-(y*SQUARE_SIZE*TREE_SQUARE_SIZE + SQUARE_SIZE*TREE_SQUARE_SIZE/2);
	float dist=dif.Length();
	dif/=dist;

	if(dist<SQUARE_SIZE*TREE_SQUARE_SIZE*treeDistance*2 && dist>SQUARE_SIZE*TREE_SQUARE_SIZE*(treeDistance)){//far trees
		tss->lastSeenFar=gs->frameNum;
		if(!tss->farDisplist || dif.dot(tss->viewVector)<0.97f){
			va=GetVertexArray();
			va->Initialize();
			tss->viewVector=dif;
			if(!tss->farDisplist)
				tss->farDisplist=glGenLists(1);
			float3 up(0,1,0);
			float3 side=up.cross(dif);

			for(std::map<int,CAdvTreeDrawer::TreeStruct>::iterator ti=tss->trees.begin();ti!=tss->trees.end();++ti){
				CAdvTreeDrawer::TreeStruct* ts=&ti->second;

				float3 base(ts->pos);
				int type=ts->type;

				float height=MAX_TREE_HEIGHT;
				float width=MAX_TREE_HEIGHT*0.5f;

				float xdif;
				float ydif;
				if(ts->type<8){
					xdif=type*0.125f;
					ydif=0.5f;
				} else {
					xdif=(type-8)*0.125f;
					ydif=0;
				}
				SetArray(TEX_LEAF_START_X1+xdif,TEX_LEAF_START_Y4+ydif,base+side*width);
				SetArray(TEX_LEAF_START_X1+xdif,TEX_LEAF_END_Y4+ydif  ,base+side*width+float3(0,height,0));
				SetArray(TEX_LEAF_END_X1+xdif  ,TEX_LEAF_END_Y4+ydif  ,base-side*width+float3(0,height,0));
				SetArray(TEX_LEAF_END_X1+xdif  ,TEX_LEAF_START_Y4+ydif,base-side*width);
			}
			glNewList(td->trees[y*treesX+x].farDisplist,GL_COMPILE);
			va->DrawArrayT(GL_QUADS);
			glEndList();
		}
		if(dist>SQUARE_SIZE*TREE_SQUARE_SIZE*(treeDistance*2-1)){
			float trans=(SQUARE_SIZE*TREE_SQUARE_SIZE*treeDistance*2-dist)/(SQUARE_SIZE*TREE_SQUARE_SIZE);
			glEnable(GL_BLEND);
			glColor4f(1,1,1,trans);
			glAlphaFunc(GL_GREATER,(SQUARE_SIZE*TREE_SQUARE_SIZE*treeDistance*2-dist)/(SQUARE_SIZE*TREE_SQUARE_SIZE*2));
		} else {
			glColor4f(1,1,1,1);
			glDisable(GL_BLEND);
			glAlphaFunc(GL_GREATER,0.5f);
		}
		glCallList(tss->farDisplist);
	}

	if(dist<SQUARE_SIZE*TREE_SQUARE_SIZE*treeDistance){	//midle distance trees
		tss->lastSeen=gs->frameNum;
		if(!tss->displist){
			va=GetVertexArray();
			va->Initialize();
			tss->displist=glGenLists(1);

			for(std::map<int,CAdvTreeDrawer::TreeStruct>::iterator ti=tss->trees.begin();ti!=tss->trees.end();++ti){
				CAdvTreeDrawer::TreeStruct* ts=&ti->second;
				float3 pos(ts->pos);
				int type=ts->type;

				float height=MAX_TREE_HEIGHT;
				float width=MAX_TREE_HEIGHT*0.5f;
				float xdif;
				float ydif;
				if(ts->type<8){
					xdif=type*0.125f;
					ydif=0.5f;
				} else {
					xdif=(type-8)*0.125f;
					ydif=0;
				}
				SetArray(TEX_LEAF_START_X1+xdif,TEX_LEAF_START_Y1+ydif,pos+float3(width,0,0));
				SetArray(TEX_LEAF_START_X1+xdif,TEX_LEAF_END_Y1+ydif,pos+float3(width,height,0));
				SetArray(TEX_LEAF_END_X1+xdif,TEX_LEAF_END_Y1+ydif,pos+float3(-width,height,0));
				SetArray(TEX_LEAF_END_X1+xdif,TEX_LEAF_START_Y1+ydif,pos+float3(-width,0,0));

				SetArray(TEX_LEAF_START_X2+xdif,TEX_LEAF_START_Y2+ydif,pos+float3(0,0,width));
				SetArray(TEX_LEAF_START_X2+xdif,TEX_LEAF_END_Y2+ydif,pos+float3(0,height,width));
				SetArray(TEX_LEAF_END_X2+xdif,TEX_LEAF_END_Y2+ydif,pos+float3(0,height,-width));
				SetArray(TEX_LEAF_END_X2+xdif,TEX_LEAF_START_Y2+ydif,pos+float3(0,0,-width));

				//width*=1.41f;
				SetArray(TEX_LEAF_START_X3+xdif,TEX_LEAF_START_Y3+ydif,pos+float3(width,height*0.4f,0));
				SetArray(TEX_LEAF_START_X3+xdif,TEX_LEAF_END_Y3+ydif,pos+float3(0,height*0.4f,-width));
				SetArray(TEX_LEAF_END_X3+xdif,TEX_LEAF_END_Y3+ydif,pos+float3(-width,height*0.4f,0));
				SetArray(TEX_LEAF_END_X3+xdif,TEX_LEAF_START_Y3+ydif,pos+float3(0,height*0.4f,width));
			}
			glNewList(tss->displist,GL_COMPILE);
			va->DrawArrayT(GL_QUADS);
			glEndList();
		}
		glColor4f(1,1,1,1);
		glDisable(GL_BLEND);
		glAlphaFunc(GL_GREATER,0.5f);
		glCallList(tss->displist);
	}
}

void CAdvTreeDrawer::Draw(float treeDistance,bool drawReflection)
{
	int activeFarTex=camera->forward.z<0 ? treeGen->farTex[0] : treeGen->farTex[1];

	bool drawDetailed=true;
	if(treeDistance<4)
		drawDetailed=false;
	if(drawReflection)
		drawDetailed=false;

	CBaseGroundDrawer *gd = readmap->GetGroundDrawer ();

	glEnable(GL_ALPHA_TEST);

	if(shadowHandler->drawShadows && !gd->DrawExtraTex()){
		glBindProgramARB( GL_VERTEX_PROGRAM_ARB, treeGen->treeFarVP );
		glEnable(GL_VERTEX_PROGRAM_ARB);

		glBindTexture(GL_TEXTURE_2D,shadowHandler->shadowTexture);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
		glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);

		if(shadowHandler->useFPShadows){
			glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, treeGen->treeFPShadow );
			glEnable( GL_FRAGMENT_PROGRAM_ARB );
			glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB,10, readmap->ambientColor.x,readmap->ambientColor.y,readmap->ambientColor.z,1);
			glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB,11, 0,0,0,1-readmap->shadowDensity*0.5f);

			glActiveTextureARB(GL_TEXTURE1_ARB);
			glBindTexture(GL_TEXTURE_2D, activeFarTex);
		} else {
			glEnable(GL_TEXTURE_2D);
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 1-readmap->shadowDensity*0.5f);

			float texConstant[]={readmap->ambientColor.x,readmap->ambientColor.y,readmap->ambientColor.z,0.0f};
			glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR,texConstant);
			glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_PREVIOUS_ARB);
			glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_CONSTANT);
			glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE2_RGB_ARB,GL_TEXTURE);
			glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND2_RGB_ARB,GL_SRC_ALPHA);
			glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_INTERPOLATE_ARB);

			glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_ALPHA_ARB,GL_PREVIOUS_ARB);
			glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_ALPHA_ARB,GL_CONSTANT);
			glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_ALPHA_ARB,GL_ADD);

			glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);

			glActiveTextureARB(GL_TEXTURE1_ARB);
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, activeFarTex);
		}
		glActiveTextureARB(GL_TEXTURE0_ARB);

		glMatrixMode(GL_MATRIX0_ARB);
		glLoadMatrixf(shadowHandler->shadowMatrix.m);
		glMatrixMode(GL_MODELVIEW);
	} else {
		glBindTexture(GL_TEXTURE_2D, activeFarTex);
	}
	glEnable(GL_TEXTURE_2D);

	int cx=(int)(camera->pos.x/(SQUARE_SIZE*TREE_SQUARE_SIZE));
	int cy=(int)(camera->pos.z/(SQUARE_SIZE*TREE_SQUARE_SIZE));

	CAdvTreeSquareDrawer drawer;
	drawer.td = this;
	drawer.cx = cx;
	drawer.cy = cy;
	drawer.treeDistance = treeDistance;
	drawer.drawDetailed = drawDetailed;

⌨️ 快捷键说明

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