Cogs.Core
Terrain.cpp
1#include "Terrain.h"
2
3#include "ClipmapManager.h"
4#include "ClipmapQueryHandler.h"
5
6#include "Raster/BridgeRasterSource.h"
7
8#include "Rendering/IGraphicsDevice.h"
9
10#include "Foundation/Logging/Logger.h"
11
12#include <unordered_map>
13#include <memory>
14
15using namespace Cogs;
16
17namespace
18{
20}
21
22namespace Cogs
23{
24 std::unordered_map<int64_t, RasterSourcePtr> activeSources;
25
27 {
28 ClipmapManager manager;
29 ClipmapQueryHandler queryHandler;
30
31 size_t maxLevel;
32
33 bool postInitialized = false;
34 };
35}
36
37void terrainInitialize()
38{
39 LOG_DEBUG(logger, "Initialized terrain.");
40}
41
42Cogs::TerrainContext * terrainCreate()
43{
44 LOG_DEBUG(logger, "Creating terrain...");
45
46 auto context = new Cogs::TerrainContext();
47
48 return context;
49}
50
51void terrainDestroy(Cogs::TerrainContext * terrain)
52{
53 LOG_DEBUG(logger, "Destroying terrain...");
54
55 terrain->manager.cleanupLevels();
56
57 delete terrain;
58
59 LOG_DEBUG(logger, "Terrain destroyed.");
60}
61
62void terrainInitializeInstance(Cogs::TerrainContext * context, void * device)
63{
64 auto graphicsDevice = reinterpret_cast<Cogs::IGraphicsDevice *>(device);
65
66 context->manager.initialize(graphicsDevice);
67 context->queryHandler.initialize(&context->manager.terrainLevels, &context->manager.imagery);
68}
69
70void terrainUpdate(Cogs::TerrainContext * context)
71{
72 context->manager.update();
73}
74
75void terrainInvalidateTile(int64_t rasterSourceId, int level, int x, int y, int flags)
76{
77 auto sIt = activeSources.find(rasterSourceId);
78
79 if (sIt == activeSources.end()) {
80 LOG_ERROR(logger, "Cannot invalidate tiles from unregistered raster source (unused or disposed).");
81 return;
82 }
83
84 WriteLock lock(*sIt->second);
85
86 sIt->second->invalidateTile({ level, x, y }, (InvalidationFlags::EInvalidationFlags)flags);
87}
88
89void terrainPreRender(Cogs::TerrainContext * context, void * rc)
90{
91 auto renderContext = reinterpret_cast<Cogs::RenderContext *>(rc);
92
93 context->maxLevel = context->manager.preRender(*renderContext);
94}
95
96void terrainDepthRender(Cogs::TerrainContext * terrain, void * rc)
97{
98 auto renderContext = reinterpret_cast<Cogs::RenderContext *>(rc);
99
100 terrain->manager.renderDepth(*renderContext, terrain->maxLevel);
101}
102
103void terrainRender(Cogs::TerrainContext * terrain, void * rc)
104{
105 auto renderContext = reinterpret_cast<Cogs::RenderContext *>(rc);
106
107 terrain->manager.render(*renderContext, terrain->maxLevel);
108}
109
110void oceanRender(Cogs::TerrainContext * terrain, void * rc)
111{
112 auto renderContext = reinterpret_cast<Cogs::RenderContext *>(rc);
113
114 terrain->manager.renderOcean(*renderContext, terrain->maxLevel);
115}
116
117void oceanSetOptions(Cogs::TerrainContext * terrain, const Cogs::OceanOptions * options)
118{
119 terrain->manager.oceanRenderer.setOptions(options);
120}
121
122void terrainPostRender(Cogs::TerrainContext * context, void * rc)
123{
124 auto renderContext = reinterpret_cast<Cogs::RenderContext *>(rc);
125
126 context->manager.postRender(*renderContext);
127
128 context->manager.previousContext = *renderContext;
129
130 if (!context->postInitialized) {
131 context->queryHandler.postInitialize();
132
133 context->postInitialized = true;
134 }
135}
136
137void terrainSetRasterSources(Cogs::TerrainContext * context,
138 Cogs::RasterSourceParameters * terrainParameters,
139 const size_t /*numTerrain*/,
140 Cogs::RasterSourceParameters * imageryParameters,
141 const size_t numImagery)
142{
143 if (activeSources.find(terrainParameters->id) == activeSources.end()) {
144 auto terrainSource = std::make_shared<Cogs::BridgeRasterSource>(nullptr, terrainParameters);
145 activeSources[terrainParameters->id] = std::move(terrainSource);
146 }
147
148 std::vector<RasterSourcePtr> imagery(numImagery);
149
150 for (size_t i = 0; i < numImagery; ++i) {
151 auto id = imageryParameters[i].id;
152
153 if (activeSources.find(id) == activeSources.end()) {
154 // If no bridge exists for the given id, create a new one.
155 activeSources[id] = std::make_shared<Cogs::BridgeRasterSource>(nullptr, &imageryParameters[i]);
156 }
157
158 imagery[i] = activeSources[id];
159 }
160
161 context->manager.setRasterSources(activeSources[terrainParameters->id], imagery);
162}
163
164void terrainDisposeRasterSource(int64_t id)
165{
166 activeSources.erase(id);
167}
168
169void terrainSetParameters(Cogs::TerrainContext * context, const Cogs::ClipmapParameters * parameters)
170{
171 context->manager.setClipmapParameters(parameters);
172}
173
174void terrainReset(Cogs::TerrainContext *, void * rc)
175{
176 auto & renderContext = *reinterpret_cast<Cogs::RenderContext *>(rc);
177
178 Cogs::IContext * context = renderContext.context;
179
181
182 for (size_t i = 0; i < 8; ++i) {
183 context->setTexture("", static_cast<unsigned int>(i), TextureHandle::NoHandle);
184 context->setSamplerState("", static_cast<unsigned int>(i), SamplerStateHandle::NoHandle);
185 }
186
188
189 if (!renderContext.wireframe) {
191 }
192
193 context->reset();
194}
195
196void terrainSetDebugOptions(Cogs::TerrainContext * context, const Cogs::DebugOptions * debugOptions)
197{
198 context->manager.debugOptions = *debugOptions;
199}
200
201void terrainInvalidateRasterSource(Cogs::TerrainContext * context, const int64_t rasterSourceId, const bool clearContents)
202{
203 context->manager.invalidateRasterSource(activeSources[rasterSourceId].get(), clearContents);
204}
205
206float terrainGetNearestSample(Cogs::TerrainContext * context)
207{
208 return context->manager.getNearestSample();
209}
210
211void terrainSetCustomParameters(Cogs::TerrainContext * context, const unsigned char * data, int count)
212{
213 context->manager.clipmapRenderer.setCustomParameters(data, count);
214}
215
216void terrainSetImageryEnabled(Cogs::TerrainContext * context, const bool * data, int count)
217{
218 for (int i = 0; i < count; ++i) {
219 context->manager.imageryEnabled[i] = data[i];
220 }
221}
222
223void terrainGetTerrainMetrics(Cogs::TerrainContext * context, Cogs::TerrainMetrics * metrics)
224{
225 context->manager.getTerrainMetrics(metrics);
226}
227
228bool terrainRayPick(Cogs::TerrainContext * terrain,
229 const float * screenPos,
230 const float * inverseViewProjection,
231 float * pickedPosition,
232 int rayPickId)
233{
234 bool valid;
235 bool picked = terrain->manager.depthQuery.getPositions((const Cogs::Vector2 *)screenPos,
236 *(Cogs::Matrix *)inverseViewProjection,
237 1,
238 (Cogs::Vector4 *)pickedPosition, &valid, rayPickId == -1 ? 0 : rayPickId);
239
240 return picked && valid;
241}
242
243void terrainGetBounds(Cogs::TerrainContext * terrain, double * bounds)
244{
245 if (!terrain->manager.isInitialized() || !terrain->manager.terrainSource.isReady()) return;
246
247 if (!terrain->manager.terrainLevels.size()) return;
248
249 auto & levelZero = terrain->manager.terrainLevels[0];
250 auto & geoExtent = levelZero.rasterLevel->getGeoExtent();
251 auto & worldScale = terrain->manager.worldOptions.worldScale;
252
253 auto bbox = reinterpret_cast<Cogs::Vector3d *>(bounds);
254
255 bbox[0] = Cogs::Vector3d(geoExtent.getWest() * worldScale.x, geoExtent.getSouth() * worldScale.y, levelZero.minZ * terrain->manager.worldOptions.heightExaggeration);
256 bbox[1] = Cogs::Vector3d(geoExtent.getEast() * worldScale.x, geoExtent.getNorth() * worldScale.y, levelZero.maxZ * terrain->manager.worldOptions.heightExaggeration);
257}
258
259void terrainSetWorldOptions(Cogs::TerrainContext * terrain, const Cogs::WorldOptions * worldOptions)
260{
261 terrain->manager.worldOptions = *worldOptions;
262
263 terrain->manager.updateOptions.invalidateNormals = true;
264}
265
266void terrainSetUpdateOptions(Cogs::TerrainContext * terrain, const Cogs::UpdateOptions * updateOptions)
267{
268 terrain->manager.updateOptions = *updateOptions;
269}
270
271void terrainSetRenderOptions(Cogs::TerrainContext * terrain, const Cogs::RenderOptions * renderOptions)
272{
273 terrain->manager.renderOptions = *renderOptions;
274}
275
276bool terrainRequiresRedraw(Cogs::TerrainContext * terrain)
277{
278 return terrain->manager.updateRequired();
279}
280
281void terrainPostQuery(Cogs::TerrainContext * terrain, Cogs::TerrainQuery * query, Cogs::TerrainQueryCallback callback)
282{
283 terrain->queryHandler.postRequest(query, callback, terrain->manager.worldOptions);
284}
285
286void terrainProcessQueries(Cogs::TerrainContext * terrain)
287{
288 terrain->queryHandler.processQueries();
289}
290
291void terrainGetEffectParameters(Cogs::TerrainContext * terrain, Cogs::EffectParameters * effectParameters)
292{
293 effectParameters->changed = terrain->manager.effectsNeedUpdate;
294 effectParameters->numTextures = NUM_TEXTURES;
295 effectParameters->numActiveImagery = (int)terrain->manager.imagerySources.size();
296 effectParameters->precomputeNormals = terrain->manager.parameters.precomputeNormals;
297
298 terrain->manager.effectsNeedUpdate = false;
299}
Represents a graphics device used to manage graphics resources and issue drawing commands.
Log implementation class.
Definition: LogManager.h:139
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:77
Represents a graphics device context which can receive rendering commands.
Definition: IContext.h:43
virtual void setTexture(const StringView &name, unsigned int unit, TextureHandle textureHandle)=0
Sets the texture slot given by unit with the given name to contain the given texture.
virtual void setRasterizerState(const RasterizerStateHandle handle)=0
Set the current rasterizer state.
virtual void setInputLayout(const InputLayoutHandle inputLayoutHandle)=0
Sets the current input layout.
virtual void reset()
Resets all state changes made to the GPU since the last call to beginFrame.
Definition: IContext.h:593
virtual void setSamplerState(const StringView &name, unsigned int unit, SamplerStateHandle samplerStateHandle)=0
Sets the sampler slot given by unit with the given name to contain the given sampler state.
virtual void setEffect(EffectHandle handle)=0
Set the current effect.