ChunkTerrainGenerator.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using KairoEngine.Core;
  5. using KairoEngine.Chunks;
  6. using KairoEngine.NoiseUtilities;
  7. using KairoEngine.UniverseGenerator;
  8. using Sirenix.OdinInspector;
  9. using UniRx;
  10. namespace KairoEngine.TerrainEngine
  11. {
  12. [HideMonoScript]
  13. public class ChunkTerrainGenerator : MonoBehaviour
  14. {
  15. public MarchingCubes4 marchingCubes3;
  16. public MarchingCubes2 marchingCubes2;
  17. public Vector3 voxelSize = new Vector3(1f, 1f, 1f);
  18. public Vector3Int chunkSize = new Vector3Int(16, 16, 16);
  19. public Vector3Int chunkLimit = new Vector3Int(2, 1, 2);
  20. //public float noiseMultiplier = 1.5f;
  21. [InlineEditor(InlineEditorObjectFieldModes.Foldout)] public PlanetTemplate planetTemplate;
  22. public ChunkSystem<BlockBase> chunkSystem;
  23. [Button("Generate"), ButtonGroup("Buttons")]
  24. void CreateChunks()
  25. {
  26. if(planetTemplate == null)
  27. {
  28. Debug.LogError("Missing planet template", this.gameObject);
  29. return;
  30. }
  31. DestroyTerrain();
  32. Debug.Log("Starting chunk generation");
  33. chunkSystem = new ChunkSystem<BlockBase>(chunkSize,voxelSize, true);
  34. for (int x = 0; x < chunkLimit.x; x++) {
  35. for (int z = 0; z < chunkLimit.z; z++) {
  36. for (int y = 0; y < chunkLimit.y; y++) {
  37. Vector3 chunkGlobalPos = new Vector3(x * chunkSize.x * voxelSize.x, y * chunkSize.y * voxelSize.y, z * chunkSize.z * voxelSize.z);
  38. Vector3Int chunkPos = new Vector3Int(x * chunkSize.x, y * chunkSize.y, z * chunkSize.z);
  39. chunkSystem.CreateChunk(chunkGlobalPos, chunkPos, (Chunk<BlockBase> c, Vector3Int pos) => new BlockBase(0, 0));
  40. GenerateChunkTerrain(chunkGlobalPos);
  41. }
  42. }
  43. }
  44. for (int x = 0; x < chunkLimit.x; x++) {
  45. for (int z = 0; z < chunkLimit.z; z++) {
  46. for (int y = 0; y < chunkLimit.y; y++) {
  47. //Vector3Int chunkPos = new Vector3Int(x * chunkSize.x, y * chunkSize.y, z * chunkSize.z);
  48. Vector3 chunkPos = new Vector3(x * chunkSize.x * voxelSize.x, y * chunkSize.y * voxelSize.y, z * chunkSize.z * voxelSize.z);
  49. if(marchingCubes3 != null) marchingCubes3.Generate(chunkSystem, chunkPos);
  50. //else if(marchingCubes2 != null) marchingCubes2.Generate(chunkSystem, chunkPos);
  51. }
  52. }
  53. }
  54. #if UNITY_EDITOR
  55. UpdateEditor ();
  56. #endif
  57. }
  58. void GenerateChunkTerrain(Vector3 initialPos)
  59. {
  60. float width = (float)(chunkLimit.x * chunkSize.x * voxelSize.x);
  61. float height = (float)(chunkLimit.y * chunkSize.y * voxelSize.y);
  62. float length = (float)(chunkLimit.z * chunkSize.z * voxelSize.z);
  63. for (int x = 0; x < chunkSize.x; x++) {
  64. for (int z = 0; z < chunkSize.z; z++) {
  65. for (int y = 0; y < chunkSize.y; y++) {
  66. // Get a terrain height using regular old Perlin noise.
  67. Vector3 pos = initialPos + new Vector3(x * voxelSize.x, y * voxelSize.y, z * voxelSize.z);
  68. // Old example noise:
  69. //float thisHeight = height * Mathf.PerlinNoise((float)pos.x / width * noiseMultiplier + 0.001f, (float)pos.z / length * noiseMultiplier + 0.001f);
  70. float elevation = planetTemplate.SamplePoint((float)pos.x / width, (float)pos.z / length);
  71. float thisHeight = height * elevation;
  72. uint code = planetTemplate.SamplePointCode((float)pos.x / width, (float)pos.z / length, elevation);
  73. BlockBase block = new BlockBase(code, (uint)Mathf.FloorToInt(thisHeight / voxelSize.y));
  74. chunkSystem.SetBlock(pos, block);
  75. }
  76. }
  77. }
  78. }
  79. void UpdateEditor ()
  80. {
  81. Timer.ExecuteRealTime(50, () => {
  82. if(marchingCubes3 != null)
  83. {
  84. marchingCubes3.UpdateFinishedJobs();
  85. if(!marchingCubes3.IsGeneratorDone()) UpdateEditor();
  86. }
  87. });
  88. }
  89. [Button("Destroy"), ButtonGroup("Buttons")]
  90. private void DestroyTerrain()
  91. {
  92. var childTransforms = this.gameObject.transform.GetComponentsInChildren<Transform>();
  93. if(childTransforms.Length > 0) Debug.Log($"Destroying {childTransforms.Length - 1} terrain objects");
  94. for (int i = 0; i < childTransforms.Length; i++)
  95. {
  96. if(childTransforms[i] == this.transform) continue;
  97. #if UNITY_EDITOR
  98. DestroyImmediate(childTransforms[i].gameObject);
  99. #else
  100. Destroy(childTransforms[i].gameObject);
  101. #endif
  102. }
  103. }
  104. }
  105. }