1
0
forked from 0ad/0ad

# Add solid black sides to the map, to hide underwater terrain.

This was SVN commit r8886.
This commit is contained in:
Ykkrosh 2011-02-03 14:36:54 +00:00
parent c710e718aa
commit 02e7eb69ff
7 changed files with 165 additions and 16 deletions

View File

@ -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;
}

View File

@ -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();
};

View File

@ -25,7 +25,6 @@
#include "lib/sysdep/cpu.h"
#include "renderer/Renderer.h"
#include "renderer/WaterManager.h"
#include "TerrainProperties.h"
#include "TerrainTextureEntry.h"

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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))