Skip to content

Commit 25bdcd6

Browse files
committed
Server: Load chunks in parallel when spawning a planet
1 parent 43fbde7 commit 25bdcd6

File tree

10 files changed

+176
-67
lines changed

10 files changed

+176
-67
lines changed

include/CommonLib/Components/PlanetComponent.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace tsom
1717
{
1818
struct PlanetComponent
1919
{
20-
std::unique_ptr<Planet> planet;
20+
std::shared_ptr<Planet> planet;
2121
std::array<std::unique_ptr<ChunkEntities>, Constants::MaxChunkLayerCount> planetEntities;
2222
};
2323
}

include/CommonLib/Planet.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include <tsl/hopscotch_map.h>
1616
#include <memory>
1717
#include <mutex>
18-
#include <vector>
1918

2019
namespace Nz
2120
{
@@ -44,8 +43,8 @@ namespace tsom
4443
void ForEachChunk(Nz::FunctionRef<void(const ChunkIndices& chunkIndices, Chunk& chunk)> callback) override;
4544
void ForEachChunk(Nz::FunctionRef<void(const ChunkIndices& chunkIndices, const Chunk& chunk)> callback) const override;
4645

47-
void GenerateChunk(const BlockLibrary& blockLibrary, Chunk& chunk, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string scriptName);
48-
void GenerateChunks(const BlockLibrary& blockLibrary, Nz::TaskScheduler& taskScheduler, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string scriptName);
46+
void GenerateChunk(Chunk& chunk, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string_view scriptName);
47+
void GenerateChunks(Nz::TaskScheduler& taskScheduler, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string_view scriptName);
4948
void GeneratePlatform(const BlockLibrary& blockLibrary, Direction upDirection, const BlockIndices& platformCenter);
5049

5150
inline Nz::Vector3f GetCenter() const override;

include/ServerLib/Database/ServerDatabase.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ namespace tsom
3737
void GetAllPlanets(Nz::FunctionRef<bool(Database::Planet&& /*planet*/)> callback) const;
3838
void GetAllPlanetEntities(Nz::UInt32 planetEntityId, Nz::FunctionRef<bool(Database::PlanetEntity&& /*planetEntities*/)> callback) const;
3939
void GetAllPlanetLinks(Nz::FunctionRef<bool(Database::PlanetLink&& /*planetLink*/)> callback) const;
40-
void GetPlanetChunks(Nz::UInt32 planetId, Nz::FunctionRef<bool(Database::PlanetChunk&& /*PlanetChunk*/)> callback) const;
40+
void GetAllPlanetChunks(Nz::UInt32 planetId, Nz::FunctionRef<bool(Database::PlanetChunk&& /*PlanetChunk*/)> callback) const;
41+
bool GetPlanetChunk(Nz::UInt32 planetId, const Nz::Vector3i32& chunkIndices, Nz::FunctionRef<void(Database::PlanetChunk&& /*PlanetChunk*/)> callback) const;
4142

4243
void StorePlanet(const Database::Planet& planetChunk);
4344
void StorePlanetChunk(const Database::PlanetChunk& planetChunk);
@@ -70,6 +71,7 @@ namespace tsom
7071

7172
SQLite::Statement getAllPlanetQuery;
7273
SQLite::Statement getAllPlanetLinkQuery;
74+
SQLite::Statement getAllPlanetChunksQuery;
7375
SQLite::Statement getPlanetChunkQuery;
7476
SQLite::Statement storePlanetQuery;
7577
SQLite::Statement storePlanetChunkQuery;

include/ServerLib/ServerPlanetEnvironment.hpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@
1111
#include <CommonLib/Chunk.hpp>
1212
#include <ServerLib/ServerAtmosphere.hpp>
1313
#include <ServerLib/ServerEnvironment.hpp>
14+
#include <tsl/hopscotch_set.h>
15+
#include <atomic>
1416
#include <filesystem>
17+
#include <mutex>
1518
#include <optional>
19+
#include <queue>
1620

1721
namespace tsom
1822
{
@@ -41,6 +45,7 @@ namespace tsom
4145
inline entt::handle GetPlanetEntity() const;
4246

4347
void OnSave() override;
48+
void OnTick(Nz::Time elapsedTime) override;
4449

4550
ServerPlanetEnvironment& operator=(const ServerPlanetEnvironment&) = delete;
4651
ServerPlanetEnvironment& operator=(ServerPlanetEnvironment&&) = delete;
@@ -50,11 +55,27 @@ namespace tsom
5055
void LoadChunksFromDatabase();
5156
void LoadEntitiesFromDatabase();
5257

58+
struct ChunkLoadingData
59+
{
60+
Nz::Vector3ui chunkCount;
61+
std::atomic_uint chunkLoadingCount;
62+
std::mutex mutex;
63+
std::shared_ptr<Planet> planet;
64+
std::queue<ChunkIndices> remainingChunks;
65+
tsl::hopscotch_set<ChunkIndices> visitedChunks;
66+
67+
void HandleChunkLoaded(const ChunkIndices& chunkIndices);
68+
};
69+
5370
ServerAtmosphere m_atmosphere;
5471
std::filesystem::path m_savePath;
5572
std::optional<Nz::UInt32> m_databaseId;
73+
std::shared_ptr<ChunkLoadingData> m_chunkLoadingData;
74+
std::string m_generatorName;
5675
std::unordered_set<ChunkIndices /*chunkIndex*/> m_dirtyChunks;
5776
entt::handle m_planetEntity;
77+
Nz::UInt32 m_generationSeed;
78+
Nz::Vector3ui m_chunkCount;
5879
};
5980
}
6081

