13 #include "TerrainMod.h"
15 #include "BasePoint.h"
19 #include <wfmath/MersenneTwister.h>
38 m_res(resolution), m_size(m_res+1),
40 m_heightMap(resolution)
63 populateHeightMap(m_heightMap);
65 for (
auto& entry : m_terrainMods) {
66 applyMod(entry.second);
70 void Segment::populateHeightMap(
HeightMap& heightMap)
72 heightMap.
fill2d(m_controlPoints(0, 0), m_controlPoints(1, 0),
73 m_controlPoints(1, 1), m_controlPoints(0, 1));
98 void Segment::invalidateSurfaces()
100 for(
auto& entry : m_surfaces) {
101 entry.second->invalidate();
115 assert(m_res == m_size - 1);
117 if (m_normals.empty()) {
118 m_normals.reserve(m_size * m_size * 3);
121 auto * np = m_normals.data();
125 for (
int j = 1; j < m_res; ++j) {
126 for (
int i = 1; i < m_res; ++i) {
133 np[j * m_size * 3 + i * 3] = (h1 - h3) / 2.f;
134 np[j * m_size * 3 + i * 3 + 1] = 1.0;
135 np[j * m_size * 3 + i * 3 + 2] = (h4 - h2) / 2.f;
142 for (
int i=1; i < m_res; ++i) {
143 h1 = m_heightMap.
get(i - 1, 0);
144 h2 = m_heightMap.
get(i + 1, 0);
146 np[i * 3] = (h1 - h2) / 2.f;
150 h1 = m_heightMap.
get(i - 1, m_res);
151 h2 = m_heightMap.
get(i + 1, m_res);
153 np[m_res * m_size * 3 + i * 3] = (h1 - h2) / 2.f;
154 np[m_res * m_size * 3 + i * 3 + 1] = 1.0f;
155 np[m_res * m_size * 3 + i * 3 + 2] = 0.0f;
159 for (
int j=1; j < m_res; ++j) {
160 h1 = m_heightMap.
get(0, j - 1);
161 h2 = m_heightMap.
get(0, j + 1);
163 np[j * m_size * 3] = 0;
164 np[j * m_size * 3 + 1] = 1.f;
165 np[j * m_size * 3 + 2] = (h1 - h2) / 2.f;
167 h1 = m_heightMap.
get(m_res, j - 1);
168 h2 = m_heightMap.
get(m_res, j + 1);
170 np[j * m_size * 3 + m_res * 3] = 0.f;
171 np[j * m_size * 3 + m_res * 3 + 1] = 1.f;
172 np[j * m_size * 3 + m_res * 3 + 2] = (h1 - h2) / 2.f;
181 np[m_res * m_size * 3] = 0.f;
182 np[m_res * m_size * 3 + 1] = 1.f;
183 np[m_res * m_size * 3 + 2] = 0.f;
186 np[m_res * 3 + 1] = 1.f;
187 np[m_res * 3 + 2] = 0.f;
189 np[m_res * m_size * 3 + m_res * 3] = 0.f;
190 np[m_res * m_size * 3 + m_res * 3 + 1] = 1.f;
191 np[m_res * m_size * 3 + m_res * 3 + 2] = 0.f;
199 for (
const auto& entry : m_surfaces) {
200 if (entry.second->m_shader.checkIntersect(*
this)) {
201 entry.second->populate();
206 void Segment::getHeight(
float x,
float y,
float &h)
const
208 m_heightMap.getHeight(x, y, h);
224 WFMath::Vector<3> &normal)
const
239 int &lx,
int &hx,
int &lz,
int &hz)
const
241 lx = I_ROUND(bbox.lowCorner()[0]);
242 if (lx > m_res)
return false;
245 hx = I_ROUND(bbox.highCorner()[0]);
246 if (hx < 0)
return false;
247 if (hx > m_res) hx = m_res;
249 lz = I_ROUND(bbox.lowCorner()[1]);
250 if (lz > m_res)
return false;
253 hz = I_ROUND(bbox.highCorner()[1]);
254 if (hz < 0)
return false;
255 if (hz > m_res) hz = m_res;
260 void Segment::updateMod(
long id,
const TerrainMod *t)
263 m_terrainMods[id] = t;
265 m_terrainMods.erase(
id);
276 if (!m_terrainMods.empty()) {
277 m_terrainMods.clear();
290 float* points = m_heightMap.
getData();
291 WFMath::AxisBox<2> bbox=t->
bbox();
292 bbox.shift(WFMath::Vector<2>(-m_xRef, -m_zRef));
294 for (
int i=lz; i<=hz; i++) {
295 for (
int j=lx; j<=hx; j++) {
296 float& h = points[i * m_size + j];
297 t->
apply(h, j + m_xRef, i + m_zRef);
307 void Segment::updateArea(
long id,
const Area* area,
const Shader* shader)
309 auto areaLookupI = m_areaLookup.find(
id);
310 if (areaLookupI != m_areaLookup.end()) {
311 auto& areaEntry = areaLookupI->second->second;
312 auto J = m_surfaces.find(areaEntry.area->getLayer());
313 if (J != m_surfaces.end()) {
316 J->second->invalidate();
318 m_areas.erase(areaLookupI->second);
319 m_areaLookup.erase(areaLookupI);
324 auto result = m_areas.emplace(area->getLayer(), AreaEntry{id, area});
325 m_areaLookup.emplace(
id, result);
326 auto J = m_surfaces.find(area->getLayer());
327 if (J != m_surfaces.end()) {
328 J->second->invalidate();
331 m_surfaces[area->getLayer()] = shader->newSurface(*
this);
339 WFMath::Point<2> lp(m_xRef, m_zRef),
340 hp(lp.x() + m_res, lp.y() + m_res);
341 return WFMath::AxisBox<2>(lp, hp);