11 #include "HeightMap.h" 13 #include "TerrainMod.h" 15 #include "BasePoint.h" 19 #include <wfmath/MersenneTwister.h> 42 inline float calc(
float loc)
44 return ((noCalc) ? ep1 :
45 ((m_size-loc) * ep1 + loc * ep2));
52 LinInterp(
float size,
float l,
float h) : m_size(size), noCalc(false),
53 ep1(l/size), ep2(h/size)
76 float ep1, ep2, ep3, ep4;
78 inline float calc(
float locX,
float locY)
80 return ((noCalc) ? ep1 :
81 (( ep1*(m_size-locX) + ep2 * locX) * (m_size-locY) +
82 ( ep4*(m_size-locX) + ep3 * locX) * (locY) ) / m_size );
91 QuadInterp(
float size,
float e1,
float e2,
float e3,
float e4)
92 : m_size(size), noCalc(false),
93 ep1(e1/size), ep2(e2/size), ep3(e3/size), ep4(e4/size)
95 if ((e1==e2) && (e3==e4) && (e2==e3)) {
107 m_max(
std::numeric_limits<float>::lowest()),
108 m_min(
std::numeric_limits<float>::max())
128 inline float randHalf(WFMath::MTRand& rng)
131 return rng.rand<
float>() - 0.5f;
136 float HeightMap::qRMD(WFMath::MTRand& rng,
float nn,
float fn,
float ff,
float nf,
137 float roughness,
float falloff,
float depth)
const 139 float max = std::max(std::max(nn, fn), std::max(nf, ff)),
140 min = std::min(std::min(nn, fn), std::min(nf, ff)),
141 heightDifference = max - min;
143 return ((nn+fn+ff+nf)/4.f) + randHalf(rng) * roughness * heightDifference / (1.f+std::pow(depth,falloff));
156 array[m_res] = h.
height();
164 WFMath::MTRand::uint32 seed[2]={ l.
seed(), h.
seed() };
165 WFMath::MTRand rng(seed, 2);
171 int stride = m_res/2;
178 for (
int i=stride;i<m_res;i+=stride*2) {
179 float hh = array[i-stride];
180 float lh = array[i+stride];
181 float hd = std::fabs(hh-lh);
182 float roughness = li.calc((
float)i);
185 if ((hd*100.f) < roughness) {
186 hd+=0.05f * roughness;
189 array[i] = ((hh+lh)/2.f) + randHalf(rng) * roughness * hd / (1.f+std::pow(depth,
BasePoint::FALLOFF));
205 m_max = std::numeric_limits<float>::lowest();
206 m_min = std::numeric_limits<float>::max();
215 std::vector<float> edgeData;
217 float* edge = edgeData.data();
219 float* points =
m_data.data();
223 for (
int i=0;i<=m_res;i++) {
224 points[0*
m_size + i] = edge[i];
230 for (
int i=0;i<=m_res;i++) {
231 points[i*
m_size + 0] = edge[i];
237 for (
int i=0;i<=m_res;i++) {
238 points[i*
m_size + m_res] = edge[i];
244 for (
int i=0;i<=m_res;i++) {
245 points[m_res*
m_size + i] = edge[i];
252 WFMath::MTRand::uint32 seed[4]={ p1.
seed(), p2.
seed(), p3.
seed(), p4.
seed() };
253 WFMath::MTRand rng(seed, 4);
261 int stride = m_res/2;
264 float roughness = qi.
calc((
float)stride,(
float) stride);
265 float f = falloffQi.calc((
float)stride, (
float)stride);
266 points[stride*
m_size + stride] = qRMD(rng, points[0 *
m_size + stride],
267 points[stride*
m_size + 0],
268 points[stride*
m_size + m_res],
269 points[m_res*
m_size + stride],
286 for (
int i=stride;i<m_res;i+=stride*2) {
287 for (
int j=stride;j<m_res;j+=stride*2) {
288 roughness=qi.calc((
float)i,(
float)j);
289 f = falloffQi.calc((
float)i, (
float)j);
290 points[j*
m_size + i] = qRMD(rng, points[(i-stride) + (j+stride) * (
m_size)],
291 points[(i+stride) + (j-stride) * (
m_size)],
292 points[(i+stride) + (j+stride) * (
m_size)],
293 points[(i-stride) + (j-stride) * (
m_size)],
294 roughness, f, depth);
304 for (
int i=stride*2;i<m_res;i+=stride*2) {
305 for (
int j=stride;j<m_res;j+=stride*2) {
306 roughness=qi.calc((
float)i,(
float)j);
307 f = falloffQi.calc((
float)i, (
float)j);
308 points[j*
m_size + i] = qRMD(rng, points[(i-stride) + (j) * (
m_size)],
309 points[(i+stride) + (j) * (
m_size)],
310 points[(i) + (j+stride) * (
m_size)],
311 points[(i) + (j-stride) * (
m_size)],
312 roughness, f , depth);
317 for (
int i=stride;i<m_res;i+=stride*2) {
318 for (
int j=stride*2;j<m_res;j+=stride*2) {
319 roughness=qi.calc((
float)i,(
float)j);
320 f = falloffQi.calc((
float)i, (
float)j);
321 points[j*
m_size + i] = qRMD(rng, points[(i-stride) + (j) * (
m_size)],
322 points[(i+stride) + (j) * (
m_size)],
323 points[(i) + (j+stride) * (
m_size)],
324 points[(i) + (j-stride) * (
m_size)],
325 roughness, f, depth);
335 void HeightMap::getHeight(
float x,
float z,
float &h)
const 344 int tile_x = I_ROUND(std::floor(x));
345 int tile_z = I_ROUND(std::floor(z));
348 float off_x = x - (float)tile_x;
349 float off_z = z - (float)tile_z;
351 float h1=
get(tile_x, tile_z);
352 float h2=
get(tile_x, tile_z+1);
353 float h3=
get(tile_x+1, tile_z+1);
354 float h4=
get(tile_x+1, tile_z);
358 if ((off_x - off_z) <= 0.f) {
359 h = h1 + (h3-h2) * off_x + (h2-h1) * off_z;
363 h = h1 + (h4-h1) * off_x + (h3-h4) * off_z;
381 WFMath::Vector<3> &normal)
const 390 int tile_x = I_ROUND(std::floor(x));
391 int tile_z = I_ROUND(std::floor(z));
394 float off_x = x - (float)tile_x;
395 float off_z = z - (float)tile_z;
397 float h1=
get(tile_x, tile_z);
398 float h2=
get(tile_x, tile_z+1);
399 float h3=
get(tile_x+1, tile_z+1);
400 float h4=
get(tile_x+1, tile_z);
404 if ((off_x - off_z) <= 0.f) {
405 normal = WFMath::Vector<3>(h2-h3, 1.0f, h1-h2);
408 if (off_x == off_z) {
409 normal += WFMath::Vector<3>(h1-h4, 1.0f, h4-h3);
412 h = h1 + (h3-h2) * off_x + (h2-h1) * off_z;
416 normal = WFMath::Vector<3>(h1-h4, 1.0f, h4-h3);
418 h = h1 + (h4-h1) * off_x + (h3-h4) * off_z;
void fill2d(const BasePoint &p1, const BasePoint &p2, const BasePoint &p3, const BasePoint &p4)
Two dimensional midpoint displacement fractal.
float ep1
Values at the two ends.
void getHeightAndNormal(float x, float z, float &h, WFMath::Vector< 3 > &normal) const
Get an accurate height and normal vector at a given coordinate relative to this segment.
float calc(float loc)
Determine the interpolated value along the line.
Template for managing buffers of data for a segment.
QuadInterp(float size, float e1, float e2, float e3, float e4)
Constructor.
const unsigned int m_size
The size of segment, m_res + 1.
float falloff() const
Accessor for the falloff at the base point.
float height() const
Accessor for the height at the base point.
Helper to interpolate in a quad.
LinInterp(float size, float l, float h)
Constructor.
float roughness() const
Accessor for the roughness at the base point.
float calc(float locX, float locY)
Determine the interpolated value within the quad.
Point on the fundamental grid that is used as the basis for terrain.
float ep1
Values at the four corners.
unsigned int seed() const
Calculate the random seed used at this base point.
Helper to interpolate on a line.
std::vector< float > m_data
Pointer to buffer containing data values.
static constexpr float FALLOFF
Default falloff at the base point.
void checkMaxMin(float h)
Check a value against m_min and m_max and set one of them if appropriate.
HeightMap(int resolution)
Construct an empty height map with the given resolution.