src/CommonLib/Entities/ChunkClassLibrary.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ namespace tsom
3636
Nz::EnttWorld* world = entity.registry()->ctx().get<Nz::EnttWorld*>();
3737

3838
auto& planetComponent = entity.emplace<PlanetComponent>();
39-
planetComponent.planet = std::make_unique<Planet>(m_app, cellSize, cornerRadius, gravity);
39+
planetComponent.planet = std::make_shared<Planet>(m_app, cellSize, cornerRadius, gravity);
4040
for (std::size_t layerIndex = 0; layerIndex < planetComponent.planetEntities.size(); ++layerIndex)
4141
{
4242
if (!m_blockLibrary.IsValidLayer(layerIndex))

src/CommonLib/Planet.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -330,11 +330,11 @@ namespace tsom
330330
callback(chunkIndices, *chunkData.chunk);
331331
}
332332

333-
void Planet::GenerateChunk(const BlockLibrary& blockLibrary, Chunk& chunk, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string scriptName)
333+
void Planet::GenerateChunk(Chunk& chunk, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string_view scriptName)
334334
{
335335
ChunkIndices chunkIndices = chunk.GetIndices();
336336

337-
ScriptingContext scriptingContext = ScriptingContext(m_app);
337+
ScriptingContext scriptingContext(m_app);
338338
scriptingContext.RegisterLibrary<MathScriptingLibrary>();
339339
scriptingContext.RegisterLibrary<ChunkScriptingLibrary>();
340340

@@ -356,7 +356,7 @@ namespace tsom
356356
}
357357
}
358358

