@@ -227,289 +227,30 @@ namespace tsom
227227 callback (chunkIndices, *chunkData.chunk );
228228 }
229229
230- void Planet::GenerateChunk (const BlockLibrary& blockLibrary, Chunk& chunk, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount)
230+ void Planet::GenerateChunk (const BlockLibrary& blockLibrary, Chunk& chunk, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string scriptName )
231231 {
232- constexpr std::size_t freeSpace = 30 ;
233-
234232 ChunkIndices chunkIndices = chunk.GetIndices ();
235- Nz::UInt32 chunkSeed = seed + static_cast <Nz::UInt32>(chunkIndices.x ) + static_cast <Nz::UInt32>(chunkIndices.y ) + static_cast <Nz::UInt32>(chunkIndices.z );
236233
237- std::minstd_rand rand (chunkSeed);
238- std::bernoulli_distribution dis (0.9 );
234+ ScriptingContext scriptingContext = ScriptingContext (m_app);
235+ scriptingContext.RegisterLibrary <MathScriptingLibrary>();
236+ scriptingContext.RegisterLibrary <ChunkScriptingLibrary>();
239237
240- BlockIndex dirtBlockIndex = blockLibrary.GetBlockIndex (" dirt" );
241- BlockIndex grassBlockIndex = blockLibrary.GetBlockIndex (" grass" );
242- BlockIndex stoneBlockIndex = blockLibrary.GetBlockIndex (" stone" );
243- BlockIndex stoneMossyBlockIndex = blockLibrary.GetBlockIndex (" stone_mossy" );
244- BlockIndex snowBlockIndex = blockLibrary.GetBlockIndex (" snow" );
238+ Nz::Result execResult = scriptingContext.LoadFile (fmt::format (" scripts/planets/{}.lua" , scriptName));
239+ if (!execResult)
240+ return ;
245241
246- Nz::Vector3i maxHeight ((Nz::Vector3i (chunkCount) + Nz::Vector3i (1 )) / 2 );
247- maxHeight *= int (Planet::ChunkSize);
242+ sol::protected_function generationFunction = execResult.GetValue ();
248243
249244 chunk.LockWrite ();
250245 NAZARA_DEFER ({ chunk.UnlockWrite (); });
251246
252- chunk.Reset ([&](BlockIndex* blockIndices)
247+ auto result = generationFunction (chunk, seed, chunkCount);
248+ if (!result.valid ())
253249 {
254- // Fill all blocks based on their depth
255- ChunkIndices chunkIndices = chunk.GetIndices ();
256-
257- double heightScale = 1 .5f * m_tileSize;
258- double scale = 0 .02f * m_tileSize;
259-
260- siv::PerlinNoise perlin;
261-
262- BlockIndex* blockIndexPtr = blockIndices;
263- #if 0
264- for (unsigned int z = 0; z < Planet::ChunkSize; ++z)
265- {
266- for (unsigned int y = 0; y < Planet::ChunkSize; ++y)
267- {
268- for (unsigned int x = 0; x < Planet::ChunkSize; ++x)
269- {
270- Nz::Vector3i blockPos = GetBlockIndices(chunkIndices, { x, y, z });
271- float distToSurface = sdRoundBox(Nz::Vector3f(blockPos), Nz::Vector3f(80.f, 80.f, 80.f), m_cornerRadius);
272-
273- if (distToSurface <= 0.f)
274- *blockIndexPtr++ = dirtBlockIndex;
275- else
276- *blockIndexPtr++ = EmptyBlockIndex;
277- }
278- }
279- }
280- #endif
281-
282- #if 1
283- for (unsigned int z = 0 ; z < Planet::ChunkSize; ++z)
284- {
285- for (unsigned int y = 0 ; y < Planet::ChunkSize; ++y)
286- {
287- for (unsigned int x = 0 ; x < Planet::ChunkSize; ++x)
288- {
289- Nz::Vector3i blockPos = GetBlockIndices (chunkIndices, { x, y, z });
290- unsigned int depth = Nz::SafeCaster (std::min ({
291- maxHeight.x - std::abs (blockPos.x ),
292- maxHeight.y - std::abs (blockPos.z ),
293- maxHeight.z - std::abs (blockPos.y )
294- }));
295-
296- if (depth < freeSpace)
297- {
298- *blockIndexPtr++ = EmptyBlockIndex;
299- continue ;
300- }
301-
302- depth -= freeSpace;
303-
304- BlockIndices mapPos = GetBlockIndices (chunkIndices, { x, y, z });
305- double presence = perlin.normalizedOctave3D_01 (mapPos.x * scale, mapPos.y * scale, mapPos.z * scale, 4 );
306-
307- if (depth < 20 )
308- presence *= std::max (double (depth) / 20.0 , 1.0 );
309-
310- presence += double (depth) / std::max ({ maxHeight.x , maxHeight.y , maxHeight.z });
311-
312- BlockIndex blockIndex;
313- if (presence > 0.6 )
314- {
315- if (depth <= 6 * 2 )
316- blockIndex = snowBlockIndex;
317- else if (depth <= 18 * 2 )
318- blockIndex = dirtBlockIndex;
319- else
320- blockIndex = (dis (rand)) ? stoneBlockIndex : stoneMossyBlockIndex;
321- }
322- else
323- blockIndex = EmptyBlockIndex;
324-
325- if (std::abs (blockPos.x ) <= 2 && std::abs (blockPos.z ) <= 2 )
326- blockIndex = EmptyBlockIndex;
327-
328- if (blockIndex != InvalidBlockIndex)
329- *blockIndexPtr++ = blockIndex;
330-
331- #if 0
332-
333- depth -= freeSpace;
334-
335- BlockIndex blockIndex;
336- if (depth <= 6 * 2)
337- blockIndex = snowBlockIndex;
338- else if (depth <= 18 * 2)
339- blockIndex = dirtBlockIndex;
340- else
341- blockIndex = (dis(rand)) ? stoneBlockIndex : stoneMossyBlockIndex;
342-
343- if (std::abs(blockPos.x) <= 2 && std::abs(blockPos.z) <= 2)
344- blockIndex = EmptyBlockIndex;
345-
346- if (blockIndex != InvalidBlockIndex)
347- *blockIndexPtr++ = blockIndex;
348- #endif
349- }
350- }
351- }
352- #endif
353-
354- #if 0
355- Nz::EnumArray<Direction, siv::PerlinNoise> perlin;
356- for (auto&& [dir, noise] : perlin.iter_kv())
357- noise.reseed(seed + static_cast<unsigned int>(dir));
358-
359- double heightScale = 1.5f * m_tileSize;
360- double scale = 0.02f * m_tileSize;
361-
362- // +X
363- for (unsigned int y = 0; y < Planet::ChunkSize; ++y)
364- {
365- for (unsigned int x = 0; x < Planet::ChunkSize; ++x)
366- {
367- BlockIndices mapPos = GetBlockIndices(chunkIndices, { 0, x, y });
368- double height = perlin[Direction::Right].normalizedOctave2D_01(mapPos.y * scale, mapPos.z * scale, 4) * heightScale;
369-
370- int terrainDepth = std::round(std::min<double>(height * (maxHeight.x / 2 - freeSpace) + freeSpace, maxHeight.x / 2));
371- int blockDepth = maxHeight.x - mapPos.x + 1;
372- if (blockDepth < terrainDepth)
373- continue;
374-
375- unsigned int startHeight = Nz::SafeCaster(blockDepth - terrainDepth);
376- if (startHeight >= Planet::ChunkSize)
377- continue;
378-
379- if (BlockIndex& blockType = blockIndices[chunk.GetBlockLocalIndex({ startHeight, x, y })]; blockType == dirtBlockIndex)
380- blockType = grassBlockIndex;
381-
382- for (unsigned int height = startHeight + 1; height < Planet::ChunkSize; ++height)
383- blockIndices[chunk.GetBlockLocalIndex({ height, x, y })] = EmptyBlockIndex;
384- }
385- }
386-
387- // -X
388- for (unsigned int y = 0; y < Planet::ChunkSize; ++y)
389- {
390- for (unsigned int x = 0; x < Planet::ChunkSize; ++x)
391- {
392- BlockIndices mapPos = GetBlockIndices(chunkIndices, { Planet::ChunkSize - 1, x, y });
393- double height = perlin[Direction::Left].normalizedOctave2D_01(mapPos.y * scale, mapPos.z * scale, 4) * heightScale;
394-
395- int terrainDepth = std::round(std::min<double>(height * (maxHeight.x / 2 - freeSpace) + freeSpace, maxHeight.x / 2));
396- int blockDepth = maxHeight.x + mapPos.x + 1;
397- if (blockDepth < terrainDepth)
398- continue;
399-
400- unsigned int startHeight = Nz::SafeCast<unsigned int>(blockDepth - terrainDepth);
401- if (startHeight >= Planet::ChunkSize)
402- continue;
403-
404- if (BlockIndex& blockType = blockIndices[chunk.GetBlockLocalIndex({ Planet::ChunkSize - startHeight - 1, x, y })]; blockType == dirtBlockIndex)
405- blockType = grassBlockIndex;
406-
407- for (unsigned int height = startHeight + 1; height < Planet::ChunkSize; ++height)
408- blockIndices[chunk.GetBlockLocalIndex({ Planet::ChunkSize - height - 1, x, y })] = EmptyBlockIndex;
409- }
410- }
411-
412- // +Y
413- for (unsigned int z = 0; z < Planet::ChunkSize; ++z)
414- {
415- for (unsigned int x = 0; x < Planet::ChunkSize; ++x)
416- {
417- BlockIndices mapPos = GetBlockIndices(chunkIndices, { x, z, 0 });
418- double height = perlin[Direction::Up].normalizedOctave2D_01(mapPos.x * scale, mapPos.z * scale, 4) * heightScale;
419-
420- int terrainDepth = std::round(std::min<double>(height * (maxHeight.y / 2 - freeSpace) + freeSpace, maxHeight.y / 2));
421- int blockDepth = maxHeight.y - mapPos.y + 1;
422- if (blockDepth < terrainDepth)
423- continue;
424-
425- unsigned int startHeight = Nz::SafeCaster(blockDepth - terrainDepth);
426- if (startHeight >= Planet::ChunkSize)
427- continue;
428-
429- if (BlockIndex& blockType = blockIndices[chunk.GetBlockLocalIndex({ x, z, startHeight })]; blockType == dirtBlockIndex)
430- blockType = grassBlockIndex;
431-
432- for (unsigned int height = startHeight + 1; height < Planet::ChunkSize; ++height)
433- blockIndices[chunk.GetBlockLocalIndex({ x, z, height })] = EmptyBlockIndex;
434- }
435- }
436-
437- // -Y
438- for (unsigned int z = 0; z < Planet::ChunkSize; ++z)
439- {
440- for (unsigned int x = 0; x < Planet::ChunkSize; ++x)
441- {
442- BlockIndices mapPos = GetBlockIndices(chunkIndices, { x, z, Planet::ChunkSize - 1 });
443- double height = perlin[Direction::Down].normalizedOctave2D_01(mapPos.x * scale, mapPos.z * scale, 4) * heightScale;
444-
445- int terrainDepth = std::round(std::min<double>(height * (maxHeight.y / 2 - freeSpace) + freeSpace, maxHeight.y / 2));
446- int blockDepth = maxHeight.y + mapPos.y + 1;
447- if (blockDepth < terrainDepth)
448- continue;
449-
450- unsigned int startHeight = Nz::SafeCast<unsigned int>(blockDepth - terrainDepth);
451- if (startHeight >= Planet::ChunkSize)
452- continue;
453-
454- if (BlockIndex& blockType = blockIndices[chunk.GetBlockLocalIndex({ x, z, Planet::ChunkSize - startHeight - 1 })]; blockType == dirtBlockIndex)
455- blockType = grassBlockIndex;
456-
457- for (unsigned int height = startHeight + 1; height < Planet::ChunkSize; ++height)
458- blockIndices[chunk.GetBlockLocalIndex({ x, z, Planet::ChunkSize - height - 1 })] = EmptyBlockIndex;
459- }
460- }
461-
462- // +Z
463- for (unsigned int y = 0; y < Planet::ChunkSize; ++y)
464- {
465- for (unsigned int x = 0; x < Planet::ChunkSize; ++x)
466- {
467- BlockIndices mapPos = GetBlockIndices(chunkIndices, { x, 0, y });
468- double height = perlin[Direction::Back].normalizedOctave2D_01(mapPos.x * scale, mapPos.y * scale, 4) * heightScale;
469-
470- int terrainDepth = std::round(std::min<double>(height * (maxHeight.z / 2 - freeSpace) + freeSpace, maxHeight.z / 2));
471- int blockDepth = maxHeight.z - mapPos.z + 1;
472- if (blockDepth < terrainDepth)
473- continue;
474-
475- unsigned int startHeight = Nz::SafeCaster(blockDepth - terrainDepth);
476- if (startHeight >= Planet::ChunkSize)
477- continue;
478-
479- if (BlockIndex& blockType = blockIndices[chunk.GetBlockLocalIndex({ x, startHeight, y })]; blockType == dirtBlockIndex)
480- blockType = grassBlockIndex;
481-
482- for (unsigned int height = startHeight + 1; height < Planet::ChunkSize; ++height)
483- blockIndices[chunk.GetBlockLocalIndex({ x, height, y })] = EmptyBlockIndex;
484- }
485- }
486-
487- // -Z
488- for (unsigned int y = 0; y < Planet::ChunkSize; ++y)
489- {
490- for (unsigned int x = 0; x < Planet::ChunkSize; ++x)
491- {
492- BlockIndices mapPos = GetBlockIndices(chunkIndices, { x, Planet::ChunkSize - 1, y });
493- double height = perlin[Direction::Front].normalizedOctave2D_01(mapPos.x * scale, mapPos.y * scale, 4) * heightScale;
494-
495- int terrainDepth = std::round(std::min<double>(height * (maxHeight.z / 2 - freeSpace) + freeSpace, maxHeight.z / 2));
496- int blockDepth = maxHeight.z + mapPos.z + 1;
497- if (blockDepth < terrainDepth)
498- continue;
499-
500- unsigned int startHeight = Nz::SafeCaster(blockDepth - terrainDepth);
501- if (startHeight >= Planet::ChunkSize)
502- continue;
503-
504- if (BlockIndex& blockType = blockIndices[chunk.GetBlockLocalIndex({ x, Planet::ChunkSize - startHeight - 1, y })]; blockType == dirtBlockIndex)
505- blockType = grassBlockIndex;
506-
507- for (unsigned int height = startHeight + 1; height < Planet::ChunkSize; ++height)
508- blockIndices[chunk.GetBlockLocalIndex({ x, Planet::ChunkSize - height - 1, y })] = EmptyBlockIndex;
509- }
510- }
511- #endif
512- });
250+ sol::error err = result;
251+ spdlog::error (" chunk {};{};{} failed to generate: {}" , chunkIndices.x , chunkIndices.y , chunkIndices.z , err.what ());
252+ return ;
253+ }
513254 }
514255
515256 void Planet::GenerateChunks (const BlockLibrary& blockLibrary, Nz::TaskScheduler& taskScheduler, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string scriptName)
0 commit comments