📄 bfgrounddrawer.cpp
字号:
#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 + -