359-
void Planet::GenerateChunks(const BlockLibrary& blockLibrary, Nz::TaskScheduler& taskScheduler, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string scriptName)
359+
void Planet::GenerateChunks(Nz::TaskScheduler& taskScheduler, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string_view scriptName)
360360
{
361361
struct ThreadState
362362
{
@@ -376,6 +376,7 @@ namespace tsom
376376
};
377377

378378
auto context = std::make_shared<GenerationContext>();
379+
std::string scriptPath = fmt::format("scripts/planets/{}.lua", scriptName);
379380

380381
ForEachChunk([=, this, &taskScheduler](const ChunkIndices& chunkIndices, Chunk& chunk)
381382
{
@@ -397,7 +398,7 @@ namespace tsom
397398
threadState->scriptingContext.RegisterLibrary<MathScriptingLibrary>();
398399
threadState->scriptingContext.RegisterLibrary<ChunkScriptingLibrary>();
399400

400-
Nz::Result execResult = threadState->scriptingContext.LoadFile(fmt::format("scripts/planets/{}.lua", scriptName));
401+
Nz::Result execResult = threadState->scriptingContext.LoadFile(scriptPath);
401402
if (!execResult)
402403
return;
403404

src/Game/States/PlanetEditorState.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ namespace tsom
418418

419419
m_planet->ClearChunks();
420420
m_planet->AddChunks(*stateData.blockLibrary, m_planetSettings.chunkCount);
421-
m_planet->GenerateChunks(*stateData.blockLibrary, taskScheduler, m_planetSettings.seed, m_planetSettings.chunkCount, m_planetSettings.scriptName);
421+
m_planet->GenerateChunks(taskScheduler, m_planetSettings.seed, m_planetSettings.chunkCount, m_planetSettings.scriptName);
422422
}
423423

424424
void PlanetEditorState::LayoutWidgets(const Nz::Vector2f& /*newSize*/)

src/ServerLib/Database/ServerDatabase.cpp

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ namespace tsom
2121
partialUpdatePlanetEntityQuery(database, "UPDATE planet_entities SET class_version = ?, position_x = ?, position_y = ?, position_z = ?, rotation_x = ?, rotation_y = ?, rotation_z = ?, rotation_w = ?, properties = ?, last_update = datetime() WHERE id = ?"),
2222
getAllPlanetQuery(database, "SELECT id, generator, seed, chunk_count_x, chunk_count_y, chunk_count_z, corner_radius, gravity FROM planets"),
2323
getAllPlanetLinkQuery(database, "SELECT source_planet_id, destination_planet_id, position_x, position_y, position_z FROM planet_links"),
24-
getPlanetChunkQuery(database, "SELECT position_x, position_y, position_z, version, chunk_data FROM planet_chunks WHERE planet_id = ?"),
24+
getAllPlanetChunksQuery(database, "SELECT position_x, position_y, position_z, version, chunk_data FROM planet_chunks WHERE planet_id = ?"),
25+
getPlanetChunkQuery(database, "SELECT version, chunk_data FROM planet_chunks WHERE planet_id = ? AND position_x = ? AND position_y = ? AND position_z = ?"),
2526
storePlanetQuery(database, "REPLACE INTO planets(id, generator, seed, chunk_count_x, chunk_count_y, chunk_count_z, corner_radius, gravity) VALUES(?, ?, ?, ?, ?, ?, ?, ?)"),
2627
storePlanetChunkQuery(database, "REPLACE INTO planet_chunks(planet_id, position_x, position_y, position_z, version, chunk_data, last_update) VALUES(?, ?, ?, ?, ?, ?, datetime())"),
2728
storePlanetLinkQuery(database, "REPLACE INTO planet_links(source_planet_id, destination_planet_id, position_x, position_y, position_z) VALUES(?, ?, ?, ?, ?)")
@@ -164,21 +165,21 @@ namespace tsom
164165
}
165166
}
166167

167-
void ServerDatabase::GetPlanetChunks(Nz::UInt32 planetId, Nz::FunctionRef<bool(Database::PlanetChunk&& /*planetChunk*/)> callback) const
168+
void ServerDatabase::GetAllPlanetChunks(Nz::UInt32 planetId, Nz::FunctionRef<bool(Database::PlanetChunk&& /*planetChunk*/)> callback) const
168169
{
169-
NAZARA_DEFER({ m_preparedStatements->getPlanetChunkQuery.reset(); });
170-
m_preparedStatements->getPlanetChunkQuery.bind(1, planetId);
170+
NAZARA_DEFER({ m_preparedStatements->getAllPlanetChunksQuery.reset(); });
171+
m_preparedStatements->getAllPlanetChunksQuery.bind(1, planetId);
171172

172-
while (m_preparedStatements->getPlanetChunkQuery.executeStep())
173+
while (m_preparedStatements->getAllPlanetChunksQuery.executeStep())
173174
{
174175
Database::PlanetChunk planetChunk;
175176
planetChunk.planetId = planetId;
176-
planetChunk.position.x = Nz::SafeCaster(m_preparedStatements->getPlanetChunkQuery.getColumn(0).getDouble());
177-
planetChunk.position.y = Nz::SafeCaster(m_preparedStatements->getPlanetChunkQuery.getColumn(1).getDouble());
178-
planetChunk.position.z = Nz::SafeCaster(m_preparedStatements->getPlanetChunkQuery.getColumn(2).getDouble());
179-
planetChunk.version = m_preparedStatements->getPlanetChunkQuery.getColumn(3);
177+
planetChunk.position.x = Nz::SafeCaster(m_preparedStatements->getAllPlanetChunksQuery.getColumn(0).getDouble());
178+
planetChunk.position.y = Nz::SafeCaster(m_preparedStatements->getAllPlanetChunksQuery.getColumn(1).getDouble());
179+
planetChunk.position.z = Nz::SafeCaster(m_preparedStatements->getAllPlanetChunksQuery.getColumn(2).getDouble());
180+
planetChunk.version = m_preparedStatements->getAllPlanetChunksQuery.getColumn(3);
180181

181-
SQLite::Column column = m_preparedStatements->getPlanetChunkQuery.getColumn(4);
182+
SQLite::Column column = m_preparedStatements->getAllPlanetChunksQuery.getColumn(4);
182183
const Nz::UInt8* chunkData = static_cast<const Nz::UInt8*>(column.getBlob());
183184
planetChunk.chunkData = std::span(chunkData, chunkData + column.getBytes());
184185

@@ -187,6 +188,32 @@ namespace tsom
187188
}
188189
}
189190

