1
0
forked from mirrors/0ad

# New territory border rendering.

Add textured line overlay rendering.
Change terrain height calculations to be triangulation-dependent for
improved accuracy.
Add triangulation-dependent terrain normal function.
Support separate S/T wrap modes for textures.
Rename CVector2D_Maths since it no longer conflicts with simulation
CVector2D.
Coalesce freed chunks in vertex buffers, to avoid excessive
fragmentation.
Add some things to help debug vertex buffer allocation a little.

This was SVN commit r9929.
This commit is contained in:
Ykkrosh
2011-07-30 00:56:45 +00:00
parent 239685d754
commit 8fee3d8ef8
36 changed files with 1084 additions and 143 deletions
+106 -9
View File
@@ -25,12 +25,14 @@
#include "graphics/Overlay.h"
#include "graphics/Terrain.h"
#include "maths/MathUtil.h"
#include "maths/Vector2D.h"
#include "ps/Profile.h"
static const float RENDER_HEIGHT_DELTA = 0.25f; // distance above terrain
void SimRender::ConstructLineOnGround(const CSimContext& context, std::vector<float> xz,
SOverlayLine& overlay, bool floating)
void SimRender::ConstructLineOnGround(const CSimContext& context, const std::vector<float>& xz,
SOverlayLine& overlay, bool floating, float heightOffset)
{
PROFILE("ConstructLineOnGround");
overlay.m_Coords.clear();
CmpPtr<ICmpTerrain> cmpTerrain(context, SYSTEM_ENTITY);
@@ -54,7 +56,7 @@ void SimRender::ConstructLineOnGround(const CSimContext& context, std::vector<fl
{
float px = xz[i];
float pz = xz[i+1];
float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + RENDER_HEIGHT_DELTA;
float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + heightOffset;
overlay.m_Coords.push_back(px);
overlay.m_Coords.push_back(py);
overlay.m_Coords.push_back(pz);
@@ -62,7 +64,7 @@ void SimRender::ConstructLineOnGround(const CSimContext& context, std::vector<fl
}
void SimRender::ConstructCircleOnGround(const CSimContext& context, float x, float z, float radius,
SOverlayLine& overlay, bool floating)
SOverlayLine& overlay, bool floating, float heightOffset)
{
overlay.m_Coords.clear();
@@ -88,7 +90,7 @@ void SimRender::ConstructCircleOnGround(const CSimContext& context, float x, flo
float a = i * 2 * (float)M_PI / numPoints;
float px = x + radius * sin(a);
float pz = z + radius * cos(a);
float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + RENDER_HEIGHT_DELTA;
float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + heightOffset;
overlay.m_Coords.push_back(px);
overlay.m_Coords.push_back(py);
overlay.m_Coords.push_back(pz);
@@ -113,7 +115,7 @@ static void SplitLine(std::vector<std::pair<float, float> >& coords, float x1, f
}
void SimRender::ConstructSquareOnGround(const CSimContext& context, float x, float z, float w, float h, float a,
SOverlayLine& overlay, bool floating)
SOverlayLine& overlay, bool floating, float heightOffset)
{
overlay.m_Coords.clear();
@@ -150,9 +152,104 @@ void SimRender::ConstructSquareOnGround(const CSimContext& context, float x, flo
{
float px = coords[i].first;
float pz = coords[i].second;
float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + RENDER_HEIGHT_DELTA;
float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + heightOffset;
overlay.m_Coords.push_back(px);
overlay.m_Coords.push_back(py);
overlay.m_Coords.push_back(pz);
}
}
void SimRender::SmoothPointsAverage(std::vector<CVector2D>& points, bool closed)
{
PROFILE("SmoothPointsAverage");
size_t n = points.size();
if (n < 2)
return; // avoid out-of-bounds array accesses, and leave the points unchanged
std::vector<CVector2D> newPoints;
newPoints.resize(points.size());
// Handle the end points appropriately
if (closed)
{
newPoints[0] = (points[n-1] + points[0] + points[1]) / 3.f;
newPoints[n-1] = (points[n-2] + points[n-1] + points[0]) / 3.f;
}
else
{
newPoints[0] = points[0];
newPoints[n-1] = points[n-1];
}
// Average all the intermediate points
for (size_t i = 1; i < n-1; ++i)
newPoints[i] = (points[i-1] + points[i] + points[i+1]) / 3.f;
points.swap(newPoints);
}
static CVector2D EvaluateSpline(float t, CVector2D a0, CVector2D a1, CVector2D a2, CVector2D a3, float offset)
{
// Compute position on spline
CVector2D p = a0*(t*t*t) + a1*(t*t) + a2*t + a3;
// Compute unit-vector direction of spline
CVector2D dp = (a0*(3*t*t) + a1*(2*t) + a2).Normalized();
// Offset position perpendicularly
return p + CVector2D(dp.Y*-offset, dp.X*offset);
}
void SimRender::InterpolatePointsRNS(std::vector<CVector2D>& points, bool closed, float offset)
{
PROFILE("InterpolatePointsRNS");
std::vector<CVector2D> newPoints;
// (This does some redundant computations for adjacent vertices,
// but it's fairly fast (<1ms typically) so we don't worry about it yet)
// TODO: Instead of doing a fixed number of line segments between each
// control point, it should probably be somewhat adaptive to get a nicer
// curve with fewer points
size_t n = points.size();
if (n < 1)
return; // can't do anything unless we have two points
size_t imax = closed ? n : n-1; // TODO: we probably need to do a bit more to handle non-closed paths
newPoints.reserve(imax*4);
for (size_t i = 0; i < imax; ++i)
{
// Get the relevant points for this spline segment
CVector2D p0 = points[(i-1+n)%n];
CVector2D p1 = points[i];
CVector2D p2 = points[(i+1)%n];
CVector2D p3 = points[(i+2)%n];
// Do the RNS computation (based on GPG4 "Nonuniform Splines")
float l1 = (p2 - p1).Length(); // length of spline segment (i)..(i+1)
CVector2D s0 = (p1 - p0).Normalized(); // unit vector of spline segment (i-1)..(i)
CVector2D s1 = (p2 - p1).Normalized(); // unit vector of spline segment (i)..(i+1)
CVector2D s2 = (p3 - p2).Normalized(); // unit vector of spline segment (i+1)..(i+2)
CVector2D v1 = (s0 + s1).Normalized() * l1; // spline velocity at i
CVector2D v2 = (s1 + s2).Normalized() * l1; // spline velocity at i+1
// Compute standard cubic spline parameters
CVector2D a0 = p1*2 + p2*-2 + v1 + v2;
CVector2D a1 = p1*-3 + p2*3 + v1*-2 + v2*-1;
CVector2D a2 = v1;
CVector2D a3 = p1;
// Interpolate at various points
newPoints.push_back(EvaluateSpline(0.f, a0, a1, a2, a3, offset));
newPoints.push_back(EvaluateSpline(1.f/4.f, a0, a1, a2, a3, offset));
newPoints.push_back(EvaluateSpline(2.f/4.f, a0, a1, a2, a3, offset));
newPoints.push_back(EvaluateSpline(3.f/4.f, a0, a1, a2, a3, offset));
}
points.swap(newPoints);
}