📄 terrrender.cc
字号:
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "terrain/terrData.h"
#include "game/fx/Celestial.h"//celestial
#include "math/mMath.h"
#include "dgl/dgl.h"
#include "console/console.h"
#include "console/consoleTypes.h"
#include "dgl/gBitmap.h"
#include "terrain/terrRender.h"
#include "dgl/materialList.h"
#include "sceneGraph/sceneState.h"
#include "terrain/waterBlock.h"
#include "terrain/blender.h"
#include "core/frameAllocator.h"
#include "sceneGraph/sceneGraph.h"
#include "sceneGraph/sgUtil.h"
#include "platform/profiler.h"
struct LightTriangle {
ColorF color;
Point2F texco1;
Point3F point1;
Point2F texco2;
Point3F point2;
Point2F texco3;
Point3F point3;
LightTriangle* next;
U32 flags; // 0 if inactive
};
static LightTriangle* sgCurrLightTris = NULL;
GBitmap* TerrainRender::mBlendBitmap = NULL;
S32 TerrainRender::mTextureMinSquareSize;
bool TerrainRender::mEnableTerrainDetails = true;
// CW - stuff with bump maps
// So, this is how it works...
// There are 3 fields:
// 1) bumpScale: This is the size of the bumps. It determines how much the bump texture is stretched
// 2) bumpOffset: How much the two textures are offset from each other. This should be VERY close to
// 0. An appropriate value is usually around 0.004 and 0.01. Play around with it and see what
// works best for your implementation.
// 3) zeroBumpScale: This is a bitshift value for how far the bumps are drawn. The LESS the value
// the FARTHER they will exist. If you go above 7-8, the bumps tend to go a little wacky.
// 8 should be the max. 6-7 are good values.
bool TerrainRender::mEnableTerrainEmbossBumps = true;
// This is only for win32
#ifdef TORQUE_OS_WIN32
bool TerrainRender::mRenderGL = false;
#endif
// CW - end bump map stuff
bool TerrainRender::mEnableTerrainDynLights = true;
U32 TerrainRender::mNumClipPlanes = 4;
MatrixF TerrainRender::mCameraToObject;
AllocatedTexture TerrainRender::mTextureFrameListHead;
AllocatedTexture TerrainRender::mTextureFrameListTail;
AllocatedTexture TerrainRender::mTextureFreeListHead;
AllocatedTexture TerrainRender::mTextureFreeListTail;
AllocatedTexture TerrainRender::mTextureFreeBigListHead;
AllocatedTexture TerrainRender::mTextureFreeBigListTail;
AllocatedTexture *TerrainRender::mTextureGrid[AllocatedTextureCount];
AllocatedTexture **TerrainRender::mTextureGridPtr[5];
AllocatedTexture *TerrainRender::mCurrentTexture = NULL;
#if defined(TORQUE_OS_LINUX) || defined(TORQUE_OS_OPENBSD)
// Texture slop isn't necessary on Linux
U32 TerrainRender::mTextureSlopSize = 512;
#else
U32 TerrainRender::mTextureSlopSize = 220;
#endif
static bool sgTextureFreeListPrimed = false;
static U32 sgFreeListPrimeCount = 32;
Vector<TextureHandle> TerrainRender::mTextureFreeList(__FILE__, __LINE__);
SceneState* TerrainRender::mSceneState;
TerrainBlock* TerrainRender::mCurrentBlock;
S32 TerrainRender::mSquareSize;
F32 TerrainRender::mScreenSize;
U32 TerrainRender::mFrameIndex;
Point2F TerrainRender::mBlockPos;
Point2I TerrainRender::mBlockOffset;
Point2I TerrainRender::mTerrainOffset;
PlaneF TerrainRender::mClipPlane[MaxClipPlanes];
Point3F TerrainRender::mCamPos;
TextureHandle* TerrainRender::mGrainyTexture = NULL;
U32 TerrainRender::mDynamicLightCount;
F32 TerrainRender::mPixelError;
TerrLightInfo TerrainRender::mTerrainLights[MaxTerrainLights];
bool TerrainRender::mRenderingCommander = false;
F32 TerrainRender::mScreenError;
F32 TerrainRender::mMinSquareSize;
F32 TerrainRender::mFarDistance;
S32 TerrainRender::mDynamicTextureCount;
S32 TerrainRender::mStaticTextureCount;
S32 maxTerrPoints = 100;
ColorF TerrainRender::mFogColor;
bool TerrainRender::mRenderOutline;
U32 TerrainRender::mMaterialCount;
namespace {
Point4F sgTexGenS;
Point4F sgTexGenT;
Point4F sgLMGenS;
Point4F sgLMGenT;
Point4F bumpTexGenS;
Point4F bumpTexGenT;
Point2F bumpTextureOffset;
} // namespace {}
static S32 getPower(S32 x)
{
// Returns 2^n (the highest bit).
S32 i = 0;
if (x)
do
i++;
while (x >>= 1);
return i;
}
void TerrainRender::init()
{
S32 i;
mTextureMinSquareSize = 0;
mFrameIndex = 0;
mScreenError = 4;
mScreenSize = 45;
mMinSquareSize = 4;
mFarDistance = 500;
mRenderOutline = false;
mTextureFrameListHead.next = &mTextureFrameListTail;
mTextureFrameListHead.previous = NULL;
mTextureFrameListTail.next = NULL;
mTextureFrameListTail.previous = &mTextureFrameListHead;
mTextureFreeListHead.next = &mTextureFreeListTail;
mTextureFreeListHead.previous = NULL;
mTextureFreeListTail.next = NULL;
mTextureFreeListTail.previous = &mTextureFreeListHead;
mTextureFreeBigListHead.next = &mTextureFreeBigListTail;
mTextureFreeBigListHead.previous = NULL;
mTextureFreeBigListTail.next = NULL;
mTextureFreeBigListTail.previous = &mTextureFreeBigListHead;
for(i = 0; i < AllocatedTextureCount; i++)
mTextureGrid[i] = 0;
mTextureGridPtr[0] = mTextureGrid;
mTextureGridPtr[1] = mTextureGrid + 4096;
mTextureGridPtr[2] = mTextureGrid + 4096 + 1024;
mTextureGridPtr[3] = mTextureGrid + 4096 + 1024 + 256;
mTextureGridPtr[4] = mTextureGrid + 4096 + 1024 + 256 + 64;
/* for(i = 0; i < 256; i++)
{
mSquareSeqAdd[i] = 0;
for(S32 val = 0; val < 9; val++)
{
if(i & (1 << val))
mSquareSeqAdd[i] += (1 << val) * (1 << val);
}
} */
mBlendBitmap = new GBitmap(TerrainTextureSize, TerrainTextureSize, true, GBitmap::RGB5551);
Con::addVariable("T2::dynamicTextureCount", TypeS32, &mDynamicTextureCount);
Con::addVariable("T2::staticTextureCount", TypeS32, &mStaticTextureCount);
Con::addVariable("screenSize", TypeF32, &mScreenSize);
Con::addVariable("farDistance", TypeF32, &mFarDistance);
Con::addVariable("pref::Terrain::texDetail", TypeS32, &mTextureMinSquareSize);
Con::addVariable("pref::Terrain::enableDetails", TypeBool, &mEnableTerrainDetails);
// CW - stuff with bump maps
Con::addVariable("pref::Terrain::enableEmbossBumps", TypeBool, &mEnableTerrainEmbossBumps);
// CW - end bump map stuff
Con::addVariable("pref::Terrain::dynamicLights", TypeBool, &mEnableTerrainDynLights);
Con::addVariable("pref::Terrain::screenError", TypeF32, &mScreenError);
Con::addVariable("pref::Terrain::textureCacheSize", TypeS32, &mTextureSlopSize);
}
void TerrainRender::shutdown()
{
delete mBlendBitmap;
mBlendBitmap = NULL;
flushCache();
}
void TerrainRender::buildClippingPlanes(bool flipClipPlanes)
{
F64 frustumParam[6];
dglGetFrustum(&frustumParam[0], &frustumParam[1],
&frustumParam[2], &frustumParam[3],
&frustumParam[4], &frustumParam[5]);
Point3F osCamPoint(0, 0, 0);
mCameraToObject.mulP(osCamPoint);
sgComputeOSFrustumPlanes(frustumParam,
mCameraToObject,
osCamPoint,
mClipPlane[4],
mClipPlane[0],
mClipPlane[1],
mClipPlane[2],
mClipPlane[3]);
// no need
mNumClipPlanes = 4;
// near plane is needed as well...
//PlaneF p(0, 1, 0, -frustumParam[4]);
//mTransformPlane(mCameraToObject, Point3F(1,1,1), p, &mClipPlane[0]);
if (flipClipPlanes) {
mClipPlane[0].neg();
mClipPlane[1].neg();
mClipPlane[2].neg();
mClipPlane[3].neg();
mClipPlane[4].neg();
mClipPlane[5].neg();
}
}
S32 TerrainRender::TestSquareVisibility(Point3F &min, Point3F &max, S32 mask, F32 expand)
{
S32 retMask = 0;
Point3F minPoint, maxPoint;
for(S32 i = 0; i < mNumClipPlanes; i++)
{
if(mask & (1 << i))
{
if(mClipPlane[i].x > 0)
{
maxPoint.x = max.x;
minPoint.x = min.x;
}
else
{
maxPoint.x = min.x;
minPoint.x = max.x;
}
if(mClipPlane[i].y > 0)
{
maxPoint.y = max.y;
minPoint.y = min.y;
}
else
{
maxPoint.y = min.y;
minPoint.y = max.y;
}
if(mClipPlane[i].z > 0)
{
maxPoint.z = max.z;
minPoint.z = min.z;
}
else
{
maxPoint.z = min.z;
minPoint.z = max.z;
}
F32 maxDot = mDot(maxPoint, mClipPlane[i]);
F32 minDot = mDot(minPoint, mClipPlane[i]);
F32 planeD = mClipPlane[i].d;
if(maxDot <= -(planeD + expand))
return -1;
if(minDot <= -planeD)
retMask |= (1 << i);
}
}
return retMask;
}
ChunkCornerPoint *TerrainRender::allocInitialPoint(Point3F pos)
{
ChunkCornerPoint *ret = (ChunkCornerPoint *) FrameAllocator::alloc(sizeof(ChunkCornerPoint));
ret->x = pos.x;
ret->y = pos.y;
ret->z = pos.z;
ret->distance = (*ret - mCamPos).len();
gClientSceneGraph->getFogCoordPair(ret->distance, ret->z, ret->fogRed, ret->fogGreen);
ret->xfIndex = 0;
return ret;
}
ChunkCornerPoint *TerrainRender::allocPoint(Point2I pos)
{
ChunkCornerPoint *ret = (ChunkCornerPoint *) FrameAllocator::alloc(sizeof(ChunkCornerPoint));
ret->x = pos.x * mSquareSize + mBlockPos.x;
ret->y = pos.y * mSquareSize + mBlockPos.y;
ret->z = fixedToFloat(mCurrentBlock->getHeight(pos.x, pos.y));
ret->distance = (*ret - mCamPos).len();
gClientSceneGraph->getFogCoordPair(ret->distance, ret->z, ret->fogRed, ret->fogGreen);
ret->xfIndex = 0;
return ret;
}
void TerrainRender::allocRenderEdges(U32 edgeCount, EdgeParent **dest, bool renderEdge)
{
if(renderEdge)
{
for(U32 i = 0; i < edgeCount; i++)
{
ChunkEdge *edge = (ChunkEdge *) FrameAllocator::alloc(sizeof(ChunkEdge));
edge->c1 = NULL;
edge->c2 = NULL;
edge->xfIndex = 0;
dest[i] = edge;
}
}
else
{
for(U32 i = 0; i < edgeCount; i++)
{
ChunkScanEdge *edge = (ChunkScanEdge *) FrameAllocator::alloc(sizeof(ChunkScanEdge));
edge->mp = NULL;
dest[i] = edge;
}
}
}
void TerrainRender::subdivideChunkEdge(ChunkScanEdge *e, Point2I pos, bool chunkEdge)
{
if(!e->mp)
{
allocRenderEdges(2, &e->e1, chunkEdge);
e->mp = allocPoint(pos);
e->e1->p1 = e->p1;
e->e1->p2 = e->mp;
e->e2->p1 = e->mp;
e->e2->p2 = e->p2;
}
}
F32 TerrainRender::getSquareDistance(const Point3F& minPoint, const Point3F& maxPoint, F32* zDiff)
{
Point3F vec;
if(mCamPos.z < minPoint.z)
vec.z = minPoint.z - mCamPos.z;
else if(mCamPos.z > maxPoint.z)
vec.z = maxPoint.z - mCamPos.z;
else
vec.z = 0;
if(mCamPos.x < minPoint.x)
vec.x = minPoint.x - mCamPos.x;
else if(mCamPos.x > maxPoint.x)
vec.x = mCamPos.x - maxPoint.x;
else
vec.x = 0;
if(mCamPos.y < minPoint.y)
vec.y = minPoint.y - mCamPos.y;
else if(mCamPos.y > maxPoint.y)
vec.y = mCamPos.y - maxPoint.y;
else
vec.y = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -