advtreedrawer.cpp

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

CPP
893
字号

	// draw far away trees using the map dependent grid visibility
	oldTreeDistance=treeDistance;
	readmap->GridVisibility (camera, TREE_SQUARE_SIZE, treeDistance*2*SQUARE_SIZE*TREE_SQUARE_SIZE, &drawer);

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

			glActiveTextureARB(GL_TEXTURE1_ARB);
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, treeGen->barkTex);
			glActiveTextureARB(GL_TEXTURE0_ARB);

		} else {
			glBindTexture(GL_TEXTURE_2D, treeGen->barkTex);
			glBindProgramARB( GL_VERTEX_PROGRAM_ARB, treeGen->treeNSVP );
			glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,15, 1.0f/(gs->pwr2mapx*SQUARE_SIZE),1.0f/(gs->pwr2mapy*SQUARE_SIZE),1.0f/(gs->pwr2mapx*SQUARE_SIZE),1);
		}
		glEnable( GL_VERTEX_PROGRAM_ARB );
		glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,13,  camera->right.x,camera->right.y,camera->right.z,0);
		glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,9,  camera->up.x,camera->up.y,camera->up.z,0);
		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.20f*(1.0f/MAX_TREE_HEIGHT));	//w=alpha/height modifier
		glAlphaFunc(GL_GREATER,0.5f);
		glDisable(GL_BLEND);
		glColor4f(1,1,1,1);
		va=GetVertexArray();
		va->Initialize();

		struct FadeTree{
			float3 pos;
			float relDist;
			float deltaY;
			int type;
		};
		static FadeTree fadeTrees[3000];
		int curFade=0;

		for(int y=max(0,cy-2);y<=min(gs->mapy/TREE_SQUARE_SIZE-1,cy+2);++y){	//close trees
			for(int x=max(0,cx-2);x<=min(gs->mapx/TREE_SQUARE_SIZE-1,cx+2);++x){
				TreeSquareStruct* tss=&trees[y*treesX+x];
				tss->lastSeen=gs->frameNum;
				for(std::map<int,TreeStruct>::iterator ti=tss->trees.begin();ti!=tss->trees.end();++ti){
					TreeStruct* ts=&ti->second;
					float3 pos(ts->pos);
					int type=ts->type;
					float dy;
					unsigned int displist;
					if(type<8){
						dy=0.5f;
						displist=treeGen->pineDL+type;
					} else {
						type-=8;
						dy=0;
						displist=treeGen->leafDL+type;
					}
					if(camera->InView(pos+float3(0,MAX_TREE_HEIGHT/2,0),MAX_TREE_HEIGHT/2)){
						float camDist=(pos-camera->pos).SqLength();
						if(camDist<SQUARE_SIZE*SQUARE_SIZE*110*110){	//draw detailed tree
							glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,10,pos.x,pos.y,pos.z,0);
							glCallList(displist);
						} else if(camDist<SQUARE_SIZE*SQUARE_SIZE*125*125){	//draw fading tree
							float relDist=(pos.distance(camera->pos)-SQUARE_SIZE*110)/(SQUARE_SIZE*15);
							glAlphaFunc(GL_GREATER,0.8f+relDist*0.2f);
							glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,10,pos.x,pos.y,pos.z,0);
							glCallList(displist);
							glAlphaFunc(GL_GREATER,0.5f);
							fadeTrees[curFade].pos=pos;
							fadeTrees[curFade].deltaY=dy;
							fadeTrees[curFade].type=type;
							fadeTrees[curFade++].relDist=relDist;
						} else {																//draw undetailed tree
							float height=MAX_TREE_HEIGHT;
							float width=MAX_TREE_HEIGHT*0.5f;
							float xdif=type*0.125f;
							SetArray(TEX_LEAF_START_X1+xdif,TEX_LEAF_START_Y1+dy,pos+float3(width,0,0));
							SetArray(TEX_LEAF_START_X1+xdif,TEX_LEAF_END_Y1+dy,pos+float3(width,height,0));
							SetArray(TEX_LEAF_END_X1+xdif,TEX_LEAF_END_Y1+dy,pos+float3(-width,height,0));
							SetArray(TEX_LEAF_END_X1+xdif,TEX_LEAF_START_Y1+dy,pos+float3(-width,0,0));

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

							//width*=1.41f;
							SetArray(TEX_LEAF_START_X3+xdif,TEX_LEAF_START_Y3+dy,pos+float3(width,height*0.4f,width));
							SetArray(TEX_LEAF_START_X3+xdif,TEX_LEAF_END_Y3+dy,pos+float3(width,height*0.4f,-width));
							SetArray(TEX_LEAF_END_X3+xdif,TEX_LEAF_END_Y3+dy,pos+float3(-width,height*0.4f,-width));
							SetArray(TEX_LEAF_END_X3+xdif,TEX_LEAF_START_Y3+dy,pos+float3(-width,height*0.4f,width));
						}
					}
				}
			}
			//draw trees that has been marked as falling
			glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,10,0,0,0,0);
			glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,13,  camera->right.x,camera->right.y,camera->right.z,0);
			glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,9,  camera->up.x,camera->up.y,camera->up.z,0);
			for(std::list<FallingTree>::iterator fti=fallingTrees.begin();fti!=fallingTrees.end();){
				float3 pos=fti->pos-UpVector*(fti->fallPos*20);
				if(camera->InView(pos+float3(0,MAX_TREE_HEIGHT/2,0),MAX_TREE_HEIGHT/2)){
					float ang=fti->fallPos*PI;
					float3 up(fti->dir.x*sin(ang),cos(ang),fti->dir.z*sin(ang));
					float3 z(up.cross(float3(-1,0,0)));
					z.Normalize();
					float3 x(up.cross(z));
					CMatrix44f transMatrix(pos,x,up,z);

					glPushMatrix();
					glMultMatrixf(&transMatrix[0]);

					int type=fti->type;
					int displist;
					if(type<8){
						displist=treeGen->pineDL+type;
					} else {
						type-=8;
						displist=treeGen->leafDL+type;
					}
					glCallList(displist);

					glPopMatrix();
				}
				++fti;
			}
		}
		glDisable( GL_VERTEX_PROGRAM_ARB );

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

			glActiveTextureARB(GL_TEXTURE1_ARB);
			glBindTexture(GL_TEXTURE_2D, activeFarTex);
			glActiveTextureARB(GL_TEXTURE0_ARB);
		} else {
			glBindTexture(GL_TEXTURE_2D, activeFarTex);
		}
		va->DrawArrayT(GL_QUADS);

		for(int a=0;a<curFade;++a){	//faded close trees
			va=GetVertexArray();
			va->Initialize();
			int type=fadeTrees[a].type;
			float dy=fadeTrees[a].deltaY;

			float height=MAX_TREE_HEIGHT;
			float width=MAX_TREE_HEIGHT*0.5f;
			float xdif=type*0.125f;
			SetArray(TEX_LEAF_START_X1+xdif,TEX_LEAF_START_Y1+dy,fadeTrees[a].pos+float3(width,0,0));
			SetArray(TEX_LEAF_START_X1+xdif,TEX_LEAF_END_Y1+dy,fadeTrees[a].pos+float3(width,height,0));
			SetArray(TEX_LEAF_END_X1+xdif,TEX_LEAF_END_Y1+dy,fadeTrees[a].pos+float3(-width,height,0));
			SetArray(TEX_LEAF_END_X1+xdif,TEX_LEAF_START_Y1+dy,fadeTrees[a].pos+float3(-width,0,0));

			SetArray(TEX_LEAF_START_X2+xdif,TEX_LEAF_START_Y2+dy,fadeTrees[a].pos+float3(0,0,width));
			SetArray(TEX_LEAF_START_X2+xdif,TEX_LEAF_END_Y2+dy,fadeTrees[a].pos+float3(0,height,width));
			SetArray(TEX_LEAF_END_X2+xdif,TEX_LEAF_END_Y2+dy,fadeTrees[a].pos+float3(0,height,-width));
			SetArray(TEX_LEAF_END_X2+xdif,TEX_LEAF_START_Y2+dy,fadeTrees[a].pos+float3(0,0,-width));

			//width*=1.41f;
			SetArray(TEX_LEAF_START_X3+xdif,TEX_LEAF_START_Y3+dy,fadeTrees[a].pos+float3(width,height*0.4f,width));
			SetArray(TEX_LEAF_START_X3+xdif,TEX_LEAF_END_Y3+dy,fadeTrees[a].pos+float3(width,height*0.4f,-width));
			SetArray(TEX_LEAF_END_X3+xdif,TEX_LEAF_END_Y3+dy,fadeTrees[a].pos+float3(-width,height*0.4f,-width));
			SetArray(TEX_LEAF_END_X3+xdif,TEX_LEAF_START_Y3+dy,fadeTrees[a].pos+float3(-width,height*0.4f,width));

			glAlphaFunc(GL_GREATER,1-fadeTrees[a].relDist*0.5f);
			va->DrawArrayT(GL_QUADS);
		}
	}
	if(shadowHandler->drawShadows && !gd->DrawExtraTex()){
		glDisable( GL_VERTEX_PROGRAM_ARB );
		if(shadowHandler->useFPShadows){
			glDisable(GL_FRAGMENT_PROGRAM_ARB);
		}
		glActiveTextureARB(GL_TEXTURE1_ARB);
		glDisable(GL_TEXTURE_2D);
		glActiveTextureARB(GL_TEXTURE0_ARB);
		glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
		glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
	}
	glDisable(GL_ALPHA_TEST);

	//clean out squares from memory that are no longer visible
	int startClean=lastListClean*20%(treesX*treesY);
	lastListClean=gs->frameNum;
	int endClean=gs->frameNum*20%(treesX*treesY);

	if(startClean>endClean){
		for(int a=startClean;a<treesX*treesY;a++){
			if(trees[a].lastSeen<gs->frameNum-50 && trees[a].displist){
				glDeleteLists(trees[a].displist,1);
				trees[a].displist=0;
			}
			if(trees[a].lastSeenFar<gs->frameNum-50 && trees[a].farDisplist){
				glDeleteLists(trees[a].farDisplist,1);
				trees[a].farDisplist=0;
			}
		}
		for(int a=0;a<endClean;a++){
			if(trees[a].lastSeen<gs->frameNum-50 && trees[a].displist){
				glDeleteLists(trees[a].displist,1);
				trees[a].displist=0;
			}
			if(trees[a].lastSeenFar<gs->frameNum-50 && trees[a].farDisplist){
				glDeleteLists(trees[a].farDisplist,1);
				trees[a].farDisplist=0;
			}
		}
	} else {
		for(int a=startClean;a<endClean;a++){
			if(trees[a].lastSeen<gs->frameNum-50 && trees[a].displist){
				glDeleteLists(trees[a].displist,1);
				trees[a].displist=0;
			}
			if(trees[a].lastSeenFar<gs->frameNum-50 && trees[a].farDisplist){
				glDeleteLists(trees[a].farDisplist,1);
				trees[a].farDisplist=0;
			}
		}
	}
}

struct CAdvTreeSquareDrawer_SP : CReadMap::IQuadDrawer
{
	void DrawQuad (int x,int y);

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

void CAdvTreeSquareDrawer_SP::DrawQuad (int x,int y)
{
	CAdvTreeDrawer::TreeSquareStruct* tss=&td->trees[y*td->treesX+x];
	if(abs(cy-y)<=2 && abs(cx-x)<=2 && drawDetailed)	//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*td->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);
			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);
			glAlphaFunc(GL_GREATER,0.5f);
		}
		glCallList(tss->farDisplist);
	}

	if(dist<SQUARE_SIZE*TREE_SQUARE_SIZE*treeDistance){	//midle distance trees

⌨️ 快捷键说明

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