15 #include "TerrainMod.h"
34 m_spacing((float)resolution)
42 if (m_shaders.count(
id)) {
43 std::cerr <<
"WARNING: duplicate use of shader ID " <<
id << std::endl;
48 auto I = m_segments.begin();
49 auto Iend = m_segments.end();
50 for (; I != Iend; ++I) {
51 auto J = I->second.begin();
52 auto Jend = I->second.end();
53 for (; J != Jend; ++J) {
65 m_shaders.erase(m_shaders.find(
id));
68 auto I = m_segments.begin();
69 auto Iend = m_segments.end();
70 for (; I != Iend; ++I) {
71 auto J = I->second.begin();
72 auto Jend = I->second.end();
73 for (; J != Jend; ++J) {
77 auto K = sss.find(
id);
87 void Terrain::addSurfaces(
Segment & seg)
91 std::cerr <<
"WARNING: Adding surfaces to a terrain segment which has surfaces"
92 << std::endl << std::flush;
96 auto I = m_shaders.begin();
97 auto Iend = m_shaders.end();
98 for (; I != Iend; ++I) {
100 if (!I->second->checkIntersect(seg)) {
104 sss[I->first] = I->second->newSurface(seg);
108 void Terrain::shadeSurfaces(Segment & seg)
110 seg.populateSurfaces();
117 if ((s ==
nullptr) || (!s->
isValid())) {
134 WFMath::Vector<3> & n)
const
146 auto I = m_basePoints.find(x);
147 if (I == m_basePoints.end()) {
150 auto J = I->second.find(z);
151 if (J == I->second.end()) {
160 m_basePoints[x][z] = y;
161 bool pointIsSet[3][3];
163 for(
int i = x - 1, ri = 0; i < x + 2; ++i, ++ri) {
164 for(
int j = z - 1, rj = 0; j < z + 2; ++j, ++rj) {
165 pointIsSet[ri][rj] =
getBasePoint(i, j, existingPoint[ri][rj]);
168 for(
int i = x - 1, ri = 0; i < x + 1; ++i, ++ri) {
169 for(
int j = z - 1, rj = 0; j < z + 1; ++j, ++rj) {
171 if (!existingSegment) {
172 bool complete = pointIsSet[ri][rj] &&
173 pointIsSet[ri + 1][rj + 1] &&
174 pointIsSet[ri + 1][rj] &&
175 pointIsSet[ri][rj + 1];
179 auto newSegment = std::make_unique<Segment>(i * m_res, j * m_res, m_res);
181 for(
unsigned int k = 0; k < 2; ++k) {
182 for(
unsigned int l = 0; l < 2; ++l) {
183 cp(k, l) = existingPoint[ri + k][rj + l];
187 for (
auto& entry : m_terrainMods) {
188 auto& terrainMod = entry.second.terrainMod;
189 if (terrainMod->checkIntersects(*newSegment)) {
190 newSegment->updateMod(entry.first, terrainMod.get());
196 addSurfaces(*newSegment);
199 newSegment->setCornerPoint(ri ? 0 : 1, rj ? 0 : 1, y);
200 m_segments[i][j] = std::move(newSegment);
210 auto I = m_segments.find(x);
211 if (I == m_segments.end()) {
214 auto J = I->second.find(z);
215 if (J == I->second.end()) {
218 return J->second.get();
222 const std::function<
void(
Segment&,
int,
int)>& func)
const
224 int lx = I_ROUND(std::floor((area.lowCorner()[0]) / m_spacing));
225 int lz = I_ROUND(std::floor((area.lowCorner()[1]) / m_spacing));
226 int hx = I_ROUND(std::ceil((area.highCorner()[0]) / m_spacing));
227 int hz = I_ROUND(std::ceil((area.highCorner()[1]) / m_spacing));
229 for (
int i = lx; i < hx; ++i) {
230 for (
int j = lz; j < hz; ++j) {
243 std::set<Segment*> removed, added, updated;
244 std::unique_ptr<TerrainMod> old_mod;
245 auto I = m_terrainMods.find(
id);
248 if (I != m_terrainMods.end()) {
249 auto& entry = I->second;
251 old_box = entry.rect;
253 old_mod = std::move(entry.terrainMod);
256 int lx=I_ROUND(std::floor((old_box.lowCorner()[0] - 1.f) / m_spacing));
257 int lz=I_ROUND(std::floor((old_box.lowCorner()[1] - 1.f) / m_spacing));
258 int hx=I_ROUND(std::ceil((old_box.highCorner()[0] + 1.f) / m_spacing));
259 int hz=I_ROUND(std::ceil((old_box.highCorner()[1] + 1.f) / m_spacing));
261 for (
int i=lx;i<hx;++i) {
262 for (
int j=lz;j<hz;++j) {
274 m_terrainMods.erase(
id);
279 auto rect = mod->bbox();
280 int lx=I_ROUND(std::floor((rect.lowCorner()[0] - 1.f) / m_spacing));
281 int lz=I_ROUND(std::floor((rect.lowCorner()[1] - 1.f) / m_spacing));
282 int hx=I_ROUND(std::ceil((rect.highCorner()[0] + 1.f) / m_spacing));
283 int hz=I_ROUND(std::ceil((rect.highCorner()[1] + 1.f) / m_spacing));
285 for (
int i=lx;i<hx;++i) {
286 for (
int j=lz;j<hz;++j) {
292 auto J = removed.find(s);
293 if (J == removed.end()) {
302 for (
auto& segment : added) {
303 if (mod->checkIntersects(*segment)) {
304 segment->updateMod(
id, mod.get());
307 for (
auto& segment : updated) {
308 if (mod->checkIntersects(*segment)) {
309 segment->updateMod(
id, mod.get());
311 segment->updateMod(
id,
nullptr);
315 m_terrainMods[id] = TerrainModEntry{std::move(mod), rect};
318 for (
auto& segment : removed) {
319 segment->updateMod(
id,
nullptr);
328 return m_terrainMods.find(
id) != m_terrainMods.end();
331 const TerrainMod* Terrain::getMod(
long id)
const
333 auto I = m_terrainMods.find(
id);
334 if (I != m_terrainMods.end()) {
335 return I->second.terrainMod.get();
340 const Area* Terrain::getArea(
long id)
const
342 auto I = m_terrainAreas.find(
id);
343 if (I != m_terrainAreas.end()) {
344 return I->second.terrainArea.get();
352 std::set<Segment*> removed, added, updated;
353 std::unique_ptr<Area> old_area;
355 auto I = m_terrainAreas.find(
id);
358 if (I != m_terrainAreas.end()) {
359 auto& entry = I->second;
361 old_box = entry.rect;
363 old_area = std::move(entry.terrainArea);
366 int lx=I_ROUND(std::floor((old_box.lowCorner()[0] - 1.f) / m_spacing));
367 int lz=I_ROUND(std::floor((old_box.lowCorner()[1] - 1.f) / m_spacing));
368 int hx=I_ROUND(std::ceil((old_box.highCorner()[0] + 1.f) / m_spacing));
369 int hz=I_ROUND(std::ceil((old_box.highCorner()[1] + 1.f) / m_spacing));
371 for (
int i=lx;i<hx;++i) {
372 for (
int j=lz;j<hz;++j) {
384 m_terrainAreas.erase(
id);
389 auto rect = area->bbox();
390 int lx=I_ROUND(std::floor((rect.lowCorner()[0] - 1.f) / m_spacing));
391 int lz=I_ROUND(std::floor((rect.lowCorner()[1] - 1.f) / m_spacing));
392 int hx=I_ROUND(std::ceil((rect.highCorner()[0] + 1.f) / m_spacing));
393 int hz=I_ROUND(std::ceil((rect.highCorner()[1] + 1.f) / m_spacing));
395 for (
int i=lx;i<hx;++i) {
396 for (
int j=lz;j<hz;++j) {
402 auto J = removed.find(s);
403 if (J == removed.end()) {
412 const Shader* shader =
nullptr;
413 auto shaderI = m_shaders.find(area->getLayer());
414 if (shaderI != m_shaders.end()) {
415 shader = shaderI->second;
418 for (
auto& segment : added) {
419 if (area->checkIntersects(*segment)) {
420 segment->updateArea(
id, area.get(), shader);
423 for (
auto& segment : updated) {
424 if (area->checkIntersects(*segment)) {
425 segment->updateArea(
id, area.get(), shader);
427 segment->updateArea(
id,
nullptr,
nullptr);
431 m_terrainAreas[id] = TerrainAreaEntry{std::move(area), rect};
434 for (
auto& segment : removed) {
435 segment->updateArea(
id,
nullptr,
nullptr);