Cogs.Core
ClipmapParameterCalculation.h
1#pragma once
2
3#include "ClipmapTerrainTypes.h"
4
5#include "ClipmapState.h"
6#include "ClipmapLevel.h"
7#include "ClipmapRenderer.h"
8#include "Raster/RasterLevel.h"
9
10namespace Cogs
11{
12 inline Vector2 calculateViewPosInClippedLevel(const ClipmapState & clipmapState, const ClipmapLevel & terrainLevel)
13 {
14 return Vector2(
15 static_cast<float>(terrainLevel.rasterLevel->longitudeToIndex(clipmapState.clipmapCenter.x) - terrainLevel.currentExtent.west),
16 static_cast<float>(terrainLevel.rasterLevel->latitudeToIndex(clipmapState.clipmapCenter.y) - terrainLevel.currentExtent.south));
17 }
18
19 static Vector2 calculateScaleFactor(const int levelIndex)
20 {
21 const float levelScaleFactor = std::exp2(static_cast<float>(-levelIndex));
22
23 return Vector2(levelScaleFactor, levelScaleFactor);
24 }
25
26 static Vector2 calculateResolutionRatio(const ClipmapLevel & a, const ClipmapLevel & b)
27 {
28 return Vector2(
29 static_cast<float>(a.rasterLevel->getPostDeltaLongitude() / b.rasterLevel->getPostDeltaLongitude()),
30 static_cast<float>(a.rasterLevel->getPostDeltaLatitude() / b.rasterLevel->getPostDeltaLatitude())
31 );
32 }
33
34 namespace
35 {
36 template<typename InputVector>
37 Vector4 pad3to4(const InputVector in)
38 {
39 Vector4 out(in[0], in[1], in[2], 0);
40
41 return out;
42 }
43
44 template<typename InputVector>
45 vec2a pad2to4(const InputVector in)
46 {
47 vec2a out(in[0], in[1]);
48
49 return out;
50 }
51 }
52
53 inline void calculateLevelParameters(
54 const ClipmapLevel & terrainLevel,
55 const std::vector<const ClipmapLevel *> & imageryLevels,
56 LevelParameters & parameters,
57 ImageryParameters & imageryParameters,
58 const Vector3d center,
59 const bool /*enableNoData*/)
60 {
61 const ClipmapLevel & coarserLevel = *terrainLevel.coarserLevel;
62
63 const int west = terrainLevel.currentExtent.west;
64 const int south = terrainLevel.currentExtent.south;
65
66 // Converts raster space coordinates [0, extent] to texture coordinates [0, 1].
67 const float reciprocalX = 1.0f / static_cast<float>(terrainLevel.nextExtent.getWidth());
68 const float reciprocalY = 1.0f / static_cast<float>(terrainLevel.nextExtent.getHeight());
69
70 parameters.oneOverClipmapSize = Vector2(reciprocalX, reciprocalY);
71
72 // Converts coarse raster space coordinates [0, extent] to coarse texture coordinates [0, 1].
73 const float coarseReciprocalX = 1.0f / static_cast<float>(coarserLevel.nextExtent.getWidth());
74 const float coarseReciprocalY = 1.0f / static_cast<float>(coarserLevel.nextExtent.getHeight());
75
76 parameters.oneOverCoarseClipmapSize = Vector2(coarseReciprocalX, coarseReciprocalY);
77
78 // Translates level raster coordinates to be relative to the clipmap center.
79 parameters.levelOffsetFromClipmapCenter = Vector2(west - terrainLevel.rasterLevel->longitudeToIndex(center.x),
80 south - terrainLevel.rasterLevel->latitudeToIndex(center.y));
81
82 // Scales raster coordinates to the raster coordinates of the least detailed level.
83 parameters.levelScaleFactor = calculateScaleFactor(static_cast<int>(terrainLevel.index));
84
85 // See ClipmapSampling.hlsl
86 Vector2 texelOffset = Vector2(0.5f, 0.5f);
87
88 // Translates level raster coordinates to texture raster coordinates relative to the origin.
89 parameters.fineTextureOrigin = Vector2(static_cast<float>(terrainLevel.origin.x), static_cast<float>(terrainLevel.origin.y)) + texelOffset;
90
91 const auto fineToCoarseRatio = calculateResolutionRatio(terrainLevel, coarserLevel);
92
93 parameters.fineToCoarseRatio = fineToCoarseRatio;
94
95 // Represents the origin of the fine level in the raster coordinate system of the coarser level.
96 const int coarserWest = coarserLevel.currentExtent.west;
97 const int coarserSouth = coarserLevel.currentExtent.south;
98 parameters.fineLevelOriginInCoarse = Vector2(
99 static_cast<float>(coarserLevel.origin.x),
100 static_cast<float>(coarserLevel.origin.y)) +
101 Vector2(
102 static_cast<float>(west) * fineToCoarseRatio.x - static_cast<float>(coarserWest),
103 static_cast<float>(south) * fineToCoarseRatio.y - static_cast<float>(coarserSouth)) + texelOffset;
104
105 for (size_t i = 0; i < imageryLevels.size(); ++i) {
106 const ClipmapLevel & imageryLevel = *imageryLevels[i];
107 const ClipmapLevel & coarserImageryLevel = *imageryLevel.coarserLevel;
108
109 imageryParameters.terrainToImageryResolutionRatio[i] = pad2to4(calculateResolutionRatio(terrainLevel, imageryLevel));
110
111 const double terrainWest = terrainLevel.rasterLevel->indexToLongitude(west);
112 const double terrainSouth = terrainLevel.rasterLevel->indexToLatitude(south);
113 const double imageryWestIndex = imageryLevel.rasterLevel->longitudeToIndex(terrainWest);
114 const double imagerySouthIndex = imageryLevel.rasterLevel->latitudeToIndex(terrainSouth);
115
116 imageryParameters.terrainOffsetInImagery[i] = pad2to4(Vector2(
117 static_cast<float>(imageryLevel.origin.x),
118 static_cast<float>(imageryLevel.origin.y)) +
119 Vector2(
120 static_cast<float>(imageryWestIndex - imageryLevel.currentExtent.west),
121 static_cast<float>(imagerySouthIndex - imageryLevel.currentExtent.south)));
122
123 const auto fineToCoarseImageryRatio = pad2to4(calculateResolutionRatio(imageryLevel, coarserImageryLevel));
124
125 imageryParameters.fineToCoarseImageryResolutionRatio[i] = fineToCoarseImageryRatio;
126
127 const int coarserImageryWest = coarserImageryLevel.currentExtent.west;
128 const int coarserImagerySouth = coarserImageryLevel.currentExtent.south;
129 imageryParameters.fineImageryOriginInCoarse[i] = pad2to4(Vector2(
130 static_cast<float>(coarserImageryLevel.origin.x),
131 static_cast<float>(coarserImageryLevel.origin.y)) +
132 Vector2(
133 imageryLevel.currentExtent.west * fineToCoarseImageryRatio.x - coarserImageryWest,
134 imageryLevel.currentExtent.south * fineToCoarseImageryRatio.y - coarserImagerySouth));
135
136 imageryParameters.oneOverImagerySize[i] = pad2to4(Vector2(
137 1.0f / static_cast<float>(imageryLevel.currentExtent.getWidth()),
138 1.0f / static_cast<float>(imageryLevel.currentExtent.getHeight())));
139
140 imageryParameters.oneOverCoarseImagerySize[i] = pad2to4(Vector2(
141 1.0f / static_cast<float>(coarserImageryLevel.currentExtent.getWidth()),
142 1.0f / static_cast<float>(coarserImageryLevel.currentExtent.getHeight())));
143
144 imageryParameters.noData[i] = imageryLevel.rasterLevel->getNoData();
145 }
146 }
147
148 inline void calculateGlobalParameters(const ClipmapLevel & levelZero, const RenderContext & renderContext, const WorldOptions & worldOptions, const ClipmapState & clipmapState, GlobalParameters & globalParameters)
149 {
150 auto rasterLevel = levelZero.rasterLevel;
151 auto & extent = levelZero.nextExtent;
152
153 globalParameters.noClipmapData = rasterLevel->getNoData();
154
155 // Scales raster coordinates from the least detailed level to geo-coordinates relative to the clipmap center.
156 globalParameters.levelZeroWorldScaleFactor = Vector2(rasterLevel->getPostDeltaLongitude(), rasterLevel->getPostDeltaLatitude());
157
158 auto & worldScale = worldOptions.worldScale;
159
160 // Scales clipmap geo-coordinates to world coordinates. Serves as a simplified reprojection e.g from degrees to meters.
161 globalParameters.worldScale = Vector4(worldScale);
162
163 // Distance of scaled terrain coordinate system origin from global origin.
164 auto offsetFromOrigin = Vector2d(renderContext.origin) - Vector2d(renderContext.offset);
165
166 // Translates world coordinates from local to origin space.
167 globalParameters.centerOffsetFromOrigin = Vector2(Vector2d(renderContext.center) - offsetFromOrigin);
168
169 // Calculate the extent of the entire terrain relative to the current origin.
170 auto & geodeticExtent = levelZero.rasterLevel->getGeoExtent();
171 globalParameters.worldExtents = Vector4(
172 Vector2d(geodeticExtent.getWest(), geodeticExtent.getSouth()) * Vector2d(worldScale) - offsetFromOrigin,
173 Vector2d(geodeticExtent.getEast(), geodeticExtent.getNorth()) * Vector2d(worldScale) - offsetFromOrigin
174 );
175
176 // Calculate the extent of the clipmap level pyramid relative to the current origin.
177 globalParameters.clipmapExtents = Vector4(
178 Vector2d(rasterLevel->indexToLongitude(extent.west), rasterLevel->indexToLatitude(extent.south)) * Vector2d(worldScale) - offsetFromOrigin,
179 Vector2d(rasterLevel->indexToLongitude(extent.east), rasterLevel->indexToLatitude(extent.north)) * Vector2d(worldScale) - offsetFromOrigin
180 );
181
182 globalParameters.unblendedRegionSize = Vector2(clipmapState.unblendedRegionSize, clipmapState.unblendedRegionSize);
183 globalParameters.oneOverBlendedRegionSize = Vector2(clipmapState.oneOverBlendedRegionSize, clipmapState.oneOverBlendedRegionSize);
184
185 globalParameters.heightExaggeration = worldOptions.heightExaggeration;
186
187 // The xy offset is included in the centerOffsetFromOrigin value.
188 globalParameters.worldOffset = Vector4(0, 0, renderContext.offset.z, 1);
189
190 globalParameters.enableNoData = worldOptions.enableNoData;
191 }
192}
Contains all Cogs related functionality.
Definition: FieldSetter.h:23