191+
bool ServerDatabase::GetPlanetChunk(Nz::UInt32 planetId, const Nz::Vector3i32& chunkIndices, Nz::FunctionRef<void(Database::PlanetChunk&& /*PlanetChunk*/)> callback) const
192+
{
193+
NAZARA_DEFER({ m_preparedStatements->getPlanetChunkQuery.reset(); });
194+
m_preparedStatements->getPlanetChunkQuery.bind(1, planetId);
195+
m_preparedStatements->getPlanetChunkQuery.bind(2, chunkIndices.x);
196+
m_preparedStatements->getPlanetChunkQuery.bind(3, chunkIndices.y);
197+
m_preparedStatements->getPlanetChunkQuery.bind(4, chunkIndices.z);
198+
199+
if (!m_preparedStatements->getPlanetChunkQuery.executeStep())
200+
return false;
201+
202+
Database::PlanetChunk planetChunk;
203+
planetChunk.planetId = planetId;
204+
planetChunk.position.x = chunkIndices.x;
205+
planetChunk.position.y = chunkIndices.y;
206+
planetChunk.position.z = chunkIndices.z;
207+
planetChunk.version = m_preparedStatements->getPlanetChunkQuery.getColumn(0);
208+
209+
SQLite::Column column = m_preparedStatements->getPlanetChunkQuery.getColumn(1);
210+
const Nz::UInt8* chunkData = static_cast<const Nz::UInt8*>(column.getBlob());
211+
planetChunk.chunkData = std::span(chunkData, chunkData + column.getBytes());
212+
213+
callback(std::move(planetChunk));
214+
return true;
215+
}
216+
190217
void ServerDatabase::Migrate()
191218
{
192219
tsl::hopscotch_set<std::string, std::hash<std::string_view>, std::equal_to<>> migrated;

src/ServerLib/ServerPlanetEnvironment.cpp

Lines changed: 104 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ namespace tsom
2828

2929
ServerPlanetEnvironment::ServerPlanetEnvironment(ServerInstance& serverInstance, std::optional<Nz::UInt32> databaseId, std::string generatorName, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, float cellSize, float cornerRadius) :
3030
ServerEnvironment(serverInstance, ServerEnvironmentType::Planet, true),
31-
m_databaseId(databaseId)
31+
m_databaseId(databaseId),
32+
m_generatorName(std::move(generatorName)),
33+
m_generationSeed(seed),
34+
m_chunkCount(chunkCount)
3235
{
3336
m_world->GetRegistry().ctx().emplace<ServerPlanetEnvironment*>(this);
3437
m_world->AddSystem<EnvironmentSwitchSystem>();
@@ -49,31 +52,20 @@ namespace tsom
4952
planetClass->InitAndActivateEntity(m_planetEntity);
5053

5154
auto& planetComponent = m_planetEntity.get<PlanetComponent>();
52-
planetComponent.planet->AddChunks(blockLibrary, chunkCount);
5355

54-
if (m_databaseId)
55-
LoadChunksFromDatabase();
56-
57-
auto& app = serverInstance.GetApplication();
58-
auto& taskScheduler = app.GetComponent<Nz::TaskSchedulerAppComponent>();
59-
60-
planetComponent.planet->GenerateChunks(blockLibrary, taskScheduler, seed, chunkCount, std::move(generatorName));
61-
taskScheduler.WaitForTasks();
62-
63-
planetComponent.planet->GeneratePlatform(blockLibrary, Direction::Right, { 65, -18, -39 });
64-
planetComponent.planet->GeneratePlatform(blockLibrary, Direction::Back, { -34, 2, 53 });
65-
planetComponent.planet->GeneratePlatform(blockLibrary, Direction::Front, { 22, -35, -59 });
66-
planetComponent.planet->GeneratePlatform(blockLibrary, Direction::Down, { 23, -62, 26 });
56+
m_chunkLoadingData = std::make_shared<ChunkLoadingData>();
57+
m_chunkLoadingData->chunkCount = m_chunkCount;
58+
m_chunkLoadingData->planet = planetComponent.planet;
59+
m_chunkLoadingData->remainingChunks.emplace(-int(m_chunkCount.x / 2), -int(m_chunkCount.y / 2), -int(m_chunkCount.z / 2));
6760

68-
std::size_t emptyChunkCount = 0;
69-
planetComponent.planet->ForEachChunk([&](const ChunkIndices& /*osef*/, const Chunk& chunk)
70-
{
71-
emptyChunkCount += chunk.GetBlockCount(EmptyBlockIndex);
72-
});
61+
//planetComponent.planet->GeneratePlatform(blockLibrary, Direction::Right, { 65, -18, -39 });
62+
//planetComponent.planet->GeneratePlatform(blockLibrary, Direction::Back, { -34, 2, 53 });
63+
//planetComponent.planet->GeneratePlatform(blockLibrary, Direction::Front, { 22, -35, -59 });
64+
//planetComponent.planet->GeneratePlatform(blockLibrary, Direction::Down, { 23, -62, 26 });
7365

7466
// We want the player to be able to breathe 5s per empty block count
7567
// the player breathe 100ml per second
76-
Nz::UInt64 oxygenAmount = Constants::SecondsToEmptyOxygenBlock * Nz::UInt64(Constants::PlayerOxygenConsumption) * emptyChunkCount;
68+
Nz::UInt64 oxygenAmount = Constants::SecondsToEmptyOxygenBlock * Nz::UInt64(Constants::PlayerOxygenConsumption) * m_chunkCount.x * m_chunkCount.y * m_chunkCount.z;
7769
m_atmosphere.SetGasAmount(GasType::Oxygen, oxygenAmount);
7870

7971
// We also want oxygen to be 21% of the atmosphere and have the rest as nitrogen
@@ -213,6 +205,73 @@ namespace tsom
213205
databaseSystem->Save();
214206
}
215207

208+
void ServerPlanetEnvironment::OnTick(Nz::Time elapsedTime)
209+
{
210+
ServerEnvironment::OnTick(elapsedTime);
211+
212+
std::unique_lock lock(m_chunkLoadingData->mutex);
213+
214+
if (!m_chunkLoadingData->remainingChunks.empty())
215+
{
216+
ChunkIndices indices = m_chunkLoadingData->remainingChunks.front();
217+
m_chunkLoadingData->remainingChunks.pop();
218+
219+
spdlog::debug("loading chunk {};{};{} ({} remaining)\n", indices.x, indices.y, indices.z, m_chunkLoadingData->remainingChunks.size());
220+
221+
lock.unlock();
222+
223+
Chunk* chunk = GetPlanet().GetChunk(indices);
224+
if (!chunk)
225+
chunk = &GetPlanet().AddChunk(m_serverInstance.GetBlockLibrary(), indices);
226+
227+
auto& taskScheduler = m_serverInstance.GetApplication().GetComponent<Nz::TaskSchedulerAppComponent>();
228+
229+
m_chunkLoadingData->chunkLoadingCount++;
230+
taskScheduler.AddTask([chunk, serverInstance = &m_serverInstance, databaseId = m_databaseId, chunkLoadingData = m_chunkLoadingData, seed = m_generationSeed, chunkCount = m_chunkCount, generatorName = m_generatorName]
231+
{
232+
bool chunkFound = false;
233+
if (databaseId)
234+
{
235+
ServerDatabase& serverDatabase = serverInstance->GetServerDatabase();
236+
chunkFound = serverDatabase.GetPlanetChunk(*databaseId, chunk->GetIndices(), [&](Database::PlanetChunk&& planetChunk)
237+
{
238+
if (planetChunk.version != s_chunkVersion)
239+
throw std::runtime_error(fmt::format("unhandled version {}", planetChunk.version));
240+
241+
// Chunk data has decompressedSize first
242+
Nz::UInt32 decompressedSize;
243+
std::memcpy(&decompressedSize, &planetChunk.chunkData[0], sizeof(decompressedSize));
244+
decompressedSize = Nz::LittleEndianToHost(decompressedSize);
245+
246+
BinaryCompressor& binaryCompressor = BinaryCompressor::GetThreadCompressor();
247+
248+
std::vector<Nz::UInt8> decompressedData(decompressedSize);
249+
std::optional compressedDataOpt = binaryCompressor.Decompress(planetChunk.chunkData.data() + sizeof(decompressedSize), planetChunk.chunkData.size() - sizeof(decompressedSize), decompressedData.data(), decompressedData.size());
250+
if (!compressedDataOpt)
251+
throw std::runtime_error("chunk decompression failed");
252+
253+
if (*compressedDataOpt != decompressedSize)
254+
throw std::runtime_error("chunk decompression failed (corrupt size)");
255+
256+
Nz::ByteStream byteStream(decompressedData.data(), decompressedData.size());
257+
258+
chunk->LockWrite();
259+
chunk->Deserialize(byteStream);
260+
chunk->UnlockWrite();
261+
});
262+
}
263+
264+
if (!chunkFound)
265+
chunkLoadingData->planet->GenerateChunk(*chunk, seed, chunkCount, generatorName);
266+
267+
chunkLoadingData->HandleChunkLoaded(chunk->GetIndices());
268+
269+
if (--chunkLoadingData->chunkLoadingCount == 0 && chunkLoadingData->remainingChunks.empty())
270+
spdlog::debug("planet chunk loading finished, total chunks: {} (out of {})\n", chunkLoadingData->visitedChunks.size(), chunkCount.x * chunkCount.y * chunkCount.z);
271+
});
272+
}
273+
}
274+
216275
ServerAtmosphere* ServerPlanetEnvironment::GetFallbackAtmosphereAtPosition(const Nz::Vector3f& position)
217276
{
218277
Planet& planet = GetPlanet();
@@ -286,4 +345,28 @@ namespace tsom
286345
return true;
287346
});
288347
}
348+
349+
void ServerPlanetEnvironment::ChunkLoadingData::HandleChunkLoaded(const ChunkIndices& chunkIndices)
350+
{
351+
ChunkIndices minIndices(-int(chunkCount.x / 2), -int(chunkCount.y / 2), -int(chunkCount.z / 2));
352+
ChunkIndices maxIndices = minIndices + ChunkIndices(chunkCount) - ChunkIndices(1);
353+
354+
std::unique_lock lock(mutex);
355+
356+
DirectionMask visibilityMask = planet->GetChunkVisibilityMask(chunkIndices);
357+
for (Direction visibleNeighborDir : visibilityMask)
358+
{
359+
ChunkIndices neighborIndices = chunkIndices + s_chunkDirOffset[visibleNeighborDir];
360+
if (neighborIndices.x < minIndices.x || neighborIndices.x > maxIndices.x ||
361+
neighborIndices.y < minIndices.y || neighborIndices.y > maxIndices.y ||
362+
neighborIndices.z < minIndices.z || neighborIndices.z > maxIndices.z)
363+
continue;
364+
365+
if (visitedChunks.contains(neighborIndices))
366+
continue;
367+
368+
visitedChunks.insert(neighborIndices);
369+
remainingChunks.push(neighborIndices);
370+
}
371+
}
289372
}

0 commit comments

Comments
 (0)