2011-01-29 08:31:48 -08:00
|
|
|
/* Copyright (C) 2011 Wildfire Games.
|
2009-04-18 10:00:33 -07:00
|
|
|
* This file is part of 0 A.D.
|
|
|
|
|
*
|
|
|
|
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* 0 A.D. is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2004-06-01 10:34:12 -07:00
|
|
|
#include "precompiled.h"
|
2004-05-29 17:46:58 -07:00
|
|
|
|
|
|
|
|
#include <set>
|
|
|
|
|
#include <algorithm>
|
2011-01-29 08:31:48 -08:00
|
|
|
|
|
|
|
|
#include "graphics/GameView.h"
|
2006-02-13 06:18:20 -08:00
|
|
|
#include "graphics/LightEnv.h"
|
2011-01-29 08:31:48 -08:00
|
|
|
#include "graphics/Patch.h"
|
|
|
|
|
#include "graphics/Terrain.h"
|
|
|
|
|
#include "lib/res/graphics/unifont.h"
|
|
|
|
|
#include "maths/MathUtil.h"
|
2004-07-15 12:29:56 -07:00
|
|
|
#include "ps/CLogger.h"
|
2007-01-13 14:44:42 -08:00
|
|
|
#include "ps/Game.h"
|
2011-01-29 08:31:48 -08:00
|
|
|
#include "ps/Profile.h"
|
|
|
|
|
#include "ps/Pyrogenesis.h"
|
2007-01-13 14:44:42 -08:00
|
|
|
#include "ps/World.h"
|
2011-01-29 08:31:48 -08:00
|
|
|
#include "ps/GameSetup/Config.h"
|
|
|
|
|
#include "renderer/AlphaMapCalculator.h"
|
|
|
|
|
#include "renderer/PatchRData.h"
|
|
|
|
|
#include "renderer/Renderer.h"
|
2011-02-03 06:36:54 -08:00
|
|
|
#include "renderer/WaterManager.h"
|
2010-05-01 09:20:58 -07:00
|
|
|
#include "simulation2/Simulation2.h"
|
2011-02-03 06:36:54 -08:00
|
|
|
#include "simulation2/components/ICmpWaterManager.h"
|
2004-05-29 17:46:58 -07:00
|
|
|
|
2011-01-29 08:31:48 -08:00
|
|
|
const ssize_t BlendOffsets[9][2] = {
|
2004-05-29 17:46:58 -07:00
|
|
|
{ 0, -1 },
|
|
|
|
|
{ -1, -1 },
|
|
|
|
|
{ -1, 0 },
|
|
|
|
|
{ -1, 1 },
|
|
|
|
|
{ 0, 1 },
|
|
|
|
|
{ 1, 1 },
|
|
|
|
|
{ 1, 0 },
|
2011-01-29 08:31:48 -08:00
|
|
|
{ 1, -1 },
|
|
|
|
|
{ 0, 0 }
|
2004-05-29 17:46:58 -07:00
|
|
|
};
|
|
|
|
|
|
2004-06-10 15:24:03 -07:00
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
|
// CPatchRData constructor
|
2011-02-03 06:36:54 -08:00
|
|
|
CPatchRData::CPatchRData(CPatch* patch) :
|
|
|
|
|
m_Patch(patch), m_VBBase(0), m_VBSides(0), m_VBBlends(0), m_Vertices(0)
|
2004-05-29 17:46:58 -07:00
|
|
|
{
|
2005-06-27 21:06:25 -07:00
|
|
|
debug_assert(patch);
|
2004-05-29 17:46:58 -07:00
|
|
|
Build();
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-10 15:24:03 -07:00
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
|
// CPatchRData destructor
|
2006-02-13 06:18:20 -08:00
|
|
|
CPatchRData::~CPatchRData()
|
2004-05-29 17:46:58 -07:00
|
|
|
{
|
2004-06-10 15:24:03 -07:00
|
|
|
// delete copy of vertex data
|
|
|
|
|
delete[] m_Vertices;
|
2004-06-07 12:53:58 -07:00
|
|
|
// release vertex buffer chunks
|
2004-06-10 15:24:03 -07:00
|
|
|
if (m_VBBase) g_VBMan.Release(m_VBBase);
|
2011-02-03 06:36:54 -08:00
|
|
|
if (m_VBSides) g_VBMan.Release(m_VBSides);
|
2004-06-10 15:24:03 -07:00
|
|
|
if (m_VBBlends) g_VBMan.Release(m_VBBlends);
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
|
|
|
|
|
2006-03-21 12:55:45 -08:00
|
|
|
const float uvFactor = 0.125f / sqrt(2.f);
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
static void CalculateUV(float uv[2], ssize_t x, ssize_t z)
|
2004-05-29 17:46:58 -07:00
|
|
|
{
|
2006-03-21 12:55:45 -08:00
|
|
|
// The UV axes are offset 45 degrees from XZ
|
|
|
|
|
uv[0] = ( x-z)*uvFactor;
|
|
|
|
|
uv[1] = (-x-z)*uvFactor;
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
|
|
|
|
|
2011-01-29 08:31:48 -08:00
|
|
|
/**
|
|
|
|
|
* Represents a blend for a single tile, texture and shape.
|
|
|
|
|
*/
|
|
|
|
|
struct STileBlend
|
|
|
|
|
{
|
|
|
|
|
CTerrainTextureEntry* m_Texture;
|
|
|
|
|
int m_Priority;
|
|
|
|
|
u16 m_TileMask; // bit n set if this blend contains neighbour tile BlendOffsets[n]
|
|
|
|
|
|
|
|
|
|
struct DecreasingPriority
|
|
|
|
|
{
|
|
|
|
|
bool operator()(const STileBlend& a, const STileBlend& b) const
|
|
|
|
|
{
|
|
|
|
|
if (a.m_Priority > b.m_Priority)
|
|
|
|
|
return true;
|
|
|
|
|
if (a.m_Priority < b.m_Priority)
|
|
|
|
|
return false;
|
|
|
|
|
if (a.m_Texture && b.m_Texture)
|
|
|
|
|
return a.m_Texture->GetTag() > b.m_Texture->GetTag();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct CurrentTile
|
|
|
|
|
{
|
|
|
|
|
bool operator()(const STileBlend& a) const
|
|
|
|
|
{
|
2011-02-02 18:33:37 -08:00
|
|
|
return (a.m_TileMask & (1 << 8)) != 0;
|
2011-01-29 08:31:48 -08:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Represents the ordered collection of blends drawn on a particular tile.
|
|
|
|
|
*/
|
|
|
|
|
struct STileBlendStack
|
|
|
|
|
{
|
|
|
|
|
u8 i, j;
|
|
|
|
|
std::vector<STileBlend> blends; // back of vector is lowest-priority texture
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Represents a batched collection of blends using the same texture.
|
|
|
|
|
*/
|
|
|
|
|
struct SBlendLayer
|
|
|
|
|
{
|
|
|
|
|
struct Tile
|
|
|
|
|
{
|
|
|
|
|
u8 i, j;
|
|
|
|
|
u8 shape;
|
|
|
|
|
};
|
|
|
|
|
|
2010-09-10 14:02:10 -07:00
|
|
|
CTerrainTextureEntry* m_Texture;
|
2011-01-29 08:31:48 -08:00
|
|
|
std::vector<Tile> m_Tiles;
|
2004-05-29 17:46:58 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void CPatchRData::BuildBlends()
|
|
|
|
|
{
|
|
|
|
|
m_BlendSplats.clear();
|
|
|
|
|
m_BlendVertices.clear();
|
|
|
|
|
|
2011-01-29 08:31:48 -08:00
|
|
|
CTerrain* terrain = m_Patch->m_Parent;
|
2004-05-29 17:46:58 -07:00
|
|
|
|
2011-01-29 08:31:48 -08:00
|
|
|
std::vector<STileBlendStack> blendStacks;
|
|
|
|
|
blendStacks.reserve(PATCH_SIZE*PATCH_SIZE);
|
2004-05-29 17:46:58 -07:00
|
|
|
|
2011-01-29 08:31:48 -08:00
|
|
|
// For each tile in patch ..
|
|
|
|
|
for (ssize_t j = 0; j < PATCH_SIZE; ++j)
|
|
|
|
|
{
|
|
|
|
|
for (ssize_t i = 0; i < PATCH_SIZE; ++i)
|
|
|
|
|
{
|
2010-05-27 16:31:03 -07:00
|
|
|
ssize_t gx = m_Patch->m_X * PATCH_SIZE + i;
|
|
|
|
|
ssize_t gz = m_Patch->m_Z * PATCH_SIZE + j;
|
2004-05-29 17:46:58 -07:00
|
|
|
|
2011-01-29 08:31:48 -08:00
|
|
|
std::vector<STileBlend> blends;
|
|
|
|
|
blends.reserve(9);
|
|
|
|
|
|
|
|
|
|
// Compute a blend for every tile in the 3x3 square around this tile
|
|
|
|
|
for (size_t n = 0; n < 9; ++n)
|
|
|
|
|
{
|
|
|
|
|
ssize_t ox = gx + BlendOffsets[n][1];
|
|
|
|
|
ssize_t oz = gz + BlendOffsets[n][0];
|
|
|
|
|
|
|
|
|
|
CMiniPatch* nmp = terrain->GetTile(ox, oz);
|
|
|
|
|
if (!nmp)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
STileBlend blend;
|
|
|
|
|
blend.m_Texture = nmp->GetTextureEntry();
|
|
|
|
|
blend.m_Priority = nmp->GetPriority();
|
|
|
|
|
blend.m_TileMask = 1 << n;
|
|
|
|
|
blends.push_back(blend);
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
2011-01-29 08:31:48 -08:00
|
|
|
|
|
|
|
|
// Sort the blends, highest priority first
|
|
|
|
|
std::sort(blends.begin(), blends.end(), STileBlend::DecreasingPriority());
|
|
|
|
|
|
|
|
|
|
STileBlendStack blendStack;
|
|
|
|
|
blendStack.i = i;
|
|
|
|
|
blendStack.j = j;
|
|
|
|
|
|
|
|
|
|
// Put the blends into the tile's stack, merging any adjacent blends with the same texture
|
|
|
|
|
for (size_t k = 0; k < blends.size(); ++k)
|
|
|
|
|
{
|
|
|
|
|
if (!blendStack.blends.empty() && blendStack.blends.back().m_Texture == blends[k].m_Texture)
|
|
|
|
|
blendStack.blends.back().m_TileMask |= blends[k].m_TileMask;
|
|
|
|
|
else
|
|
|
|
|
blendStack.blends.push_back(blends[k]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove blends that are after (i.e. lower priority than) the current tile
|
|
|
|
|
// (including the current tile), since we don't want to render them on top of
|
|
|
|
|
// the tile's base texture
|
|
|
|
|
blendStack.blends.erase(
|
|
|
|
|
std::find_if(blendStack.blends.begin(), blendStack.blends.end(), STileBlend::CurrentTile()),
|
|
|
|
|
blendStack.blends.end());
|
|
|
|
|
|
|
|
|
|
blendStacks.push_back(blendStack);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Given the blend stack per tile, we want to batch together as many blends as possible.
|
|
|
|
|
// Group them into a series of layers (each of which has a single texture):
|
|
|
|
|
|
|
|
|
|
std::vector<SBlendLayer> blendLayers;
|
|
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
if (!blendLayers.empty())
|
|
|
|
|
{
|
|
|
|
|
// Try to grab as many tiles as possible that match our current layer,
|
|
|
|
|
// from off the blend stacks of all the tiles
|
|
|
|
|
|
|
|
|
|
CTerrainTextureEntry* tex = blendLayers.back().m_Texture;
|
|
|
|
|
|
|
|
|
|
for (size_t k = 0; k < blendStacks.size(); ++k)
|
|
|
|
|
{
|
|
|
|
|
if (!blendStacks[k].blends.empty() && blendStacks[k].blends.back().m_Texture == tex)
|
|
|
|
|
{
|
|
|
|
|
SBlendLayer::Tile t = { blendStacks[k].i, blendStacks[k].j, blendStacks[k].blends.back().m_TileMask };
|
|
|
|
|
blendLayers.back().m_Tiles.push_back(t);
|
|
|
|
|
blendStacks[k].blends.pop_back();
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
2011-01-29 08:31:48 -08:00
|
|
|
// (We've already merged adjacent entries of the same texture in each stack,
|
|
|
|
|
// so we don't need to bother looping to check the next entry in this stack again)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We've grabbed as many tiles as possible; now we need to start a new layer.
|
|
|
|
|
// The new layer's texture could come from the back of any non-empty stack;
|
|
|
|
|
// choose the longest stack as a heuristic to reduce the number of layers
|
|
|
|
|
CTerrainTextureEntry* bestTex = NULL;
|
|
|
|
|
size_t bestStackSize = 0;
|
|
|
|
|
|
|
|
|
|
for (size_t k = 0; k < blendStacks.size(); ++k)
|
|
|
|
|
{
|
|
|
|
|
if (blendStacks[k].blends.size() > bestStackSize)
|
|
|
|
|
{
|
|
|
|
|
bestStackSize = blendStacks[k].blends.size();
|
|
|
|
|
bestTex = blendStacks[k].blends.back().m_Texture;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If all our stacks were empty, we're done
|
|
|
|
|
if (bestStackSize == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// Otherwise add the new layer, then loop back and start filling it in
|
|
|
|
|
|
|
|
|
|
SBlendLayer layer;
|
|
|
|
|
layer.m_Texture = bestTex;
|
|
|
|
|
blendLayers.push_back(layer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now build outgoing splats
|
|
|
|
|
m_BlendSplats.resize(blendLayers.size());
|
|
|
|
|
|
|
|
|
|
for (size_t k = 0; k < blendLayers.size(); ++k)
|
|
|
|
|
{
|
|
|
|
|
SSplat& splat = m_BlendSplats[k];
|
2011-01-30 06:43:35 -08:00
|
|
|
splat.m_IndexStart = m_BlendVertices.size();
|
2011-01-29 08:31:48 -08:00
|
|
|
splat.m_Texture = blendLayers[k].m_Texture;
|
|
|
|
|
|
|
|
|
|
for (size_t t = 0; t < blendLayers[k].m_Tiles.size(); ++t)
|
|
|
|
|
{
|
|
|
|
|
SBlendLayer::Tile& tile = blendLayers[k].m_Tiles[t];
|
2011-01-30 06:43:35 -08:00
|
|
|
AddBlend(tile.i, tile.j, tile.shape);
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
2011-01-30 06:43:35 -08:00
|
|
|
|
|
|
|
|
splat.m_IndexCount = m_BlendVertices.size() - splat.m_IndexStart;
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
2006-02-13 06:18:20 -08:00
|
|
|
|
2011-01-29 08:31:48 -08:00
|
|
|
// Release existing vertex buffer chunk
|
|
|
|
|
if (m_VBBlends)
|
|
|
|
|
{
|
2004-06-07 12:53:58 -07:00
|
|
|
g_VBMan.Release(m_VBBlends);
|
2011-01-29 08:31:48 -08:00
|
|
|
m_VBBlends = 0;
|
2004-06-10 15:24:03 -07:00
|
|
|
}
|
2006-02-13 06:18:20 -08:00
|
|
|
|
2011-01-29 08:31:48 -08:00
|
|
|
if (m_BlendVertices.size())
|
|
|
|
|
{
|
|
|
|
|
// Construct vertex buffer
|
|
|
|
|
|
|
|
|
|
m_VBBlends = g_VBMan.Allocate(sizeof(SBlendVertex), m_BlendVertices.size(), true);
|
|
|
|
|
m_VBBlends->m_Owner->UpdateChunkVertices(m_VBBlends, &m_BlendVertices[0]);
|
2006-02-13 06:18:20 -08:00
|
|
|
|
2005-06-27 21:06:25 -07:00
|
|
|
debug_assert(m_VBBlends->m_Index < 65536);
|
2004-10-06 11:44:47 -07:00
|
|
|
unsigned short base = (unsigned short)m_VBBlends->m_Index;
|
2011-01-29 08:31:48 -08:00
|
|
|
|
|
|
|
|
// Update the indices to include the base offset
|
2011-01-30 06:43:35 -08:00
|
|
|
for (size_t k = 0; k < m_BlendSplats.size(); ++k)
|
|
|
|
|
m_BlendSplats[k].m_IndexStart += base;
|
2004-06-10 15:24:03 -07:00
|
|
|
}
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
|
|
|
|
|
2011-01-30 06:43:35 -08:00
|
|
|
void CPatchRData::AddBlend(u16 i, u16 j, u8 shape)
|
2011-01-29 08:31:48 -08:00
|
|
|
{
|
|
|
|
|
ssize_t gx = m_Patch->m_X * PATCH_SIZE + i;
|
|
|
|
|
ssize_t gz = m_Patch->m_Z * PATCH_SIZE + j;
|
|
|
|
|
|
|
|
|
|
// uses the current neighbour texture
|
|
|
|
|
BlendShape8 shape8;
|
|
|
|
|
for (size_t m = 0; m < 8; ++m)
|
|
|
|
|
shape8[m] = (shape & (1 << m)) ? 0 : 1;
|
|
|
|
|
|
|
|
|
|
// calculate the required alphamap and the required rotation of the alphamap from blendshape
|
|
|
|
|
unsigned int alphamapflags;
|
|
|
|
|
int alphamap = CAlphaMapCalculator::Calculate(shape8, alphamapflags);
|
|
|
|
|
|
|
|
|
|
// now actually render the blend tile (if we need one)
|
|
|
|
|
if (alphamap == -1)
|
2011-01-30 06:43:35 -08:00
|
|
|
return;
|
2011-01-29 08:31:48 -08:00
|
|
|
|
|
|
|
|
float u0 = g_Renderer.m_AlphaMapCoords[alphamap].u0;
|
|
|
|
|
float u1 = g_Renderer.m_AlphaMapCoords[alphamap].u1;
|
|
|
|
|
float v0 = g_Renderer.m_AlphaMapCoords[alphamap].v0;
|
|
|
|
|
float v1 = g_Renderer.m_AlphaMapCoords[alphamap].v1;
|
|
|
|
|
|
|
|
|
|
if (alphamapflags & BLENDMAP_FLIPU)
|
|
|
|
|
std::swap(u0, u1);
|
|
|
|
|
|
|
|
|
|
if (alphamapflags & BLENDMAP_FLIPV)
|
|
|
|
|
std::swap(v0, v1);
|
|
|
|
|
|
|
|
|
|
int base = 0;
|
|
|
|
|
if (alphamapflags & BLENDMAP_ROTATE90)
|
|
|
|
|
base = 1;
|
|
|
|
|
else if (alphamapflags & BLENDMAP_ROTATE180)
|
|
|
|
|
base = 2;
|
|
|
|
|
else if (alphamapflags & BLENDMAP_ROTATE270)
|
|
|
|
|
base = 3;
|
|
|
|
|
|
|
|
|
|
SBlendVertex vtx[4];
|
|
|
|
|
vtx[(base + 0) % 4].m_AlphaUVs[0] = u0;
|
|
|
|
|
vtx[(base + 0) % 4].m_AlphaUVs[1] = v0;
|
|
|
|
|
vtx[(base + 1) % 4].m_AlphaUVs[0] = u1;
|
|
|
|
|
vtx[(base + 1) % 4].m_AlphaUVs[1] = v0;
|
|
|
|
|
vtx[(base + 2) % 4].m_AlphaUVs[0] = u1;
|
|
|
|
|
vtx[(base + 2) % 4].m_AlphaUVs[1] = v1;
|
|
|
|
|
vtx[(base + 3) % 4].m_AlphaUVs[0] = u0;
|
|
|
|
|
vtx[(base + 3) % 4].m_AlphaUVs[1] = v1;
|
|
|
|
|
|
|
|
|
|
ssize_t vsize = PATCH_SIZE + 1;
|
|
|
|
|
|
|
|
|
|
SBlendVertex dst;
|
|
|
|
|
|
|
|
|
|
const SBaseVertex& vtx0 = m_Vertices[(j * vsize) + i];
|
|
|
|
|
CalculateUV(dst.m_UVs, gx, gz);
|
|
|
|
|
dst.m_AlphaUVs[0] = vtx[0].m_AlphaUVs[0];
|
|
|
|
|
dst.m_AlphaUVs[1] = vtx[0].m_AlphaUVs[1];
|
|
|
|
|
dst.m_Position = vtx0.m_Position;
|
|
|
|
|
m_BlendVertices.push_back(dst);
|
|
|
|
|
|
|
|
|
|
const SBaseVertex& vtx1 = m_Vertices[(j * vsize) + i + 1];
|
|
|
|
|
CalculateUV(dst.m_UVs, gx + 1, gz);
|
|
|
|
|
dst.m_AlphaUVs[0] = vtx[1].m_AlphaUVs[0];
|
|
|
|
|
dst.m_AlphaUVs[1] = vtx[1].m_AlphaUVs[1];
|
|
|
|
|
dst.m_Position = vtx1.m_Position;
|
|
|
|
|
m_BlendVertices.push_back(dst);
|
|
|
|
|
|
|
|
|
|
const SBaseVertex& vtx2 = m_Vertices[((j + 1) * vsize) + i + 1];
|
|
|
|
|
CalculateUV(dst.m_UVs, gx + 1, gz + 1);
|
|
|
|
|
dst.m_AlphaUVs[0] = vtx[2].m_AlphaUVs[0];
|
|
|
|
|
dst.m_AlphaUVs[1] = vtx[2].m_AlphaUVs[1];
|
|
|
|
|
dst.m_Position = vtx2.m_Position;
|
|
|
|
|
m_BlendVertices.push_back(dst);
|
|
|
|
|
|
|
|
|
|
const SBaseVertex& vtx3 = m_Vertices[((j + 1) * vsize) + i];
|
|
|
|
|
CalculateUV(dst.m_UVs, gx, gz + 1);
|
|
|
|
|
dst.m_AlphaUVs[0] = vtx[3].m_AlphaUVs[0];
|
|
|
|
|
dst.m_AlphaUVs[1] = vtx[3].m_AlphaUVs[1];
|
|
|
|
|
dst.m_Position = vtx3.m_Position;
|
|
|
|
|
m_BlendVertices.push_back(dst);
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-29 17:46:58 -07:00
|
|
|
void CPatchRData::BuildIndices()
|
2004-06-10 15:24:03 -07:00
|
|
|
{
|
|
|
|
|
// must have allocated some vertices before trying to build corresponding indices
|
2005-06-27 21:06:25 -07:00
|
|
|
debug_assert(m_VBBase);
|
2004-06-07 12:53:58 -07:00
|
|
|
|
2004-05-29 17:46:58 -07:00
|
|
|
// number of vertices in each direction in each patch
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
ssize_t vsize=PATCH_SIZE+1;
|
2004-05-29 17:46:58 -07:00
|
|
|
|
|
|
|
|
// release existing indices and bins
|
|
|
|
|
m_Indices.clear();
|
|
|
|
|
m_Splats.clear();
|
|
|
|
|
|
|
|
|
|
// build grid of textures on this patch and boundaries of adjacent patches
|
2010-09-10 14:02:10 -07:00
|
|
|
std::vector<CTerrainTextureEntry*> textures;
|
|
|
|
|
CTerrainTextureEntry* texgrid[PATCH_SIZE][PATCH_SIZE];
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
for (ssize_t j=0;j<PATCH_SIZE;j++) {
|
|
|
|
|
for (ssize_t i=0;i<PATCH_SIZE;i++) {
|
2010-09-10 14:02:10 -07:00
|
|
|
CTerrainTextureEntry* tex=m_Patch->m_MiniPatches[j][i].GetTextureEntry();
|
|
|
|
|
texgrid[j][i]=tex;
|
|
|
|
|
if (std::find(textures.begin(),textures.end(),tex)==textures.end()) {
|
|
|
|
|
textures.push_back(tex);
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// now build base splats from interior textures
|
|
|
|
|
m_Splats.resize(textures.size());
|
2006-02-13 06:18:20 -08:00
|
|
|
// build indices for base splats
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
size_t base=m_VBBase->m_Index;
|
|
|
|
|
for (size_t i=0;i<m_Splats.size();i++) {
|
2010-09-10 14:02:10 -07:00
|
|
|
CTerrainTextureEntry* tex=textures[i];
|
2004-05-29 17:46:58 -07:00
|
|
|
|
|
|
|
|
SSplat& splat=m_Splats[i];
|
2010-09-10 14:02:10 -07:00
|
|
|
splat.m_Texture=tex;
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
splat.m_IndexStart=m_Indices.size();
|
2006-02-13 06:18:20 -08:00
|
|
|
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
for (ssize_t j=0;j<PATCH_SIZE;j++) {
|
|
|
|
|
for (ssize_t i=0;i<PATCH_SIZE;i++) {
|
2010-09-10 14:02:10 -07:00
|
|
|
if (texgrid[j][i]==tex){
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
m_Indices.push_back(u16(((j+0)*vsize+(i+0))+base));
|
|
|
|
|
m_Indices.push_back(u16(((j+0)*vsize+(i+1))+base));
|
|
|
|
|
m_Indices.push_back(u16(((j+1)*vsize+(i+1))+base));
|
|
|
|
|
m_Indices.push_back(u16(((j+1)*vsize+(i+0))+base));
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
splat.m_IndexCount=m_Indices.size()-splat.m_IndexStart;
|
2004-06-10 15:24:03 -07:00
|
|
|
}
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CPatchRData::BuildVertices()
|
|
|
|
|
{
|
2005-10-09 01:14:42 -07:00
|
|
|
// create both vertices and lighting colors
|
|
|
|
|
|
2004-05-29 17:46:58 -07:00
|
|
|
// number of vertices in each direction in each patch
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
ssize_t vsize=PATCH_SIZE+1;
|
2006-02-13 06:18:20 -08:00
|
|
|
|
2004-05-29 17:46:58 -07:00
|
|
|
if (!m_Vertices) {
|
|
|
|
|
m_Vertices=new SBaseVertex[vsize*vsize];
|
|
|
|
|
}
|
|
|
|
|
SBaseVertex* vertices=m_Vertices;
|
2006-02-13 06:18:20 -08:00
|
|
|
|
|
|
|
|
|
2004-05-29 17:46:58 -07:00
|
|
|
// get index of this patch
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
ssize_t px=m_Patch->m_X;
|
|
|
|
|
ssize_t pz=m_Patch->m_Z;
|
2006-02-13 06:18:20 -08:00
|
|
|
|
2004-05-29 17:46:58 -07:00
|
|
|
CTerrain* terrain=m_Patch->m_Parent;
|
2006-02-13 06:18:20 -08:00
|
|
|
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
|
2004-05-29 17:46:58 -07:00
|
|
|
|
2004-06-10 15:24:03 -07:00
|
|
|
// build vertices
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
for (ssize_t j=0;j<vsize;j++) {
|
|
|
|
|
for (ssize_t i=0;i<vsize;i++) {
|
|
|
|
|
ssize_t ix=px*PATCH_SIZE+i;
|
|
|
|
|
ssize_t iz=pz*PATCH_SIZE+j;
|
|
|
|
|
ssize_t v=(j*vsize)+i;
|
2004-06-07 12:53:58 -07:00
|
|
|
|
2005-10-09 01:14:42 -07:00
|
|
|
// calculate vertex data
|
2006-02-13 06:18:20 -08:00
|
|
|
terrain->CalcPosition(ix,iz,vertices[v].m_Position);
|
2006-03-21 12:55:45 -08:00
|
|
|
CalculateUV(vertices[v].m_UVs, ix, iz);
|
2006-02-13 06:18:20 -08:00
|
|
|
|
|
|
|
|
// 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)
|
2011-02-03 06:36:54 -08:00
|
|
|
CVector3D normal;
|
2005-10-09 01:14:42 -07:00
|
|
|
terrain->CalcNormal(ix,iz,normal);
|
2006-02-13 06:18:20 -08:00
|
|
|
|
|
|
|
|
RGBColor diffuse;
|
|
|
|
|
lightEnv.EvaluateDirect(normal, diffuse);
|
2008-06-30 12:08:29 -07:00
|
|
|
vertices[v].m_DiffuseColor = ConvertRGBColorTo4ub(diffuse);
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
|
|
|
|
}
|
2006-02-13 06:18:20 -08:00
|
|
|
|
2005-10-09 01:14:42 -07:00
|
|
|
// upload to vertex buffer
|
2004-06-10 15:24:03 -07:00
|
|
|
if (!m_VBBase) {
|
2005-11-05 20:16:19 -08:00
|
|
|
m_VBBase=g_VBMan.Allocate(sizeof(SBaseVertex),vsize*vsize,true);
|
2006-01-06 17:04:26 -08:00
|
|
|
}
|
2004-06-07 12:53:58 -07:00
|
|
|
m_VBBase->m_Owner->UpdateChunkVertices(m_VBBase,m_Vertices);
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
|
|
|
|
|
2011-02-03 06:36:54 -08:00
|
|
|
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]);
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-29 17:46:58 -07:00
|
|
|
void CPatchRData::Build()
|
|
|
|
|
{
|
|
|
|
|
BuildVertices();
|
2011-02-03 06:36:54 -08:00
|
|
|
BuildSides();
|
2004-05-29 17:46:58 -07:00
|
|
|
BuildIndices();
|
|
|
|
|
BuildBlends();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CPatchRData::Update()
|
|
|
|
|
{
|
|
|
|
|
if (m_UpdateFlags!=0) {
|
|
|
|
|
// TODO,RC 11/04/04 - need to only rebuild necessary bits of renderdata rather
|
|
|
|
|
// than everything; it's complicated slightly because the blends are dependent
|
|
|
|
|
// on both vertex and index data
|
2005-10-09 01:14:42 -07:00
|
|
|
BuildVertices();
|
2011-02-03 06:36:54 -08:00
|
|
|
BuildSides();
|
2004-05-29 17:46:58 -07:00
|
|
|
BuildIndices();
|
2005-10-09 01:14:42 -07:00
|
|
|
BuildBlends();
|
2004-05-29 17:46:58 -07:00
|
|
|
|
|
|
|
|
m_UpdateFlags=0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-02 17:12:24 -08:00
|
|
|
void CPatchRData::RenderBase()
|
2004-05-29 17:46:58 -07:00
|
|
|
{
|
2005-06-27 21:06:25 -07:00
|
|
|
debug_assert(m_UpdateFlags==0);
|
2004-05-29 17:46:58 -07:00
|
|
|
|
2006-01-29 10:23:47 -08:00
|
|
|
SBaseVertex *base=(SBaseVertex *)m_VBBase->m_Owner->Bind();
|
2004-05-29 17:46:58 -07:00
|
|
|
|
|
|
|
|
// setup data pointers
|
2011-02-02 17:12:24 -08:00
|
|
|
GLsizei stride = sizeof(SBaseVertex);
|
|
|
|
|
glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]);
|
|
|
|
|
glColorPointer(4, GL_UNSIGNED_BYTE, stride, &base->m_DiffuseColor);
|
|
|
|
|
glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs[0]);
|
2006-02-13 06:18:20 -08:00
|
|
|
|
2004-05-29 17:46:58 -07:00
|
|
|
// render each splat
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
for (size_t i=0;i<m_Splats.size();i++) {
|
2004-05-29 17:46:58 -07:00
|
|
|
SSplat& splat=m_Splats[i];
|
2010-09-10 14:02:10 -07:00
|
|
|
|
|
|
|
|
if (splat.m_Texture)
|
|
|
|
|
splat.m_Texture->GetTexture()->Bind();
|
|
|
|
|
else
|
|
|
|
|
g_Renderer.GetTextureManager().GetErrorTexture()->Bind();
|
2006-09-23 09:04:54 -07:00
|
|
|
|
|
|
|
|
if (!g_Renderer.m_SkipSubmit) {
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
glDrawElements(GL_QUADS, (GLsizei)splat.m_IndexCount,
|
2006-09-23 09:04:54 -07:00
|
|
|
GL_UNSIGNED_SHORT, &m_Indices[splat.m_IndexStart]);
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-29 17:46:58 -07:00
|
|
|
// bump stats
|
|
|
|
|
g_Renderer.m_Stats.m_DrawCalls++;
|
|
|
|
|
g_Renderer.m_Stats.m_TerrainTris+=splat.m_IndexCount/2;
|
|
|
|
|
}
|
2010-05-30 06:42:56 -07:00
|
|
|
|
|
|
|
|
CVertexBuffer::Unbind();
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
|
|
|
|
|
2011-02-02 17:12:24 -08:00
|
|
|
void CPatchRData::RenderStreams(int streamflags)
|
2004-05-29 17:46:58 -07:00
|
|
|
{
|
2005-06-27 21:06:25 -07:00
|
|
|
debug_assert(m_UpdateFlags==0);
|
2004-05-29 17:46:58 -07:00
|
|
|
|
2006-01-29 10:23:47 -08:00
|
|
|
SBaseVertex* base=(SBaseVertex *)m_VBBase->m_Owner->Bind();
|
2004-05-29 17:46:58 -07:00
|
|
|
|
|
|
|
|
// setup data pointers
|
2011-02-02 17:12:24 -08:00
|
|
|
GLsizei stride = sizeof(SBaseVertex);
|
2006-01-29 10:23:47 -08:00
|
|
|
glVertexPointer(3, GL_FLOAT, stride, &base->m_Position);
|
2011-02-02 17:12:24 -08:00
|
|
|
if (streamflags & STREAM_UV0)
|
|
|
|
|
{
|
2006-01-29 10:23:47 -08:00
|
|
|
glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs);
|
2011-02-02 17:12:24 -08:00
|
|
|
}
|
|
|
|
|
else if (streamflags & STREAM_POSTOUV0)
|
|
|
|
|
{
|
|
|
|
|
glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position);
|
|
|
|
|
}
|
|
|
|
|
if (streamflags & STREAM_POSTOUV1)
|
|
|
|
|
{
|
|
|
|
|
pglClientActiveTextureARB(GL_TEXTURE1);
|
|
|
|
|
glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position);
|
|
|
|
|
pglClientActiveTextureARB(GL_TEXTURE0);
|
|
|
|
|
}
|
|
|
|
|
if (streamflags & STREAM_POSTOUV2)
|
|
|
|
|
{
|
|
|
|
|
pglClientActiveTextureARB(GL_TEXTURE2);
|
|
|
|
|
glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position);
|
|
|
|
|
pglClientActiveTextureARB(GL_TEXTURE0);
|
|
|
|
|
}
|
|
|
|
|
if (streamflags & STREAM_POSTOUV3)
|
|
|
|
|
{
|
|
|
|
|
pglClientActiveTextureARB(GL_TEXTURE3);
|
2006-01-29 10:23:47 -08:00
|
|
|
glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position);
|
2011-02-02 17:12:24 -08:00
|
|
|
pglClientActiveTextureARB(GL_TEXTURE0);
|
2004-10-06 11:44:47 -07:00
|
|
|
}
|
2006-02-13 06:18:20 -08:00
|
|
|
if (streamflags & STREAM_COLOR)
|
|
|
|
|
{
|
2011-02-02 17:12:24 -08:00
|
|
|
glColorPointer(4, GL_UNSIGNED_BYTE, stride, &base->m_DiffuseColor);
|
2006-02-13 06:18:20 -08:00
|
|
|
}
|
|
|
|
|
|
2004-05-29 17:46:58 -07:00
|
|
|
// render all base splats at once
|
2006-09-23 09:04:54 -07:00
|
|
|
if (!g_Renderer.m_SkipSubmit) {
|
|
|
|
|
glDrawElements(GL_QUADS,(GLsizei)m_Indices.size(),GL_UNSIGNED_SHORT,&m_Indices[0]);
|
|
|
|
|
}
|
2004-05-29 17:46:58 -07:00
|
|
|
|
|
|
|
|
// bump stats
|
|
|
|
|
g_Renderer.m_Stats.m_DrawCalls++;
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
g_Renderer.m_Stats.m_TerrainTris+=m_Indices.size()/2;
|
2010-05-30 06:42:56 -07:00
|
|
|
|
|
|
|
|
CVertexBuffer::Unbind();
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CPatchRData::RenderBlends()
|
|
|
|
|
{
|
2005-06-27 21:06:25 -07:00
|
|
|
debug_assert(m_UpdateFlags==0);
|
2004-05-29 17:46:58 -07:00
|
|
|
|
2011-01-29 08:31:48 -08:00
|
|
|
if (m_BlendVertices.empty())
|
|
|
|
|
return;
|
2004-05-29 17:46:58 -07:00
|
|
|
|
2004-06-10 15:24:03 -07:00
|
|
|
u8* base=m_VBBlends->m_Owner->Bind();
|
2004-05-29 17:46:58 -07:00
|
|
|
|
|
|
|
|
// setup data pointers
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
GLsizei stride=sizeof(SBlendVertex);
|
2006-11-07 05:28:03 -08:00
|
|
|
// ((GCC warns about offsetof: SBlendVertex contains a CVector3D which has
|
|
|
|
|
// a constructor, and so is not a POD type, and so offsetof is theoretically
|
|
|
|
|
// invalid - see http://gcc.gnu.org/ml/gcc/2003-11/msg00281.html - but it
|
|
|
|
|
// doesn't seem to be worth changing this code since it works anyway.))
|
2004-05-29 17:46:58 -07:00
|
|
|
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_Position));
|
2006-02-13 06:18:20 -08:00
|
|
|
|
2005-10-29 18:18:15 -07:00
|
|
|
pglClientActiveTextureARB(GL_TEXTURE0);
|
2004-05-29 17:46:58 -07:00
|
|
|
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_UVs[0]));
|
|
|
|
|
|
2005-10-29 18:18:15 -07:00
|
|
|
pglClientActiveTextureARB(GL_TEXTURE1);
|
2004-05-29 17:46:58 -07:00
|
|
|
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_AlphaUVs[0]));
|
|
|
|
|
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
for (size_t i=0;i<m_BlendSplats.size();i++) {
|
2004-05-29 17:46:58 -07:00
|
|
|
SSplat& splat=m_BlendSplats[i];
|
2010-09-10 14:02:10 -07:00
|
|
|
|
|
|
|
|
if (splat.m_Texture)
|
|
|
|
|
splat.m_Texture->GetTexture()->Bind();
|
|
|
|
|
else
|
|
|
|
|
g_Renderer.GetTextureManager().GetErrorTexture()->Bind();
|
2006-09-23 09:04:54 -07:00
|
|
|
|
|
|
|
|
if (!g_Renderer.m_SkipSubmit) {
|
2011-01-30 06:43:35 -08:00
|
|
|
// Since every blend vertex likely has distinct UV even if they
|
|
|
|
|
// share positions, there's no value in using indexed arrays, so
|
|
|
|
|
// we just use DrawArrays instead of DrawElements
|
|
|
|
|
glDrawArrays(GL_QUADS, (GLint)splat.m_IndexStart, (GLsizei)splat.m_IndexCount);
|
2006-09-23 09:04:54 -07:00
|
|
|
}
|
2004-05-29 17:46:58 -07:00
|
|
|
|
|
|
|
|
// bump stats
|
|
|
|
|
g_Renderer.m_Stats.m_DrawCalls++;
|
|
|
|
|
g_Renderer.m_Stats.m_BlendSplats++;
|
|
|
|
|
g_Renderer.m_Stats.m_TerrainTris+=splat.m_IndexCount/2;
|
|
|
|
|
}
|
2010-05-30 06:42:56 -07:00
|
|
|
|
|
|
|
|
CVertexBuffer::Unbind();
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
|
|
|
|
|
2004-10-06 11:44:47 -07:00
|
|
|
void CPatchRData::RenderOutline()
|
|
|
|
|
{
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
size_t vsize=PATCH_SIZE+1;
|
2004-05-29 17:46:58 -07:00
|
|
|
|
2004-10-06 11:44:47 -07:00
|
|
|
glBegin(GL_LINES);
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
for (ssize_t i=0;i<PATCH_SIZE;i++) {
|
2004-10-06 11:44:47 -07:00
|
|
|
glVertex3fv(&m_Vertices[i].m_Position.X);
|
|
|
|
|
glVertex3fv(&m_Vertices[i+1].m_Position.X);
|
|
|
|
|
}
|
|
|
|
|
glEnd();
|
|
|
|
|
glBegin(GL_LINES);
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
for (ssize_t i=0;i<PATCH_SIZE;i++) {
|
2004-10-06 11:44:47 -07:00
|
|
|
glVertex3fv(&m_Vertices[PATCH_SIZE+(i*(PATCH_SIZE+1))].m_Position.X);
|
|
|
|
|
glVertex3fv(&m_Vertices[PATCH_SIZE+((i+1)*(PATCH_SIZE+1))].m_Position.X);
|
|
|
|
|
}
|
|
|
|
|
glEnd();
|
|
|
|
|
glBegin(GL_LINES);
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
for (ssize_t i=1;i<PATCH_SIZE;i++) {
|
2004-10-06 11:44:47 -07:00
|
|
|
glVertex3fv(&m_Vertices[(vsize*vsize)-i].m_Position.X);
|
|
|
|
|
glVertex3fv(&m_Vertices[(vsize*vsize)-(i+1)].m_Position.X);
|
|
|
|
|
}
|
|
|
|
|
glEnd();
|
|
|
|
|
glBegin(GL_LINES);
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 11:48:32 -07:00
|
|
|
for (ssize_t i=1;i<PATCH_SIZE;i++) {
|
2004-10-06 11:44:47 -07:00
|
|
|
glVertex3fv(&m_Vertices[(vsize*(vsize-1))-(i*vsize)].m_Position.X);
|
|
|
|
|
glVertex3fv(&m_Vertices[(vsize*(vsize-1))-((i+1)*vsize)].m_Position.X);
|
|
|
|
|
}
|
|
|
|
|
glEnd();
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
2011-01-29 08:31:48 -08:00
|
|
|
|
2011-02-03 06:36:54 -08:00
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-29 08:31:48 -08:00
|
|
|
void CPatchRData::RenderPriorities()
|
|
|
|
|
{
|
|
|
|
|
CTerrain* terrain = m_Patch->m_Parent;
|
|
|
|
|
CCamera* camera = g_Game->GetView()->GetCamera();
|
|
|
|
|
|
|
|
|
|
for (ssize_t j = 0; j < PATCH_SIZE; ++j)
|
|
|
|
|
{
|
|
|
|
|
for (ssize_t i = 0; i < PATCH_SIZE; ++i)
|
|
|
|
|
{
|
|
|
|
|
ssize_t gx = m_Patch->m_X * PATCH_SIZE + i;
|
|
|
|
|
ssize_t gz = m_Patch->m_Z * PATCH_SIZE + j;
|
|
|
|
|
|
|
|
|
|
CVector3D pos;
|
|
|
|
|
terrain->CalcPosition(gx, gz, pos);
|
|
|
|
|
|
|
|
|
|
// Move a bit towards the center of the tile
|
|
|
|
|
pos.X += CELL_SIZE/4.f;
|
|
|
|
|
pos.Z += CELL_SIZE/4.f;
|
|
|
|
|
|
|
|
|
|
float x, y;
|
|
|
|
|
camera->GetScreenCoordinates(pos, x, y);
|
|
|
|
|
|
|
|
|
|
glPushMatrix();
|
|
|
|
|
glTranslatef(x, g_yres - y, 0.f);
|
|
|
|
|
|
|
|
|
|
// Draw the text upside-down, because it's aligned with
|
|
|
|
|
// the GUI (which uses the top-left as (0,0))
|
|
|
|
|
glScalef(1.0f, -1.0f, 1.0f);
|
|
|
|
|
|
|
|
|
|
glwprintf(L"%d", m_Patch->m_MiniPatches[j][i].Priority);
|
|
|
|
|
glPopMatrix();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|