├── .gitattributes
├── Assets
├── Heightmaps
│ ├── circle.png
│ ├── terrainheightmap.png
│ ├── Heightmap Terrain Presets.meta
│ ├── Heightmap Terrain Presets
│ │ ├── DefaultHeightmapTerrain.asset.meta
│ │ └── DefaultHeightmapTerrain.asset
│ ├── circle.png.meta
│ └── terrainheightmap.png.meta
├── Prefabs
│ ├── Chunk.prefab.meta
│ └── Chunk.prefab
├── Prefabs.meta
├── Scenes.meta
├── Scripts.meta
├── Shaders.meta
├── Heightmaps.meta
├── Materials.meta
├── VoxelTerrain.meta
├── Scenes
│ ├── Heightmap World Example.unity.meta
│ └── Procedural World Example.unity.meta
├── Scripts
│ ├── Player.meta
│ └── Player
│ │ ├── PlayerCamera.cs.meta
│ │ ├── TerrainDeformer.cs.meta
│ │ └── PlayerCamera.cs
├── VoxelTerrain
│ ├── Core.meta
│ ├── Modules.meta
│ ├── Core
│ │ ├── Chunk.meta
│ │ ├── Meshing.meta
│ │ ├── Settings.meta
│ │ ├── Utilities.meta
│ │ ├── VoxelData.meta
│ │ ├── World.meta
│ │ ├── Meshing
│ │ │ ├── Data.meta
│ │ │ ├── MesherJob.cs.meta
│ │ │ ├── NativeCounter.cs.meta
│ │ │ ├── VoxelMesher.cs.meta
│ │ │ ├── Data
│ │ │ │ ├── VoxelCorners.cs.meta
│ │ │ │ ├── MeshingVertexData.cs.meta
│ │ │ │ ├── MeshingVertexData.cs
│ │ │ │ └── VoxelCorners.cs
│ │ │ ├── VoxelMesher.cs
│ │ │ ├── MesherJob.cs
│ │ │ └── NativeCounter.cs
│ │ ├── VoxelTerrain.Core.asmdef.meta
│ │ ├── Utilities
│ │ │ ├── Intersection.meta
│ │ │ ├── BoundsUtilities.cs.meta
│ │ │ ├── IndexUtilities.cs.meta
│ │ │ ├── LookupTables.cs.meta
│ │ │ ├── VectorUtilities.cs.meta
│ │ │ ├── CoordinateUtilities.cs.meta
│ │ │ ├── DistanceUtilities.cs.meta
│ │ │ ├── JobHandleWithData.cs.meta
│ │ │ ├── Intersection
│ │ │ │ ├── IntersectionUtilities.cs.meta
│ │ │ │ ├── PlaneLineIntersectionResult.cs.meta
│ │ │ │ ├── PlaneLineIntersectionResult.cs
│ │ │ │ └── IntersectionUtilities.cs
│ │ │ ├── JobHandleWithData.cs
│ │ │ ├── LookupTables.cs
│ │ │ ├── BoundsUtilities.cs
│ │ │ ├── DistanceUtilities.cs
│ │ │ ├── IndexUtilities.cs
│ │ │ └── VectorUtilities.cs
│ │ ├── Chunk
│ │ │ ├── ChunkStore.cs.meta
│ │ │ ├── ChunkProperties.cs.meta
│ │ │ ├── ChunkProvider.cs.meta
│ │ │ ├── ChunkUpdater.cs.meta
│ │ │ ├── ChunkStore.cs
│ │ │ ├── ChunkProperties.cs
│ │ │ ├── ChunkProvider.cs
│ │ │ └── ChunkUpdater.cs
│ │ ├── World
│ │ │ ├── VoxelWorld.cs.meta
│ │ │ └── VoxelWorld.cs
│ │ ├── Settings
│ │ │ ├── WorldSettings.cs.meta
│ │ │ └── WorldSettings.cs
│ │ ├── VoxelData
│ │ │ ├── PerChunkStore.cs.meta
│ │ │ ├── PerVoxelStore.cs.meta
│ │ │ ├── VoxelColorStore.cs.meta
│ │ │ ├── VoxelDataStore.cs.meta
│ │ │ ├── VoxelDataVolume.cs.meta
│ │ │ ├── VoxelDataGenerator.cs.meta
│ │ │ ├── IVoxelDataGenerationJob.cs.meta
│ │ │ ├── IVoxelDataGenerationJob.cs
│ │ │ ├── VoxelColorStore.cs
│ │ │ └── VoxelDataGenerator.cs
│ │ └── VoxelTerrain.Core.asmdef
│ └── Modules
│ │ ├── Chunk.meta
│ │ ├── World.meta
│ │ ├── Meshing.meta
│ │ ├── VoxelData.meta
│ │ ├── TerrainSettings.meta
│ │ ├── Meshing
│ │ ├── MarchingCubes.meta
│ │ └── MarchingCubes
│ │ │ ├── VertexList.cs.meta
│ │ │ ├── MarchingCubesJob.cs.meta
│ │ │ ├── MarchingCubesMesher.cs.meta
│ │ │ ├── MarchingCubesFunctions.cs.meta
│ │ │ ├── MarchingCubesLookupTables.cs.meta
│ │ │ ├── MarchingCubesMesher.cs
│ │ │ ├── VertexList.cs
│ │ │ ├── MarchingCubesJob.cs
│ │ │ └── MarchingCubesFunctions.cs
│ │ ├── VoxelTerrain.Modules.asmdef.meta
│ │ ├── Chunk
│ │ ├── ProceduralChunkProvider.cs.meta
│ │ └── ProceduralChunkProvider.cs
│ │ ├── World
│ │ ├── HeightmapWorldGenerator.cs.meta
│ │ ├── ProceduralWorldGenerator.cs.meta
│ │ ├── HeightmapWorldGenerator.cs
│ │ └── ProceduralWorldGenerator.cs
│ │ ├── VoxelData
│ │ ├── HeightmapVoxelDataGenerator.cs.meta
│ │ ├── ProceduralVoxelDataGenerator.cs.meta
│ │ ├── HeightmapTerrainVoxelDataCalculationJob.cs.meta
│ │ ├── ProceduralTerrainVoxelDataCalculationJob.cs.meta
│ │ ├── ProceduralVoxelDataGenerator.cs
│ │ ├── HeightmapVoxelDataGenerator.cs
│ │ ├── ProceduralTerrainVoxelDataCalculationJob.cs
│ │ └── HeightmapTerrainVoxelDataCalculationJob.cs
│ │ ├── TerrainSettings
│ │ ├── HeightmapTerrainSettings.cs.meta
│ │ ├── ProceduralTerrainSettings.cs.meta
│ │ ├── ProceduralTerrainSettings.cs
│ │ └── HeightmapTerrainSettings.cs
│ │ └── VoxelTerrain.Modules.asmdef
├── VoxelTerrain.Tests.meta
├── VoxelTerrain.Tests
│ ├── Core.meta
│ ├── Modules.meta
│ ├── Core
│ │ ├── MeshingTests.meta
│ │ ├── UtilitiesTests.meta
│ │ ├── ChunkUtilitiesTests.meta
│ │ ├── VoxelDataVolumeTests.meta
│ │ ├── VoxelTerrain.Core.Tests.asmdef.meta
│ │ ├── UtilitiesTests
│ │ │ ├── ModTests.cs.meta
│ │ │ ├── IndexToXyzTests.cs.meta
│ │ │ ├── ToInt3Tests.cs.meta
│ │ │ ├── XyzToIndexTests.cs.meta
│ │ │ ├── ToVectorIntTests.cs.meta
│ │ │ ├── FloorToMultipleOfXTests.cs.meta
│ │ │ ├── GetIntersectionAreaTests.cs.meta
│ │ │ ├── PlaneLineIntersectionTests.cs.meta
│ │ │ ├── ModTests.cs
│ │ │ ├── FloorToMultipleOfXTests.cs
│ │ │ ├── ToVectorIntTests.cs
│ │ │ ├── ToInt3Tests.cs
│ │ │ ├── IndexToXyzTests.cs
│ │ │ ├── XyzToIndexTests.cs
│ │ │ ├── GetIntersectionAreaTests.cs
│ │ │ └── PlaneLineIntersectionTests.cs
│ │ ├── MeshingTests
│ │ │ ├── NativeCounterTests.cs.meta
│ │ │ └── NativeCounterTests.cs
│ │ ├── ChunkUtilitiesTests
│ │ │ ├── CoordinateUtilitiesTests.cs.meta
│ │ │ └── CoordinateUtilitiesTests.cs
│ │ ├── VoxelDataVolumeTests
│ │ │ ├── VoxelDataVolumeTests.cs.meta
│ │ │ └── VoxelDataVolumeTests.cs
│ │ └── VoxelTerrain.Core.Tests.asmdef
│ └── Modules
│ │ ├── WorldTests.meta
│ │ ├── MeshingTests.meta
│ │ ├── VoxelTerrain.Modules.Tests.asmdef.meta
│ │ ├── MeshingTests
│ │ ├── MarchingCubesTests.meta
│ │ └── MarchingCubesTests
│ │ │ └── MarchingCubesFunctionsTests.cs.meta
│ │ └── VoxelTerrain.Modules.Tests.asmdef
├── VertexColorMaterial.mat.meta
├── Materials
│ ├── Triplanar Shading.mat.meta
│ └── Triplanar Shading.mat
├── Shaders
│ ├── Triplanar Shader.shader.meta
│ └── Triplanar Shader.shader
└── VertexColorMaterial.mat
├── ProjectSettings
├── ProjectVersion.txt
├── ClusterInputManager.asset
├── NetworkManager.asset
├── XRSettings.asset
├── TimeManager.asset
├── VFXManager.asset
├── EditorBuildSettings.asset
├── BurstAotSettings_StandaloneWindows.json
├── AudioManager.asset
├── TagManager.asset
├── EditorSettings.asset
├── PresetManager.asset
├── UnityConnectSettings.asset
├── DynamicsManager.asset
├── Physics2DSettings.asset
├── NavMeshAreas.asset
├── GraphicsSettings.asset
└── InputManager.asset
├── Packages
└── manifest.json
├── .github
└── ISSUE_TEMPLATE
│ └── bug_report.md
├── .gitignore
├── LICENSE
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/Assets/Heightmaps/circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Eldemarkki/Marching-Cubes-Terrain/HEAD/Assets/Heightmaps/circle.png
--------------------------------------------------------------------------------
/ProjectSettings/ProjectVersion.txt:
--------------------------------------------------------------------------------
1 | m_EditorVersion: 2019.3.15f1
2 | m_EditorVersionWithRevision: 2019.3.15f1 (59ff3e03856d)
3 |
--------------------------------------------------------------------------------
/Assets/Heightmaps/terrainheightmap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Eldemarkki/Marching-Cubes-Terrain/HEAD/Assets/Heightmaps/terrainheightmap.png
--------------------------------------------------------------------------------
/ProjectSettings/ClusterInputManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!236 &1
4 | ClusterInputManager:
5 | m_ObjectHideFlags: 0
6 | m_Inputs: []
7 |
--------------------------------------------------------------------------------
/Assets/Prefabs/Chunk.prefab.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d3008c1365ac1cb49b849d43fffdc19e
3 | PrefabImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Prefabs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a2b4aaaac306311499459e651ffa8c58
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Scenes.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 716fc49c0a0c0614791a670768976209
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Scripts.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ca90e8ce0d35b044cbbc5fa04e45a622
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Shaders.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d8decea629e652246ac5135df54c1a98
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/ProjectSettings/NetworkManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!149 &1
4 | NetworkManager:
5 | m_ObjectHideFlags: 0
6 | m_DebugLevel: 0
7 | m_Sendrate: 15
8 | m_AssetToPrefab: {}
9 |
--------------------------------------------------------------------------------
/Assets/Heightmaps.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5c3c6f4417d1093469fdcfa8b90fde28
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Materials.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5a869d5378e598f4c9b821ece5cf852d
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 90b8ebac1963a364f847499726d66989
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Scenes/Heightmap World Example.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9d5a5b0b410836b45ad7e6bf30ec1e9c
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Scenes/Procedural World Example.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2c5cddc6c031b8b489bfc1264e60bb24
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Scripts/Player.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9087dfe2cc3e10a4c9e1951a62a5f107
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: aad75f62a17578a4faf116b0d13a541b
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ff96f12ef0cf9ab4084f4ed63a3455f1
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 816df23405de2334399f4889b92487e1
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/ProjectSettings/XRSettings.asset:
--------------------------------------------------------------------------------
1 | {
2 | "m_SettingKeys": [
3 | "VR Device Disabled",
4 | "VR Device User Alert"
5 | ],
6 | "m_SettingValues": [
7 | "False",
8 | "False"
9 | ]
10 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fe69be840f3b22c45878a41155fc8a43
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Modules.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: dfde9d0260a3dc54f82f5345d46f95d6
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Chunk.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1ca93dd062277114498cf2f1922b1f12
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Meshing.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c5b169ebe28a0634f8b211235935b9d2
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Settings.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cbdf8c6d681549b4ab2c6ab88fa42d42
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e2ca2b9bda48fc24fb3de22e9f74e9b9
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/VoxelData.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4e93627528ea18344a25b6fb86c4994a
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/World.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e02ddd589e98ad64381fed09240298d7
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/Chunk.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a21125a24156c1d4fad75d66f42b8c59
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/World.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 73ec69dfe74011140b940d61b01537c4
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Meshing/Data.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 167840751702d0f4d94734947b59be72
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/VoxelTerrain.Core.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6ff95134247574242a0f8bcdbf3bdc70
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/Meshing.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: addc2312dd40c7e42b50f1020651e89f
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/VoxelData.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d358380057200764a99e6d19564272cb
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Heightmaps/Heightmap Terrain Presets.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ad883cb9ab34e7a4e96eaef2addcc11f
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VertexColorMaterial.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6f4ec41ce043e2940a19224905527b38
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 0
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/MeshingTests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b0c50375e9baf0648b8f65f5384088fd
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Modules/WorldTests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9fedb4671decadb43b62b05edc55ff36
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/TerrainSettings.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a997d4f10c9521b47a010d6ed189552d
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9b386bf31d498954884a1f3543e76a51
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Modules/MeshingTests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3ef0b6170112ca94786f616bbbb9553b
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/Intersection.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 774c2310663fdc0468488052050420e0
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/Meshing/MarchingCubes.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ac2bd5e8fecf63944b1b99df1b9474fd
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/VoxelTerrain.Modules.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ec6dc5c40c3d1164fa192bfa6f5db865
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/Materials/Triplanar Shading.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c10a75e53f4f277418f0e3a03569e6ce
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 2100000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/ChunkUtilitiesTests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: eb6f507884caa944b86f549365bc7eef
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/VoxelDataVolumeTests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ac4e9403346d9584caafde4fc071f24e
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/VoxelTerrain.Core.Tests.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 83835746ea3fcba4e819c4e703967f86
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Modules/VoxelTerrain.Modules.Tests.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fb8da5dee15273b4792b76e71ac760e4
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Modules/MeshingTests/MarchingCubesTests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: dbd2f188f539ed84e89f8331cc86a5a1
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/ProjectSettings/TimeManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!5 &1
4 | TimeManager:
5 | m_ObjectHideFlags: 0
6 | Fixed Timestep: 0.02
7 | Maximum Allowed Timestep: 0.1
8 | m_TimeScale: 1
9 | Maximum Particle Timestep: 0.03
10 |
--------------------------------------------------------------------------------
/Packages/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "com.unity.burst": "1.3.3",
4 | "com.unity.jobs": "0.2.9-preview.15",
5 | "com.unity.ugui": "1.0.0",
6 | "com.unity.modules.physics": "1.0.0",
7 | "com.unity.modules.ui": "1.0.0"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Assets/Heightmaps/Heightmap Terrain Presets/DefaultHeightmapTerrain.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b09c379fa88978d4d83dcf65edad60bf
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 0
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Shaders/Triplanar Shader.shader.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: db8c18db5cb480d4c8523e1b745f5af5
3 | ShaderImporter:
4 | externalObjects: {}
5 | defaultTextures: []
6 | nonModifiableTextures: []
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/Scripts/Player/PlayerCamera.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fceb88e3d7c83554b9539a0da91feda1
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Scripts/Player/TerrainDeformer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b25c4f659e9d0f84d9897b9f38efef04
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 100
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Chunk/ChunkStore.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 35a265702d5a74545892631579dfcbd8
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/World/VoxelWorld.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4ea9986f028d4e04b91a350741140621
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Chunk/ChunkProperties.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 00de47b60a9ba744da3bbdc17cd942fd
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Chunk/ChunkProvider.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e72216e47af7e58408454b827e439157
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Chunk/ChunkUpdater.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7f754d5f5e2253a409594cb8cd7a4278
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Meshing/MesherJob.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d61cdfeda8139ac43b47639051b8055a
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Meshing/NativeCounter.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2505c9fe53002c644b50fbb09d80ae1e
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Meshing/VoxelMesher.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: bc122460c884a7744aa5b708cfc99771
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Meshing/Data/VoxelCorners.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 604a276c9361e0b48bac99b9446cff8c
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Settings/WorldSettings.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d2e0cd28018556c40811d70f1621df66
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/BoundsUtilities.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 48439e638aa2cb140b4b3b6f17204f0c
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/IndexUtilities.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b979723edb3aefa48b4e069eaf2e546e
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/LookupTables.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 679090026106fa84398558c6f071420a
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/VectorUtilities.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 73e6a8cc3e246194d90a1ccd6c923cf1
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/VoxelData/PerChunkStore.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c6e9379ca73a25741a49fcb6d292c477
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/VoxelData/PerVoxelStore.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 702596fe13400164cb93d8ea72e39725
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/VoxelData/VoxelColorStore.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e66f3dd9a72a0f2449b26a410bde7d38
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/VoxelData/VoxelDataStore.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c3117ed0cc55e1846874b46688138374
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/VoxelData/VoxelDataVolume.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 42b915ef1200c3844bed576d3a837b6c
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/ModTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7d145f5c2b18ed842a4ff0b40cfd4c2e
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Meshing/Data/MeshingVertexData.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fe34939e1b76afe45a211c759f9de425
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/CoordinateUtilities.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e7cb35d6a1b2ed44c8ba74df4220f65f
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/DistanceUtilities.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ac4b697b7ff3073458a055ea76817d29
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/JobHandleWithData.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b98fb069e8c9f5942bd60fdf274a2118
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/VoxelData/VoxelDataGenerator.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0d73a1710889a074f8244fb35cb2b8ab
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/ProjectSettings/VFXManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!937362698 &1
4 | VFXManager:
5 | m_ObjectHideFlags: 0
6 | m_IndirectShader: {fileID: 0}
7 | m_CopyBufferShader: {fileID: 0}
8 | m_SortShader: {fileID: 0}
9 | m_RenderPipeSettingsPath:
10 | m_FixedTimeStep: 0.016666668
11 | m_MaxDeltaTime: 0.05
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/IndexToXyzTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a89f89788505aab4391174e602da3105
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/ToInt3Tests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 081907ffde2bcd049b6ad55b63553ea9
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/XyzToIndexTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: eb8674bc8d15c5a4b9607fb1aedaa841
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/VoxelData/IVoxelDataGenerationJob.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1cea74814d0d0ed4ab5b130a9a377873
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/Chunk/ProceduralChunkProvider.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cf2139c3087ce95439212cb2d0c8091a
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/Meshing/MarchingCubes/VertexList.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ef1904457e6a9b1429b338df0710fbd2
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/World/HeightmapWorldGenerator.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b126af6880531864c942905cea6158c9
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/World/ProceduralWorldGenerator.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0f97e4ff6bf8c0541aca7cfae307087f
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/MeshingTests/NativeCounterTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3b77183f52692984eaf1d44a691b3ee5
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/ToVectorIntTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 031c8469554469942a6484a382c33f3a
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/Meshing/MarchingCubes/MarchingCubesJob.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a2a1d711be887de4891ba2e4a76a7028
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/VoxelData/HeightmapVoxelDataGenerator.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: af9d5b8307eaa9f499db7bcc0a15c223
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/VoxelData/ProceduralVoxelDataGenerator.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4cc09cb714c6b8345896680d67a9b421
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/FloorToMultipleOfXTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0ba00df0479f64c4da49ef7927d23dce
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/GetIntersectionAreaTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9cf434a8b1706ec438fbb3d0ae2c0f9f
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/Intersection/IntersectionUtilities.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 72934639dbdd3b646aef5f60c9429493
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/Meshing/MarchingCubes/MarchingCubesMesher.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8ef462ca49da6db4d89a0aaa43a026c4
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/TerrainSettings/HeightmapTerrainSettings.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 440bc03213899e148bed19eec6e99127
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/TerrainSettings/ProceduralTerrainSettings.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 389b1d0824494f84cb1b877da681e3aa
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/ProjectSettings/EditorBuildSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!1045 &1
4 | EditorBuildSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_Scenes:
8 | - enabled: 1
9 | path: Assets/Examples/Scenes/Procedural World Example.unity
10 | guid: 2c5cddc6c031b8b489bfc1264e60bb24
11 | m_configObjects: {}
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/ChunkUtilitiesTests/CoordinateUtilitiesTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2efd6c6ac28a03545b02723346305385
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/PlaneLineIntersectionTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 650fe6ec44610bb46b2bc3e67be3194c
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/VoxelDataVolumeTests/VoxelDataVolumeTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e032e88065fc040408f92a50b4b1c7fc
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/Intersection/PlaneLineIntersectionResult.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ef3d64bef79f4e7ca703ce2c15e8f337
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/Meshing/MarchingCubes/MarchingCubesFunctions.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 79957911854a43d458793b9bc537dea6
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/Meshing/MarchingCubes/MarchingCubesLookupTables.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8390fa0bd304238458d03fba06ec8ff6
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/VoxelData/HeightmapTerrainVoxelDataCalculationJob.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5373d320718af2240a2fff3a7fd2f8a1
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/VoxelData/ProceduralTerrainVoxelDataCalculationJob.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 544bf4c1b0890a047ae74b642cff373a
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Modules/MeshingTests/MarchingCubesTests/MarchingCubesFunctionsTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e3464cc25b0a0394ab02b2bff7d824c8
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/ProjectSettings/BurstAotSettings_StandaloneWindows.json:
--------------------------------------------------------------------------------
1 | {
2 | "MonoBehaviour": {
3 | "m_Enabled": true,
4 | "m_EditorHideFlags": 0,
5 | "m_Name": "",
6 | "m_EditorClassIdentifier": "Unity.Burst.Editor:Unity.Burst.Editor:BurstPlatformAotSettings",
7 | "DisableOptimisations": false,
8 | "DisableSafetyChecks": true,
9 | "DisableBurstCompilation": false
10 | }
11 | }
--------------------------------------------------------------------------------
/ProjectSettings/AudioManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!11 &1
4 | AudioManager:
5 | m_ObjectHideFlags: 0
6 | m_Volume: 1
7 | Rolloff Scale: 1
8 | Doppler Factor: 1
9 | Default Speaker Mode: 2
10 | m_SampleRate: 0
11 | m_DSPBufferSize: 1024
12 | m_VirtualVoiceCount: 512
13 | m_RealVoiceCount: 32
14 | m_SpatializerPlugin:
15 | m_AmbisonicDecoderPlugin:
16 | m_DisableAudio: 0
17 | m_VirtualizeEffects: 1
18 |
--------------------------------------------------------------------------------
/ProjectSettings/TagManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!78 &1
4 | TagManager:
5 | serializedVersion: 2
6 | tags: []
7 | layers:
8 | - Default
9 | - TransparentFX
10 | - Ignore Raycast
11 | -
12 | - Water
13 | - UI
14 | -
15 | -
16 | - PostProcessing
17 | -
18 | -
19 | -
20 | -
21 | -
22 | -
23 | -
24 | -
25 | -
26 | -
27 | -
28 | -
29 | -
30 | -
31 | -
32 | -
33 | -
34 | -
35 | -
36 | -
37 | -
38 | -
39 | -
40 | m_SortingLayers:
41 | - name: Default
42 | uniqueID: 0
43 | locked: 0
44 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/VoxelTerrain.Core.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "VoxelTerrain.Core",
3 | "references": [
4 | "GUID:2665a8d13d1b3f18800f46e256720795",
5 | "GUID:e0cd26848372d4e5c891c569017e11f1",
6 | "GUID:8a2eafa29b15f444eb6d74f94a930e1d",
7 | "GUID:d8b63aba1907145bea998dd612889d6b"
8 | ],
9 | "includePlatforms": [],
10 | "excludePlatforms": [],
11 | "allowUnsafeCode": true,
12 | "overrideReferences": false,
13 | "precompiledReferences": [],
14 | "autoReferenced": true,
15 | "defineConstraints": [],
16 | "versionDefines": [],
17 | "noEngineReferences": false
18 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/JobHandleWithData.cs:
--------------------------------------------------------------------------------
1 | using Unity.Jobs;
2 |
3 | namespace Eldemarkki.VoxelTerrain.Utilities
4 | {
5 | ///
6 | /// A class that associates a JobHandle to some data
7 | ///
8 | /// The type of the data
9 | public class JobHandleWithData
10 | {
11 | ///
12 | /// The job handle
13 | ///
14 | public JobHandle JobHandle { get; set; }
15 |
16 | ///
17 | /// The associated data
18 | ///
19 | public T JobData { get; set; }
20 | }
21 | }
--------------------------------------------------------------------------------
/Assets/Heightmaps/Heightmap Terrain Presets/DefaultHeightmapTerrain.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &11400000
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 0
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 11500000, guid: 440bc03213899e148bed19eec6e99127, type: 3}
13 | m_Name: DefaultHeightmapTerrain
14 | m_EditorClassIdentifier:
15 | heightmap: {fileID: 2800000, guid: c592a59b98b6d2149bd5cdf21483ecd0, type: 3}
16 | amplitude: 35
17 | heightOffset: 0
18 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/VoxelData/IVoxelDataGenerationJob.cs:
--------------------------------------------------------------------------------
1 | using Unity.Jobs;
2 | using Unity.Mathematics;
3 |
4 | namespace Eldemarkki.VoxelTerrain.VoxelData
5 | {
6 | ///
7 | /// An interface for voxel data generation jobs
8 | ///
9 | public interface IVoxelDataGenerationJob : IJob
10 | {
11 | ///
12 | /// The sampling point's world position offset
13 | ///
14 | int3 WorldPositionOffset { get; set; }
15 |
16 | ///
17 | /// The generated voxel data
18 | ///
19 | VoxelDataVolume OutputVoxelData { get; set; }
20 | }
21 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/ModTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using Unity.Mathematics;
3 |
4 | namespace Eldemarkki.VoxelTerrain.Utilities.Tests
5 | {
6 | public class ModTests
7 | {
8 | [TestCase(10, 16, 74, 5, 0, 1, 4)]
9 | [TestCase(84, -24, 0, 8, 4, 0, 0)]
10 | [TestCase(-85, -8, 14, 3, 2, 1, 2 )]
11 | [TestCase(20, 35, 71, 35, 20, 0, 1)]
12 | public void TestMod(int nx, int ny, int nz, int x, int expectedX, int expectedY, int expectedZ)
13 | {
14 | Assert.AreEqual(new int3(expectedX, expectedY, expectedZ), VectorUtilities.Mod(new int3(nx, ny, nz), x));
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/VoxelTerrain.Modules.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "VoxelTerrain.Modules",
3 | "references": [
4 | "GUID:6ff95134247574242a0f8bcdbf3bdc70",
5 | "GUID:2665a8d13d1b3f18800f46e256720795",
6 | "GUID:e0cd26848372d4e5c891c569017e11f1",
7 | "GUID:d8b63aba1907145bea998dd612889d6b",
8 | "GUID:8a2eafa29b15f444eb6d74f94a930e1d"
9 | ],
10 | "includePlatforms": [],
11 | "excludePlatforms": [],
12 | "allowUnsafeCode": true,
13 | "overrideReferences": false,
14 | "precompiledReferences": [],
15 | "autoReferenced": true,
16 | "defineConstraints": [],
17 | "versionDefines": [],
18 | "noEngineReferences": false
19 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is. What were you doing when the bug happened? Did something not work, or did it throw an error? What error (include stacktrace)
12 |
13 | **Branch**
14 | Which branch did this bug happen on?
15 |
16 | **To Reproduce**
17 | Steps to reproduce the behavior:
18 |
19 | **Expected behavior**
20 | This should have happened instead:
21 |
22 | **Screenshots**
23 | Include screenshots if applicable
24 |
25 | **Other**
26 | Some other information that may be relevant
27 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/Intersection/PlaneLineIntersectionResult.cs:
--------------------------------------------------------------------------------
1 | namespace Eldemarkki.VoxelTerrain.Utilities.Intersection
2 | {
3 | ///
4 | /// A plane-line intersection result
5 | ///
6 | public enum PlaneLineIntersectionResult
7 | {
8 | ///
9 | /// The plane and the line don't intersect
10 | ///
11 | NoHit,
12 |
13 | ///
14 | /// The plane and the line intersected once
15 | ///
16 | OneHit,
17 |
18 | ///
19 | /// The line is inside the plane parallel to it
20 | ///
21 | ParallelInsidePlane
22 | }
23 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/LookupTables.cs:
--------------------------------------------------------------------------------
1 | using Unity.Mathematics;
2 |
3 | namespace Eldemarkki.VoxelTerrain.Utilities
4 | {
5 | ///
6 | /// A class to hold miscellaneous lookup tables
7 | ///
8 | public static class LookupTables
9 | {
10 | ///
11 | /// The corners of a voxel
12 | ///
13 | public static readonly int3[] CubeCorners =
14 | {
15 | new int3(0, 0, 0),
16 | new int3(1, 0, 0),
17 | new int3(1, 0, 1),
18 | new int3(0, 0, 1),
19 | new int3(0, 1, 0),
20 | new int3(1, 1, 0),
21 | new int3(1, 1, 1),
22 | new int3(0, 1, 1)
23 | };
24 | }
25 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/VoxelTerrain.Core.Tests.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "VoxelTerrain.Core.Tests",
3 | "references": [
4 | "UnityEngine.TestRunner",
5 | "UnityEditor.TestRunner",
6 | "Unity.Mathematics",
7 | "Unity.Collections",
8 | "Unity.Burst",
9 | "Unity.Jobs",
10 | "VoxelTerrain.Core"
11 | ],
12 | "includePlatforms": [
13 | "Editor"
14 | ],
15 | "excludePlatforms": [],
16 | "allowUnsafeCode": true,
17 | "overrideReferences": true,
18 | "precompiledReferences": [
19 | "nunit.framework.dll"
20 | ],
21 | "autoReferenced": false,
22 | "defineConstraints": [
23 | "UNITY_INCLUDE_TESTS"
24 | ],
25 | "versionDefines": [],
26 | "noEngineReferences": false
27 | }
28 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ###
2 | # Unity folders and files
3 | ###
4 | [Aa]ssets/AssetStoreTools*
5 | [Bb]uild/
6 | [Ll]ibrary/
7 | [Ll]ocal[Cc]ache/
8 | [Ll]ogs/
9 | [Oo]bj/
10 | [Tt]emp/
11 | [Uu]nityGenerated/
12 |
13 | # file on crash reports
14 | sysinfo.txt
15 | # Unity3D generated meta files
16 | *.pidb.meta
17 |
18 |
19 | db.lock
20 | storage.ide
21 | storage.ide-shm
22 | storage.ide-wal
23 |
24 | .collabignore
25 |
26 | ###
27 | # VS/MD solution and project files
28 | ###
29 | [Ee]xportedObj/
30 | *.booproj
31 | *.csproj
32 | *.sln
33 | *.suo
34 | *.svd
35 | *.unityproj
36 | *.user
37 | *.userprefs
38 | *.pidb
39 | .DS_Store
40 | .vscode/
41 | .vs/
42 |
43 | ###
44 | # OS generated
45 | ###
46 | .DS_Store
47 | .DS_Store?
48 | ._*
49 | .Spotlight-V100
50 | .Trashes
51 | Icon?
52 | ehthumbs.db
53 | Thumbs.db
54 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/FloorToMultipleOfXTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using Unity.Mathematics;
3 |
4 | namespace Eldemarkki.VoxelTerrain.Utilities.Tests
5 | {
6 | public class FloorToMultipleOfXTests
7 | {
8 | [TestCase(16f , 16f , 16f , 4, 16, 16 , 16)]
9 | [TestCase(16.5f , 16.5f , 16.5f , 4, 16, 16 , 16)]
10 | [TestCase(16f , 16f , 16f , 3, 15, 15 , 15)]
11 | [TestCase(15.9f , 6.1f , 129.3f , 2, 14, 6 , 128)]
12 | public void Test_Floor_To_Multiple_Of_X(float nx, float ny, float nz, int x, int expectedX, int expectedY, int expectedZ)
13 | {
14 | Assert.AreEqual(new int3(expectedX, expectedY, expectedZ), VectorUtilities.FloorToMultipleOfX(new float3(nx, ny, nz), x));
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Modules/VoxelTerrain.Modules.Tests.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "VoxelTerrain.Modules.Tests",
3 | "references": [
4 | "UnityEngine.TestRunner",
5 | "UnityEditor.TestRunner",
6 | "Unity.Mathematics",
7 | "Unity.Collections",
8 | "Unity.Burst",
9 | "Unity.Jobs",
10 | "VoxelTerrain.Core",
11 | "VoxelTerrain.Modules"
12 | ],
13 | "includePlatforms": [
14 | "Editor"
15 | ],
16 | "excludePlatforms": [],
17 | "allowUnsafeCode": true,
18 | "overrideReferences": true,
19 | "precompiledReferences": [
20 | "nunit.framework.dll"
21 | ],
22 | "autoReferenced": false,
23 | "defineConstraints": [
24 | "UNITY_INCLUDE_TESTS"
25 | ],
26 | "versionDefines": [],
27 | "noEngineReferences": false
28 | }
29 |
--------------------------------------------------------------------------------
/ProjectSettings/EditorSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!159 &1
4 | EditorSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 7
7 | m_ExternalVersionControlSupport: Visible Meta Files
8 | m_SerializationMode: 2
9 | m_LineEndingsForNewScripts: 2
10 | m_DefaultBehaviorMode: 0
11 | m_PrefabRegularEnvironment: {fileID: 0}
12 | m_PrefabUIEnvironment: {fileID: 0}
13 | m_SpritePackerMode: 0
14 | m_SpritePackerPaddingPower: 1
15 | m_EtcTextureCompressorBehavior: 1
16 | m_EtcTextureFastCompressor: 1
17 | m_EtcTextureNormalCompressor: 2
18 | m_EtcTextureBestCompressor: 4
19 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef
20 | m_ProjectGenerationRootNamespace:
21 | m_CollabEditorSettings:
22 | inProgressEnabled: 1
23 | m_EnableTextureStreamingInEditMode: 1
24 | m_EnableTextureStreamingInPlayMode: 1
25 | m_AsyncShaderCompilation: 1
26 |
--------------------------------------------------------------------------------
/ProjectSettings/PresetManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!1386491679 &1
4 | PresetManager:
5 | m_ObjectHideFlags: 0
6 | m_DefaultList:
7 | - type:
8 | m_NativeTypeID: 108
9 | m_ManagedTypePPtr: {fileID: 0}
10 | m_ManagedTypeFallback:
11 | defaultPresets:
12 | - m_Preset: {fileID: 2655988077585873504, guid: c1cf8506f04ef2c4a88b64b6c4202eea,
13 | type: 2}
14 | - type:
15 | m_NativeTypeID: 1020
16 | m_ManagedTypePPtr: {fileID: 0}
17 | m_ManagedTypeFallback:
18 | defaultPresets:
19 | - m_Preset: {fileID: 2655988077585873504, guid: 0cd792cc87e492d43b4e95b205fc5cc6,
20 | type: 2}
21 | - type:
22 | m_NativeTypeID: 1006
23 | m_ManagedTypePPtr: {fileID: 0}
24 | m_ManagedTypeFallback:
25 | defaultPresets:
26 | - m_Preset: {fileID: 2655988077585873504, guid: 7a99f8aa944efe94cb9bd74562b7d5f9,
27 | type: 2}
28 |
--------------------------------------------------------------------------------
/ProjectSettings/UnityConnectSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!310 &1
4 | UnityConnectSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 1
7 | m_Enabled: 0
8 | m_TestMode: 0
9 | m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events
10 | m_EventUrl: https://cdp.cloud.unity3d.com/v1/events
11 | m_ConfigUrl: https://config.uca.cloud.unity3d.com
12 | m_TestInitMode: 0
13 | CrashReportingSettings:
14 | m_EventUrl: https://perf-events.cloud.unity3d.com
15 | m_Enabled: 0
16 | m_LogBufferSize: 10
17 | m_CaptureEditorExceptions: 1
18 | UnityPurchasingSettings:
19 | m_Enabled: 0
20 | m_TestMode: 0
21 | UnityAnalyticsSettings:
22 | m_Enabled: 0
23 | m_TestMode: 0
24 | m_InitializeOnStartup: 1
25 | UnityAdsSettings:
26 | m_Enabled: 0
27 | m_InitializeOnStartup: 1
28 | m_TestMode: 0
29 | m_IosGameId:
30 | m_AndroidGameId:
31 | m_GameIds: {}
32 | m_GameId:
33 | PerformanceReportingSettings:
34 | m_Enabled: 0
35 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Settings/WorldSettings.cs:
--------------------------------------------------------------------------------
1 | using Unity.Mathematics;
2 | using UnityEngine;
3 |
4 | namespace Eldemarkki.VoxelTerrain.Settings
5 | {
6 | ///
7 | /// Parameters that specify how the world will be generated
8 | ///
9 | [System.Serializable]
10 | public class WorldSettings
11 | {
12 | ///
13 | /// The chunk's size. This represents the width, height and depth in Unity units.
14 | ///
15 | [SerializeField] private int3 chunkSize = new int3(16, 16, 16);
16 |
17 | ///
18 | /// The chunk's prefab that will be instantiated
19 | ///
20 | [SerializeField] private GameObject chunkPrefab;
21 |
22 | ///
23 | /// The chunk's size. This represents the width, height and depth in Unity units.
24 | ///
25 | public int3 ChunkSize => chunkSize;
26 |
27 | ///
28 | /// The chunk's prefab that will be instantiated
29 | ///
30 | public GameObject ChunkPrefab => chunkPrefab;
31 | }
32 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Eldemarkki
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Meshing/VoxelMesher.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Utilities;
2 | using Eldemarkki.VoxelTerrain.VoxelData;
3 | using Eldemarkki.VoxelTerrain.World;
4 | using Unity.Mathematics;
5 | using UnityEngine;
6 |
7 | namespace Eldemarkki.VoxelTerrain.Meshing
8 | {
9 | public abstract class VoxelMesher : MonoBehaviour
10 | {
11 | ///
12 | /// The voxel world the owns this voxel mesher
13 | ///
14 | public VoxelWorld VoxelWorld { get; set; }
15 |
16 | ///
17 | /// Starts a mesh generation job
18 | ///
19 | /// The store where to retrieve the voxel data from
20 | /// The store where to retrieve the voxels' color data from
21 | /// The coordinate of the chunk that will be generated
22 | /// The job handle and the actual mesh generation job
23 | public abstract JobHandleWithData CreateMesh(VoxelDataStore voxelDataStore, VoxelColorStore voxelColorStore, int3 chunkCoordinate);
24 | }
25 | }
--------------------------------------------------------------------------------
/ProjectSettings/DynamicsManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!55 &1
4 | PhysicsManager:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 8
7 | m_Gravity: {x: 0, y: -9.81, z: 0}
8 | m_DefaultMaterial: {fileID: 0}
9 | m_BounceThreshold: 2
10 | m_SleepThreshold: 0.005
11 | m_DefaultContactOffset: 0.01
12 | m_DefaultSolverIterations: 6
13 | m_DefaultSolverVelocityIterations: 1
14 | m_QueriesHitBackfaces: 0
15 | m_QueriesHitTriggers: 1
16 | m_EnableAdaptiveForce: 0
17 | m_ClothInterCollisionDistance: 0
18 | m_ClothInterCollisionStiffness: 0
19 | m_ContactsGeneration: 1
20 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
21 | m_AutoSimulation: 1
22 | m_AutoSyncTransforms: 0
23 | m_ReuseCollisionCallbacks: 1
24 | m_ClothInterCollisionSettingsToggle: 0
25 | m_ContactPairsMode: 0
26 | m_BroadphaseType: 0
27 | m_WorldBounds:
28 | m_Center: {x: 0, y: 0, z: 0}
29 | m_Extent: {x: 250, y: 250, z: 250}
30 | m_WorldSubdivisions: 8
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Marching-Cubes-Terrain
2 | This is my implementation of the Marching Cubes algorithm using Unity.
3 |
4 | Demo video: https://www.youtube.com/watch?v=7GrKaSCoyvs
5 |
6 | Discord Server: https://discord.gg/tKhNq7sCYu
7 |
8 | ## Features
9 | - Unity Job System with the Burst Compiler
10 | - Realtime terrain editing
11 | - Smooth the terrain by holding the left ctrl key and left click
12 | - Two world types:
13 | - Procedurally-generated infinite world
14 | - Import from black-and-white heightmap texture
15 |
16 | ## System Requirements
17 | - Unity3D (I'm developing this project with version **2019.3.0f6**, but any newer version should also work)
18 |
19 | ## Setup
20 | 1. Clone the repository with `git clone https://github.com/Eldemarkki/Marching-Cubes-Terrain.git`
21 | 2. Open the project with Unity
22 |
23 | ## Contributing
24 | All contributions are welcome.
25 |
26 | When creating a new issue, please describe the bug in as much detail as possible, and include the branch and commit id where the bug happened. If applicable, also include screenshots.
27 |
28 | ## Acknowledgements:
29 | - Paul Bourke for an example implementation of the Marching Cubes algorithm (http://paulbourke.net/geometry/polygonise/)
30 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/MeshingTests/NativeCounterTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using Unity.Collections;
3 |
4 | namespace Eldemarkki.VoxelTerrain.Meshing.Tests
5 | {
6 | public class NativeCounterTests
7 | {
8 | private NativeCounter counter;
9 |
10 | [SetUp]
11 | public void SetupNativeCounterTest()
12 | {
13 | counter = new NativeCounter(Allocator.Temp);
14 | }
15 |
16 | [TearDown]
17 | public void TeardownNativeCounterTest()
18 | {
19 | counter.Dispose();
20 | }
21 |
22 | [Test]
23 | public void NativeCounter_Count_Initialized_As_0()
24 | {
25 | Assert.AreEqual(0, counter.Count);
26 | }
27 |
28 | [Test]
29 | public void NativeCounter_Increment_Increases_Count_By_1()
30 | {
31 | counter.Increment();
32 | Assert.AreEqual(1, counter.Count);
33 | }
34 |
35 | [Test]
36 | public void NativeCounter_Random_Increment_Sets_Count_To_N([Random(5, 100, 3)] int value)
37 | {
38 | for (int i = 0; i < value; i++)
39 | {
40 | counter.Increment();
41 | }
42 |
43 | Assert.AreEqual(value, counter.Count);
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Meshing/MesherJob.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Meshing.Data;
2 | using Unity.Collections;
3 | using Unity.Jobs;
4 | using UnityEngine;
5 | using Eldemarkki.VoxelTerrain.VoxelData;
6 |
7 | namespace Eldemarkki.VoxelTerrain.Meshing
8 | {
9 | ///
10 | /// An interface for all the jobs that can extract a surface from voxel data
11 | ///
12 | public interface IMesherJob : IJob
13 | {
14 | ///
15 | /// A counter that keeps track of how many vertices there are
16 | ///
17 | NativeCounter VertexCountCounter { get; set; }
18 |
19 | ///
20 | /// The voxel data to generate the mesh from
21 | ///
22 | VoxelDataVolume VoxelData { get; set; }
23 |
24 | ///
25 | /// The voxel colors used to color the triangles
26 | ///
27 | VoxelDataVolume VoxelColors { get; set; }
28 |
29 | ///
30 | /// The generated vertices
31 | ///
32 | NativeArray OutputVertices { get; set; }
33 |
34 | ///
35 | /// The generated triangles
36 | ///
37 | NativeArray OutputTriangles { get; set; }
38 | }
39 | }
--------------------------------------------------------------------------------
/Assets/Shaders/Triplanar Shader.shader:
--------------------------------------------------------------------------------
1 | Shader "Marching Cubes/Triplanar Shader"
2 | {
3 | Properties
4 | {
5 | XColor("X Color", Color) = (0,0,0,0)
6 | YColor("Y Color", Color) = (0,0,0,0)
7 | NegativeYColor("Negative Y Color", Color) = (0,0,0,0)
8 | ZColor("Z Color", Color) = (0,0,0,0)
9 | YColorAmount("Y Color Amount", float) = 0.4
10 | }
11 |
12 | SubShader
13 | {
14 | Tags { "RenderType" = "Opaque"}
15 |
16 | CGPROGRAM
17 | #pragma surface surf Standard fullforwardshadows
18 | #pragma target 3.0
19 |
20 | fixed4 XColor;
21 | fixed4 YColor;
22 | fixed4 NegativeYColor;
23 | fixed4 ZColor;
24 | fixed YColorAmount;
25 |
26 |
27 | struct Input
28 | {
29 | float3 worldNormal;
30 | };
31 |
32 | void surf (Input IN, inout SurfaceOutputStandard o)
33 | {
34 | fixed x = abs(IN.worldNormal.x);
35 | fixed yNormal = IN.worldNormal.y;
36 | fixed y = abs(yNormal) * YColorAmount;
37 | fixed z = abs(IN.worldNormal.z);
38 |
39 | fixed total = (x + y + z);
40 | x /= total;
41 | y /= total;
42 | z /= total;
43 |
44 | // X
45 | fixed3 col = (XColor * x);
46 |
47 | // Y
48 | if (yNormal < 0)
49 | col += NegativeYColor * y;
50 | else
51 | col += YColor * y;
52 |
53 | // Z
54 | col += (ZColor * z);
55 |
56 | o.Albedo = col;
57 | }
58 | ENDCG
59 | }
60 | FallBack "Diffuse"
61 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/ToVectorIntTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using Unity.Mathematics;
3 |
4 | namespace Eldemarkki.VoxelTerrain.Utilities.Tests
5 | {
6 | public class ToVectorIntTests
7 | {
8 | [Test]
9 | public void TestToVectorIntValueX([Random(0, 100, 4)] int x)
10 | {
11 | // Just some arbitrary values for y and z
12 | int y = 61;
13 | int z = 42;
14 |
15 | int3 vector = new int3(x, y, z);
16 | Assert.AreEqual(vector.x, VectorUtilities.ToVectorInt(vector).x);
17 | }
18 |
19 | [Test]
20 | public void TestToVectorIntValueY([Random(0, 100, 4)] int y)
21 | {
22 | // Just some arbitrary values for x and z
23 | int x = 33;
24 | int z = 98;
25 |
26 | int3 vector = new int3(x, y, z);
27 | Assert.AreEqual(vector.y, VectorUtilities.ToVectorInt(vector).y);
28 | }
29 |
30 | [Test]
31 | public void TestToVectorIntValueZ([Random(0, 100, 4)] int z)
32 | {
33 | // Just some arbitrary values for x and y
34 | int x = 48;
35 | int y = 86;
36 |
37 | int3 vector = new int3(x, y, z);
38 | Assert.AreEqual(vector.z, VectorUtilities.ToVectorInt(vector).z);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/ToInt3Tests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using Unity.Mathematics;
3 | using UnityEngine;
4 |
5 | namespace Eldemarkki.VoxelTerrain.Utilities.Tests
6 | {
7 | public class ToInt3Tests
8 | {
9 | [Test]
10 | public void TestToInt3ValueX([Random(0, 100, 4)] int x)
11 | {
12 | // Just some arbitrary values for y and z
13 | int y = 61;
14 | int z = 42;
15 |
16 | Vector3Int vector = new Vector3Int(x, y, z);
17 | Assert.AreEqual(vector.x, VectorUtilities.ToInt3(vector).x);
18 | }
19 |
20 | [Test]
21 | public void TestToInt3ValueY([Random(0, 100, 4)] int y)
22 | {
23 | // Just some arbitrary values for x and z
24 | int x = 33;
25 | int z = 98;
26 |
27 | Vector3Int vector = new Vector3Int(x, y, z);
28 | Assert.AreEqual(vector.y, VectorUtilities.ToInt3(vector).y);
29 | }
30 |
31 | [Test]
32 | public void TestToInt3ValueZ([Random(0, 100, 4)] int z)
33 | {
34 | // Just some arbitrary values for x and y
35 | int x = 48;
36 | int y = 86;
37 |
38 | Vector3Int vector = new Vector3Int(x, y, z);
39 | Assert.AreEqual(vector.z, VectorUtilities.ToInt3(vector).z);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/BoundsUtilities.cs:
--------------------------------------------------------------------------------
1 | using Unity.Mathematics;
2 | using UnityEngine;
3 |
4 | namespace Eldemarkki.VoxelTerrain.Utilities
5 | {
6 | public static class BoundsUtilities
7 | {
8 | ///
9 | /// Calculates the world space bounds of a chunk
10 | ///
11 | /// The coordinate of the chunk
12 | /// The size of the chunk
13 | /// That chunk's world space bounds
14 | public static BoundsInt GetChunkBounds(int3 chunkCoordinate, int3 chunkSize)
15 | {
16 | int3 min = chunkCoordinate * chunkSize;
17 | int3 size = new int3(1, 1, 1) * (chunkSize + new int3(1, 1, 1));
18 |
19 | return new BoundsInt(min.ToVectorInt(), size.ToVectorInt());
20 | }
21 |
22 | ///
23 | /// Calculates the volume of ; how many points are inside of
24 | ///
25 | /// The bounds whose volume is calculated
26 | /// The amount of points inside of
27 | public static int CalculateVolume(this BoundsInt bounds)
28 | {
29 | Vector3Int size = bounds.size;
30 | return size.x * size.y * size.z;
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/ProjectSettings/Physics2DSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!19 &1
4 | Physics2DSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 4
7 | m_Gravity: {x: 0, y: -9.81}
8 | m_DefaultMaterial: {fileID: 0}
9 | m_VelocityIterations: 8
10 | m_PositionIterations: 3
11 | m_VelocityThreshold: 1
12 | m_MaxLinearCorrection: 0.2
13 | m_MaxAngularCorrection: 8
14 | m_MaxTranslationSpeed: 100
15 | m_MaxRotationSpeed: 360
16 | m_BaumgarteScale: 0.2
17 | m_BaumgarteTimeOfImpactScale: 0.75
18 | m_TimeToSleep: 0.5
19 | m_LinearSleepTolerance: 0.01
20 | m_AngularSleepTolerance: 2
21 | m_DefaultContactOffset: 0.01
22 | m_AutoSimulation: 1
23 | m_QueriesHitTriggers: 1
24 | m_QueriesStartInColliders: 1
25 | m_ChangeStopsCallbacks: 0
26 | m_CallbacksOnDisable: 1
27 | m_ReuseCollisionCallbacks: 1
28 | m_AutoSyncTransforms: 0
29 | m_AlwaysShowColliders: 0
30 | m_ShowColliderSleep: 1
31 | m_ShowColliderContacts: 0
32 | m_ShowColliderAABB: 0
33 | m_ContactArrowScale: 0.2
34 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412}
35 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432}
36 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745}
37 | m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804}
38 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
39 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/VoxelData/ProceduralVoxelDataGenerator.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Settings;
2 | using Eldemarkki.VoxelTerrain.Utilities;
3 | using Unity.Collections;
4 | using Unity.Jobs;
5 | using Unity.Mathematics;
6 | using UnityEngine;
7 |
8 | namespace Eldemarkki.VoxelTerrain.VoxelData
9 | {
10 | ///
11 | /// A generator that creates voxel data procedurally
12 | ///
13 | public class ProceduralVoxelDataGenerator : VoxelDataGenerator
14 | {
15 | ///
16 | /// The settings for the procedural generation
17 | ///
18 | [SerializeField] private ProceduralTerrainSettings proceduralTerrainSettings = new ProceduralTerrainSettings(1, 9, 120, 0, 0);
19 |
20 | ///
21 | public override JobHandleWithData GenerateVoxelData(int3 worldSpaceOrigin, VoxelDataVolume outputVoxelDataArray)
22 | {
23 | ProceduralTerrainVoxelDataCalculationJob job = new ProceduralTerrainVoxelDataCalculationJob
24 | {
25 | WorldPositionOffset = worldSpaceOrigin,
26 | OutputVoxelData = outputVoxelDataArray,
27 | ProceduralTerrainSettings = proceduralTerrainSettings
28 | };
29 |
30 | JobHandle jobHandle = job.Schedule();
31 |
32 | JobHandleWithData jobHandleWithData = new JobHandleWithData
33 | {
34 | JobHandle = jobHandle,
35 | JobData = job
36 | };
37 |
38 | return jobHandleWithData;
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/DistanceUtilities.cs:
--------------------------------------------------------------------------------
1 | using Unity.Mathematics;
2 |
3 | namespace Eldemarkki.VoxelTerrain.Utilities
4 | {
5 | public static class DistanceUtilities
6 | {
7 | ///
8 | /// Calculates the difference between and , and returns true if any of the xyz components of the difference is greater than . If all of the xyz components of the difference is less than or equal to it returns false. The formal name of this distance calculation is Chebyshev distance. This compares if the Chebyshev distance is greater than
9 | ///
10 | /// Point A
11 | /// Point B
12 | /// Maximum allowed component-wise difference of the difference between and
13 | /// True if any of the component-wise differences in the difference between and is greater than , false otherwise
14 | public static bool ChebyshevDistanceGreaterThan(int3 pointA, int3 pointB, int maximumAllowed)
15 | {
16 | int abx = pointA.x - pointB.x;
17 | int aby = pointA.y - pointB.y;
18 | int abz = pointA.z - pointB.z;
19 |
20 | return abx > maximumAllowed || -abx > maximumAllowed || aby > maximumAllowed || -aby > maximumAllowed || abz > maximumAllowed || -abz > maximumAllowed;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Meshing/Data/MeshingVertexData.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 | using Unity.Mathematics;
3 | using UnityEngine;
4 | using UnityEngine.Rendering;
5 |
6 | namespace Eldemarkki.VoxelTerrain.Meshing.Data
7 | {
8 | ///
9 | /// A struct to hold the data every vertex should have
10 | ///
11 | [StructLayout(LayoutKind.Sequential)]
12 | public struct MeshingVertexData
13 | {
14 | ///
15 | /// The vertex's local position
16 | ///
17 | public float3 position;
18 |
19 | ///
20 | /// The vertex's normal
21 | ///
22 | public float3 normal;
23 |
24 | public Color32 color;
25 |
26 | ///
27 | /// The constructor to create a
28 | ///
29 | /// The vertex's local position
30 | /// The vertex's normal
31 | public MeshingVertexData(float3 position, float3 normal, Color32 color)
32 | {
33 | this.position = position;
34 | this.normal = normal;
35 | this.color = color;
36 | }
37 |
38 | ///
39 | /// The memory layout of a single vertex in memory
40 | ///
41 | public static readonly VertexAttributeDescriptor[] VertexBufferMemoryLayout =
42 | {
43 | new VertexAttributeDescriptor(VertexAttribute.Position),
44 | new VertexAttributeDescriptor(VertexAttribute.Normal),
45 | new VertexAttributeDescriptor(VertexAttribute.Color, VertexAttributeFormat.UNorm8, 4)
46 | };
47 | }
48 | }
--------------------------------------------------------------------------------
/ProjectSettings/NavMeshAreas.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!126 &1
4 | NavMeshProjectSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | areas:
8 | - name: Walkable
9 | cost: 1
10 | - name: Not Walkable
11 | cost: 1
12 | - name: Jump
13 | cost: 2
14 | - name:
15 | cost: 1
16 | - name:
17 | cost: 1
18 | - name:
19 | cost: 1
20 | - name:
21 | cost: 1
22 | - name:
23 | cost: 1
24 | - name:
25 | cost: 1
26 | - name:
27 | cost: 1
28 | - name:
29 | cost: 1
30 | - name:
31 | cost: 1
32 | - name:
33 | cost: 1
34 | - name:
35 | cost: 1
36 | - name:
37 | cost: 1
38 | - name:
39 | cost: 1
40 | - name:
41 | cost: 1
42 | - name:
43 | cost: 1
44 | - name:
45 | cost: 1
46 | - name:
47 | cost: 1
48 | - name:
49 | cost: 1
50 | - name:
51 | cost: 1
52 | - name:
53 | cost: 1
54 | - name:
55 | cost: 1
56 | - name:
57 | cost: 1
58 | - name:
59 | cost: 1
60 | - name:
61 | cost: 1
62 | - name:
63 | cost: 1
64 | - name:
65 | cost: 1
66 | - name:
67 | cost: 1
68 | - name:
69 | cost: 1
70 | - name:
71 | cost: 1
72 | m_LastAgentTypeID: -887442657
73 | m_Settings:
74 | - serializedVersion: 2
75 | agentTypeID: 0
76 | agentRadius: 0.5
77 | agentHeight: 2
78 | agentSlope: 45
79 | agentClimb: 0.75
80 | ledgeDropHeight: 0
81 | maxJumpAcrossDistance: 0
82 | minRegionArea: 2
83 | manualCellSize: 0
84 | cellSize: 0.16666667
85 | manualTileSize: 0
86 | tileSize: 256
87 | accuratePlacement: 0
88 | debug:
89 | m_Flags: 0
90 | m_SettingNames:
91 | - Humanoid
92 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Chunk/ChunkStore.cs:
--------------------------------------------------------------------------------
1 | using Unity.Mathematics;
2 |
3 | namespace Eldemarkki.VoxelTerrain.World.Chunks
4 | {
5 | ///
6 | /// A container for all of the chunks in the world
7 | ///
8 | public class ChunkStore : PerChunkStore
9 | {
10 | ///
11 | /// Generates the data for a chunk at coordinate , and adds it to the chunks dictionary in
12 | ///
13 | /// The coordinate to generate the data for
14 | public override void GenerateDataForChunkUnchecked(int3 chunkCoordinate)
15 | {
16 | ChunkProperties chunkProperties = new ChunkProperties();
17 | chunkProperties.Initialize(chunkCoordinate, VoxelWorld.WorldSettings.ChunkSize);
18 | AddChunk(chunkCoordinate, chunkProperties);
19 | }
20 |
21 | ///
22 | /// Generates the data for a chunk at coordinate , and adds it to the chunks dictionary in . The new data is generated to .
23 | ///
24 | /// The coordinate to generate the data for
25 | /// The already existing data that will be used to generate the data into
26 | public override void GenerateDataForChunkUnchecked(int3 chunkCoordinate, ChunkProperties existingData)
27 | {
28 | existingData.MeshCollider.enabled = false;
29 | existingData.MeshRenderer.enabled = false;
30 | existingData.Initialize(chunkCoordinate, VoxelWorld.WorldSettings.ChunkSize);
31 | AddChunk(chunkCoordinate, existingData);
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Meshing/NativeCounter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using Unity.Collections;
4 | using Unity.Collections.LowLevel.Unsafe;
5 |
6 | namespace Eldemarkki.VoxelTerrain.Meshing
7 | {
8 | ///
9 | /// An incremental counter made for the Unity Job System
10 | ///
11 | public unsafe struct NativeCounter : IDisposable
12 | {
13 | ///
14 | /// The allocator for the counter
15 | ///
16 | private readonly Allocator _allocator;
17 |
18 | ///
19 | /// The pointer to the value
20 | ///
21 | [NativeDisableUnsafePtrRestriction] private readonly int* _counter;
22 |
23 | ///
24 | /// The counter's value
25 | ///
26 | public int Count
27 | {
28 | get => *_counter;
29 | set => (*_counter) = value;
30 | }
31 |
32 | ///
33 | /// The constructor
34 | ///
35 | /// What type of allocator to use
36 | public NativeCounter(Allocator allocator)
37 | {
38 | _allocator = allocator;
39 | _counter = (int*)UnsafeUtility.Malloc(sizeof(int), 4, allocator);
40 | Count = 0;
41 | }
42 |
43 | ///
44 | /// Increments the count by 1
45 | ///
46 | /// The original count
47 | public int Increment()
48 | {
49 | return Interlocked.Increment(ref *_counter) - 1;
50 | }
51 |
52 | ///
53 | /// Disposes the counter
54 | ///
55 | public void Dispose()
56 | {
57 | UnsafeUtility.Free(_counter, _allocator);
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/VoxelData/VoxelColorStore.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.World;
2 | using Unity.Collections.LowLevel.Unsafe;
3 | using Unity.Mathematics;
4 | using UnityEngine;
5 |
6 | namespace Eldemarkki.VoxelTerrain.VoxelData
7 | {
8 | ///
9 | /// A store which handles getting and setting the voxel colors for the world
10 | ///
11 | public class VoxelColorStore : PerVoxelStore
12 | {
13 | ///
14 | /// The default color that the terrain will be colored with on load
15 | ///
16 | [SerializeField] private Color32 defaultTerrainColor = new Color32(11, 91, 33, 255);
17 |
18 | ///
19 | /// Generates the colors for a chunk at , where the output array is to save memory by not needing to allocate a new array. This does not check if a color array already exists at
20 | ///
21 | /// The coordinate of the chunk which to generate the colors for
22 | /// The array that should be filled with the new colors
23 | public override unsafe void GenerateDataForChunkUnchecked(int3 chunkCoordinate, VoxelDataVolume outputColors)
24 | {
25 | // Fill the array with the default terrain color
26 | Color32* defaultColorArray = stackalloc Color32[1]
27 | {
28 | defaultTerrainColor
29 | };
30 |
31 | unsafe
32 | {
33 | UnsafeUtility.MemCpyReplicate(outputColors.GetUnsafePtr(), defaultColorArray, sizeof(Color32), outputColors.Length);
34 | }
35 |
36 | SetDataChunkUnchecked(chunkCoordinate, outputColors, false);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/World/VoxelWorld.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Meshing;
2 | using Eldemarkki.VoxelTerrain.Settings;
3 | using Eldemarkki.VoxelTerrain.VoxelData;
4 | using Eldemarkki.VoxelTerrain.World.Chunks;
5 | using UnityEngine;
6 |
7 | namespace Eldemarkki.VoxelTerrain.World
8 | {
9 | ///
10 | /// The main entry point for interacting with the voxel world
11 | ///
12 | public class VoxelWorld : MonoBehaviour
13 | {
14 | [SerializeField] private WorldSettings worldSettings;
15 | public WorldSettings WorldSettings => worldSettings;
16 |
17 | [SerializeField] private VoxelMesher voxelMesher;
18 | public VoxelMesher VoxelMesher => voxelMesher;
19 |
20 | [SerializeField] private VoxelDataStore voxelDataStore;
21 | public VoxelDataStore VoxelDataStore => voxelDataStore;
22 |
23 | [SerializeField] private VoxelColorStore voxelColorStore;
24 | public VoxelColorStore VoxelColorStore => voxelColorStore;
25 |
26 | [SerializeField] private VoxelDataGenerator voxelDataGenerator;
27 | public VoxelDataGenerator VoxelDataGenerator => voxelDataGenerator;
28 |
29 | [SerializeField] private ChunkProvider chunkProvider;
30 | public ChunkProvider ChunkProvider => chunkProvider;
31 |
32 | [SerializeField] private ChunkStore chunkStore;
33 | public ChunkStore ChunkStore => chunkStore;
34 |
35 | [SerializeField] private ChunkUpdater chunkUpdater;
36 | public ChunkUpdater ChunkUpdater => chunkUpdater;
37 |
38 | private void Awake()
39 | {
40 | voxelDataStore.VoxelWorld = this;
41 | voxelColorStore.VoxelWorld = this;
42 | chunkProvider.VoxelWorld = this;
43 | chunkUpdater.VoxelWorld = this;
44 | chunkStore.VoxelWorld = this;
45 | voxelMesher.VoxelWorld = this;
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/IndexToXyzTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using Unity.Mathematics;
3 |
4 | namespace Eldemarkki.VoxelTerrain.Utilities.Tests
5 | {
6 | public class IndexToXyzTests
7 | {
8 | private static void TestIndexToXyz(int index, int expectedX, int expectedY, int expectedZ, int width, int height)
9 | {
10 | Assert.AreEqual(new int3(expectedX, expectedY, expectedZ), IndexUtilities.IndexToXyz(index, width, height));
11 | }
12 |
13 | [TestCaseSource(nameof(Width_1_Height_5_Cases))]
14 | public void Width_1_Height_5(int index, int expectedX, int expectedY, int expectedZ)
15 | {
16 | TestIndexToXyz(index, expectedX, expectedY, expectedZ, 1, 5);
17 | }
18 |
19 | [TestCaseSource(nameof(Width_2_Height_5_Cases))]
20 | public void Width_2_Height_5(int index, int expectedX, int expectedY, int expectedZ)
21 | {
22 | TestIndexToXyz(index, expectedX, expectedY, expectedZ, 2, 5);
23 | }
24 |
25 | private static object[] Width_1_Height_5_Cases =
26 | {
27 | new object[] { 1, 0, 1, 0},
28 | new object[] { 2, 0, 2, 0},
29 | new object[] { 2, 0, 2, 0},
30 | new object[] { 3, 0, 3, 0},
31 | new object[] { 4, 0, 4, 0},
32 | new object[] { 5, 0, 0, 1}
33 | };
34 |
35 | private static object[] Width_2_Height_5_Cases =
36 | {
37 | new object[] { 1 , 1, 0, 0},
38 | new object[] { 2 , 0, 1, 0},
39 | new object[] { 3 , 1, 1, 0},
40 | new object[] { 4 , 0, 2, 0},
41 | new object[] { 10, 0, 0, 1},
42 | new object[] { 11, 1, 0, 1},
43 | new object[] { 12, 0, 1, 1},
44 | new object[] { 13, 1, 1, 1},
45 | new object[] { 20, 0, 0, 2},
46 | new object[] { 30, 0, 0, 3},
47 | new object[] { 33, 1, 1, 3}
48 | };
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/VoxelData/HeightmapVoxelDataGenerator.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Utilities;
2 | using Eldemarkki.VoxelTerrain.World;
3 | using Unity.Collections;
4 | using Unity.Jobs;
5 | using Unity.Mathematics;
6 | using UnityEngine;
7 |
8 | namespace Eldemarkki.VoxelTerrain.VoxelData
9 | {
10 | ///
11 | /// A generator that creates voxel data from a heightmap
12 | ///
13 | public class HeightmapVoxelDataGenerator : VoxelDataGenerator
14 | {
15 | ///
16 | /// The heightmap world generator which gives this class the HeightmapTerrainSettings
17 | ///
18 | [SerializeField] private HeightmapWorldGenerator heightmapWorldGenerator;
19 |
20 | ///
21 | public override JobHandleWithData GenerateVoxelData(int3 worldSpaceOrigin, VoxelDataVolume outputVoxelDataArray)
22 | {
23 | HeightmapTerrainVoxelDataCalculationJob job = new HeightmapTerrainVoxelDataCalculationJob
24 | {
25 | WorldPositionOffset = worldSpaceOrigin,
26 | OutputVoxelData = outputVoxelDataArray,
27 | HeightmapData = heightmapWorldGenerator.HeightmapTerrainSettings.HeightmapData,
28 | HeightmapWidth = heightmapWorldGenerator.HeightmapTerrainSettings.Width,
29 | HeightmapHeight = heightmapWorldGenerator.HeightmapTerrainSettings.Height,
30 | Amplitude = heightmapWorldGenerator.HeightmapTerrainSettings.Amplitude,
31 | HeightOffset = heightmapWorldGenerator.HeightmapTerrainSettings.HeightOffset
32 | };
33 |
34 | JobHandle jobHandle = job.Schedule();
35 |
36 | JobHandleWithData jobHandleWithData = new JobHandleWithData
37 | {
38 | JobHandle = jobHandle,
39 | JobData = job
40 | };
41 |
42 | return jobHandleWithData;
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Chunk/ChunkProperties.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Utilities;
2 | using Unity.Mathematics;
3 | using UnityEngine;
4 |
5 | namespace Eldemarkki.VoxelTerrain.World.Chunks
6 | {
7 | ///
8 | /// A class that contains properties for a chunk
9 | ///
10 | public class ChunkProperties
11 | {
12 | ///
13 | /// The game object that corresponds to these properties
14 | ///
15 | public GameObject ChunkGameObject { get; set; }
16 | public MeshFilter MeshFilter { get; set; }
17 | public MeshCollider MeshCollider { get; set; }
18 | public MeshRenderer MeshRenderer { get; set; }
19 |
20 | public int3 ChunkCoordinate { get; set; }
21 |
22 | ///
23 | /// Has the voxel data of this chunk been changed during the last frame
24 | ///
25 | public bool HasChanges { get; set; }
26 | public bool IsMeshGenerated { get; set; }
27 |
28 | ///
29 | /// Initializes the chunk's properties.
30 | ///
31 | /// The coordinate of this chunk
32 | /// The size of this chunk
33 | public void Initialize(int3 chunkCoordinate, int3 chunkSize)
34 | {
35 | #if UNITY_EDITOR
36 | ChunkGameObject.name = GetName(chunkCoordinate);
37 | #endif
38 | ChunkGameObject.transform.position = (chunkCoordinate * chunkSize).ToVectorInt();
39 | ChunkCoordinate = chunkCoordinate;
40 |
41 | IsMeshGenerated = false;
42 | HasChanges = false;
43 | }
44 |
45 | ///
46 | /// Generates a chunk name from a chunk coordinate
47 | ///
48 | /// The coordinate of the chunk
49 | /// The name of the chunk
50 | public static string GetName(int3 chunkCoordinate)
51 | {
52 | return $"Chunk_{chunkCoordinate.x}_{chunkCoordinate.y}_{chunkCoordinate.z}";
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/VoxelData/VoxelDataGenerator.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Utilities;
2 | using Unity.Collections;
3 | using Unity.Mathematics;
4 | using UnityEngine;
5 |
6 | namespace Eldemarkki.VoxelTerrain.VoxelData
7 | {
8 | ///
9 | /// A base class for all voxel data generators
10 | ///
11 | public abstract class VoxelDataGenerator : MonoBehaviour
12 | {
13 | ///
14 | /// Starts generating the voxel data for a specified volume with a persistent allocator
15 | ///
16 | /// The world-space volume to generate the voxel data for
17 | /// The job handle and the voxel data generation job
18 | public JobHandleWithData GenerateVoxelData(BoundsInt bounds)
19 | {
20 | return GenerateVoxelData(bounds, Allocator.Persistent);
21 | }
22 |
23 | ///
24 | /// Starts generating the voxel data for a specified volume
25 | ///
26 | /// The world-space volume to generate the voxel data for
27 | /// The allocator for the new voxel data array
28 | /// The job handle and the voxel data generation job
29 | public JobHandleWithData GenerateVoxelData(BoundsInt bounds, Allocator allocator)
30 | {
31 | VoxelDataVolume voxelDataArray = new VoxelDataVolume(bounds.size, allocator);
32 | int3 worldSpaceOrigin = bounds.min.ToInt3();
33 | return GenerateVoxelData(worldSpaceOrigin, voxelDataArray);
34 | }
35 |
36 | ///
37 | /// Starts generating the voxel data for the given volume, where the origin of the volume is at
38 | ///
39 | /// The world space origin of
40 | /// The volume where the new voxel data should be generated to
41 | /// The job handle and the voxel data generation job
42 | public abstract JobHandleWithData GenerateVoxelData(int3 worldSpaceOrigin, VoxelDataVolume outputVoxelDataArray);
43 | }
44 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/World/HeightmapWorldGenerator.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Settings;
2 | using Unity.Mathematics;
3 | using UnityEngine;
4 |
5 | namespace Eldemarkki.VoxelTerrain.World
6 | {
7 | ///
8 | /// A world generated from a heightmap
9 | ///
10 | public class HeightmapWorldGenerator : MonoBehaviour
11 | {
12 | ///
13 | /// The voxel world the "owns" this world generator
14 | ///
15 | [SerializeField] private VoxelWorld voxelWorld;
16 |
17 | ///
18 | /// The settings for generating the heightmap terrain
19 | ///
20 | [SerializeField] private HeightmapTerrainSettings heightmapTerrainSettings;
21 |
22 | ///
23 | /// The settings for generating the heightmap terrain
24 | ///
25 | public HeightmapTerrainSettings HeightmapTerrainSettings => heightmapTerrainSettings;
26 |
27 | private void Awake()
28 | {
29 | heightmapTerrainSettings.Initialize(heightmapTerrainSettings.Heightmap, heightmapTerrainSettings.Amplitude, heightmapTerrainSettings.HeightOffset);
30 | }
31 |
32 | private void Start()
33 | {
34 | CreateHeightmapTerrainImmediate();
35 | }
36 |
37 | private void OnDestroy()
38 | {
39 | heightmapTerrainSettings.Dispose();
40 | }
41 |
42 | ///
43 | /// Creates the heightmap terrain and loads the chunks.
44 | ///
45 | private void CreateHeightmapTerrainImmediate()
46 | {
47 | int chunkCountX = (int)math.ceil((float)(heightmapTerrainSettings.Width - 1) / voxelWorld.WorldSettings.ChunkSize.x);
48 | int chunkCountZ = (int)math.ceil((float)(heightmapTerrainSettings.Height - 1) / voxelWorld.WorldSettings.ChunkSize.z);
49 | int chunkCountY = (int)math.ceil(heightmapTerrainSettings.Amplitude / voxelWorld.WorldSettings.ChunkSize.y);
50 |
51 | for (int x = 0; x < chunkCountX; x++)
52 | {
53 | for (int y = 0; y < chunkCountY; y++)
54 | {
55 | for (int z = 0; z < chunkCountZ; z++)
56 | {
57 | voxelWorld.ChunkProvider.CreateLoadedChunkToCoordinateImmediate(new int3(x, y, z));
58 | }
59 | }
60 | }
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Chunk/ChunkProvider.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Utilities;
2 | using Unity.Mathematics;
3 | using UnityEngine;
4 |
5 | namespace Eldemarkki.VoxelTerrain.World.Chunks
6 | {
7 | ///
8 | /// A class for providing chunks to the world
9 | ///
10 | public class ChunkProvider : MonoBehaviour
11 | {
12 | ///
13 | /// The world for which to provide chunks for
14 | ///
15 | public VoxelWorld VoxelWorld { get; set; }
16 |
17 | ///
18 | /// Instantiates a chunk to and initializes it, but does not generate its mesh
19 | ///
20 | /// The chunk's coordinate
21 | /// The new chunk
22 | protected ChunkProperties CreateUnloadedChunkToCoordinate(int3 chunkCoordinate)
23 | {
24 | int3 worldPosition = chunkCoordinate * VoxelWorld.WorldSettings.ChunkSize;
25 | GameObject chunkGameObject = Instantiate(VoxelWorld.WorldSettings.ChunkPrefab, worldPosition.ToVectorInt(), Quaternion.identity);
26 |
27 | ChunkProperties chunkProperties = new ChunkProperties
28 | {
29 | ChunkGameObject = chunkGameObject,
30 | MeshCollider = chunkGameObject.GetComponent(),
31 | MeshFilter = chunkGameObject.GetComponent(),
32 | MeshRenderer = chunkGameObject.GetComponent()
33 | };
34 |
35 | chunkProperties.Initialize(chunkCoordinate, VoxelWorld.WorldSettings.ChunkSize);
36 |
37 | VoxelWorld.ChunkStore.AddChunk(chunkCoordinate, chunkProperties);
38 |
39 | return chunkProperties;
40 | }
41 |
42 | ///
43 | /// Instantiates a chunk to , initializes it and generates its mesh
44 | ///
45 | /// The coordinate of the chunk to create
46 | /// The new chunk
47 | public ChunkProperties CreateLoadedChunkToCoordinateImmediate(int3 chunkCoordinate)
48 | {
49 | ChunkProperties chunkProperties = CreateUnloadedChunkToCoordinate(chunkCoordinate);
50 | VoxelWorld.ChunkUpdater.GenerateVoxelDataAndMeshImmediate(chunkProperties);
51 | return chunkProperties;
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/IndexUtilities.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 | using Unity.Mathematics;
3 |
4 | namespace Eldemarkki.VoxelTerrain.Utilities
5 | {
6 | public static class IndexUtilities
7 | {
8 | ///
9 | /// Converts a 3D location to a 1D index
10 | ///
11 | /// The position of the point
12 | /// The size of the "container" in the x-direction
13 | /// The size of the "container" in the y-direction
14 | /// The 1D representation of the specified location in the "container"
15 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
16 | public static int XyzToIndex(int3 xyz, int width, int height)
17 | {
18 | return XyzToIndex(xyz.x, xyz.y, xyz.z, width, height);
19 | }
20 |
21 | ///
22 | /// Converts a 3D location to a 1D index
23 | ///
24 | /// The x value of the location
25 | /// The y value of the location
26 | /// The z value of the location
27 | /// The size of the "container" in the x-direction
28 | /// The size of the "container" in the y-direction
29 | /// The 1D representation of the specified location in the "container"
30 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
31 | public static int XyzToIndex(int x, int y, int z, int width, int height)
32 | {
33 | return z * width * height + y * width + x;
34 | }
35 |
36 |
37 | ///
38 | /// Converts a 1D index to a 3D location
39 | ///
40 | /// The 1D index in the "container"
41 | /// The size of the "container" in the x-direction
42 | /// The size of the "container" in the y-direction
43 | /// The 3D representation of the specified index in the "container"
44 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
45 | public static int3 IndexToXyz(int index, int width, int height)
46 | {
47 | int3 position = new int3(
48 | index % width,
49 | index / width % height,
50 | index / (width * height));
51 | return position;
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/Intersection/IntersectionUtilities.cs:
--------------------------------------------------------------------------------
1 | using Unity.Mathematics;
2 | using UnityEngine;
3 |
4 | namespace Eldemarkki.VoxelTerrain.Utilities.Intersection
5 | {
6 | ///
7 | /// A utilities class for different kinds of geometric intersections
8 | ///
9 | public static class IntersectionUtilities
10 | {
11 | ///
12 | /// Intersects a plane with a line
13 | ///
14 | /// The origin of the plane
15 | /// The normal of the plane
16 | /// The origin of the line
17 | /// The direction of the line
18 | /// The point where the line hit the plane (if any)
19 | /// The collision result
20 | public static PlaneLineIntersectionResult PlaneLineIntersection(float3 planeOrigin, float3 planeNormal, float3 lineOrigin,
21 | float3 lineDirection, out float3 intersectionPoint)
22 | {
23 | planeNormal = math.normalize(planeNormal);
24 | lineDirection = math.normalize(lineDirection);
25 |
26 | if (math.dot(planeNormal, lineDirection) == 0)
27 | {
28 | intersectionPoint = float3.zero;
29 | return (planeOrigin - lineOrigin).Equals(float3.zero) ? PlaneLineIntersectionResult.ParallelInsidePlane : PlaneLineIntersectionResult.NoHit;
30 | }
31 |
32 | float d = math.dot(planeOrigin, -planeNormal);
33 | float t = -(d + lineOrigin.z * planeNormal.z + lineOrigin.y * planeNormal.y + lineOrigin.x * planeNormal.x) / (lineDirection.z * planeNormal.z + lineDirection.y * planeNormal.y + lineDirection.x * planeNormal.x);
34 | intersectionPoint = lineOrigin + t * lineDirection;
35 | return PlaneLineIntersectionResult.OneHit;
36 | }
37 |
38 | ///
39 | /// Gets the volume where the bounds intersect
40 | ///
41 | /// The first bounds
42 | /// The second bounds
43 | /// The volume that is contained in both bounds
44 | public static BoundsInt GetIntersectionVolume(BoundsInt a, BoundsInt b)
45 | {
46 | int3 min = math.max(a.min.ToInt3(), b.min.ToInt3());
47 | int3 max = math.min(a.max.ToInt3(), b.max.ToInt3());
48 |
49 | int3 size = max - min;
50 | return new BoundsInt(min.ToVectorInt(), size.ToVectorInt());
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/ProjectSettings/GraphicsSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!30 &1
4 | GraphicsSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 12
7 | m_Deferred:
8 | m_Mode: 1
9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0}
10 | m_DeferredReflections:
11 | m_Mode: 1
12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0}
13 | m_ScreenSpaceShadows:
14 | m_Mode: 1
15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0}
16 | m_LegacyDeferred:
17 | m_Mode: 1
18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0}
19 | m_DepthNormals:
20 | m_Mode: 1
21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0}
22 | m_MotionVectors:
23 | m_Mode: 1
24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0}
25 | m_LightHalo:
26 | m_Mode: 1
27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0}
28 | m_LensFlare:
29 | m_Mode: 1
30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0}
31 | m_AlwaysIncludedShaders:
32 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0}
33 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0}
34 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0}
35 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0}
36 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
37 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
38 | - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0}
39 | - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0}
40 | - {fileID: 16001, guid: 0000000000000000f000000000000000, type: 0}
41 | - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0}
42 | m_PreloadedShaders: []
43 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000,
44 | type: 0}
45 | m_CustomRenderPipeline: {fileID: 0}
46 | m_TransparencySortMode: 0
47 | m_TransparencySortAxis: {x: 0, y: 0, z: 1}
48 | m_DefaultRenderingPath: 1
49 | m_DefaultMobileRenderingPath: 1
50 | m_TierSettings: []
51 | m_LightmapStripping: 0
52 | m_FogStripping: 0
53 | m_InstancingStripping: 0
54 | m_LightmapKeepPlain: 1
55 | m_LightmapKeepDirCombined: 1
56 | m_LightmapKeepDynamicPlain: 1
57 | m_LightmapKeepDynamicDirCombined: 1
58 | m_LightmapKeepShadowMask: 1
59 | m_LightmapKeepSubtractive: 1
60 | m_FogKeepLinear: 1
61 | m_FogKeepExp: 1
62 | m_FogKeepExp2: 1
63 | m_AlbedoSwatchInfos: []
64 | m_LightsUseLinearIntensity: 0
65 | m_LightsUseColorTemperature: 0
66 |
--------------------------------------------------------------------------------
/Assets/Materials/Triplanar Shading.mat:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!21 &2100000
4 | Material:
5 | serializedVersion: 6
6 | m_ObjectHideFlags: 0
7 | m_CorrespondingSourceObject: {fileID: 0}
8 | m_PrefabInstance: {fileID: 0}
9 | m_PrefabAsset: {fileID: 0}
10 | m_Name: Triplanar Shading
11 | m_Shader: {fileID: 4800000, guid: db8c18db5cb480d4c8523e1b745f5af5, type: 3}
12 | m_ShaderKeywords:
13 | m_LightmapFlags: 4
14 | m_EnableInstancingVariants: 0
15 | m_DoubleSidedGI: 0
16 | m_CustomRenderQueue: -1
17 | stringTagMap: {}
18 | disabledShaderPasses: []
19 | m_SavedProperties:
20 | serializedVersion: 3
21 | m_TexEnvs:
22 | - Tex1:
23 | m_Texture: {fileID: 2800000, guid: 2fdf9aa38a68a274cbfa7b62d7a8841b, type: 3}
24 | m_Scale: {x: 0.1, y: 0.1}
25 | m_Offset: {x: 0, y: 0}
26 | - Tex2:
27 | m_Texture: {fileID: 2800000, guid: c6bd348a701e4904097c86dc74e1ea0d, type: 3}
28 | m_Scale: {x: 0.1, y: 0.1}
29 | m_Offset: {x: 0, y: 0}
30 | - Tex3:
31 | m_Texture: {fileID: 2800000, guid: 2fdf9aa38a68a274cbfa7b62d7a8841b, type: 3}
32 | m_Scale: {x: 0.1, y: 0.1}
33 | m_Offset: {x: 0, y: 0}
34 | - Texture2D_1B8FCD66:
35 | m_Texture: {fileID: 2800000, guid: c6bd348a701e4904097c86dc74e1ea0d, type: 3}
36 | m_Scale: {x: 1, y: 1}
37 | m_Offset: {x: 0, y: 0}
38 | - Texture2D_2C986A40:
39 | m_Texture: {fileID: 2800000, guid: 2fdf9aa38a68a274cbfa7b62d7a8841b, type: 3}
40 | m_Scale: {x: 1, y: 1}
41 | m_Offset: {x: 0, y: 0}
42 | - Texture2D_35130819:
43 | m_Texture: {fileID: 2800000, guid: 2fdf9aa38a68a274cbfa7b62d7a8841b, type: 3}
44 | m_Scale: {x: 1, y: 1}
45 | m_Offset: {x: 0, y: 0}
46 | - _XTexture:
47 | m_Texture: {fileID: 2800000, guid: 2fdf9aa38a68a274cbfa7b62d7a8841b, type: 3}
48 | m_Scale: {x: 1, y: 1}
49 | m_Offset: {x: 0, y: 0}
50 | - _YTexture:
51 | m_Texture: {fileID: 2800000, guid: c6bd348a701e4904097c86dc74e1ea0d, type: 3}
52 | m_Scale: {x: 1, y: 1}
53 | m_Offset: {x: 0, y: 0}
54 | - _ZTexture:
55 | m_Texture: {fileID: 2800000, guid: 2fdf9aa38a68a274cbfa7b62d7a8841b, type: 3}
56 | m_Scale: {x: 1, y: 1}
57 | m_Offset: {x: 0, y: 0}
58 | m_Floats:
59 | - YColorAmount: 1
60 | - _Glossiness: 0
61 | - _Metallic: 0
62 | m_Colors:
63 | - NegativeYColor: {r: 0.3490566, g: 0.22091156, b: 0.09055714, a: 1}
64 | - XColor: {r: 0.5849056, g: 0.35697895, b: 0.124154516, a: 1}
65 | - YColor: {r: 0.21813813, g: 0.8113208, b: 0.3686471, a: 1}
66 | - ZColor: {r: 0.5849056, g: 0.35697892, b: 0.124154486, a: 1}
67 | - _TintColor: {r: 1, g: 1, b: 1, a: 1}
68 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/Chunk/ProceduralChunkProvider.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.World.Chunks;
2 | using System.Collections.Generic;
3 | using Unity.Mathematics;
4 | using UnityEngine;
5 |
6 | namespace Eldemarkki.VoxelTerrain.Chunks
7 | {
8 | ///
9 | /// Provider for procedurally generated chunks
10 | ///
11 | public class ProceduralChunkProvider : ChunkProvider
12 | {
13 | ///
14 | /// The maximum amount of chunks that can be generated in one frame
15 | ///
16 | [SerializeField] private int chunkGenerationRate = 10;
17 |
18 | ///
19 | /// A queue that contains all the coordinates where a chunk will eventually have to be generated
20 | ///
21 | private Queue _generationQueue;
22 |
23 | private void Awake()
24 | {
25 | _generationQueue = new Queue();
26 | }
27 |
28 | private void Update()
29 | {
30 | int chunksGenerated = 0;
31 | while (_generationQueue.Count > 0 && chunksGenerated < chunkGenerationRate)
32 | {
33 | int3 chunkCoordinate = _generationQueue.Dequeue();
34 |
35 | if (VoxelWorld.ChunkStore.TryGetDataChunk(chunkCoordinate, out ChunkProperties chunkProperties))
36 | {
37 | if (!chunkProperties.IsMeshGenerated)
38 | {
39 | VoxelWorld.ChunkUpdater.GenerateVoxelDataAndMeshImmediate(chunkProperties);
40 | chunksGenerated++;
41 | }
42 | }
43 | }
44 | }
45 |
46 | ///
47 | /// Ensures that a chunk exists at a coordinate, if there is not, a new chunk is instantiated there, and its will eventually be generated
48 | ///
49 | /// The chunk's coordinate
50 | public void EnsureChunkExistsAtCoordinate(int3 chunkCoordinate)
51 | {
52 | if (!VoxelWorld.ChunkStore.DoesChunkExistAtCoordinate(chunkCoordinate))
53 | {
54 | CreateUnloadedChunkToCoordinate(chunkCoordinate);
55 | AddChunkToGenerationQueue(chunkCoordinate);
56 | }
57 | }
58 |
59 | ///
60 | /// Adds the coordinate to the list of chunks that will eventually have to be generated
61 | ///
62 | ///
63 | public void AddChunkToGenerationQueue(int3 chunkCoordinate)
64 | {
65 | _generationQueue.Enqueue(chunkCoordinate);
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/XyzToIndexTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using Unity.Mathematics;
3 |
4 | namespace Eldemarkki.VoxelTerrain.Utilities.Tests
5 | {
6 | public class XyzToIndexTests
7 | {
8 | private static void TestXyzToIndex_Using_int3(int3 xyz, int expectedIndex, int width, int height)
9 | {
10 | int actualIndex = IndexUtilities.XyzToIndex(xyz, width, height);
11 | Assert.AreEqual(expectedIndex, actualIndex);
12 | }
13 |
14 | private static void TestXyzToIndex_Using_int_xyz(int x, int y, int z, int expectedIndex, int width, int height)
15 | {
16 | int actualIndex = IndexUtilities.XyzToIndex(x, y, z, width, height);
17 | Assert.AreEqual(expectedIndex, actualIndex);
18 | }
19 |
20 | [TestCaseSource(nameof(Width_1_Height_5_Cases))]
21 | public void Width_1_Height_5_Using_int3(int x, int y, int z, int expectedIndex)
22 | {
23 | TestXyzToIndex_Using_int3(new int3(x, y, z), expectedIndex, 1, 5);
24 | }
25 |
26 | [TestCaseSource(nameof(Width_2_Height_5_Cases))]
27 | public void Width_2_Height_5_Using_int3(int x, int y, int z, int expectedIndex)
28 | {
29 | TestXyzToIndex_Using_int3(new int3(x, y, z), expectedIndex, 2, 5);
30 | }
31 |
32 | [TestCaseSource(nameof(Width_1_Height_5_Cases))]
33 | public void Width_1_Height_5_Using_int_xyz(int x, int y, int z, int expectedIndex)
34 | {
35 | TestXyzToIndex_Using_int_xyz(x, y, z, expectedIndex, 1, 5);
36 | }
37 |
38 | [TestCaseSource(nameof(Width_2_Height_5_Cases))]
39 | public void Width_2_Height_5_Using_int_xyz(int x, int y, int z, int expectedIndex)
40 | {
41 | TestXyzToIndex_Using_int_xyz(x, y, z, expectedIndex, 2, 5);
42 | }
43 |
44 | static object[] Width_1_Height_5_Cases =
45 | {
46 | new object[] { 0, 1, 0, 1 },
47 | new object[] { 0, 2, 0, 2 },
48 | new object[] { 0, 2, 0, 2 },
49 | new object[] { 0, 3, 0, 3 },
50 | new object[] { 0, 4, 0, 4 },
51 | new object[] { 0, 0, 1, 5 }
52 | };
53 |
54 | static object[] Width_2_Height_5_Cases =
55 | {
56 | new object[] { 1, 0, 0, 1 },
57 | new object[] { 0, 1, 0, 2 },
58 | new object[] { 1, 1, 0, 3 },
59 | new object[] { 0, 2, 0, 4 },
60 | new object[] { 0, 0, 1, 10 },
61 | new object[] { 1, 0, 1, 11 },
62 | new object[] { 0, 1, 1, 12 },
63 | new object[] { 1, 1, 1, 13 },
64 | new object[] { 0, 0, 2, 20 },
65 | new object[] { 0, 0, 3, 30 },
66 | new object[] { 1, 1, 3, 33 }
67 | };
68 | }
69 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/TerrainSettings/ProceduralTerrainSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 |
4 | namespace Eldemarkki.VoxelTerrain.Settings
5 | {
6 | ///
7 | /// The procedural terrain generation settings
8 | ///
9 | [Serializable]
10 | public struct ProceduralTerrainSettings
11 | {
12 | ///
13 | [SerializeField] private float noiseFrequency;
14 |
15 | ///
16 | [SerializeField] private int noiseOctaveCount;
17 |
18 | ///
19 | [SerializeField] private float amplitude;
20 |
21 | ///
22 | [SerializeField] private float heightOffset;
23 |
24 | ///
25 | [SerializeField] private int noiseSeed;
26 |
27 | ///
28 | /// The frequency of the noise
29 | ///
30 | public float NoiseFrequency { get => noiseFrequency; set => noiseFrequency = value; }
31 |
32 | ///
33 | /// How many octaves the noise will have
34 | ///
35 | public int NoiseOctaveCount { get => noiseOctaveCount; set => noiseOctaveCount = value; }
36 |
37 | ///
38 | /// The height multiplier
39 | ///
40 | public float Amplitude { get => amplitude; set => amplitude = value; }
41 |
42 | ///
43 | /// Moves the height up and down
44 | ///
45 | public float HeightOffset { get => heightOffset; set => heightOffset = value; }
46 |
47 | ///
48 | /// The seed that the noise function will be initialized with
49 | ///
50 | public int NoiseSeed { get => noiseSeed; set => noiseSeed = value; }
51 |
52 | ///
53 | /// Constructor
54 | ///
55 | /// The frequency of the noise
56 | /// How many octaves the noise will have
57 | /// The height multiplier
58 | /// Moves the height up and down
59 | /// The seed that the noise function will be initialized with
60 | public ProceduralTerrainSettings(float noiseFrequency, int noiseOctaveCount, float amplitude, float heightOffset, int noiseSeed)
61 | {
62 | this.noiseFrequency = noiseFrequency;
63 | this.noiseOctaveCount = noiseOctaveCount;
64 | this.amplitude = amplitude;
65 | this.heightOffset = heightOffset;
66 | this.noiseSeed = noiseSeed;
67 | }
68 | }
69 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/Meshing/MarchingCubes/MarchingCubesMesher.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Meshing.Data;
2 | using Eldemarkki.VoxelTerrain.VoxelData;
3 | using Eldemarkki.VoxelTerrain.Utilities;
4 | using Unity.Collections;
5 | using Unity.Jobs;
6 | using Unity.Mathematics;
7 | using UnityEngine;
8 |
9 | namespace Eldemarkki.VoxelTerrain.Meshing.MarchingCubes
10 | {
11 | ///
12 | /// A mesher for the marching cubes algorithm
13 | ///
14 | public class MarchingCubesMesher : VoxelMesher
15 | {
16 | ///
17 | [SerializeField, Range(0, 1)] private float isolevel = 0.5f;
18 |
19 | ///
20 | /// The density level where a surface will be created. Densities below this will be inside the surface (solid),
21 | /// and densities above this will be outside the surface (air)
22 | ///
23 | public float Isolevel => isolevel;
24 |
25 | ///
26 | public override JobHandleWithData CreateMesh(VoxelDataStore voxelDataStore, VoxelColorStore voxelColorStore, int3 chunkCoordinate)
27 | {
28 | if (!voxelDataStore.TryGetDataChunk(chunkCoordinate, out VoxelDataVolume boundsVoxelData))
29 | {
30 | return null;
31 | }
32 |
33 | if (!voxelColorStore.TryGetDataChunk(chunkCoordinate, out VoxelDataVolume boundsVoxelColors))
34 | {
35 | return null;
36 | }
37 |
38 | NativeCounter vertexCountCounter = new NativeCounter(Allocator.TempJob);
39 |
40 | int voxelCount = VoxelWorld.WorldSettings.ChunkSize.x * VoxelWorld.WorldSettings.ChunkSize.y * VoxelWorld.WorldSettings.ChunkSize.z;
41 | int maxLength = 15 * voxelCount;
42 |
43 | NativeArray outputVertices = new NativeArray(maxLength, Allocator.TempJob);
44 | NativeArray outputTriangles = new NativeArray(maxLength, Allocator.TempJob);
45 |
46 | MarchingCubesJob marchingCubesJob = new MarchingCubesJob
47 | {
48 | VoxelData = boundsVoxelData,
49 | VoxelColors = boundsVoxelColors,
50 | Isolevel = Isolevel,
51 | VertexCountCounter = vertexCountCounter,
52 |
53 | OutputVertices = outputVertices,
54 | OutputTriangles = outputTriangles
55 | };
56 |
57 | JobHandle jobHandle = marchingCubesJob.Schedule();
58 |
59 | JobHandleWithData jobHandleWithData = new JobHandleWithData
60 | {
61 | JobHandle = jobHandle,
62 | JobData = marchingCubesJob
63 | };
64 |
65 | return jobHandleWithData;
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/GetIntersectionAreaTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using UnityEngine;
3 |
4 | namespace Eldemarkki.VoxelTerrain.Utilities.Intersection.Tests
5 | {
6 | public class GetIntersectionVolumeTests
7 | {
8 | private static void TestIntersection(Vector3Int aPosition, Vector3Int aSize, Vector3Int bPosition, Vector3Int bSize, Vector3Int expectedPosition, Vector3Int expectedSize)
9 | {
10 | BoundsInt a = new BoundsInt(aPosition, aSize);
11 | BoundsInt b = new BoundsInt(bPosition, bSize);
12 | BoundsInt expected = new BoundsInt(expectedPosition, expectedSize);
13 |
14 | string message = $"Test failed with objects {a} and {b}. Expected {expected}";
15 |
16 | BoundsInt intersection = IntersectionUtilities.GetIntersectionVolume(a, b);
17 | Assert.AreEqual(expected, intersection, "Regular: " + message);
18 |
19 | BoundsInt intersectionSwapped = IntersectionUtilities.GetIntersectionVolume(b, a);
20 | Assert.AreEqual(expected, intersectionSwapped, "Swapped: " + message);
21 | }
22 |
23 | [Test]
24 | public void Bounds_Are_Same_Should_Return_Same()
25 | {
26 | Vector3Int position = new Vector3Int(41, 24, 85);
27 | Vector3Int size = new Vector3Int(48, 26, 23);
28 |
29 | TestIntersection(position, size,
30 | position, size,
31 | position, size);
32 | }
33 |
34 | [Test]
35 | public void Test1()
36 | {
37 | TestIntersection(new Vector3Int(-2, -2, -2), new Vector3Int(4, 4, 4),
38 | new Vector3Int(0, 0, 0), new Vector3Int(4, 4, 4),
39 | new Vector3Int(0, 0, 0), new Vector3Int(2, 2, 2));
40 | }
41 |
42 | [Test]
43 | public void Test2()
44 | {
45 | TestIntersection(new Vector3Int(-3, -1, -1), new Vector3Int(5, 8, 4),
46 | new Vector3Int(0, 4, 2), new Vector3Int(1, 5, 3),
47 | new Vector3Int(0, 4, 2), new Vector3Int(1, 3, 1));
48 | }
49 |
50 | [Test]
51 | public void Test3()
52 | {
53 | TestIntersection(new Vector3Int(-12, -12, -12), new Vector3Int(4, 4, 4),
54 | new Vector3Int(-8, -8, -8), new Vector3Int(16, 16, 16),
55 | new Vector3Int(-8, -8, -8), new Vector3Int(0, 0, 0));
56 | }
57 |
58 | [Test]
59 | public void Test4()
60 | {
61 | TestIntersection(new Vector3Int(-12, -12, -12), new Vector3Int(4, 4, 4),
62 | new Vector3Int(-9, -9, -9), new Vector3Int(16, 16, 16),
63 | new Vector3Int(-9, -9, -9), new Vector3Int(1, 1, 1));
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Assets/Prefabs/Chunk.prefab:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!1 &1042568357287805991
4 | GameObject:
5 | m_ObjectHideFlags: 0
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | serializedVersion: 6
10 | m_Component:
11 | - component: {fileID: 8302165401843338731}
12 | - component: {fileID: 773550656402152373}
13 | - component: {fileID: 8131520927842024086}
14 | - component: {fileID: 7519686632171402987}
15 | m_Layer: 0
16 | m_Name: Chunk
17 | m_TagString: Untagged
18 | m_Icon: {fileID: 0}
19 | m_NavMeshLayer: 0
20 | m_StaticEditorFlags: 0
21 | m_IsActive: 1
22 | --- !u!4 &8302165401843338731
23 | Transform:
24 | m_ObjectHideFlags: 0
25 | m_CorrespondingSourceObject: {fileID: 0}
26 | m_PrefabInstance: {fileID: 0}
27 | m_PrefabAsset: {fileID: 0}
28 | m_GameObject: {fileID: 1042568357287805991}
29 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
30 | m_LocalPosition: {x: 0, y: 0, z: 0}
31 | m_LocalScale: {x: 1, y: 1, z: 1}
32 | m_Children: []
33 | m_Father: {fileID: 0}
34 | m_RootOrder: 0
35 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
36 | --- !u!23 &773550656402152373
37 | MeshRenderer:
38 | m_ObjectHideFlags: 0
39 | m_CorrespondingSourceObject: {fileID: 0}
40 | m_PrefabInstance: {fileID: 0}
41 | m_PrefabAsset: {fileID: 0}
42 | m_GameObject: {fileID: 1042568357287805991}
43 | m_Enabled: 1
44 | m_CastShadows: 1
45 | m_ReceiveShadows: 1
46 | m_DynamicOccludee: 1
47 | m_MotionVectors: 1
48 | m_LightProbeUsage: 1
49 | m_ReflectionProbeUsage: 1
50 | m_RayTracingMode: 2
51 | m_RenderingLayerMask: 1
52 | m_RendererPriority: 0
53 | m_Materials:
54 | - {fileID: 2100000, guid: 6f4ec41ce043e2940a19224905527b38, type: 2}
55 | m_StaticBatchInfo:
56 | firstSubMesh: 0
57 | subMeshCount: 0
58 | m_StaticBatchRoot: {fileID: 0}
59 | m_ProbeAnchor: {fileID: 0}
60 | m_LightProbeVolumeOverride: {fileID: 0}
61 | m_ScaleInLightmap: 1
62 | m_ReceiveGI: 1
63 | m_PreserveUVs: 0
64 | m_IgnoreNormalsForChartDetection: 0
65 | m_ImportantGI: 0
66 | m_StitchLightmapSeams: 1
67 | m_SelectedEditorRenderState: 3
68 | m_MinimumChartSize: 4
69 | m_AutoUVMaxDistance: 0.5
70 | m_AutoUVMaxAngle: 89
71 | m_LightmapParameters: {fileID: 0}
72 | m_SortingLayerID: 0
73 | m_SortingLayer: 0
74 | m_SortingOrder: 0
75 | --- !u!33 &8131520927842024086
76 | MeshFilter:
77 | m_ObjectHideFlags: 0
78 | m_CorrespondingSourceObject: {fileID: 0}
79 | m_PrefabInstance: {fileID: 0}
80 | m_PrefabAsset: {fileID: 0}
81 | m_GameObject: {fileID: 1042568357287805991}
82 | m_Mesh: {fileID: 0}
83 | --- !u!64 &7519686632171402987
84 | MeshCollider:
85 | m_ObjectHideFlags: 0
86 | m_CorrespondingSourceObject: {fileID: 0}
87 | m_PrefabInstance: {fileID: 0}
88 | m_PrefabAsset: {fileID: 0}
89 | m_GameObject: {fileID: 1042568357287805991}
90 | m_Material: {fileID: 0}
91 | m_IsTrigger: 0
92 | m_Enabled: 1
93 | serializedVersion: 4
94 | m_Convex: 0
95 | m_CookingOptions: 30
96 | m_Mesh: {fileID: 0}
97 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Chunk/ChunkUpdater.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Meshing;
2 | using Eldemarkki.VoxelTerrain.Meshing.Data;
3 | using Eldemarkki.VoxelTerrain.Utilities;
4 | using UnityEngine;
5 | using UnityEngine.Rendering;
6 |
7 | namespace Eldemarkki.VoxelTerrain.World.Chunks
8 | {
9 | public class ChunkUpdater : MonoBehaviour
10 | {
11 | ///
12 | /// The world for which to provide chunks for
13 | ///
14 | public VoxelWorld VoxelWorld { get; set; }
15 |
16 | private void Update()
17 | {
18 | foreach (ChunkProperties chunkProperties in VoxelWorld.ChunkStore.Chunks)
19 | {
20 | if (chunkProperties.HasChanges)
21 | {
22 | GenerateMeshImmediate(chunkProperties);
23 | }
24 | }
25 | }
26 |
27 | ///
28 | /// Generates the voxel data and colors for this chunk and generates the mesh
29 | ///
30 | public void GenerateVoxelDataAndMeshImmediate(ChunkProperties chunkProperties)
31 | {
32 | VoxelWorld.VoxelDataStore.GenerateDataForChunk(chunkProperties.ChunkCoordinate);
33 | VoxelWorld.VoxelColorStore.GenerateDataForChunk(chunkProperties.ChunkCoordinate);
34 | GenerateMeshImmediate(chunkProperties);
35 | }
36 |
37 | ///
38 | /// Forces the regeneration of the mesh
39 | ///
40 | public void GenerateMeshImmediate(ChunkProperties chunkProperties)
41 | {
42 | JobHandleWithData jobHandleWithData = VoxelWorld.VoxelMesher.CreateMesh(VoxelWorld.VoxelDataStore, VoxelWorld.VoxelColorStore, chunkProperties.ChunkCoordinate);
43 | if (jobHandleWithData == null) { return; }
44 |
45 | IMesherJob job = jobHandleWithData.JobData;
46 |
47 | Mesh mesh = new Mesh();
48 | SubMeshDescriptor subMesh = new SubMeshDescriptor(0, 0);
49 |
50 | jobHandleWithData.JobHandle.Complete();
51 |
52 | int vertexCount = job.VertexCountCounter.Count * 3;
53 | job.VertexCountCounter.Dispose();
54 |
55 | mesh.SetVertexBufferParams(vertexCount, MeshingVertexData.VertexBufferMemoryLayout);
56 | mesh.SetIndexBufferParams(vertexCount, IndexFormat.UInt16);
57 |
58 | mesh.SetVertexBufferData(job.OutputVertices, 0, 0, vertexCount, 0, MeshUpdateFlags.DontValidateIndices);
59 | mesh.SetIndexBufferData(job.OutputTriangles, 0, 0, vertexCount, MeshUpdateFlags.DontValidateIndices);
60 |
61 | job.OutputVertices.Dispose();
62 | job.OutputTriangles.Dispose();
63 |
64 | mesh.subMeshCount = 1;
65 | subMesh.indexCount = vertexCount;
66 | mesh.SetSubMesh(0, subMesh);
67 |
68 | mesh.RecalculateBounds();
69 |
70 | chunkProperties.MeshFilter.sharedMesh = mesh;
71 | chunkProperties.MeshCollider.sharedMesh = mesh;
72 |
73 | chunkProperties.MeshCollider.enabled = true;
74 | chunkProperties.MeshRenderer.enabled = true;
75 |
76 | chunkProperties.HasChanges = false;
77 |
78 | chunkProperties.IsMeshGenerated = true;
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Assets/VertexColorMaterial.mat:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!21 &2100000
4 | Material:
5 | serializedVersion: 6
6 | m_ObjectHideFlags: 0
7 | m_CorrespondingSourceObject: {fileID: 0}
8 | m_PrefabInstance: {fileID: 0}
9 | m_PrefabAsset: {fileID: 0}
10 | m_Name: VertexColorMaterial
11 | m_Shader: {fileID: 210, guid: 0000000000000000f000000000000000, type: 0}
12 | m_ShaderKeywords:
13 | m_LightmapFlags: 0
14 | m_EnableInstancingVariants: 0
15 | m_DoubleSidedGI: 0
16 | m_CustomRenderQueue: -1
17 | stringTagMap: {}
18 | disabledShaderPasses:
19 | - ALWAYS
20 | m_SavedProperties:
21 | serializedVersion: 3
22 | m_TexEnvs:
23 | - _BumpMap:
24 | m_Texture: {fileID: 0}
25 | m_Scale: {x: 1, y: 1}
26 | m_Offset: {x: 0, y: 0}
27 | - _DetailAlbedoMap:
28 | m_Texture: {fileID: 0}
29 | m_Scale: {x: 1, y: 1}
30 | m_Offset: {x: 0, y: 0}
31 | - _DetailMask:
32 | m_Texture: {fileID: 0}
33 | m_Scale: {x: 1, y: 1}
34 | m_Offset: {x: 0, y: 0}
35 | - _DetailNormalMap:
36 | m_Texture: {fileID: 0}
37 | m_Scale: {x: 1, y: 1}
38 | m_Offset: {x: 0, y: 0}
39 | - _EmissionMap:
40 | m_Texture: {fileID: 0}
41 | m_Scale: {x: 1, y: 1}
42 | m_Offset: {x: 0, y: 0}
43 | - _MainTex:
44 | m_Texture: {fileID: 0}
45 | m_Scale: {x: 1, y: 1}
46 | m_Offset: {x: 0, y: 0}
47 | - _MetallicGlossMap:
48 | m_Texture: {fileID: 0}
49 | m_Scale: {x: 1, y: 1}
50 | m_Offset: {x: 0, y: 0}
51 | - _OcclusionMap:
52 | m_Texture: {fileID: 0}
53 | m_Scale: {x: 1, y: 1}
54 | m_Offset: {x: 0, y: 0}
55 | - _ParallaxMap:
56 | m_Texture: {fileID: 0}
57 | m_Scale: {x: 1, y: 1}
58 | m_Offset: {x: 0, y: 0}
59 | - _SpecGlossMap:
60 | m_Texture: {fileID: 0}
61 | m_Scale: {x: 1, y: 1}
62 | m_Offset: {x: 0, y: 0}
63 | m_Floats:
64 | - _BlendOp: 0
65 | - _BumpScale: 1
66 | - _CameraFadingEnabled: 0
67 | - _CameraFarFadeDistance: 2
68 | - _CameraNearFadeDistance: 1
69 | - _Cull: 2
70 | - _Cutoff: 0.5
71 | - _DetailNormalMapScale: 1
72 | - _DistortionBlend: 0.5
73 | - _DistortionEnabled: 0
74 | - _DistortionStrength: 1
75 | - _DistortionStrengthScaled: 0
76 | - _DstBlend: 0
77 | - _EmissionEnabled: 0
78 | - _FlipbookMode: 0
79 | - _GlossMapScale: 1
80 | - _Glossiness: 0.215
81 | - _GlossyReflections: 1
82 | - _LightingEnabled: 1
83 | - _Metallic: 0
84 | - _Mode: 0
85 | - _OcclusionStrength: 1
86 | - _Parallax: 0.02
87 | - _SmoothnessTextureChannel: 0
88 | - _SoftParticlesEnabled: 0
89 | - _SoftParticlesFarFadeDistance: 1
90 | - _SoftParticlesNearFadeDistance: 0
91 | - _SpecularHighlights: 1
92 | - _SrcBlend: 1
93 | - _UVSec: 0
94 | - _ZWrite: 1
95 | m_Colors:
96 | - _CameraFadeParams: {r: 0, g: Infinity, b: 0, a: 0}
97 | - _Color: {r: 1, g: 1, b: 1, a: 1}
98 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
99 | - _SoftParticleFadeParams: {r: 0, g: 0, b: 0, a: 0}
100 | - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
101 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/VoxelData/ProceduralTerrainVoxelDataCalculationJob.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 | using Eldemarkki.VoxelTerrain.Settings;
3 | using Unity.Burst;
4 | using Unity.Mathematics;
5 |
6 | namespace Eldemarkki.VoxelTerrain.VoxelData
7 | {
8 | ///
9 | /// A procedural terrain voxel data calculation job
10 | ///
11 | [BurstCompile]
12 | public struct ProceduralTerrainVoxelDataCalculationJob : IVoxelDataGenerationJob
13 | {
14 | ///
15 | /// The procedural terrain generation settings
16 | ///
17 | public ProceduralTerrainSettings ProceduralTerrainSettings { get; set; }
18 |
19 | ///
20 | public int3 WorldPositionOffset { get; set; }
21 |
22 | ///
23 | public VoxelDataVolume OutputVoxelData { get; set; }
24 |
25 | ///
26 | /// The execute method required for Unity's IJobParallelFor job type
27 | ///
28 | public void Execute()
29 | {
30 | for (int x = 0; x < OutputVoxelData.Width; x++)
31 | {
32 | for (int z = 0; z < OutputVoxelData.Depth; z++)
33 | {
34 | int2 terrainPosition = new int2(x + WorldPositionOffset.x, z + WorldPositionOffset.z);
35 | float terrainNoise = OctaveNoise(terrainPosition.x, terrainPosition.y, ProceduralTerrainSettings.NoiseFrequency * 0.001f, ProceduralTerrainSettings.NoiseOctaveCount, ProceduralTerrainSettings.NoiseSeed) * ProceduralTerrainSettings.Amplitude;
36 |
37 | for (int y = 0; y < OutputVoxelData.Height; y++)
38 | {
39 | int3 worldPosition = new int3(terrainPosition.x, y + WorldPositionOffset.y, terrainPosition.y);
40 |
41 | float voxelData = (worldPosition.y - ProceduralTerrainSettings.HeightOffset - terrainNoise) * 0.5f;
42 | OutputVoxelData.SetVoxelData((byte)math.clamp(voxelData * 255, 0, 255), new int3(x, y, z));
43 | }
44 | }
45 | }
46 | }
47 |
48 | ///
49 | /// Calculates octave noise
50 | ///
51 | /// Sampling point's x position
52 | /// Sampling point's y position
53 | /// The frequency of the noise
54 | /// How many layers of noise to combine
55 | /// The sampled noise value
56 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
57 | private static float OctaveNoise(float x, float y, float frequency, int octaveCount, int seed)
58 | {
59 | float value = 0;
60 |
61 | for (int i = 0; i < octaveCount; i++)
62 | {
63 | int octaveModifier = (int)math.pow(2, i);
64 |
65 | // (x+1)/2 because noise.snoise returns a value from -1 to 1 so it needs to be scaled to go from 0 to 1.
66 | float pureNoise = (noise.snoise(new float3(octaveModifier * x * frequency, octaveModifier * y * frequency, seed)) + 1) / 2f;
67 | value += pureNoise / octaveModifier;
68 | }
69 |
70 | return value;
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/UtilitiesTests/PlaneLineIntersectionTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using Unity.Mathematics;
3 |
4 | namespace Eldemarkki.VoxelTerrain.Utilities.Intersection.Tests
5 | {
6 | public class PlaneLineIntersectionTests
7 | {
8 | private static void TestPlaneLineIntersectionResult(float3 planeOrigin, float3 planeNormal, float3 lineOrigin, float3 lineDirection, PlaneLineIntersectionResult expected)
9 | {
10 | PlaneLineIntersectionResult result = IntersectionUtilities.PlaneLineIntersection(planeOrigin, math.normalize(planeNormal), lineOrigin, lineDirection, out _);
11 | Assert.AreEqual(expected, result);
12 | }
13 |
14 | private static void TestPlaneLineIntersectionPoint(float3 planeOrigin, float3 planeNormal, float3 lineOrigin, float3 lineDirection, float3 expected)
15 | {
16 | _ = IntersectionUtilities.PlaneLineIntersection(planeOrigin, planeNormal, lineOrigin, lineDirection, out float3 intersectionPoint);
17 | Assert.AreEqual(expected, intersectionPoint);
18 | }
19 |
20 | [Test]
21 | public void Line_Above_Directly_Down_Result_Should_Be_OneHit()
22 | {
23 | TestPlaneLineIntersectionResult(new float3(0, 0, 0), new float3(0, 1, 0), new float3(0, 10, 0), new float3(0, -1, 0), PlaneLineIntersectionResult.OneHit);
24 | }
25 |
26 | [Test]
27 | public void Line_Above_Directly_Down_Should_Hit_0_0_0()
28 | {
29 | TestPlaneLineIntersectionPoint(new float3(0, 0, 0), new float3(0, 1, 0), new float3(0, 10, 0), new float3(0, -1, 0), new float3(0, 0, 0));
30 | }
31 |
32 | [Test]
33 | public void Line_At_10_4_5_Directly_Down_Should_Hit_10_0_5()
34 | {
35 | TestPlaneLineIntersectionPoint(new float3(0, 0, 0), new float3(0, 1, 0), new float3(10, 4, 5), new float3(0, -1, 0), new float3(10, 0, 5));
36 | }
37 |
38 | [Test]
39 | public void Line_Parallel_To_Plane_Not_Inside_Result_Should_Be_NoHit()
40 | {
41 | TestPlaneLineIntersectionResult(new float3(0, 4, 0), new float3(0, 1, 0), new float3(0, 10, 0), new float3(1, 0, 0), PlaneLineIntersectionResult.NoHit);
42 | }
43 |
44 | [Test]
45 | public void Line_Parallel_To_Plane_Inside_Result_Should_Be_ParallelInsidePlane()
46 | {
47 | TestPlaneLineIntersectionResult(new float3(0, 4, 0), new float3(0, 1, 0), new float3(0, 4, 0), new float3(1, 0, 0), PlaneLineIntersectionResult.ParallelInsidePlane);
48 | }
49 |
50 | [Test]
51 | public void Line_At_1_0_0_Plane_At_0_0_0_45_Degree_Angle_Should_Be_1_Negative1_0()
52 | {
53 | TestPlaneLineIntersectionPoint(new float3(0, 0, 0), new float3(1, 1, 0), new float3(1, 0, 0), new float3(0, -1, 0), new float3(1, -1, 0));
54 | }
55 |
56 | [Test]
57 | public void Line_At_1_0_0_Plane_At_Negative1_0_0_45_Degree_Angle_Should_Be_1_Negative2_0()
58 | {
59 | TestPlaneLineIntersectionPoint(new float3(-1, 0, 0), new float3(1, 1, 0), new float3(1, 0, 0), new float3(0, -1, 0), new float3(1, -2, 0));
60 | }
61 |
62 | [Test]
63 | public void Line_At_1_0_0_Plane_At_0_0_0_Custom_Angle_Should_Be_1_Negative2_0()
64 | {
65 | TestPlaneLineIntersectionPoint(new float3(0, 0, 0), new float3(1, 0.5f, 0), new float3(1, 0, 0), new float3(0, -1, 0), new float3(1, -2, 0));
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/Assets/Heightmaps/circle.png.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c592a59b98b6d2149bd5cdf21483ecd0
3 | TextureImporter:
4 | internalIDToNameTable: []
5 | externalObjects: {}
6 | serializedVersion: 10
7 | mipmaps:
8 | mipMapMode: 0
9 | enableMipMap: 0
10 | sRGBTexture: 1
11 | linearTexture: 0
12 | fadeOut: 0
13 | borderMipMap: 0
14 | mipMapsPreserveCoverage: 0
15 | alphaTestReferenceValue: 0.5
16 | mipMapFadeDistanceStart: 1
17 | mipMapFadeDistanceEnd: 3
18 | bumpmap:
19 | convertToNormalMap: 0
20 | externalNormalMap: 0
21 | heightScale: 0.25
22 | normalMapFilter: 0
23 | isReadable: 1
24 | streamingMipmaps: 0
25 | streamingMipmapsPriority: 0
26 | grayScaleToAlpha: 0
27 | generateCubemap: 6
28 | cubemapConvolution: 0
29 | seamlessCubemap: 0
30 | textureFormat: 1
31 | maxTextureSize: 2048
32 | textureSettings:
33 | serializedVersion: 2
34 | filterMode: 0
35 | aniso: -1
36 | mipBias: -100
37 | wrapU: -1
38 | wrapV: -1
39 | wrapW: -1
40 | nPOTScale: 0
41 | lightmap: 0
42 | compressionQuality: 50
43 | spriteMode: 0
44 | spriteExtrude: 1
45 | spriteMeshType: 1
46 | alignment: 0
47 | spritePivot: {x: 0.5, y: 0.5}
48 | spritePixelsToUnits: 100
49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
50 | spriteGenerateFallbackPhysicsShape: 1
51 | alphaUsage: 1
52 | alphaIsTransparency: 0
53 | spriteTessellationDetail: -1
54 | textureType: 0
55 | textureShape: 1
56 | singleChannelComponent: 0
57 | maxTextureSizeSet: 0
58 | compressionQualitySet: 0
59 | textureFormatSet: 0
60 | platformSettings:
61 | - serializedVersion: 3
62 | buildTarget: DefaultTexturePlatform
63 | maxTextureSize: 2048
64 | resizeAlgorithm: 0
65 | textureFormat: -1
66 | textureCompression: 1
67 | compressionQuality: 50
68 | crunchedCompression: 0
69 | allowsAlphaSplitting: 0
70 | overridden: 0
71 | androidETC2FallbackOverride: 0
72 | forceMaximumCompressionQuality_BC6H_BC7: 0
73 | - serializedVersion: 3
74 | buildTarget: Standalone
75 | maxTextureSize: 2048
76 | resizeAlgorithm: 0
77 | textureFormat: -1
78 | textureCompression: 1
79 | compressionQuality: 50
80 | crunchedCompression: 0
81 | allowsAlphaSplitting: 0
82 | overridden: 0
83 | androidETC2FallbackOverride: 0
84 | forceMaximumCompressionQuality_BC6H_BC7: 0
85 | - serializedVersion: 3
86 | buildTarget: Android
87 | maxTextureSize: 2048
88 | resizeAlgorithm: 0
89 | textureFormat: -1
90 | textureCompression: 1
91 | compressionQuality: 50
92 | crunchedCompression: 0
93 | allowsAlphaSplitting: 0
94 | overridden: 0
95 | androidETC2FallbackOverride: 0
96 | forceMaximumCompressionQuality_BC6H_BC7: 0
97 | - serializedVersion: 3
98 | buildTarget: WebGL
99 | maxTextureSize: 2048
100 | resizeAlgorithm: 0
101 | textureFormat: -1
102 | textureCompression: 1
103 | compressionQuality: 50
104 | crunchedCompression: 0
105 | allowsAlphaSplitting: 0
106 | overridden: 0
107 | androidETC2FallbackOverride: 0
108 | forceMaximumCompressionQuality_BC6H_BC7: 0
109 | spriteSheet:
110 | serializedVersion: 2
111 | sprites: []
112 | outline: []
113 | physicsShape: []
114 | bones: []
115 | spriteID:
116 | internalID: 0
117 | vertices: []
118 | indices:
119 | edges: []
120 | weights: []
121 | secondaryTextures: []
122 | spritePackingTag:
123 | pSDRemoveMatte: 0
124 | pSDShowRemoveMatteOption: 0
125 | userData:
126 | assetBundleName:
127 | assetBundleVariant:
128 |
--------------------------------------------------------------------------------
/Assets/Heightmaps/terrainheightmap.png.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2cb1cd891623f1643b57dd752a2e2c45
3 | TextureImporter:
4 | internalIDToNameTable: []
5 | externalObjects: {}
6 | serializedVersion: 10
7 | mipmaps:
8 | mipMapMode: 0
9 | enableMipMap: 0
10 | sRGBTexture: 1
11 | linearTexture: 0
12 | fadeOut: 0
13 | borderMipMap: 0
14 | mipMapsPreserveCoverage: 0
15 | alphaTestReferenceValue: 0.5
16 | mipMapFadeDistanceStart: 1
17 | mipMapFadeDistanceEnd: 3
18 | bumpmap:
19 | convertToNormalMap: 0
20 | externalNormalMap: 0
21 | heightScale: 0.25
22 | normalMapFilter: 0
23 | isReadable: 1
24 | streamingMipmaps: 0
25 | streamingMipmapsPriority: 0
26 | grayScaleToAlpha: 0
27 | generateCubemap: 6
28 | cubemapConvolution: 0
29 | seamlessCubemap: 0
30 | textureFormat: 1
31 | maxTextureSize: 2048
32 | textureSettings:
33 | serializedVersion: 2
34 | filterMode: 0
35 | aniso: -1
36 | mipBias: -100
37 | wrapU: -1
38 | wrapV: -1
39 | wrapW: -1
40 | nPOTScale: 1
41 | lightmap: 0
42 | compressionQuality: 50
43 | spriteMode: 0
44 | spriteExtrude: 1
45 | spriteMeshType: 1
46 | alignment: 0
47 | spritePivot: {x: 0.5, y: 0.5}
48 | spritePixelsToUnits: 100
49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0}
50 | spriteGenerateFallbackPhysicsShape: 1
51 | alphaUsage: 1
52 | alphaIsTransparency: 0
53 | spriteTessellationDetail: -1
54 | textureType: 0
55 | textureShape: 1
56 | singleChannelComponent: 0
57 | maxTextureSizeSet: 0
58 | compressionQualitySet: 0
59 | textureFormatSet: 0
60 | platformSettings:
61 | - serializedVersion: 3
62 | buildTarget: DefaultTexturePlatform
63 | maxTextureSize: 512
64 | resizeAlgorithm: 0
65 | textureFormat: -1
66 | textureCompression: 0
67 | compressionQuality: 50
68 | crunchedCompression: 0
69 | allowsAlphaSplitting: 0
70 | overridden: 0
71 | androidETC2FallbackOverride: 0
72 | forceMaximumCompressionQuality_BC6H_BC7: 0
73 | - serializedVersion: 3
74 | buildTarget: Standalone
75 | maxTextureSize: 512
76 | resizeAlgorithm: 0
77 | textureFormat: -1
78 | textureCompression: 0
79 | compressionQuality: 50
80 | crunchedCompression: 0
81 | allowsAlphaSplitting: 0
82 | overridden: 0
83 | androidETC2FallbackOverride: 0
84 | forceMaximumCompressionQuality_BC6H_BC7: 0
85 | - serializedVersion: 3
86 | buildTarget: Android
87 | maxTextureSize: 512
88 | resizeAlgorithm: 0
89 | textureFormat: -1
90 | textureCompression: 0
91 | compressionQuality: 50
92 | crunchedCompression: 0
93 | allowsAlphaSplitting: 0
94 | overridden: 0
95 | androidETC2FallbackOverride: 0
96 | forceMaximumCompressionQuality_BC6H_BC7: 0
97 | - serializedVersion: 3
98 | buildTarget: WebGL
99 | maxTextureSize: 512
100 | resizeAlgorithm: 0
101 | textureFormat: -1
102 | textureCompression: 0
103 | compressionQuality: 50
104 | crunchedCompression: 0
105 | allowsAlphaSplitting: 0
106 | overridden: 0
107 | androidETC2FallbackOverride: 0
108 | forceMaximumCompressionQuality_BC6H_BC7: 0
109 | spriteSheet:
110 | serializedVersion: 2
111 | sprites: []
112 | outline: []
113 | physicsShape: []
114 | bones: []
115 | spriteID:
116 | internalID: 0
117 | vertices: []
118 | indices:
119 | edges: []
120 | weights: []
121 | secondaryTextures: []
122 | spritePackingTag:
123 | pSDRemoveMatte: 0
124 | pSDShowRemoveMatteOption: 0
125 | userData:
126 | assetBundleName:
127 | assetBundleVariant:
128 |
--------------------------------------------------------------------------------
/Assets/Scripts/Player/PlayerCamera.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace Eldemarkki.VoxelTerrain.Player
4 | {
5 | ///
6 | /// A class to allow moving, rotating and zooming the camera
7 | ///
8 | [RequireComponent(typeof(Camera))]
9 | public class PlayerCamera : MonoBehaviour
10 | {
11 | ///
12 | /// The movement speed of the camera
13 | ///
14 | [Header("Movement")]
15 | [SerializeField] private float movementSpeed = 30f;
16 |
17 | ///
18 | /// How fast the camera rotates when the player moves the mouse
19 | ///
20 | [Header("Rotation")]
21 | [SerializeField] private float sensitivity = 3f;
22 |
23 | ///
24 | /// The minimum field of view the player can go to
25 | ///
26 | [Header("Zoom")]
27 | [SerializeField] private float minimumFieldOfView = 2;
28 |
29 | ///
30 | /// The maximum field of view the player can go to
31 | ///
32 | [SerializeField] private float maximumFieldOfView = 170;
33 |
34 | ///
35 | /// How fast the player can zoom (change the FOV) their camera
36 | ///
37 | [SerializeField] private float zoomSpeed = 3f;
38 |
39 | ///
40 | /// The target camera component cached
41 | ///
42 | private Camera _cam;
43 |
44 | ///
45 | /// The camera's current rotation in the x-axis
46 | ///
47 | private float _rotationX;
48 |
49 | ///
50 | /// The camera's current rotation in the y-axis
51 | ///
52 | private float _rotationY;
53 |
54 | private void Awake()
55 | {
56 | _cam = GetComponent();
57 | _rotationX = -transform.eulerAngles.x;
58 | _rotationY = transform.eulerAngles.y;
59 | }
60 |
61 | private void Update()
62 | {
63 | Move();
64 | LookAround();
65 | Zoom();
66 | }
67 |
68 | ///
69 | /// Gets the user input from the keyboard and uses that to move the camera
70 | ///
71 | private void Move()
72 | {
73 | Vector3 movement = Vector3.zero;
74 | movement.x += Input.GetAxisRaw("Horizontal");
75 | if (Input.GetKey(KeyCode.Space))
76 | {
77 | movement.y++;
78 | }
79 | else if (Input.GetKey(KeyCode.LeftShift))
80 | {
81 | movement.y--;
82 | }
83 |
84 | movement.z += Input.GetAxisRaw("Vertical");
85 |
86 | _cam.transform.Translate(movementSpeed * Time.deltaTime * movement.normalized, Space.Self);
87 | }
88 |
89 | ///
90 | /// Gets the user input from the mouse and uses that to rotate the camera
91 | ///
92 | private void LookAround()
93 | {
94 | // Dividing by 60 makes the sensitivity scale based on the FOV because the default FOV is 60.
95 | float rotationSpeed = sensitivity * _cam.fieldOfView / 60f;
96 | _rotationX += Input.GetAxis("Mouse Y") * rotationSpeed;
97 | _rotationY += Input.GetAxis("Mouse X") * rotationSpeed;
98 |
99 | _rotationX = Mathf.Clamp(_rotationX, -90, 90);
100 |
101 | transform.eulerAngles = new Vector3(-_rotationX, _rotationY, 0);
102 | }
103 |
104 | ///
105 | /// Gets the user input from the mouse scroll and uses that to zoom (change the FOV)
106 | ///
107 | private void Zoom()
108 | {
109 | _cam.fieldOfView = Mathf.Clamp(_cam.fieldOfView - Input.mouseScrollDelta.y * zoomSpeed, minimumFieldOfView, maximumFieldOfView);
110 | }
111 | }
112 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/VoxelData/HeightmapTerrainVoxelDataCalculationJob.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Utilities;
2 | using System.Runtime.CompilerServices;
3 | using Unity.Burst;
4 | using Unity.Collections;
5 | using Unity.Mathematics;
6 |
7 | namespace Eldemarkki.VoxelTerrain.VoxelData
8 | {
9 | ///
10 | /// A heightmap terrain voxel data calculation job
11 | ///
12 | [BurstCompile]
13 | public struct HeightmapTerrainVoxelDataCalculationJob : IVoxelDataGenerationJob
14 | {
15 | ///
16 | /// The height data from the heightmap
17 | ///
18 | [ReadOnly] private NativeArray _heightmapData;
19 |
20 | ///
21 | /// How wide the heightmap is (in pixels). 1 pixel = 1 Unity unit
22 | ///
23 | public int HeightmapWidth { get; set; }
24 |
25 | ///
26 | /// How high the heightmap is (in pixels). 1 pixel = 1 Unity unit
27 | ///
28 | public int HeightmapHeight { get; set; }
29 |
30 | ///
31 | /// The value to multiply the height with
32 | ///
33 | public float Amplitude { get; set; }
34 |
35 | ///
36 | /// The offset to move the sampling point up and down
37 | ///
38 | public float HeightOffset { get; set; }
39 |
40 | ///
41 | public int3 WorldPositionOffset { get; set; }
42 |
43 | ///
44 | public VoxelDataVolume OutputVoxelData { get; set; }
45 |
46 | ///
47 | /// The height data from the heightmap
48 | ///
49 | public NativeArray HeightmapData { get => _heightmapData; set => _heightmapData = value; }
50 |
51 | ///
52 | /// The execute method required for Unity's IJobParallelFor job type
53 | ///
54 | public void Execute()
55 | {
56 | int index = 0;
57 | for (int z = 0; z < OutputVoxelData.Depth; z++)
58 | {
59 | for (int y = 0; y < OutputVoxelData.Height; y++)
60 | {
61 | for (int x = 0; x < OutputVoxelData.Width; x++)
62 | {
63 | int3 worldPosition = new int3(x, y, z) + WorldPositionOffset;
64 | int worldPositionX = worldPosition.x;
65 | int worldPositionY = worldPosition.y;
66 | int worldPositionZ = worldPosition.z;
67 |
68 | float voxelData = 1; // 1, because the default voxel data should be air
69 | if (worldPositionX < HeightmapWidth && worldPositionZ < HeightmapHeight)
70 | {
71 | voxelData = CalculateVoxelData(worldPositionX, worldPositionY, worldPositionZ);
72 | }
73 |
74 | OutputVoxelData.SetVoxelData((byte)math.clamp(voxelData * 255, 0, 255), index);
75 | index++;
76 | }
77 | }
78 | }
79 | }
80 |
81 | ///
82 | /// Calculates the voxel data at the world-space position
83 | ///
84 | /// Sampling point's world-space x position
85 | /// Sampling point's world-space y position
86 | /// Sampling point's world-space z position
87 | /// The voxel data sampled from the world-space position
88 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
89 | public float CalculateVoxelData(int worldPositionX, int worldPositionY, int worldPositionZ)
90 | {
91 | float heightmapValue = _heightmapData[worldPositionX + worldPositionZ * HeightmapWidth];
92 | float h = Amplitude * heightmapValue;
93 | return worldPositionY - h - HeightOffset;
94 | }
95 | }
96 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Meshing/Data/VoxelCorners.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 | namespace Eldemarkki.VoxelTerrain.Meshing.Data
6 | {
7 | ///
8 | /// A container for the corners of a voxel
9 | ///
10 | /// The element's type to hold in the corners
11 | public struct VoxelCorners : IEnumerable
12 | {
13 | ///
14 | /// The first corner
15 | ///
16 | public T Corner1 { get; set; }
17 |
18 | ///
19 | /// The second corner
20 | ///
21 | public T Corner2 { get; set; }
22 |
23 | ///
24 | /// The third corner
25 | ///
26 | public T Corner3 { get; set; }
27 |
28 | ///
29 | /// The fourth corner
30 | ///
31 | public T Corner4 { get; set; }
32 |
33 | ///
34 | /// The fifth corner
35 | ///
36 | public T Corner5 { get; set; }
37 |
38 | ///
39 | /// The sixth corner
40 | ///
41 | public T Corner6 { get; set; }
42 |
43 | ///
44 | /// The seventh corner
45 | ///
46 | public T Corner7 { get; set; }
47 |
48 | ///
49 | /// The eighth corner
50 | ///
51 | public T Corner8 { get; set; }
52 |
53 | ///
54 | /// The indexer for the voxel corners
55 | ///
56 | /// The corner's index
57 | /// Thrown when index is larger than 7.
58 | public T this[int index]
59 | {
60 | get
61 | {
62 | switch (index)
63 | {
64 | case 0: return Corner1;
65 | case 1: return Corner2;
66 | case 2: return Corner3;
67 | case 3: return Corner4;
68 | case 4: return Corner5;
69 | case 5: return Corner6;
70 | case 6: return Corner7;
71 | case 7: return Corner8;
72 | default: throw new ArgumentOutOfRangeException($"There are only 8 corners! You tried to access the corner at index {index}");
73 | }
74 | }
75 | set
76 | {
77 | switch (index)
78 | {
79 | case 0:
80 | Corner1 = value;
81 | break;
82 | case 1:
83 | Corner2 = value;
84 | break;
85 | case 2:
86 | Corner3 = value;
87 | break;
88 | case 3:
89 | Corner4 = value;
90 | break;
91 | case 4:
92 | Corner5 = value;
93 | break;
94 | case 5:
95 | Corner6 = value;
96 | break;
97 | case 6:
98 | Corner7 = value;
99 | break;
100 | case 7:
101 | Corner8 = value;
102 | break;
103 | default: throw new ArgumentOutOfRangeException($"There are only 8 corners! You tried to access the corner at index {index}");
104 | }
105 | }
106 | }
107 |
108 | public IEnumerator GetEnumerator()
109 | {
110 | for (int i = 0; i < 8; i++)
111 | {
112 | yield return this[i];
113 | }
114 | }
115 |
116 | IEnumerator IEnumerable.GetEnumerator()
117 | {
118 | return GetEnumerator();
119 | }
120 | }
121 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/TerrainSettings/HeightmapTerrainSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Unity.Collections;
3 | using UnityEngine;
4 |
5 | namespace Eldemarkki.VoxelTerrain.Settings
6 | {
7 | ///
8 | /// A class that contains information about how the heightmap world should be generated
9 | ///
10 | [CreateAssetMenu(fileName = "New Heightmap Terrain Settings", menuName = "Marching Cubes Terrain/Heightmap Terrain Settings")]
11 | public class HeightmapTerrainSettings : ScriptableObject, IDisposable
12 | {
13 | ///
14 | /// The black and white heightmap texture
15 | ///
16 | [SerializeField] private Texture2D heightmap;
17 |
18 | ///
19 | /// The generated height data from the the heightmap
20 | ///
21 | [SerializeField] private NativeArray heightmapData;
22 |
23 | ///
24 | /// Height multiplier
25 | ///
26 | [SerializeField] private float amplitude;
27 |
28 | ///
29 | /// Moves the sampling point up and down
30 | ///
31 | [SerializeField] private float heightOffset;
32 |
33 | ///
34 | /// The width of the heightmap in pixels
35 | ///
36 | public int Width { get; private set; }
37 |
38 | ///
39 | /// The height of the heightmap in pixels
40 | ///
41 | public int Height { get; private set; }
42 |
43 | ///
44 | /// The black and white heightmap texture
45 | ///
46 | public Texture2D Heightmap
47 | {
48 | get => heightmap;
49 | set => heightmap = value;
50 | }
51 |
52 | ///
53 | /// The generated height data from the the heightmap
54 | ///
55 | public NativeArray HeightmapData
56 | {
57 | get => heightmapData;
58 | set => heightmapData = value;
59 | }
60 |
61 | ///
62 | /// Height multiplier
63 | ///
64 | public float Amplitude
65 | {
66 | get => amplitude;
67 | set => amplitude = value;
68 | }
69 |
70 | ///
71 | /// Moves the sampling point up and down
72 | ///
73 | public float HeightOffset
74 | {
75 | get => heightOffset;
76 | set => heightOffset = value;
77 | }
78 |
79 | ///
80 | /// Converts the parameters to a format the can be used by the Job System
81 | ///
82 | /// The black and white heightmap
83 | /// Height multiplier
84 | /// Moves the sampling point up and down
85 | public void Initialize(Texture2D heightmap, float amplitude, float heightOffset)
86 | {
87 | this.amplitude = amplitude;
88 | this.heightOffset = heightOffset;
89 |
90 | this.heightmap = heightmap;
91 | Width = heightmap.width;
92 | Height = heightmap.height;
93 |
94 | heightmapData = new NativeArray(Width * Height, Allocator.Persistent);
95 | SetHeightmap(heightmap);
96 | }
97 |
98 | ///
99 | /// Generates the HeightmapData from the heightmap
100 | ///
101 | /// The black and white heightmap
102 | private void SetHeightmap(Texture2D heightmap)
103 | {
104 | for (int x = 0; x < Width; x++)
105 | {
106 | for (int y = 0; y < Height; y++)
107 | {
108 | heightmapData[x + Width * y] = heightmap.GetPixel(x, y).grayscale;
109 | }
110 | }
111 | }
112 |
113 | ///
114 | /// Disposes HeightmapData
115 | ///
116 | public void Dispose()
117 | {
118 | heightmapData.Dispose();
119 | }
120 | }
121 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Core/Utilities/VectorUtilities.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 | using Unity.Mathematics;
3 | using UnityEngine;
4 |
5 | namespace Eldemarkki.VoxelTerrain.Utilities
6 | {
7 | ///
8 | /// A collection of utilities that operate on vectors (int3/float3)
9 | ///
10 | public static class VectorUtilities
11 | {
12 | ///
13 | /// Floors the value to a multiple of x
14 | ///
15 | /// The value to floor
16 | /// The multiple to floor to
17 | /// The floored value
18 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
19 | public static int3 FloorToMultipleOfX(this float3 n, int3 x)
20 | {
21 | return (int3)(math.floor(n / x) * x);
22 | }
23 |
24 | ///
25 | /// Floors the value to a multiple of x
26 | ///
27 | /// The value to floor
28 | /// The multiple to floor to
29 | /// The floored value
30 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
31 | public static int3 FloorToMultipleOfX(this Vector3 n, int3 x)
32 | {
33 | return (int3)(math.floor(new float3(n.x / x.x, n.y / x.y, n.z / x.z)) * x);
34 | }
35 |
36 | ///
37 | /// Converts an int3 value to Vector3Int
38 | ///
39 | /// The int3 value to convert
40 | /// The converted value
41 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
42 | public static Vector3Int ToVectorInt(this int3 n)
43 | {
44 | return new Vector3Int(n.x, n.y, n.z);
45 | }
46 |
47 | ///
48 | /// Converts a Vector3 to a int3 by casting the xyz values to ints
49 | ///
50 | /// The Vector3 to be converted
51 | /// The converted int3
52 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
53 | public static int3 ToInt3(this Vector3 n)
54 | {
55 | return new int3((int)n.x, (int)n.y, (int)n.z);
56 | }
57 |
58 | ///
59 | /// Converts a Vector3 to a int3 by casting the xyz values to ints
60 | ///
61 | /// The Vector3 to be converted
62 | /// The converted int3
63 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
64 | public static int3 ToInt3(this Vector3Int n)
65 | {
66 | return new int3(n.x, n.y, n.z);
67 | }
68 |
69 | ///
70 | /// Calculates the remainder of a division operation for int3. Ensures that the returned value is positive
71 | ///
72 | /// The dividend
73 | /// The divisor
74 | /// The remainder of n/x
75 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
76 | public static int3 Mod(this int3 n, int3 x)
77 | {
78 | return (n % x + x) % x;
79 | }
80 |
81 | ///
82 | /// Converts a world position to a chunk coordinate
83 | ///
84 | /// The world-position that should be converted
85 | /// The size of a chunk in the world
86 | /// The chunk coordinate
87 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
88 | public static int3 WorldPositionToCoordinate(float3 worldPosition, int3 chunkSize)
89 | {
90 | return worldPosition.FloorToMultipleOfX(chunkSize) / chunkSize;
91 | }
92 |
93 | ///
94 | /// Converts a world position to a chunk coordinate
95 | ///
96 | /// The world-position that should be converted
97 | /// The size of a chunk in the world
98 | /// The chunk coordinate
99 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
100 | public static int3 WorldPositionToCoordinate(Vector3 worldPosition, int3 chunkSize)
101 | {
102 | return worldPosition.FloorToMultipleOfX(chunkSize) / chunkSize;
103 | }
104 | }
105 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/Meshing/MarchingCubes/VertexList.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using Unity.Mathematics;
5 |
6 | namespace Eldemarkki.VoxelTerrain.Meshing.MarchingCubes
7 | {
8 | ///
9 | /// A container for a vertex list with 12 vertices
10 | ///
11 | public struct VertexList : IEnumerable
12 | {
13 | ///
14 | /// The first vertex
15 | ///
16 | private float3 _c1;
17 |
18 | ///
19 | /// The second vertex
20 | ///
21 | private float3 _c2;
22 |
23 | ///
24 | /// The third vertex
25 | ///
26 | private float3 _c3;
27 |
28 | ///
29 | /// The fourth vertex
30 | ///
31 | private float3 _c4;
32 |
33 | ///
34 | /// The fifth vertex
35 | ///
36 | private float3 _c5;
37 |
38 | ///
39 | /// The sixth vertex
40 | ///
41 | private float3 _c6;
42 |
43 | ///
44 | /// The seventh vertex
45 | ///
46 | private float3 _c7;
47 |
48 | ///
49 | /// The eighth vertex
50 | ///
51 | private float3 _c8;
52 |
53 | ///
54 | /// The ninth vertex
55 | ///
56 | private float3 _c9;
57 |
58 | ///
59 | /// The tenth vertex
60 | ///
61 | private float3 _c10;
62 |
63 | ///
64 | /// The eleventh vertex
65 | ///
66 | private float3 _c11;
67 |
68 | ///
69 | /// The twelfth vertex
70 | ///
71 | private float3 _c12;
72 |
73 | ///
74 | /// The indexer for the vertex list
75 | ///
76 | /// The vertex's index
77 | /// Thrown when the index is more than 11.
78 | public float3 this[int index]
79 | {
80 | get
81 | {
82 | switch (index)
83 | {
84 | case 0: return _c1;
85 | case 1: return _c2;
86 | case 2: return _c3;
87 | case 3: return _c4;
88 | case 4: return _c5;
89 | case 5: return _c6;
90 | case 6: return _c7;
91 | case 7: return _c8;
92 | case 8: return _c9;
93 | case 9: return _c10;
94 | case 10: return _c11;
95 | case 11: return _c12;
96 | default: throw new ArgumentOutOfRangeException($"There are only 12 vertices! You tried to access the vertex at index {index}");
97 | }
98 | }
99 | set
100 | {
101 | switch (index)
102 | {
103 | case 0:
104 | _c1 = value;
105 | break;
106 | case 1:
107 | _c2 = value;
108 | break;
109 | case 2:
110 | _c3 = value;
111 | break;
112 | case 3:
113 | _c4 = value;
114 | break;
115 | case 4:
116 | _c5 = value;
117 | break;
118 | case 5:
119 | _c6 = value;
120 | break;
121 | case 6:
122 | _c7 = value;
123 | break;
124 | case 7:
125 | _c8 = value;
126 | break;
127 | case 8:
128 | _c9 = value;
129 | break;
130 | case 9:
131 | _c10 = value;
132 | break;
133 | case 10:
134 | _c11 = value;
135 | break;
136 | case 11:
137 | _c12 = value;
138 | break;
139 | default: throw new ArgumentOutOfRangeException($"There are only 12 vertices! You tried to access the vertex at index {index}");
140 | }
141 | }
142 | }
143 |
144 | public IEnumerator GetEnumerator()
145 | {
146 | for (int i = 0; i < 12; i++)
147 | {
148 | yield return this[i];
149 | }
150 | }
151 |
152 | IEnumerator IEnumerable.GetEnumerator()
153 | {
154 | return GetEnumerator();
155 | }
156 | }
157 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/Meshing/MarchingCubes/MarchingCubesJob.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Meshing.Data;
2 | using Eldemarkki.VoxelTerrain.VoxelData;
3 | using Unity.Burst;
4 | using Unity.Collections;
5 | using Unity.Mathematics;
6 | using UnityEngine;
7 |
8 | namespace Eldemarkki.VoxelTerrain.Meshing.MarchingCubes
9 | {
10 | ///
11 | /// A marching cubes mesh generation job
12 | ///
13 | [BurstCompile]
14 | public struct MarchingCubesJob : IMesherJob
15 | {
16 | ///
17 | [ReadOnly] private VoxelDataVolume _voxelData;
18 |
19 | ///
20 | [ReadOnly] private VoxelDataVolume _voxelColors;
21 |
22 | ///
23 | /// The density level where a surface will be created. Densities below this will be inside the surface (solid),
24 | /// and densities above this will be outside the surface (air)
25 | ///
26 | public float Isolevel { get; set; }
27 |
28 | ///
29 | public NativeCounter VertexCountCounter { get; set; }
30 |
31 | ///
32 | [NativeDisableParallelForRestriction, WriteOnly] private NativeArray _vertices;
33 |
34 | ///
35 | [NativeDisableParallelForRestriction, WriteOnly] private NativeArray _triangles;
36 |
37 | ///
38 | public VoxelDataVolume VoxelData { get => _voxelData; set => _voxelData = value; }
39 |
40 | ///
41 | public VoxelDataVolume VoxelColors { get => _voxelColors; set => _voxelColors = value; }
42 |
43 | ///
44 | public NativeArray OutputVertices { get => _vertices; set => _vertices = value; }
45 |
46 | ///
47 | public NativeArray OutputTriangles { get => _triangles; set => _triangles = value; }
48 |
49 | ///
50 | /// The execute method required by the Unity Job System's IJob
51 | ///
52 | public void Execute()
53 | {
54 | byte isolevelByte = (byte)math.clamp(Isolevel * 255, 0, 255);
55 | for (int x = 0; x < VoxelData.Width - 1; x++)
56 | {
57 | for (int y = 0; y < VoxelData.Height - 1; y++)
58 | {
59 | for (int z = 0; z < VoxelData.Depth - 1; z++)
60 | {
61 | int3 voxelLocalPosition = new int3(x, y, z);
62 |
63 | VoxelCorners densities = _voxelData.GetVoxelDataUnitCube(voxelLocalPosition);
64 |
65 | byte cubeIndex = MarchingCubesFunctions.CalculateCubeIndex(densities, isolevelByte);
66 | if (cubeIndex == 0 || cubeIndex == 255)
67 | {
68 | continue;
69 | }
70 |
71 | int edgeIndex = MarchingCubesLookupTables.EdgeTable[cubeIndex];
72 |
73 | VertexList vertexList = MarchingCubesFunctions.GenerateVertexList(densities, voxelLocalPosition, edgeIndex, isolevelByte);
74 |
75 | // Index at the beginning of the row
76 | int rowIndex = 15 * cubeIndex;
77 |
78 | for (int i = 0; MarchingCubesLookupTables.TriangleTable[rowIndex + i] != -1 && i < 15; i += 3)
79 | {
80 | float3 vertex1 = vertexList[MarchingCubesLookupTables.TriangleTable[rowIndex + i + 0]];
81 | float3 vertex2 = vertexList[MarchingCubesLookupTables.TriangleTable[rowIndex + i + 1]];
82 | float3 vertex3 = vertexList[MarchingCubesLookupTables.TriangleTable[rowIndex + i + 2]];
83 |
84 | if (!vertex1.Equals(vertex2) && !vertex1.Equals(vertex3) && !vertex2.Equals(vertex3))
85 | {
86 | float3 normal = math.normalize(math.cross(vertex2 - vertex1, vertex3 - vertex1));
87 |
88 | int triangleIndex = VertexCountCounter.Increment() * 3;
89 |
90 | float3 triangleMiddlePoint = (vertex1 + vertex2 + vertex3) / 3f;
91 |
92 | // Take the position of the closest corner of the current voxel
93 | int3 colorSamplePoint = (int3)math.round(triangleMiddlePoint);
94 | Color32 color = VoxelColors.GetVoxelData(colorSamplePoint);
95 |
96 | _vertices[triangleIndex + 0] = new MeshingVertexData(vertex1, normal, color);
97 | _triangles[triangleIndex + 0] = (ushort)(triangleIndex + 0);
98 |
99 | _vertices[triangleIndex + 1] = new MeshingVertexData(vertex2, normal, color);
100 | _triangles[triangleIndex + 1] = (ushort)(triangleIndex + 1);
101 |
102 | _vertices[triangleIndex + 2] = new MeshingVertexData(vertex3, normal, color);
103 | _triangles[triangleIndex + 2] = (ushort)(triangleIndex + 2);
104 | }
105 | }
106 | }
107 | }
108 | }
109 | }
110 | }
111 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/Meshing/MarchingCubes/MarchingCubesFunctions.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Utilities;
2 | using System.Runtime.CompilerServices;
3 | using Eldemarkki.VoxelTerrain.Meshing.Data;
4 | using Unity.Mathematics;
5 | using Eldemarkki.VoxelTerrain.VoxelData;
6 |
7 | namespace Eldemarkki.VoxelTerrain.Meshing.MarchingCubes
8 | {
9 | ///
10 | /// A collection of Marching Cubes -related functions
11 | ///
12 | public static class MarchingCubesFunctions
13 | {
14 | ///
15 | /// Interpolates the vertex's position
16 | ///
17 | /// The first corner's position
18 | /// The second corner's position
19 | /// The first corner's density
20 | /// The second corner's density
21 | /// The density level where a surface will be created. Densities below this will be inside the surface (solid),
22 | /// and densities above this will be outside the surface (air)
23 | /// The interpolated vertex's position
24 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
25 | public static float3 VertexInterpolate(float3 p1, float3 p2, float v1, float v2, float isolevel)
26 | {
27 | return p1 + (isolevel - v1) * (p2 - p1) / (v2 - v1);
28 | }
29 |
30 | ///
31 | /// Calculates the cube index of a single voxel
32 | ///
33 | /// The densities of the voxel
34 | /// The density level where a surface will be created. Densities below this will be inside the surface (solid),
35 | /// and densities above this will be outside the surface (air)
36 | /// The calculated cube index
37 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
38 | public static byte CalculateCubeIndex(VoxelCorners voxelDensities, byte isolevel)
39 | {
40 | byte cubeIndex = (byte)math.select(0, 1, voxelDensities.Corner1 < isolevel);
41 | cubeIndex |= (byte)math.select(0, 2, voxelDensities.Corner2 < isolevel);
42 | cubeIndex |= (byte)math.select(0, 4, voxelDensities.Corner3 < isolevel);
43 | cubeIndex |= (byte)math.select(0, 8, voxelDensities.Corner4 < isolevel);
44 | cubeIndex |= (byte)math.select(0, 16, voxelDensities.Corner5 < isolevel);
45 | cubeIndex |= (byte)math.select(0, 32, voxelDensities.Corner6 < isolevel);
46 | cubeIndex |= (byte)math.select(0, 64, voxelDensities.Corner7 < isolevel);
47 | cubeIndex |= (byte)math.select(0, 128, voxelDensities.Corner8 < isolevel);
48 |
49 | return cubeIndex;
50 | }
51 |
52 | ///
53 | /// Generates the vertex list for a single voxel
54 | ///
55 | /// The densities of the voxel
56 | /// The local voxel position of the voxel whose vertex list should be generated
57 | /// The edge index
58 | /// The density level where a surface will be created. Densities below this will be inside the surface (solid),
59 | /// and densities above this will be outside the surface (air)
60 | /// The generated vertex list for the voxel
61 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
62 | public static VertexList GenerateVertexList(VoxelCorners voxelDensities, int3 voxelLocalPosition,
63 | int edgeIndex, byte isolevel)
64 | {
65 | VertexList vertexList = new VertexList();
66 |
67 | for (int i = 0; i < 12; i++)
68 | {
69 | if ((edgeIndex & (1 << i)) == 0) { continue; }
70 |
71 | int edgeStartIndex = MarchingCubesLookupTables.EdgeIndexTable[2 * i + 0];
72 | int edgeEndIndex = MarchingCubesLookupTables.EdgeIndexTable[2 * i + 1];
73 |
74 | int3 corner1 = voxelLocalPosition + LookupTables.CubeCorners[edgeStartIndex];
75 | int3 corner2 = voxelLocalPosition + LookupTables.CubeCorners[edgeEndIndex];
76 |
77 | float density1 = voxelDensities[edgeStartIndex] / 255f;
78 | float density2 = voxelDensities[edgeEndIndex] / 255f;
79 |
80 | vertexList[i] = VertexInterpolate(corner1, corner2, density1, density2, isolevel / 255f);
81 | }
82 |
83 | return vertexList;
84 | }
85 |
86 | ///
87 | /// Gets a cube-shaped volume of voxel data from . The size of the cube is 1 unit.
88 | ///
89 | /// The voxel data array to get the voxel data from
90 | /// The origin of the cube
91 | /// A cube-shaped volume of voxel data. The size of the cube is 1 unit.
92 | public static VoxelCorners GetVoxelDataUnitCube(this VoxelDataVolume voxelDataArray, int3 localPosition) where T : struct
93 | {
94 | VoxelCorners voxelDataCorners = new VoxelCorners();
95 | for (int i = 0; i < 8; i++)
96 | {
97 | int3 voxelCorner = localPosition + LookupTables.CubeCorners[i];
98 | if (voxelDataArray.TryGetVoxelData(voxelCorner, out T voxelData))
99 | {
100 | voxelDataCorners[i] = voxelData;
101 | }
102 | }
103 |
104 | return voxelDataCorners;
105 | }
106 | }
107 | }
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/VoxelDataVolumeTests/VoxelDataVolumeTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using System;
3 | using Unity.Collections;
4 | using Unity.Mathematics;
5 |
6 | namespace Eldemarkki.VoxelTerrain.VoxelData.Tests
7 | {
8 | public class VoxelDataVolumeTests
9 | {
10 | private VoxelDataVolume voxelDataVolume;
11 |
12 | [TestCase(0, 9, 3)]
13 | [TestCase(5, 2, 13)]
14 | [TestCase(16, 7, 4)]
15 | public void Test_Xyz_Constructor_Width(int width, int height, int depth)
16 | {
17 | voxelDataVolume = new VoxelDataVolume(width, height, depth, Allocator.Temp);
18 | Assert.AreEqual(width, voxelDataVolume.Width);
19 | }
20 |
21 | [TestCase(0, 9, 3)]
22 | [TestCase(5, 2, 13)]
23 | [TestCase(16, 7, 4)]
24 | public void Test_Xyz_Constructor_Height(int width, int height, int depth)
25 | {
26 | voxelDataVolume = new VoxelDataVolume(width, height, depth, Allocator.Temp);
27 | Assert.AreEqual(height, voxelDataVolume.Height);
28 | }
29 |
30 | [TestCase(0, 9, 3)]
31 | [TestCase(5, 2, 13)]
32 | [TestCase(16, 7, 4)]
33 | public void Test_Xyz_Constructor_Depth(int width, int height, int depth)
34 | {
35 | voxelDataVolume = new VoxelDataVolume(width, height, depth, Allocator.Temp);
36 | Assert.AreEqual(depth, voxelDataVolume.Depth);
37 | }
38 |
39 | [TestCase(0)]
40 | [TestCase(5)]
41 | [TestCase(16)]
42 | public void Test_Int_Size_Constructor_Size(int size)
43 | {
44 | voxelDataVolume = new VoxelDataVolume(size, Allocator.Temp);
45 | Assert.AreEqual(new int3(size, size, size), voxelDataVolume.Size);
46 | }
47 |
48 | [TestCase(0, 9, 3)]
49 | [TestCase(5, 2, 13)]
50 | [TestCase(16, 7, 4)]
51 | public void Test_Xyz_Constructor_Length(int width, int height, int depth)
52 | {
53 | voxelDataVolume = new VoxelDataVolume(width, height, depth, Allocator.Temp);
54 | Assert.AreEqual(width * height * depth, voxelDataVolume.Length);
55 | }
56 |
57 | [TestCase(0, 9, 3)]
58 | [TestCase(5, 2, 13)]
59 | [TestCase(16, 7, 4)]
60 | public void Test_Xyz_Constructor_IsCreated(int width, int height, int depth)
61 | {
62 | voxelDataVolume = new VoxelDataVolume(width, height, depth, Allocator.Temp);
63 | Assert.AreEqual(true, voxelDataVolume.IsCreated);
64 | }
65 |
66 | [TestCase(-10)]
67 | [TestCase(-5)]
68 | public void Test_Int_Size_Constructor_Negative_Throws(int size)
69 | {
70 | Assert.Throws(() =>
71 | {
72 | voxelDataVolume = new VoxelDataVolume(size, Allocator.Temp);
73 | });
74 | }
75 |
76 | [Test]
77 | public void Test_Default_Constructor_IsNotCreated()
78 | {
79 | voxelDataVolume = new VoxelDataVolume();
80 | Assert.AreEqual(false, voxelDataVolume.IsCreated);
81 | }
82 |
83 | [Test]
84 | public void Test_Voxel_Datas_Are_Initialized_To_0()
85 | {
86 | voxelDataVolume = new VoxelDataVolume(5, Allocator.Temp);
87 | for (int i = 0; i < voxelDataVolume.Length; i++)
88 | {
89 | Assert.AreEqual(0, voxelDataVolume.GetVoxelData(i));
90 | }
91 | }
92 |
93 | private void TestSetGetVoxelData(Func function, float newVoxelData)
94 | {
95 | voxelDataVolume = new VoxelDataVolume(5, Allocator.Temp);
96 | float actualVoxelData = function();
97 | Assert.IsTrue(AreVoxelDatasSame(newVoxelData, actualVoxelData), $"Expected {newVoxelData}, actual was {actualVoxelData}");
98 | }
99 |
100 | [Test]
101 | public void Test_SetGetVoxelData_Index([Random(0, 1f, 5)] float newVoxelData, [Random(0, 5 * 5 * 5 - 1, 5)] int index)
102 | {
103 | TestSetGetVoxelData(() =>
104 | {
105 | voxelDataVolume.SetVoxelData(newVoxelData, index);
106 | return voxelDataVolume.GetVoxelData(index);
107 | }, newVoxelData);
108 | }
109 |
110 | [Test]
111 | public void Test_SetGetVoxelData_Xyz([Random(0, 1f, 5)] float newVoxelData, [Random(0, 4, 3)] int x, [Random(0, 4, 3)] int y, [Random(0, 4, 3)] int z)
112 | {
113 | TestSetGetVoxelData(() =>
114 | {
115 | voxelDataVolume.SetVoxelData(newVoxelData, x, y, z);
116 | return voxelDataVolume.GetVoxelData(x, y, z);
117 | }, newVoxelData);
118 | }
119 |
120 | [Test]
121 | public void Test_SetGetVoxelData_Int3([Random(0, 1f, 5)] float newVoxelData, [Random(0, 4, 3)] int x, [Random(0, 4, 3)] int y, [Random(0, 4, 3)] int z)
122 | {
123 | TestSetGetVoxelData(() =>
124 | {
125 | voxelDataVolume.SetVoxelData(newVoxelData, new int3(x, y, z));
126 | return voxelDataVolume.GetVoxelData(new int3(x, y, z));
127 | }, newVoxelData);
128 | }
129 |
130 | private static bool AreVoxelDatasSame(float a, float b)
131 | {
132 | byte aByte = (byte)RoundUpIfDecimal5(255f * a);
133 | byte bByte = (byte)RoundUpIfDecimal5(255f * b);
134 |
135 | return aByte == bByte;
136 | }
137 |
138 | // This function is an "improvement" (not really...) of math.round()
139 | // This rounds a number down if its decimal is less than 0.5, and otherwise up:
140 | // 0.5 => 1
141 | // 0.49999 => 0
142 | // 76.5 => 77
143 | // 76.49999 => 76
144 | // This was needed because math.round rounded 0.5 => 0, which was incorrect when comparing voxel datas.
145 | private static int RoundUpIfDecimal5(float x)
146 | {
147 | if (x < 0)
148 | {
149 | throw new System.ArgumentException("This function only works with positive numbers!");
150 | }
151 |
152 | int result;
153 | float decimals = x % 1;
154 | if (decimals < 0.5f)
155 | {
156 | result = (int)math.floor(x);
157 | }
158 | else
159 | {
160 | result = (int)math.ceil(x);
161 | }
162 |
163 | return result;
164 | }
165 |
166 | [TearDown]
167 | public void Teardown()
168 | {
169 | if (voxelDataVolume.IsCreated)
170 | {
171 | voxelDataVolume.Dispose();
172 | }
173 | }
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain.Tests/Core/ChunkUtilitiesTests/CoordinateUtilitiesTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using System.Collections.Generic;
3 | using Unity.Mathematics;
4 |
5 | namespace Eldemarkki.VoxelTerrain.Utilities.Tests
6 | {
7 | public class CoordinateUtilitiesTests
8 | {
9 | [Test]
10 | public void GetChunkCoordinatesContainingPoint_Test1()
11 | {
12 | int3 worldPosition = new int3(0, 0, 0);
13 | int chunkSize = 16;
14 |
15 | IEnumerable coordinates = CoordinateUtilities.GetChunkCoordinatesContainingPoint(worldPosition, chunkSize);
16 |
17 | IEnumerable expectedCoordinates = new List
18 | {
19 | new int3( 0, 0, 0),
20 | new int3(-1, 0, 0),
21 | new int3( 0, -1, 0),
22 | new int3(-1, -1, 0),
23 | new int3( 0, 0, -1),
24 | new int3(-1, 0, -1),
25 | new int3( 0, -1, -1),
26 | new int3(-1, -1, -1),
27 | };
28 |
29 | Assert.That(coordinates, Is.EquivalentTo(expectedCoordinates));
30 | }
31 |
32 | [Test]
33 | public void GetChunkCoordinatesContainingPoint_Test2()
34 | {
35 | int3 worldPosition = new int3(16, 0, 16);
36 | int chunkSize = 16;
37 |
38 | IEnumerable coordinates = CoordinateUtilities.GetChunkCoordinatesContainingPoint(worldPosition, chunkSize);
39 |
40 | IEnumerable expectedCoordinates = new List
41 | {
42 | new int3( 1, 0, 1),
43 | new int3( 0, 0, 1),
44 | new int3( 1, -1, 1),
45 | new int3( 0, -1, 1),
46 | new int3( 1, 0, 0),
47 | new int3( 0, 0, 0),
48 | new int3( 1, -1, 0),
49 | new int3( 0, -1, 0),
50 | };
51 |
52 | Assert.That(coordinates, Is.EquivalentTo(expectedCoordinates));
53 | }
54 |
55 | [Test]
56 | public void GetChunkCoordinatesContainingPoint_Test3()
57 | {
58 | int3 worldPosition = new int3(16, 1, 16);
59 | int chunkSize = 16;
60 |
61 | IEnumerable coordinates = CoordinateUtilities.GetChunkCoordinatesContainingPoint(worldPosition, chunkSize);
62 |
63 | IEnumerable expectedCoordinates = new List
64 | {
65 | new int3( 1, 0, 1),
66 | new int3( 0, 0, 1),
67 | new int3( 1, 0, 0),
68 | new int3( 0, 0, 0),
69 | };
70 |
71 | Assert.That(coordinates, Is.EquivalentTo(expectedCoordinates));
72 | }
73 |
74 | [Test]
75 | public void GetChunkCoordinatesContainingPoint_Test4()
76 | {
77 | int3 worldPosition = new int3(5, 3, 16);
78 | int chunkSize = 16;
79 |
80 | IEnumerable coordinates = CoordinateUtilities.GetChunkCoordinatesContainingPoint(worldPosition, chunkSize);
81 |
82 | IEnumerable expectedCoordinates = new List
83 | {
84 | new int3( 0, 0, 1),
85 | new int3( 0, 0, 0),
86 | };
87 |
88 | Assert.That(coordinates, Is.EquivalentTo(expectedCoordinates));
89 | }
90 |
91 | [Test]
92 | public void GetChunkCoordinatesContainingPoint_Test5()
93 | {
94 | int3 worldPosition = new int3(-48, -32, -16);
95 | int chunkSize = 16;
96 |
97 | IEnumerable coordinates = CoordinateUtilities.GetChunkCoordinatesContainingPoint(worldPosition, chunkSize);
98 |
99 | IEnumerable expectedCoordinates = new List
100 | {
101 | new int3(-3, -2, -1),
102 | new int3(-4, -2, -1),
103 | new int3(-3, -3, -1),
104 | new int3(-4, -3, -1),
105 | new int3(-3, -2, -2),
106 | new int3(-4, -2, -2),
107 | new int3(-3, -3, -2),
108 | new int3(-4, -3, -2),
109 | };
110 |
111 | Assert.That(coordinates, Is.EquivalentTo(expectedCoordinates));
112 | }
113 |
114 | [Test]
115 | public void GetChunkCoordinatesContainingPoint_Test6()
116 | {
117 | int3 worldPosition = new int3(0, 5, 5);
118 | int chunkSize = 16;
119 |
120 | IEnumerable coordinates = CoordinateUtilities.GetChunkCoordinatesContainingPoint(worldPosition, chunkSize);
121 |
122 | IEnumerable expectedCoordinates = new List
123 | {
124 | new int3( 0, 0, 0),
125 | new int3(-1, 0, 0),
126 | };
127 |
128 | Assert.That(coordinates, Is.EquivalentTo(expectedCoordinates));
129 | }
130 |
131 |
132 | [Test]
133 | public void GetChunkCoordinatesContainingPoint_Test7()
134 | {
135 | int3 worldPosition = new int3(5, 0, 5);
136 | int chunkSize = 16;
137 |
138 | IEnumerable coordinates = CoordinateUtilities.GetChunkCoordinatesContainingPoint(worldPosition, chunkSize);
139 |
140 | IEnumerable expectedCoordinates = new List
141 | {
142 | new int3(0, 0, 0),
143 | new int3(0, -1, 0),
144 | };
145 |
146 | Assert.That(coordinates, Is.EquivalentTo(expectedCoordinates));
147 | }
148 |
149 | [Test]
150 | public void GetChunkCoordinatesContainingPoint_Test8()
151 | {
152 | int3 worldPosition = new int3(5, 5, 0);
153 | int chunkSize = 16;
154 |
155 | IEnumerable coordinates = CoordinateUtilities.GetChunkCoordinatesContainingPoint(worldPosition, chunkSize);
156 |
157 | IEnumerable expectedCoordinates = new List
158 | {
159 | new int3(0, 0, 0),
160 | new int3(0, 0, -1),
161 | };
162 |
163 | Assert.That(coordinates, Is.EquivalentTo(expectedCoordinates));
164 | }
165 |
166 |
167 | [Test]
168 | public void GetChunkCoordinatesContainingPoint_Test9()
169 | {
170 | int3 worldPosition = new int3(7, 7, 7);
171 | int chunkSize = 7;
172 |
173 | IEnumerable coordinates = CoordinateUtilities.GetChunkCoordinatesContainingPoint(worldPosition, chunkSize);
174 |
175 | IEnumerable expectedCoordinates = new List
176 | {
177 | new int3(1, 1, 1),
178 | new int3(0, 1, 1),
179 | new int3(1, 0, 1),
180 | new int3(0, 0, 1),
181 | new int3(1, 1, 0),
182 | new int3(0, 1, 0),
183 | new int3(1, 0, 0),
184 | new int3(0, 0, 0),
185 | };
186 |
187 | Assert.That(coordinates, Is.EquivalentTo(expectedCoordinates));
188 | }
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/Assets/VoxelTerrain/Modules/World/ProceduralWorldGenerator.cs:
--------------------------------------------------------------------------------
1 | using Eldemarkki.VoxelTerrain.Chunks;
2 | using Eldemarkki.VoxelTerrain.Utilities;
3 | using Eldemarkki.VoxelTerrain.Utilities.Intersection;
4 | using Unity.Mathematics;
5 | using UnityEngine;
6 |
7 | namespace Eldemarkki.VoxelTerrain.World
8 | {
9 | ///
10 | /// A procedurally generated world
11 | ///
12 | public class ProceduralWorldGenerator : MonoBehaviour
13 | {
14 | ///
15 | /// The voxel world that "owns" this world generator
16 | ///
17 | [SerializeField] private VoxelWorld voxelWorld;
18 |
19 | ///
20 | /// A chunk provider which provides chunks with procedurally generated data
21 | ///
22 | [SerializeField] private ProceduralChunkProvider chunkProvider;
23 |
24 | ///
25 | /// The radius of the chunks the player sees
26 | ///
27 | [SerializeField] private int renderDistance = 5;
28 |
29 | ///
30 | /// The size of the buffer around the render distance where voxel data will start to generate, but the mesh will not be generated yet
31 | ///
32 | [SerializeField] private int loadingBufferSize = 2;
33 |
34 | ///
35 | /// The viewer which the terrain is generated around
36 | ///
37 | [SerializeField] private Transform player;
38 |
39 | ///
40 | /// The coordinate of the chunk where terrain was last generated around
41 | ///
42 | private int3 _lastGenerationCoordinate;
43 |
44 | private void Start()
45 | {
46 | int3 playerCoordinate = GetPlayerCoordinate();
47 | GenerateTerrainAroundCoordinate(playerCoordinate);
48 | }
49 |
50 | private void Update()
51 | {
52 | int3 newPlayerCoordinate = GetPlayerCoordinate();
53 | if (!newPlayerCoordinate.Equals(_lastGenerationCoordinate))
54 | {
55 | MoveVoxelData(_lastGenerationCoordinate, newPlayerCoordinate);
56 |
57 | var newlyFreedCoordinates = voxelWorld.ChunkStore.GetChunkCoordinatesOutsideOfRange(newPlayerCoordinate, renderDistance);
58 |
59 | int3 renderSize = new int3(renderDistance * 2 + 1);
60 |
61 | int3 oldPos = _lastGenerationCoordinate - new int3(renderDistance);
62 | BoundsInt oldCoords = new BoundsInt(oldPos.ToVectorInt(), renderSize.ToVectorInt());
63 |
64 | int3 newPos = newPlayerCoordinate - new int3(renderDistance);
65 | BoundsInt newCoords = new BoundsInt(newPos.ToVectorInt(), renderSize.ToVectorInt());
66 |
67 | int3[] coordinatesThatNeedChunks = CoordinateUtilities.GetCoordinatesThatNeedChunks(oldCoords, newCoords);
68 |
69 | int i = 0;
70 | foreach (int3 source in newlyFreedCoordinates)
71 | {
72 | int3 target = coordinatesThatNeedChunks[i];
73 |
74 | // Move chunk gameobjects
75 | voxelWorld.ChunkStore.MoveChunk(source, target);
76 |
77 | // Move colors and generate new
78 | voxelWorld.VoxelColorStore.MoveChunk(source, target);
79 |
80 | chunkProvider.AddChunkToGenerationQueue(target);
81 |
82 | i++;
83 | }
84 |
85 | _lastGenerationCoordinate = newPlayerCoordinate;
86 | }
87 | }
88 |
89 | ///
90 | /// Moves all of the voxel data that existed when the player was at the coordinate to the coordinates that don't yet have data but should have when the player is at coordinate
91 | ///
92 | /// The old coordinate of the player
93 | /// The new coordinate of the player
94 | private void MoveVoxelData(int3 playerFromCoordinate, int3 playerToCoordinate)
95 | {
96 | int range = renderDistance + loadingBufferSize;
97 | int3 renderSize = new int3(range * 2 + 1);
98 |
99 | int3 oldPos = playerFromCoordinate - new int3(range);
100 | BoundsInt oldCoords = new BoundsInt(oldPos.ToVectorInt(), renderSize.ToVectorInt());
101 |
102 | int3 newPos = playerToCoordinate - new int3(range);
103 | BoundsInt newCoords = new BoundsInt(newPos.ToVectorInt(), renderSize.ToVectorInt());
104 |
105 | int3[] coordinatesThatNeedData = CoordinateUtilities.GetCoordinatesThatNeedChunks(oldCoords, newCoords);
106 |
107 | var newlyFreedCoordinates = voxelWorld.VoxelDataStore.GetChunkCoordinatesOutsideOfRange(playerToCoordinate, range);
108 |
109 | int i = 0;
110 | foreach (int3 freeCoordinate in newlyFreedCoordinates)
111 | {
112 | var targetCoordinate = coordinatesThatNeedData[i];
113 | voxelWorld.VoxelDataStore.MoveChunk(freeCoordinate, targetCoordinate);
114 | i++;
115 | }
116 | }
117 |
118 | ///
119 | /// Get's the current coordinate of
120 | ///
121 | /// The coordinate of
122 | private int3 GetPlayerCoordinate()
123 | {
124 | return VectorUtilities.WorldPositionToCoordinate(player.position, voxelWorld.WorldSettings.ChunkSize);
125 | }
126 |
127 | ///
128 | /// Generates terrain around with a radius of
129 | ///
130 | /// The coordinate to generate the terrain around
131 | private void GenerateTerrainAroundCoordinate(int3 coordinate)
132 | {
133 | // Start generating voxel data for chunks with radius 'renderDistance + loadingBufferSize'
134 | int3[] preloadCoordinates = CoordinateUtilities.GetPreloadCoordinates(coordinate, renderDistance, loadingBufferSize);
135 | for (int i = 0; i < preloadCoordinates.Length; i++)
136 | {
137 | int3 loadingCoordinate = preloadCoordinates[i];
138 | voxelWorld.VoxelDataStore.GenerateDataForChunk(loadingCoordinate);
139 | }
140 |
141 | // Generate chunks with radius 'renderDistance'
142 | int3[] chunkGenerationCoordinates = CoordinateUtilities.GetChunkGenerationCoordinates(coordinate, renderDistance);
143 | for (int i = 0; i < chunkGenerationCoordinates.Length; i++)
144 | {
145 | int3 generationCoordinate = chunkGenerationCoordinates[i];
146 | voxelWorld.VoxelColorStore.GenerateDataForChunk(generationCoordinate);
147 | chunkProvider.EnsureChunkExistsAtCoordinate(generationCoordinate);
148 | }
149 |
150 | _lastGenerationCoordinate = coordinate;
151 | }
152 | }
153 | }
--------------------------------------------------------------------------------
/ProjectSettings/InputManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!13 &1
4 | InputManager:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_Axes:
8 | - serializedVersion: 3
9 | m_Name: Horizontal
10 | descriptiveName:
11 | descriptiveNegativeName:
12 | negativeButton: left
13 | positiveButton: right
14 | altNegativeButton: a
15 | altPositiveButton: d
16 | gravity: 3
17 | dead: 0.001
18 | sensitivity: 3
19 | snap: 1
20 | invert: 0
21 | type: 0
22 | axis: 0
23 | joyNum: 0
24 | - serializedVersion: 3
25 | m_Name: Vertical
26 | descriptiveName:
27 | descriptiveNegativeName:
28 | negativeButton: down
29 | positiveButton: up
30 | altNegativeButton: s
31 | altPositiveButton: w
32 | gravity: 3
33 | dead: 0.001
34 | sensitivity: 3
35 | snap: 1
36 | invert: 0
37 | type: 0
38 | axis: 0
39 | joyNum: 0
40 | - serializedVersion: 3
41 | m_Name: Fire1
42 | descriptiveName:
43 | descriptiveNegativeName:
44 | negativeButton:
45 | positiveButton: left ctrl
46 | altNegativeButton:
47 | altPositiveButton: mouse 0
48 | gravity: 1000
49 | dead: 0.001
50 | sensitivity: 1000
51 | snap: 0
52 | invert: 0
53 | type: 0
54 | axis: 0
55 | joyNum: 0
56 | - serializedVersion: 3
57 | m_Name: Fire2
58 | descriptiveName:
59 | descriptiveNegativeName:
60 | negativeButton:
61 | positiveButton: left alt
62 | altNegativeButton:
63 | altPositiveButton: mouse 1
64 | gravity: 1000
65 | dead: 0.001
66 | sensitivity: 1000
67 | snap: 0
68 | invert: 0
69 | type: 0
70 | axis: 0
71 | joyNum: 0
72 | - serializedVersion: 3
73 | m_Name: Fire3
74 | descriptiveName:
75 | descriptiveNegativeName:
76 | negativeButton:
77 | positiveButton: left shift
78 | altNegativeButton:
79 | altPositiveButton: mouse 2
80 | gravity: 1000
81 | dead: 0.001
82 | sensitivity: 1000
83 | snap: 0
84 | invert: 0
85 | type: 0
86 | axis: 0
87 | joyNum: 0
88 | - serializedVersion: 3
89 | m_Name: Jump
90 | descriptiveName:
91 | descriptiveNegativeName:
92 | negativeButton:
93 | positiveButton: space
94 | altNegativeButton:
95 | altPositiveButton:
96 | gravity: 1000
97 | dead: 0.001
98 | sensitivity: 1000
99 | snap: 0
100 | invert: 0
101 | type: 0
102 | axis: 0
103 | joyNum: 0
104 | - serializedVersion: 3
105 | m_Name: Mouse X
106 | descriptiveName:
107 | descriptiveNegativeName:
108 | negativeButton:
109 | positiveButton:
110 | altNegativeButton:
111 | altPositiveButton:
112 | gravity: 0
113 | dead: 0
114 | sensitivity: 0.1
115 | snap: 0
116 | invert: 0
117 | type: 1
118 | axis: 0
119 | joyNum: 0
120 | - serializedVersion: 3
121 | m_Name: Mouse Y
122 | descriptiveName:
123 | descriptiveNegativeName:
124 | negativeButton:
125 | positiveButton:
126 | altNegativeButton:
127 | altPositiveButton:
128 | gravity: 0
129 | dead: 0
130 | sensitivity: 0.1
131 | snap: 0
132 | invert: 0
133 | type: 1
134 | axis: 1
135 | joyNum: 0
136 | - serializedVersion: 3
137 | m_Name: Mouse ScrollWheel
138 | descriptiveName:
139 | descriptiveNegativeName:
140 | negativeButton:
141 | positiveButton:
142 | altNegativeButton:
143 | altPositiveButton:
144 | gravity: 0
145 | dead: 0
146 | sensitivity: 0.1
147 | snap: 0
148 | invert: 0
149 | type: 1
150 | axis: 2
151 | joyNum: 0
152 | - serializedVersion: 3
153 | m_Name: Horizontal
154 | descriptiveName:
155 | descriptiveNegativeName:
156 | negativeButton:
157 | positiveButton:
158 | altNegativeButton:
159 | altPositiveButton:
160 | gravity: 0
161 | dead: 0.19
162 | sensitivity: 1
163 | snap: 0
164 | invert: 0
165 | type: 2
166 | axis: 0
167 | joyNum: 0
168 | - serializedVersion: 3
169 | m_Name: Vertical
170 | descriptiveName:
171 | descriptiveNegativeName:
172 | negativeButton:
173 | positiveButton:
174 | altNegativeButton:
175 | altPositiveButton:
176 | gravity: 0
177 | dead: 0.19
178 | sensitivity: 1
179 | snap: 0
180 | invert: 1
181 | type: 2
182 | axis: 1
183 | joyNum: 0
184 | - serializedVersion: 3
185 | m_Name: Fire1
186 | descriptiveName:
187 | descriptiveNegativeName:
188 | negativeButton:
189 | positiveButton: joystick button 0
190 | altNegativeButton:
191 | altPositiveButton:
192 | gravity: 1000
193 | dead: 0.001
194 | sensitivity: 1000
195 | snap: 0
196 | invert: 0
197 | type: 0
198 | axis: 0
199 | joyNum: 0
200 | - serializedVersion: 3
201 | m_Name: Fire2
202 | descriptiveName:
203 | descriptiveNegativeName:
204 | negativeButton:
205 | positiveButton: joystick button 1
206 | altNegativeButton:
207 | altPositiveButton:
208 | gravity: 1000
209 | dead: 0.001
210 | sensitivity: 1000
211 | snap: 0
212 | invert: 0
213 | type: 0
214 | axis: 0
215 | joyNum: 0
216 | - serializedVersion: 3
217 | m_Name: Fire3
218 | descriptiveName:
219 | descriptiveNegativeName:
220 | negativeButton:
221 | positiveButton: joystick button 2
222 | altNegativeButton:
223 | altPositiveButton:
224 | gravity: 1000
225 | dead: 0.001
226 | sensitivity: 1000
227 | snap: 0
228 | invert: 0
229 | type: 0
230 | axis: 0
231 | joyNum: 0
232 | - serializedVersion: 3
233 | m_Name: Jump
234 | descriptiveName:
235 | descriptiveNegativeName:
236 | negativeButton:
237 | positiveButton: joystick button 3
238 | altNegativeButton:
239 | altPositiveButton:
240 | gravity: 1000
241 | dead: 0.001
242 | sensitivity: 1000
243 | snap: 0
244 | invert: 0
245 | type: 0
246 | axis: 0
247 | joyNum: 0
248 | - serializedVersion: 3
249 | m_Name: Submit
250 | descriptiveName:
251 | descriptiveNegativeName:
252 | negativeButton:
253 | positiveButton: return
254 | altNegativeButton:
255 | altPositiveButton: joystick button 0
256 | gravity: 1000
257 | dead: 0.001
258 | sensitivity: 1000
259 | snap: 0
260 | invert: 0
261 | type: 0
262 | axis: 0
263 | joyNum: 0
264 | - serializedVersion: 3
265 | m_Name: Submit
266 | descriptiveName:
267 | descriptiveNegativeName:
268 | negativeButton:
269 | positiveButton: enter
270 | altNegativeButton:
271 | altPositiveButton: space
272 | gravity: 1000
273 | dead: 0.001
274 | sensitivity: 1000
275 | snap: 0
276 | invert: 0
277 | type: 0
278 | axis: 0
279 | joyNum: 0
280 | - serializedVersion: 3
281 | m_Name: Cancel
282 | descriptiveName:
283 | descriptiveNegativeName:
284 | negativeButton:
285 | positiveButton: escape
286 | altNegativeButton:
287 | altPositiveButton: joystick button 1
288 | gravity: 1000
289 | dead: 0.001
290 | sensitivity: 1000
291 | snap: 0
292 | invert: 0
293 | type: 0
294 | axis: 0
295 | joyNum: 0
296 |
--------------------------------------------------------------------------------