Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using Unity.Burst;
- using Unity.Collections;
- using Unity.Jobs;
- using Unity.Mathematics;
- [BurstCompile(CompileSynchronously = true)]
- struct ChunkJob : IJob
- {
- public NativeList<float3> vertices;
- public NativeList<int> triangles;
- public NativeList<float2> uvs;
- [ReadOnly] public NativeArray<int3> faceDirections;
- [ReadOnly] public NativeArray<float2> uvCordinates;
- [ReadOnly] public NativeArray<int3> faceVertices;
- [ReadOnly] public int2 chunkDimensions;
- //Neighbouring chunks
- [ReadOnly] public NativeArray<int> thisChunkData;
- [ReadOnly] public NativeArray<int> leftChunkData;
- [ReadOnly] public NativeArray<int> rightChunkData;
- [ReadOnly] public NativeArray<int> frontChunkData;
- [ReadOnly] public NativeArray<int> backChunkData;
- public void Execute()
- {
- for (int x = 0; x < chunkDimensions.x; x++)
- {
- for (int y = 0; y < chunkDimensions.y; y++)
- {
- for (int z = 0; z < chunkDimensions.x; z++)
- {
- int blockIndex = thisChunkData[CalculateVoxelIndex(x, y, z)];
- if (blockIndex != 0)
- {
- AddVoxel(x, y, z, blockIndex, vertices, triangles, uvs);
- }
- }
- }
- }
- }
- private void AddVoxel(int x, int y, int z, int blockIndex, NativeList<float3> vertices, NativeList<int> triangles, NativeList<float2> uvs)
- {
- NativeArray<float2> blockUVs = GetBlockUVs(blockIndex);
- for (int i = 0; i < 6; i++)
- {
- if (IsFaceVisible(x, y, z, i))
- {
- AddQuad(new int3(x, y, z), i, blockUVs[i], vertices, triangles, uvs);
- }
- }
- }
- private void AddQuad(int3 quadPos, int i, float2 bottomLeftUV, NativeList<float3> vertices, NativeList<int> triangles, NativeList<float2> uvs)
- {
- int vertCount = vertices.Length;
- NativeArray<float3> verts = new NativeArray<float3>(4, Allocator.Temp);
- for (int j = 0; j < 4; j++)
- {
- verts[j] = faceVertices[(i * 4) + j] + quadPos;
- }
- vertices.AddRange(verts);
- NativeArray<int> tris = new NativeArray<int>(6, Allocator.Temp);
- tris[0] = vertCount;
- tris[1] = vertCount + 1;
- tris[2] = vertCount + 3;
- tris[3] = vertCount + 3;
- tris[4] = vertCount + 1;
- tris[5] = vertCount + 2;
- triangles.AddRange(tris);
- NativeArray<float2> uv = new NativeArray<float2>(4, Allocator.Temp);
- uv[0] = bottomLeftUV + new float2(.5f, 0);
- uv[1] = bottomLeftUV + new float2(.5f, .25f);
- uv[2] = bottomLeftUV + new float2(0, .25f);
- uv[3] = bottomLeftUV;
- uvs.AddRange(uv);
- }
- private bool IsFaceVisible(int x, int y, int z, int faceIndex)
- {
- int3 direction = faceDirections[faceIndex];
- int3 neighbor = new int3(x + direction.x, y + direction.y, z + direction.z);
- if (neighbor.y < 0 || neighbor.y >= chunkDimensions.y)
- return false;
- if (neighbor.x < 0)
- return leftChunkData[CalculateVoxelIndex(chunkDimensions.x-1, neighbor.y, neighbor.z)] == 0;
- if (neighbor.x >= chunkDimensions.x)
- return rightChunkData[CalculateVoxelIndex(0, neighbor.y, neighbor.z)] == 0;
- if (neighbor.z < 0)
- return backChunkData[CalculateVoxelIndex(neighbor.x, neighbor.y, chunkDimensions.x-1)] == 0;
- if (neighbor.z >= chunkDimensions.x)
- return frontChunkData[CalculateVoxelIndex(neighbor.x, neighbor.y, 0)] == 0;
- return thisChunkData[CalculateVoxelIndex(neighbor.x, neighbor.y, neighbor.z)] == 0;
- }
- //Get the bottom left UV for all 6 faces
- public NativeArray<float2> GetBlockUVs(int blockIndex)
- {
- NativeArray<float2> uvs = new NativeArray<float2>(6, Allocator.Temp);
- switch (blockIndex)
- {
- case 1:
- uvs[0] = new float2(0, 0);
- uvs[1] = new float2(0, 0);
- uvs[2] = new float2(0, 0);
- uvs[3] = new float2(0, 0);
- uvs[4] = new float2(0, 0);
- uvs[5] = new float2(0, 0);
- break;
- case 2:
- uvs[0] = new float2(0, .5f);
- uvs[1] = new float2(0, .5f);
- uvs[2] = new float2(0, .5f);
- uvs[3] = new float2(0, .5f);
- uvs[4] = new float2(0, .5f);
- uvs[5] = new float2(0, .5f);
- break;
- case 3:
- uvs[0] = new float2(0, .5f);
- uvs[1] = new float2(.5f, .5f);
- uvs[2] = new float2(.5f, .5f);
- uvs[3] = new float2(.5f, .5f);
- uvs[4] = new float2(.5f, .5f);
- uvs[5] = new float2(0, .25f);
- break;
- case 4:
- uvs[0] = new float2(.5f, 0);
- uvs[1] = new float2(.5f, 0);
- uvs[2] = new float2(.5f, 0);
- uvs[3] = new float2(.5f, 0);
- uvs[4] = new float2(.5f, 0);
- uvs[5] = new float2(.5f, 0);
- break;
- case 5:
- uvs[0] = new float2(.5f, .25f);
- uvs[1] = new float2(.5f, .25f);
- uvs[2] = new float2(.5f, .25f);
- uvs[3] = new float2(.5f, .25f);
- uvs[4] = new float2(.5f, .25f);
- uvs[5] = new float2(.5f, .25f);
- break;
- }
- return uvs;
- }
- public int CalculateVoxelIndex(int x, int y, int z)
- {
- return x * (chunkDimensions.y * chunkDimensions.x) + y * chunkDimensions.x + z;
- }
- }
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- public class EndlessTerrain : MonoBehaviour
- {
- public float maxViewDst;
- public float colliderRange;
- public Transform viewer;
- public static Vector2 viewerPosition;
- int chunksVisibleInViewDst;
- Vector2Int chunkDimensions;
- Dictionary<Vector2, TerrainChunk> chunkDictionary = new Dictionary<Vector2, TerrainChunk>();
- List<TerrainChunk> chunksVisibleLastUpdate = new List<TerrainChunk>();
- void Start()
- {
- chunkDimensions = ChunkGenerator.ChunkDimensions;
- chunksVisibleInViewDst = Mathf.RoundToInt(maxViewDst / chunkDimensions.x);
- }
- void Update()
- {
- viewerPosition = new Vector2(viewer.position.x, viewer.position.z);
- UpdateVisibleChunks();
- }
- void UpdateVisibleChunks()
- {
- for (int i = 0; i < chunksVisibleLastUpdate.Count; i++)
- {
- chunksVisibleLastUpdate[i].chunkObject.SetActive(false);
- }
- chunksVisibleLastUpdate.Clear();
- int currentChunkCoordX = (int)Mathf.Round(viewerPosition.x / chunkDimensions.x);
- int currentChunkCoordY = (int)Mathf.Round(viewerPosition.y / chunkDimensions.x);
- for (int yOffset = -chunksVisibleInViewDst; yOffset <= chunksVisibleInViewDst; yOffset++) //Loops through all the current chunks
- {
- for (int xOffset = -chunksVisibleInViewDst; xOffset <= chunksVisibleInViewDst; xOffset++)
- {
- Vector2Int viewedChunkCoord = new Vector2Int(currentChunkCoordX + xOffset, currentChunkCoordY + yOffset);
- if (chunkDictionary.ContainsKey(viewedChunkCoord)) //Checks if a chunk with the correct cordinates has been loaded previously
- {
- TerrainChunk viewedChunk = chunkDictionary[viewedChunkCoord];
- viewedChunk.UpdateTerrainChunk();
- if (viewedChunk.IsVisible())
- {
- chunksVisibleLastUpdate.Add(viewedChunk);
- }
- }
- else
- {
- chunkDictionary.Add(viewedChunkCoord, new TerrainChunk(viewedChunkCoord, transform, maxViewDst, colliderRange));
- }
- }
- }
- }
- public class TerrainChunk
- {
- public GameObject chunkObject;
- ChunkGenerator chunkGen;
- Vector2Int position;
- Bounds bounds;
- float maxViewDst;
- float colliderRange;
- bool hasCollider;
- public TerrainChunk(Vector2Int coord, Transform parent, float maxViewDst, float colliderRange)
- {
- Vector2Int chunkDimensions = ChunkGenerator.ChunkDimensions;
- position = coord * chunkDimensions.x;
- bounds = new Bounds(new Vector2(position.x, position.y), Vector2.one * chunkDimensions.x);
- chunkGen = GameObject.Find("ChunkGenerator").GetComponent<ChunkGenerator>();
- chunkObject = chunkGen.CreateChunkObject(position);
- chunkObject.transform.position = new Vector3(position.x - (chunkDimensions.x / 2), 0, position.y - (chunkDimensions.x / 2));
- chunkObject.transform.parent = parent;
- chunkObject.SetActive(false);
- this.maxViewDst = maxViewDst;
- this.colliderRange = colliderRange;
- }
- public void UpdateTerrainChunk()
- {
- float viewerDstFromNearestEdge = Mathf.Sqrt(bounds.SqrDistance(viewerPosition));
- if(viewerDstFromNearestEdge < colliderRange && !hasCollider)
- {
- chunkObject.AddComponent<MeshCollider>();
- hasCollider = true;
- }
- bool visible = viewerDstFromNearestEdge <= maxViewDst; //Checks if the chunk is too far away from the player, if so it deactivates it
- chunkObject.SetActive(visible);
- }
- public bool IsVisible()
- {
- return chunkObject.activeSelf;
- }
- }
- }
- using System.Collections.Generic;
- using Unity.Collections;
- using UnityEngine;
- using Unity.Mathematics;
- using Unity.Jobs;
- using UnityEngine.Rendering;
- public class ChunkGenerator : MonoBehaviour
- {
- public Texture2D atlas;
- public Vector2Int chunkDimensions;
- public static Vector2Int ChunkDimensions;
- public int maxProccessingFrames;
- [Header("Terrain Settings")]
- public int surfaceLevel;
- public int seaLevel;
- public float sandDensity;
- public float maxTreeHeight;
- [Header("Noise Settings")]
- public float persistance;
- public float frequency;
- public float lacunarity;
- public int numOfOctaves;
- public Vector2Int offset;
- public AnimationCurve heightCurve;
- public float heightMultiplier;
- public float noise3DContribution;
- public int noiseSeed;
- [Header(" ")]
- public bool autoUpdate;
- public string executionTime;
- Noise noise;
- NativeArray<int3> faceVertices;
- NativeArray<int3> faceDirections;
- NativeArray<float2> uvCoordinates;
- NativeArray<float> sampledCurve;
- [HideInInspector]
- public NativeHashMap<int2, NativeArray<int>> chunkDataMap;
- List<JobData> jobList;
- private void Start()
- {
- Initialize();
- executionTime = "N/A";
- }
- private void OnValidate()
- {
- if (autoUpdate)
- {
- GenerateChunk();
- }
- }
- public void GenerateChunk()
- {
- Initialize();
- if(GameObject.Find("Chunk") == null)
- {
- float startTime = Time.realtimeSinceStartup;
- CreateChunkObject(offset);
- CompleteJobs(false);
- executionTime = (Time.realtimeSinceStartup - startTime) * 1000f + " ms";
- }
- else
- {
- float startTime = Time.realtimeSinceStartup;
- Mesh mesh = CreateChunkMesh(offset);
- CompleteJobs(false);
- executionTime = (Time.realtimeSinceStartup - startTime) * 1000f + " ms";
- GameObject.Find("Chunk").GetComponent<MeshFilter>().mesh = mesh;
- }
- faceVertices.Dispose();
- faceDirections.Dispose();
- uvCoordinates.Dispose();
- }
- public GameObject CreateChunkObject(Vector2Int offset)
- {
- GameObject chunk = new GameObject("Chunk");
- var meshRenderer = chunk.AddComponent<MeshRenderer>();
- meshRenderer.sharedMaterial = new Material(Shader.Find("Standard"))
- {
- mainTexture = atlas
- };
- chunk.AddComponent<MeshFilter>().mesh = CreateChunkMesh(offset);
- return chunk;
- }
- public Mesh CreateChunkMesh(Vector2Int offset, NativeArray<int> customVoxelValues = default)
- {
- Mesh mesh = new Mesh
- {
- indexFormat = IndexFormat.UInt32
- };
- NativeList<float3> vertices = new NativeList<float3>(Allocator.TempJob);
- NativeList<int> triangles = new NativeList<int>(Allocator.TempJob);
- NativeList<float2> uvs = new NativeList<float2>(Allocator.TempJob);
- int2 intOffset = new int2(offset.x, offset.y);
- if(customVoxelValues == default){
- if (!chunkDataMap.ContainsKey(intOffset))
- chunkDataMap.Add(intOffset, noise.GenerateVoxelValues(offset));
- }
- else{
- if (!chunkDataMap.ContainsKey(intOffset))
- chunkDataMap.Add(intOffset, customVoxelValues);
- }
- AddNeighboringChunkData(intOffset, offset);
- ChunkJob job = new ChunkJob
- {
- vertices = vertices,
- triangles = triangles,
- uvs = uvs,
- thisChunkData = chunkDataMap[intOffset],
- rightChunkData = chunkDataMap[intOffset + new int2(chunkDimensions.x, 0)],
- leftChunkData = chunkDataMap[intOffset + new int2(-chunkDimensions.x, 0)],
- frontChunkData = chunkDataMap[intOffset + new int2(0, chunkDimensions.x)],
- backChunkData = chunkDataMap[intOffset + new int2(0, -chunkDimensions.x)],
- faceDirections = faceDirections,
- uvCordinates = uvCoordinates,
- faceVertices = faceVertices,
- chunkDimensions = new int2(chunkDimensions.x, chunkDimensions.y)
- };
- JobHandle handle = job.Schedule();
- jobList.Add(new JobData
- {
- mesh = mesh,
- handle = handle,
- vertices = vertices,
- triangles = triangles,
- uvs = uvs,
- });
- return mesh;
- }
- private void AddNeighboringChunkData(int2 intOffset, Vector2Int offset)
- {
- if(!chunkDataMap.ContainsKey(intOffset + new int2(chunkDimensions.x, 0)))
- chunkDataMap.Add(intOffset + new int2(chunkDimensions.x, 0), noise.GenerateVoxelValues(offset + Vector2Int.right * chunkDimensions.x));
- if (!chunkDataMap.ContainsKey(intOffset + new int2(-chunkDimensions.x, 0)))
- chunkDataMap.Add(intOffset + new int2(-chunkDimensions.x, 0), noise.GenerateVoxelValues(offset + Vector2Int.left * chunkDimensions.x));
- if (!chunkDataMap.ContainsKey(intOffset + new int2(0, chunkDimensions.x)))
- chunkDataMap.Add(intOffset + new int2(0, chunkDimensions.x), noise.GenerateVoxelValues(offset + Vector2Int.up * chunkDimensions.x));
- if (!chunkDataMap.ContainsKey(intOffset + new int2(0, -chunkDimensions.x)))
- chunkDataMap.Add(intOffset + new int2(0, -chunkDimensions.x), noise.GenerateVoxelValues(offset + Vector2Int.down * chunkDimensions.x));
- }
- public static int CalculateVoxelIndex(int x, int y, int z)
- {
- return x * (ChunkDimensions.y * ChunkDimensions.x) + y * ChunkDimensions.x + z;
- }
- private void LateUpdate()
- {
- CompleteJobs(true);
- }
- void CompleteJobs(bool waitForCompletion)
- {
- for (int i = jobList.Count - 1; i >= 0; i--)
- {
- if (jobList[i].handle.IsCompleted || jobList[i].frameCount == maxProccessingFrames || !waitForCompletion)
- {
- jobList[i].handle.Complete();
- NativeArray<Vector3> vertexArray = jobList[i].vertices.AsArray().Reinterpret<Vector3>();
- NativeArray<int> triangleArray = jobList[i].triangles.AsArray();
- NativeArray<Vector2> uvArray = jobList[i].uvs.AsArray().Reinterpret<Vector2>();
- // Assign data to mesh
- jobList[i].mesh.SetVertexBufferParams(vertexArray.Length, new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3));
- jobList[i].mesh.SetVertexBufferData(vertexArray, 0, 0, vertexArray.Length, 0, MeshUpdateFlags.Default);
- jobList[i].mesh.SetIndexBufferParams(triangleArray.Length, IndexFormat.UInt32);
- jobList[i].mesh.SetIndexBufferData(triangleArray, 0, 0, triangleArray.Length, MeshUpdateFlags.Default);
- jobList[i].mesh.SetSubMesh(0, new SubMeshDescriptor(0, triangleArray.Length), MeshUpdateFlags.Default);
- jobList[i].mesh.SetUVs(0, uvArray);
- jobList[i].mesh.RecalculateBounds();
- jobList[i].mesh.RecalculateNormals();
- jobList[i].vertices.Dispose();
- jobList[i].triangles.Dispose();
- jobList[i].uvs.Dispose();
- }
- jobList[i].frameCount++;
- jobList.RemoveAt(i);
- }
- }
- class JobData
- {
- public JobHandle handle;
- public Mesh mesh;
- public NativeList<float3> vertices;
- public NativeList<int> triangles;
- public NativeList<float2> uvs;
- public int frameCount;
- }
- private NativeArray<float> SampleCurve(AnimationCurve curve, int resolution)
- {
- NativeArray<float> curveArr = new NativeArray<float>(resolution, Allocator.Persistent);
- for (int i = 0; i < resolution; i++)
- {
- curveArr[i] = curve.Evaluate((float)i / resolution);
- }
- return curveArr;
- }
- private void Initialize()
- {
- System.Random rand = new System.Random(noiseSeed);
- chunkDataMap = new NativeHashMap<int2, NativeArray<int>>(1024, Allocator.Persistent);
- jobList = new();
- sampledCurve = SampleCurve(heightCurve, 256);
- ChunkDimensions = chunkDimensions;
- noise = new Noise(frequency, persistance, lacunarity, numOfOctaves, heightMultiplier, rand.Next() / 10000, surfaceLevel, seaLevel, noise3DContribution, sandDensity, maxTreeHeight, sampledCurve);
- faceVertices = new NativeArray<int3>(24, Allocator.Persistent);
- //Bottom face
- faceVertices[0] = new int3(1, 0, 0);
- faceVertices[1] = new int3(1, 0, 1);
- faceVertices[2] = new int3(0, 0, 1);
- faceVertices[3] = new int3(0, 0, 0);
- //Front face
- faceVertices[4] = new int3(1, 0, 1);
- faceVertices[5] = new int3(1, 1, 1);
- faceVertices[6] = new int3(0, 1, 1);
- faceVertices[7] = new int3(0, 0, 1);
- //Back face
- faceVertices[8] = new int3(0, 0, 0);
- faceVertices[9] = new int3(0, 1, 0);
- faceVertices[10] = new int3(1, 1, 0);
- faceVertices[11] = new int3(1, 0, 0);
- //Left face
- faceVertices[12] = new int3(0, 0, 1);
- faceVertices[13] = new int3(0, 1, 1);
- faceVertices[14] = new int3(0, 1, 0);
- faceVertices[15] = new int3(0, 0, 0);
- //Right face
- faceVertices[16] = new int3(1, 0, 0);
- faceVertices[17] = new int3(1, 1, 0);
- faceVertices[18] = new int3(1, 1, 1);
- faceVertices[19] = new int3(1, 0, 1);
- //Top face
- faceVertices[20] = new int3(0, 1, 0);
- faceVertices[21] = new int3(0, 1, 1);
- faceVertices[22] = new int3(1, 1, 1);
- faceVertices[23] = new int3(1, 1, 0);
- uvCoordinates = new NativeArray<float2>(6, Allocator.Persistent);
- uvCoordinates[0] = new float2(.5f, 0);
- uvCoordinates[1] = new float2(.5f, .5f);
- uvCoordinates[2] = new float2(.5f, .5f);
- uvCoordinates[3] = new float2(.5f, .5f);
- uvCoordinates[4] = new float2(.5f, .5f);
- uvCoordinates[5] = new float2(0, 0);
- faceDirections = new NativeArray<int3>(6, Allocator.Persistent);
- faceDirections[0] = new int3(0, -1, 0); // Down
- faceDirections[1] = new int3(0, 0, 1); // Forward
- faceDirections[2] = new int3(0, 0, -1); // Back
- faceDirections[3] = new int3(-1, 0, 0); // Left
- faceDirections[4] = new int3(1, 0, 0); // Right
- faceDirections[5] = new int3(0, 1, 0); // Up
- }
- private void OnDestroy()
- {
- faceVertices.Dispose();
- faceDirections.Dispose();
- uvCoordinates.Dispose();
- foreach (var chunk in chunkDataMap)
- {
- chunk.Value.Dispose();
- }
- chunkDataMap.Dispose();
- }
- }
- using Unity.Collections;
- using UnityEngine;
- using Unity.Mathematics;
- using UnityEngine.Jobs;
- using Unity.Jobs;
- using Unity.Burst;
- //Block Indexes:
- //1 = Stone
- //2 = Dirt
- //3 = Grass
- //4 = Sand
- //5 = Water
- public class Noise
- {
- float frequency;
- float lacunarity;
- float persistance;
- float seed;
- float height;
- float noise3DContribution;
- int numOfOctaves;
- int surfaceLevel;
- int seaLevel;
- float sandDensity;
- float maxTreeHeight;
- NativeArray<float> curve;
- int2 chunkDimensions;
- public Noise(float frequency, float persistance, float lacunarity, int numOfOctaves, float height, float seed, int surfaceLevel, int seaLevel, float noise3DContribution, float sandDensity, float maxTreeHeight, NativeArray<float> curve)
- {
- this.frequency = frequency;
- this.persistance = persistance;
- this.lacunarity = lacunarity;
- this.numOfOctaves = numOfOctaves;
- this.height = height;
- this.seed = seed;
- this.noise3DContribution = noise3DContribution;
- this.curve = curve;
- this.surfaceLevel = surfaceLevel;
- this.seaLevel = seaLevel;
- this.sandDensity = sandDensity;
- this.maxTreeHeight = maxTreeHeight;
- chunkDimensions = new int2(ChunkGenerator.ChunkDimensions.x, ChunkGenerator.ChunkDimensions.y);
- }
- public NativeArray<int> GenerateVoxelValues(Vector2Int offset)
- {
- NativeArray<int> voxelValues = new NativeArray<int>(chunkDimensions.x * chunkDimensions.y * chunkDimensions.x, Allocator.Persistent);
- NoiseJob job = new NoiseJob
- {
- voxelValues = voxelValues,
- chunkDimensions = chunkDimensions,
- offset = new int2(offset.x, offset.y),
- curve = curve,
- height = height,
- sandDensity = sandDensity,
- maxTreeHeight = maxTreeHeight,
- surfaceLevel = surfaceLevel,
- seaLevel = seaLevel,
- numOfOctaves = numOfOctaves,
- seed = seed,
- lacunarity = lacunarity,
- persistance = persistance,
- frequency = frequency,
- noise3DContribution = noise3DContribution
- };
- job.Schedule(chunkDimensions.x * chunkDimensions.x, 16).Complete();
- return voxelValues;
- }
- [BurstCompile]
- struct NoiseJob : IJobParallelFor
- {
- [NativeDisableParallelForRestriction]
- public NativeArray<int> voxelValues;
- public int2 chunkDimensions;
- public int2 offset;
- [ReadOnly]
- public NativeArray<float> curve;
- public float height;
- public float sandDensity;
- public float maxTreeHeight;
- public float noise3DContribution;
- public int surfaceLevel;
- public int seaLevel;
- public int numOfOctaves;
- public float seed;
- public float lacunarity;
- public float persistance;
- public float frequency;
- public void Execute(int i)
- {
- int x = i % chunkDimensions.x;
- int z = i / chunkDimensions.x;
- float noiseValue = GetNoise(x + offset.x, z + offset.y);
- float noise01 = Remap(noiseValue, -1, 1, 0, 1);
- int curveIndex = (int)math.clamp(noise01 * curve.Length, 0, curve.Length - 1);
- noiseValue *= height * curve[curveIndex];
- noiseValue += surfaceLevel;
- for (int y = 0; y < chunkDimensions.y; y++)
- {
- float noise3D = Get3DNoise(x + offset.x, y, z + offset.y);
- //Water
- if (y == seaLevel)
- {
- voxelValues[CalculateVoxelIndex(x, y, z)] = 5;
- }
- if (y < noiseValue + (noise3D * height * noise3DContribution))
- {
- voxelValues[CalculateVoxelIndex(x, y, z)] = 1;
- bool isSand = (y + 1 < seaLevel && noise.snoise(new float2(x * .1f, z * .1f)) < sandDensity) || y < seaLevel - 3;
- //Add grass / sand
- if (y + 3 < chunkDimensions.y)
- {
- voxelValues[CalculateVoxelIndex(x, y + 1, z)] = isSand ? 4 : 2;
- voxelValues[CalculateVoxelIndex(x, y + 2, z)] = isSand ? 4 : 2;
- voxelValues[CalculateVoxelIndex(x, y + 3, z)] = isSand ? 4 : 3;
- }
- float treeNoise = noise.snoise(new float2((x + offset.x) * .01f, (z + offset.y) * .01f));
- float random = noise.snoise(new float2((x + offset.x) * 10000, (z + offset.y) * 10000));
- if (treeNoise < 0 && random < -0.7f && y < maxTreeHeight)
- {
- voxelValues[CalculateVoxelIndex(x, y + 4, z)] = 5;
- }
- }
- }
- }
- public float Remap(float value, float fromLow, float fromHigh, float toLow, float toHigh)
- {
- // Calculate the normalized position of the value in the original range
- float normalized = (value - fromLow) / (fromHigh - fromLow);
- // Scale and shift the normalized value to the new range
- float remapped = toLow + normalized * (toHigh - toLow);
- return remapped;
- }
- public int CalculateVoxelIndex(int x, int y, int z)
- {
- return x * (chunkDimensions.y * chunkDimensions.x) + y * chunkDimensions.x + z;
- }
- float Get3DNoise(int x, int y, int z)
- {
- float sum = 0;
- for (int i = 0; i < numOfOctaves; i++)
- {
- float frequency = math.pow(lacunarity, i) * this.frequency * 10;
- float amplitude = math.pow(persistance, i);
- sum += noise.snoise(new float3(x * frequency, y * frequency, z * frequency)) * amplitude;
- }
- return sum;
- }
- float GetNoise(int x, int y)
- {
- float sum = 0;
- for (int i = 0; i < numOfOctaves; i++)
- {
- float frequency = math.pow(lacunarity, i) * this.frequency;
- float amplitude = math.pow(persistance, i);
- sum += noise.snoise(new float2((x + seed) * frequency, (y - seed) * frequency)) * amplitude;
- }
- return sum;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement