⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bfgrounddrawer.cpp

📁 这是整套横扫千军3D版游戏的源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include "StdAfx.h"
#include "BFGroundDrawer.h"
#include "BFGroundTextures.h"
#include "Rendering/GL/myGL.h"
#include "Rendering/GL/VertexArray.h"
#include "Game/Camera.h"
#include "Map/ReadMap.h"
#include "Sim/Projectiles/ProjectileHandler.h"
#include "LogOutput.h"
#include "SmfReadMap.h"
#include "Rendering/ShadowHandler.h"
#include "Sim/Units/UnitDef.h"
#include "Rendering/GroundDecalHandler.h"
#include "Platform/ConfigHandler.h"
#include "mmgr.h"

using namespace std;

CBFGroundDrawer::CBFGroundDrawer(CSmfReadMap *rm)
{
	map = rm;

	numBigTexX=gs->mapx/128;
	numBigTexY=gs->mapy/128;

	heightData=map->heightmap;
	heightDataX=gs->mapx+1;

	if(shadowHandler->canUseShadows){
		groundVP=LoadVertexProgram("ground.vp");
		groundShadowVP=LoadVertexProgram("groundshadow.vp");
		if(shadowHandler->useFPShadows){
			groundFPShadow=LoadFragmentProgram("groundFPshadow.fp");
		}
	}

	textures=SAFE_NEW CBFGroundTextures(map);

	viewRadius=configHandler.GetInt("GroundDetail",40);
	viewRadius+=viewRadius%2;
}

CBFGroundDrawer::~CBFGroundDrawer(void)
{
	delete textures;

	if(shadowHandler->canUseShadows){
		glSafeDeleteProgram( groundVP );
		glSafeDeleteProgram( groundShadowVP );
		if(shadowHandler->useFPShadows){
			glSafeDeleteProgram( groundFPShadow);
		}
	}

	configHandler.SetInt("GroundDetail",viewRadius);
}

static bool drawWater=false;
static float bigtexsubx,bigtexsuby;
static float invMapSizeX,invMapSizeY;

#define NUM_LODS 4

inline void CBFGroundDrawer::DrawVertexA(int x,int y)
{
	float height=heightData[y*heightDataX+x];
	if(drawWater && height<0){
		height*=2;
	}

	va->AddVertex0(float3(x*SQUARE_SIZE,height,y*SQUARE_SIZE));
}

inline void CBFGroundDrawer::DrawVertexA(int x,int y,float height)
{
	if(drawWater && height<0){
		height*=2;
	}
	va->AddVertex0(float3(x*SQUARE_SIZE,height,y*SQUARE_SIZE));
}

inline void CBFGroundDrawer::EndStrip()
{
	va->EndStrip();
}

void CBFGroundDrawer::DrawGroundVertexArray()
{
	va->DrawArray0(GL_TRIANGLE_STRIP);
	va = GetVertexArray();
	va->Initialize();
}



void CBFGroundDrawer::Draw(bool drawWaterReflection, bool drawUnitReflection, unsigned int overrideVP)
{
	if (wireframe) {
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	}

	drawWater = drawWaterReflection;
	int baseViewRadius = max(4, viewRadius);

	if (drawUnitReflection)
		viewRadius = (viewRadius / 2) & 0xfffffe;

	float zoom = 45 / camera->GetFov();
	viewRadius = (int) (viewRadius * sqrt(zoom));
	viewRadius += viewRadius % 2;

	va = GetVertexArray();
	va->Initialize();
	textures->DrawUpdate();

	int x, y;
	const int maxIdx = ((gs->mapx + 1) * (gs->mapy + 1)) - 1;
	#define CLAMP(i) std::max(0, std::min((i), maxIdx))

	int neededLod = int(gu->viewRange / 8 / viewRadius * 2);
	UpdateCamRestraints();

	invMapSizeX = 1.0f / gs->mapx;
	invMapSizeY = 1.0f / gs->mapy;

	glDisable(GL_BLEND);
	glEnable(GL_TEXTURE_2D);

	if (!overrideVP)
		glEnable(GL_CULL_FACE);

	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	SetupTextureUnits(drawWaterReflection,overrideVP);
	bool inStrip = false;

	if (map->voidWater && !drawWater) {
		glEnable(GL_ALPHA_TEST);
		glAlphaFunc(GL_GREATER, 0.9f);
	}

	float camxpart = 0, oldcamxpart;
	float camypart = 0, oldcamypart;

	for (int bty = 0; bty < numBigTexY; ++bty) {
		// loop over the big texture squares (128 squares)
		bigtexsuby = bty;

		// only process the necessary big squares in the x direction
		int sx = 0;
		int ex = numBigTexX;
		float xtest, xtest2;
		const int bigSquareSize = 128;
		std::vector<fline>::iterator fli;

		for (fli = left.begin(); fli != left.end(); fli++) {
			xtest  = ((fli->base / SQUARE_SIZE + fli->dir *  (bty * bigSquareSize)                 ));
			xtest2 = ((fli->base / SQUARE_SIZE + fli->dir * ((bty * bigSquareSize) + bigSquareSize)));

			if (xtest > xtest2)
				xtest = xtest2;

			xtest = xtest / bigSquareSize;

			if (xtest > sx)
				sx = (int) xtest;
		}

		for (fli = right.begin(); fli != right.end(); fli++) {
			xtest  = ((fli->base / SQUARE_SIZE + fli->dir *  (bty * bigSquareSize)                 )) + bigSquareSize;
			xtest2 = ((fli->base / SQUARE_SIZE + fli->dir * ((bty * bigSquareSize) + bigSquareSize))) + bigSquareSize;

			if (xtest < xtest2)
				xtest = xtest2;

			xtest = xtest / bigSquareSize;

			if (xtest < ex)
				ex = (int) xtest;
		}

		for (int btx = sx; btx < ex; ++btx) {
			bigtexsubx = btx;

			// must be in drawLos mode or shadows must be off
			if (DrawExtraTex() || !shadowHandler->drawShadows) {
				textures->SetTexture(btx, bty);
				SetTexGen(1.0f / 1024, 1.0f / 1024, -btx, -bty);
				if (overrideVP) {
					glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 11, -btx, -bty, 0, 0);
				}
			} else {
				textures->SetTexture(btx, bty);
				glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 11, -btx, -bty, 0, 0);
			}
			/// for (int lod = 1; (lod * 2) < neededLod; lod *= 2) {
			for (int lod = 1; lod < neededLod; lod *= 2) {
				int cx = (int) (cam2->pos.x / (SQUARE_SIZE));
				int cy = (int) (cam2->pos.z / (SQUARE_SIZE));

				cx = (cx / lod) * lod;
				cy = (cy / lod) * lod;
				int hlod = lod >> 1;
				int ysquaremod = ((cy) % (2 * lod)) / lod;
				int xsquaremod = ((cx) % (2 * lod)) / lod;

				oldcamxpart = camxpart;
				float cx2 = (cx / (2 * lod)) * lod * 2;
				camxpart = (cam2->pos.x / (SQUARE_SIZE) - cx2) / (lod * 2);

				oldcamypart = camypart;
				float cy2 = (cy / (2 * lod)) * lod * 2;
				camypart = (cam2->pos.z / (SQUARE_SIZE) - cy2) / (lod * 2);

				int minty =  bty      * 128;
				int maxty = (bty + 1) * 128;
				int mintx =  btx      * 128;
				int maxtx = (btx + 1) * 128;

				int minly = cy + (-viewRadius + 3 - ysquaremod) * lod;
				int maxly = cy + ( viewRadius - 1 - ysquaremod) * lod;
				int minlx = cx + (-viewRadius + 3 - xsquaremod) * lod;
				int maxlx = cx + ( viewRadius - 1 - xsquaremod) * lod;

				int xstart = max(minlx, mintx);
				int xend   = min(maxlx, maxtx);
				int ystart = max(minly, minty);
				int yend   = min(maxly, maxty);

				/// for (y = ystart; (y + lod) < yend; y += lod) {
				for (y = ystart; y < yend; y += lod) {
					int xs = xstart;
					int xe = xend;
					int xtest, xtest2;
					std::vector<fline>::iterator fli;

					for (fli = left.begin(); fli != left.end(); fli++) {
						xtest  = ((int) (fli->base / (SQUARE_SIZE) + fli->dir *  y       )) / lod * lod - lod;
						xtest2 = ((int) (fli->base / (SQUARE_SIZE) + fli->dir * (y + lod))) / lod * lod - lod;

						if (xtest > xtest2)
							xtest = xtest2;
						if (xtest > xs)
							xs = xtest;
					}
					for (fli = right.begin(); fli != right.end(); fli++) {
						xtest  = ((int) (fli->base / (SQUARE_SIZE) + fli->dir *  y       )) / lod * lod + lod;
						xtest2 = ((int) (fli->base / (SQUARE_SIZE) + fli->dir * (y + lod))) / lod * lod + lod;

						if (xtest < xtest2)
							xtest = xtest2;
						if (xtest < xe)
							xe = xtest;
					}

					/// for (x = xs; (x + lod) < xe; x += lod) {
					for (x = xs; x < xe; x += lod) {
						if ((lod == 1) ||
							(x > (cx) + viewRadius * hlod) || (x < (cx) - viewRadius * hlod) ||
							(y > (cy) + viewRadius * hlod) || (y < (cy) - viewRadius * hlod)) {
								// normal terrain
								if (!inStrip) {
									DrawVertexA(x, y      );
									DrawVertexA(x, y + lod);
									inStrip = true;
								}

								DrawVertexA(x + lod, y      );
								DrawVertexA(x + lod, y + lod);
						} else {
							// inre begr�sning mot f�eg�nde lod
							if ((x >= (cx) + viewRadius * hlod)) {
								int idx1 = CLAMP((y       ) * heightDataX + x), idx1LOD = CLAMP(idx1 + lod), idx1HLOD = CLAMP(idx1 + hlod);
								int idx2 = CLAMP((y +  lod) * heightDataX + x), idx2LOD = CLAMP(idx2 + lod), idx2HLOD = CLAMP(idx2 + hlod);
								int idx3 = CLAMP((y + hlod) * heightDataX + x),                              idx3HLOD = CLAMP(idx3 + hlod);
								float h1 = (heightData[idx1] + heightData[idx2   ]) * 0.5f * (1 - oldcamxpart) + heightData[idx3    ] * (oldcamxpart);
								float h2 = (heightData[idx1] + heightData[idx1LOD]) * 0.5f * (1 - oldcamxpart) + heightData[idx1HLOD] * (oldcamxpart);
								float h3 = (heightData[idx2] + heightData[idx1LOD]) * 0.5f * (1 - oldcamxpart) + heightData[idx3HLOD] * (oldcamxpart);
								float h4 = (heightData[idx2] + heightData[idx2LOD]) * 0.5f * (1 - oldcamxpart) + heightData[idx2HLOD] * (oldcamxpart);

								if (inStrip) {
									EndStrip();
									inStrip = false;
								}

								DrawVertexA(x,        y           );
								DrawVertexA(x,        y + hlod, h1);
								DrawVertexA(x + hlod, y,        h2);
								DrawVertexA(x + hlod, y + hlod, h3);
								EndStrip();
								DrawVertexA(x,        y + hlod, h1);
								DrawVertexA(x,        y +  lod    );
								DrawVertexA(x + hlod, y + hlod, h3);
								DrawVertexA(x + hlod, y +  lod, h4);
								EndStrip();
								DrawVertexA(x + hlod, y +  lod, h4);
								DrawVertexA(x +  lod, y +  lod    );
								DrawVertexA(x + hlod, y + hlod, h3);
								DrawVertexA(x +  lod, y           );
								DrawVertexA(x + hlod, y,        h2);
								EndStrip();
							}
							if ((x <= (cx) - viewRadius * hlod)) {
								int idx1 = CLAMP((y       ) * heightDataX + x), idx1LOD = CLAMP(idx1 + lod), idx1HLOD = CLAMP(idx1 + hlod);
								int idx2 = CLAMP((y +  lod) * heightDataX + x), idx2LOD = CLAMP(idx2 + lod), idx2HLOD = CLAMP(idx2 + hlod);
								int idx3 = CLAMP((y + hlod) * heightDataX + x), idx3LOD = CLAMP(idx3 + lod), idx3HLOD = CLAMP(idx3 + hlod);
								float h1 = (heightData[idx1LOD] + heightData[idx2LOD]) * 0.5f * (oldcamxpart) + heightData[idx3LOD ] * (1 - oldcamxpart);
								float h2 = (heightData[idx1   ] + heightData[idx1LOD]) * 0.5f * (oldcamxpart) + heightData[idx1HLOD] * (1 - oldcamxpart);
								float h3 = (heightData[idx2   ] + heightData[idx1LOD]) * 0.5f * (oldcamxpart) + heightData[idx3HLOD] * (1 - oldcamxpart);
								float h4 = (heightData[idx2   ] + heightData[idx2LOD]) * 0.5f * (oldcamxpart) + heightData[idx2HLOD] * (1 - oldcamxpart);

								if (inStrip) {
									EndStrip();
									inStrip = false;
								}

								DrawVertexA(x +  lod, y + hlod, h1);
								DrawVertexA(x +  lod, y           );
								DrawVertexA(x + hlod, y + hlod, h3);
								DrawVertexA(x + hlod, y,        h2);
								EndStrip();
								DrawVertexA(x +  lod, y +  lod    );
								DrawVertexA(x +  lod, y + hlod, h1);
								DrawVertexA(x + hlod, y +  lod, h4);
								DrawVertexA(x + hlod, y + hlod, h3);
								EndStrip();
								DrawVertexA(x + hlod, y,        h2);
								DrawVertexA(x,        y           );
								DrawVertexA(x + hlod, y + hlod, h3);
								DrawVertexA(x,        y +  lod    );
								DrawVertexA(x + hlod, y +  lod, h4);
								EndStrip();
							}
							if ((y >= (cy) + viewRadius * hlod)) {
								int idx1 = (y       ) * heightDataX + x, idx1LOD = CLAMP(idx1 + lod), idx1HLOD = CLAMP(idx1 + hlod);
								int idx2 = (y +  lod) * heightDataX + x, idx2LOD = CLAMP(idx2 + lod);
								int idx3 = (y + hlod) * heightDataX + x, idx3LOD = CLAMP(idx3 + lod), idx3HLOD = CLAMP(idx3 + hlod);
								float h1 = (heightData[idx1   ] + heightData[idx1LOD]) * 0.5f * (1 - oldcamypart) + heightData[idx1HLOD] * (oldcamypart);
								float h2 = (heightData[idx1   ] + heightData[idx2   ]) * 0.5f * (1 - oldcamypart) + heightData[idx3    ] * (oldcamypart);
								float h3 = (heightData[idx2   ] + heightData[idx1LOD]) * 0.5f * (1 - oldcamypart) + heightData[idx3HLOD] * (oldcamypart);
								float h4 = (heightData[idx2LOD] + heightData[idx1LOD]) * 0.5f * (1 - oldcamypart) + heightData[idx3LOD ] * (oldcamypart);

								if (inStrip) {
									EndStrip();
									inStrip = false;
								}

								DrawVertexA(x,        y           );
								DrawVertexA(x,        y + hlod, h2);
								DrawVertexA(x + hlod, y,        h1);
								DrawVertexA(x + hlod, y + hlod, h3);
								DrawVertexA(x +  lod, y           );
								DrawVertexA(x +  lod, y + hlod, h4);
								EndStrip();
								DrawVertexA(x,        y + hlod, h2);
								DrawVertexA(x,        y +  lod    );
								DrawVertexA(x + hlod, y + hlod, h3);
								DrawVertexA(x +  lod, y +  lod    );
								DrawVertexA(x +  lod, y + hlod, h4);
								EndStrip();
							}
							if ((y <= (cy) - viewRadius * hlod)) {
								int idx1 = CLAMP((y       ) * heightDataX + x), idx1LOD = CLAMP(idx1 + lod);
								int idx2 = CLAMP((y +  lod) * heightDataX + x), idx2LOD = CLAMP(idx2 + lod), idx2HLOD = CLAMP(idx2 + hlod);
								int idx3 = CLAMP((y + hlod) * heightDataX + x), idx3LOD = CLAMP(idx3 + lod), idx3HLOD = CLAMP(idx3 + hlod);
								float h1 = (heightData[idx2   ] + heightData[idx2LOD]) * 0.5f * (oldcamypart) + heightData[idx2HLOD] * (1 - oldcamypart);
								float h2 = (heightData[idx1   ] + heightData[idx2   ]) * 0.5f * (oldcamypart) + heightData[idx3    ] * (1 - oldcamypart);
								float h3 = (heightData[idx2   ] + heightData[idx1LOD]) * 0.5f * (oldcamypart) + heightData[idx3HLOD] * (1 - oldcamypart);
								float h4 = (heightData[idx2LOD] + heightData[idx1LOD]) * 0.5f * (oldcamypart) + heightData[idx3LOD ] * (1 - oldcamypart);

								if (inStrip) {
									EndStrip();
									inStrip = false;
								}

								DrawVertexA(x,        y + hlod, h2);
								DrawVertexA(x,        y +  lod    );
								DrawVertexA(x + hlod, y + hlod, h3);
								DrawVertexA(x + hlod, y +  lod, h1);
								DrawVertexA(x +  lod, y + hlod, h4);
								DrawVertexA(x +  lod, y +  lod    );
								EndStrip();
								DrawVertexA(x +  lod, y + hlod, h4);
								DrawVertexA(x +  lod, y           );
								DrawVertexA(x + hlod, y + hlod, h3);
								DrawVertexA(x,        y           );
								DrawVertexA(x,        y + hlod, h2);
								EndStrip();
							}
						}
					}

					if (inStrip) {
						EndStrip();
						inStrip = false;
					}
				}

⌨️ 快捷键说明

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