mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-10-14 07:17:44 +00:00
# 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:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user