| 271 | } |
| 272 | |
| 273 | void CalculateHeightmapRange(Terrain* terrain, TerrainDataUpdateInfo& info, const float* heightmap, float chunkOffsets[Terrain::ChunksCount], float chunkHeights[Terrain::ChunksCount]) |
| 274 | { |
| 275 | PROFILE_CPU_NAMED("Terrain.CalculateRange"); |
| 276 | |
| 277 | // Note: terrain heightmap doesn't store raw height values but normalized into per-patch dimensions (height = normHeight * chunkPatch + patchOffset) |
| 278 | |
| 279 | float minPatchHeight = MAX_float; |
| 280 | float maxPatchHeight = MIN_float; |
| 281 | |
| 282 | for (int32 chunkIndex = 0; chunkIndex < Terrain::ChunksCount; chunkIndex++) |
| 283 | { |
| 284 | const int32 chunkX = (chunkIndex % Terrain::ChunksCountEdge) * info.ChunkSize; |
| 285 | const int32 chunkZ = (chunkIndex / Terrain::ChunksCountEdge) * info.ChunkSize; |
| 286 | |
| 287 | float minHeight = MAX_float; |
| 288 | float maxHeight = MIN_float; |
| 289 | |
| 290 | for (int32 z = 0; z < info.VertexCountEdge; z++) |
| 291 | { |
| 292 | const int32 sz = (chunkZ + z) * info.HeightmapSize; |
| 293 | for (int32 x = 0; x < info.VertexCountEdge; x++) |
| 294 | { |
| 295 | const int32 sx = chunkX + x; |
| 296 | const float height = heightmap[sz + sx]; |
| 297 | |
| 298 | minHeight = Math::Min(minHeight, height); |
| 299 | maxHeight = Math::Max(maxHeight, height); |
| 300 | } |
| 301 | } |
| 302 | |
| 303 | chunkOffsets[chunkIndex] = minHeight; |
| 304 | chunkHeights[chunkIndex] = Math::Max(maxHeight - minHeight, 1.0f); |
| 305 | |
| 306 | minPatchHeight = Math::Min(minPatchHeight, minHeight); |
| 307 | maxPatchHeight = Math::Max(maxPatchHeight, maxHeight); |
| 308 | } |
| 309 | |
| 310 | // Align the patch heightmap range error to reduce artifacts on patch edges (each patch has own height range) |
| 311 | const double error = 1.0 / MAX_uint16; |
| 312 | minPatchHeight = AlignHeight(minPatchHeight - error, error); |
| 313 | maxPatchHeight = AlignHeight(maxPatchHeight + error, error); |
| 314 | |
| 315 | info.PatchOffset = minPatchHeight; |
| 316 | info.PatchHeight = Math::Max(maxPatchHeight - minPatchHeight, 1.0f); |
| 317 | } |
| 318 | |
| 319 | void UpdateHeightMap(const TerrainDataUpdateInfo& info, const float* heightmap, const Int2& modifiedOffset, const Int2& modifiedSize, const byte* data) |
| 320 | { |
no test coverage detected