# Add solid black sides to the map, to hide underwater terrain.
This was SVN commit r8886.
This commit is contained in:
parent
c710e718aa
commit
02e7eb69ff
@ -68,4 +68,23 @@ void CPatch::CalcBounds()
|
||||
m_Bounds+=pos;
|
||||
}
|
||||
}
|
||||
|
||||
// If this a side patch, the sides go down to height 0, so add them
|
||||
// into the bounds
|
||||
if (GetSideFlags())
|
||||
m_Bounds[0].Y = std::min(m_Bounds[0].Y, 0.f);
|
||||
}
|
||||
|
||||
int CPatch::GetSideFlags()
|
||||
{
|
||||
int flags = 0;
|
||||
if (m_X == 0)
|
||||
flags |= CPATCH_SIDE_NEGX;
|
||||
if (m_Z == 0)
|
||||
flags |= CPATCH_SIDE_NEGZ;
|
||||
if (m_X == m_Parent->GetPatchesPerSide()-1)
|
||||
flags |= CPATCH_SIDE_POSX;
|
||||
if (m_Z == m_Parent->GetPatchesPerSide()-1)
|
||||
flags |= CPATCH_SIDE_POSZ;
|
||||
return flags;
|
||||
}
|
||||
|
@ -33,17 +33,14 @@ class CTerrain;
|
||||
// PATCH_SIZE: number of tiles in each patch
|
||||
const ssize_t PATCH_SIZE = 16;
|
||||
|
||||
/// neighbor IDs for CPatch
|
||||
enum CPatchNeighbors
|
||||
// Flags for whether the patch should be drawn with a solid plane
|
||||
// on each side
|
||||
enum CPatchSideFlags
|
||||
{
|
||||
CPATCH_NEIGHTBOR_LEFT_TOP = 0,
|
||||
CPATCH_NEIGHTBOR_TOP = 1,
|
||||
CPATCH_NEIGHTBOR_RIGHT_TOP = 2,
|
||||
CPATCH_NEIGHTBOR_LEFT = 3,
|
||||
CPATCH_NEIGHTBOR_RIGHT = 4,
|
||||
CPATCH_NEIGHTBOR_LEFT_BOTTOM = 5,
|
||||
CPATCH_NEIGHTBOR_BOTTOM = 6,
|
||||
CPATCH_NEIGHTBOR_RIGHT_BOTTOM = 7
|
||||
CPATCH_SIDE_NEGX = (1 << 0),
|
||||
CPATCH_SIDE_POSX = (1 << 1),
|
||||
CPATCH_SIDE_NEGZ = (1 << 2),
|
||||
CPATCH_SIDE_POSZ = (1 << 3),
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -75,6 +72,8 @@ public:
|
||||
// draw state...
|
||||
void setDrawState(bool value) { m_bWillBeDrawn = value; };
|
||||
bool getDrawState() { return m_bWillBeDrawn; };
|
||||
|
||||
int GetSideFlags();
|
||||
};
|
||||
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "lib/sysdep/cpu.h"
|
||||
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/WaterManager.h"
|
||||
|
||||
#include "TerrainProperties.h"
|
||||
#include "TerrainTextureEntry.h"
|
||||
|
@ -35,8 +35,9 @@
|
||||
#include "renderer/AlphaMapCalculator.h"
|
||||
#include "renderer/PatchRData.h"
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/WaterManager.h"
|
||||
#include "simulation2/Simulation2.h"
|
||||
#include "simulation2/components/ICmpRangeManager.h"
|
||||
#include "simulation2/components/ICmpWaterManager.h"
|
||||
|
||||
const ssize_t BlendOffsets[9][2] = {
|
||||
{ 0, -1 },
|
||||
@ -52,7 +53,8 @@ const ssize_t BlendOffsets[9][2] = {
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// CPatchRData constructor
|
||||
CPatchRData::CPatchRData(CPatch* patch) : m_Patch(patch), m_VBBase(0), m_VBBlends(0), m_Vertices(0)
|
||||
CPatchRData::CPatchRData(CPatch* patch) :
|
||||
m_Patch(patch), m_VBBase(0), m_VBSides(0), m_VBBlends(0), m_Vertices(0)
|
||||
{
|
||||
debug_assert(patch);
|
||||
Build();
|
||||
@ -66,6 +68,7 @@ CPatchRData::~CPatchRData()
|
||||
delete[] m_Vertices;
|
||||
// release vertex buffer chunks
|
||||
if (m_VBBase) g_VBMan.Release(m_VBBase);
|
||||
if (m_VBSides) g_VBMan.Release(m_VBSides);
|
||||
if (m_VBBlends) g_VBMan.Release(m_VBBlends);
|
||||
}
|
||||
|
||||
@ -427,8 +430,6 @@ void CPatchRData::BuildVertices()
|
||||
{
|
||||
// create both vertices and lighting colors
|
||||
|
||||
CVector3D normal;
|
||||
|
||||
// number of vertices in each direction in each patch
|
||||
ssize_t vsize=PATCH_SIZE+1;
|
||||
|
||||
@ -459,6 +460,7 @@ void CPatchRData::BuildVertices()
|
||||
// Calculate diffuse lighting for this vertex
|
||||
// Ambient is added by the lighting pass (since ambient is the same
|
||||
// for all vertices, it need not be stored in the vertex structure)
|
||||
CVector3D normal;
|
||||
terrain->CalcNormal(ix,iz,normal);
|
||||
|
||||
RGBColor diffuse;
|
||||
@ -474,9 +476,89 @@ void CPatchRData::BuildVertices()
|
||||
m_VBBase->m_Owner->UpdateChunkVertices(m_VBBase,m_Vertices);
|
||||
}
|
||||
|
||||
void CPatchRData::BuildSide(std::vector<SSideVertex>& vertices, CPatchSideFlags side)
|
||||
{
|
||||
ssize_t vsize = PATCH_SIZE + 1;
|
||||
CTerrain* terrain = m_Patch->m_Parent;
|
||||
CmpPtr<ICmpWaterManager> cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
|
||||
|
||||
for (ssize_t k = 0; k < vsize; k++)
|
||||
{
|
||||
ssize_t gx = m_Patch->m_X * PATCH_SIZE;
|
||||
ssize_t gz = m_Patch->m_Z * PATCH_SIZE;
|
||||
switch (side)
|
||||
{
|
||||
case CPATCH_SIDE_NEGX: gz += k; break;
|
||||
case CPATCH_SIDE_POSX: gx += PATCH_SIZE; gz += PATCH_SIZE-k; break;
|
||||
case CPATCH_SIDE_NEGZ: gx += PATCH_SIZE-k; break;
|
||||
case CPATCH_SIDE_POSZ: gz += PATCH_SIZE; gx += k; break;
|
||||
}
|
||||
|
||||
CVector3D pos;
|
||||
terrain->CalcPosition(gx, gz, pos);
|
||||
|
||||
// Clamp the height to the water level
|
||||
float waterHeight = 0.f;
|
||||
if (!cmpWaterManager.null())
|
||||
waterHeight = cmpWaterManager->GetExactWaterLevel(pos.X, pos.Z);
|
||||
pos.Y = std::max(pos.Y, waterHeight);
|
||||
|
||||
SSideVertex v0, v1;
|
||||
v0.m_Position = pos;
|
||||
v1.m_Position = pos;
|
||||
v1.m_Position.Y = 0;
|
||||
|
||||
// If this is the start of this tristrip, but we've already got a partial
|
||||
// tristrip, and a couple of degenerate triangles to join the strips properly
|
||||
if (k == 0 && !vertices.empty())
|
||||
{
|
||||
vertices.push_back(vertices.back());
|
||||
vertices.push_back(v1);
|
||||
}
|
||||
|
||||
// Now add the new triangles
|
||||
vertices.push_back(v1);
|
||||
vertices.push_back(v0);
|
||||
}
|
||||
}
|
||||
|
||||
void CPatchRData::BuildSides()
|
||||
{
|
||||
std::vector<SSideVertex> sideVertices;
|
||||
|
||||
int sideFlags = m_Patch->GetSideFlags();
|
||||
|
||||
// If no sides are enabled, we don't need to do anything
|
||||
if (!sideFlags)
|
||||
return;
|
||||
|
||||
// For each side, generate a tristrip by adding a vertex at ground/water
|
||||
// level and a vertex underneath at height 0.
|
||||
|
||||
if (sideFlags & CPATCH_SIDE_NEGX)
|
||||
BuildSide(sideVertices, CPATCH_SIDE_NEGX);
|
||||
|
||||
if (sideFlags & CPATCH_SIDE_POSX)
|
||||
BuildSide(sideVertices, CPATCH_SIDE_POSX);
|
||||
|
||||
if (sideFlags & CPATCH_SIDE_NEGZ)
|
||||
BuildSide(sideVertices, CPATCH_SIDE_NEGZ);
|
||||
|
||||
if (sideFlags & CPATCH_SIDE_POSZ)
|
||||
BuildSide(sideVertices, CPATCH_SIDE_POSZ);
|
||||
|
||||
if (sideVertices.empty())
|
||||
return;
|
||||
|
||||
if (!m_VBSides)
|
||||
m_VBSides = g_VBMan.Allocate(sizeof(SSideVertex), sideVertices.size(), true);
|
||||
m_VBSides->m_Owner->UpdateChunkVertices(m_VBSides, &sideVertices[0]);
|
||||
}
|
||||
|
||||
void CPatchRData::Build()
|
||||
{
|
||||
BuildVertices();
|
||||
BuildSides();
|
||||
BuildIndices();
|
||||
BuildBlends();
|
||||
}
|
||||
@ -488,6 +570,7 @@ void CPatchRData::Update()
|
||||
// than everything; it's complicated slightly because the blends are dependent
|
||||
// on both vertex and index data
|
||||
BuildVertices();
|
||||
BuildSides();
|
||||
BuildIndices();
|
||||
BuildBlends();
|
||||
|
||||
@ -659,6 +742,29 @@ void CPatchRData::RenderOutline()
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void CPatchRData::RenderSides()
|
||||
{
|
||||
debug_assert(m_UpdateFlags==0);
|
||||
|
||||
if (!m_VBSides)
|
||||
return;
|
||||
|
||||
SSideVertex *base = (SSideVertex *)m_VBSides->m_Owner->Bind();
|
||||
|
||||
// setup data pointers
|
||||
GLsizei stride = sizeof(SSideVertex);
|
||||
glVertexPointer(3, GL_FLOAT, stride, &base->m_Position);
|
||||
|
||||
if (!g_Renderer.m_SkipSubmit)
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, m_VBSides->m_Index, (GLsizei)m_VBSides->m_Count);
|
||||
|
||||
// bump stats
|
||||
g_Renderer.m_Stats.m_DrawCalls++;
|
||||
g_Renderer.m_Stats.m_TerrainTris += m_VBSides->m_Count - 2;
|
||||
|
||||
CVertexBuffer::Unbind();
|
||||
}
|
||||
|
||||
void CPatchRData::RenderPriorities()
|
||||
{
|
||||
CTerrain* terrain = m_Patch->m_Parent;
|
||||
|
@ -41,6 +41,7 @@ public:
|
||||
void RenderBlends();
|
||||
void RenderOutline();
|
||||
void RenderStreams(int streamflags);
|
||||
void RenderSides();
|
||||
void RenderPriorities();
|
||||
|
||||
private:
|
||||
@ -64,6 +65,11 @@ private:
|
||||
float m_UVs[2];
|
||||
};
|
||||
|
||||
struct SSideVertex {
|
||||
// vertex position
|
||||
CVector3D m_Position;
|
||||
};
|
||||
|
||||
struct SBlendVertex {
|
||||
// vertex position
|
||||
CVector3D m_Position;
|
||||
@ -81,6 +87,9 @@ private:
|
||||
void BuildBlends();
|
||||
void BuildIndices();
|
||||
void BuildVertices();
|
||||
void BuildSides();
|
||||
|
||||
void BuildSide(std::vector<SSideVertex>& vertices, CPatchSideFlags side);
|
||||
|
||||
// owner patch
|
||||
CPatch* m_Patch;
|
||||
@ -88,6 +97,9 @@ private:
|
||||
// vertex buffer handle for base vertices
|
||||
CVertexBuffer::VBChunk* m_VBBase;
|
||||
|
||||
// vertex buffer handle for side vertices
|
||||
CVertexBuffer::VBChunk* m_VBSides;
|
||||
|
||||
// vertex buffer handle for blend vertices
|
||||
CVertexBuffer::VBChunk* m_VBBlends;
|
||||
|
||||
|
@ -155,8 +155,17 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
|
||||
{
|
||||
debug_assert(m->phase == Phase_Render);
|
||||
|
||||
// switch on required client states
|
||||
// render the solid black sides of the map first
|
||||
g_Renderer.BindTexture(0, 0);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glColor3f(0, 0, 0);
|
||||
for(size_t i = 0; i < m->visiblePatches.size(); ++i)
|
||||
{
|
||||
CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
|
||||
patchdata->RenderSides();
|
||||
}
|
||||
|
||||
// switch on required client states
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
// render everything fullbright
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "simulation2/system/Component.h"
|
||||
#include "ICmpWaterManager.h"
|
||||
|
||||
#include "graphics/RenderableObject.h"
|
||||
#include "graphics/Terrain.h"
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/WaterManager.h"
|
||||
|
||||
@ -80,6 +82,9 @@ public:
|
||||
virtual void SetWaterLevel(entity_pos_t h)
|
||||
{
|
||||
m_WaterHeight = h;
|
||||
|
||||
// Tell the terrain it'll need to recompute its cached render data
|
||||
GetSimContext().GetTerrain().MakeDirty(RENDERDATA_UPDATE_VERTICES);
|
||||
}
|
||||
|
||||
virtual entity_pos_t GetWaterLevel(entity_pos_t UNUSED(x), entity_pos_t UNUSED(z))
|
||||
|
Loading…
Reference in New Issue
Block a user