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));
152 void HeightMap::fill1d(
const BasePoint& l,
const BasePoint &h,
155 array[0] = l.height();
156 array[m_res] = h.height();
157 LinInterp li((
float)m_res, l.roughness(), h.roughness());
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;