public override void GenerateDataForChunkUnchecked(int3 chunkCoordinate, VoxelDataVolume <byte> existingData) { int3 chunkWorldOrigin = chunkCoordinate * VoxelWorld.WorldSettings.ChunkSize; JobHandleWithData <IVoxelDataGenerationJob> jobHandleWithData = VoxelWorld.VoxelDataGenerator.GenerateVoxelData(chunkWorldOrigin, existingData); _generationJobHandles.Add(chunkCoordinate, jobHandleWithData); }
/// <summary> /// Sets the job handle for a chunk coordinate /// </summary> /// <param name="generationJobHandle">The job handle with data</param> /// <param name="chunkCoordinate">The coordinate of the chunk to set the job handle for</param> public void SetVoxelDataJobHandle(JobHandleWithData <IVoxelDataGenerationJob> generationJobHandle, int3 chunkCoordinate) { if (!_generationJobHandles.ContainsKey(chunkCoordinate)) { _generationJobHandles.Add(chunkCoordinate, generationJobHandle); } }
/// <summary> /// Starts a mesh generation job /// </summary> /// <param name="voxelDataStore">The store where to retrieve the voxel data from</param> /// <param name="chunkCoordinate">The coordinate of the chunk that will be generated</param> /// <returns>The job handle and the actual mesh generation job</returns> public override JobHandleWithData <IMesherJob> CreateMesh(VoxelDataStore voxelDataStore, int3 chunkCoordinate) { if (!voxelDataStore.TryGetVoxelDataChunk(chunkCoordinate, out VoxelDataVolume boundsVoxelData)) { return(null); } NativeCounter vertexCountCounter = new NativeCounter(Allocator.TempJob); int voxelCount = (boundsVoxelData.Width - 1) * (boundsVoxelData.Height - 1) * (boundsVoxelData.Depth - 1); int maxLength = 15 * voxelCount; NativeArray <MeshingVertexData> outputVertices = new NativeArray <MeshingVertexData>(maxLength, Allocator.TempJob); NativeArray <ushort> outputTriangles = new NativeArray <ushort>(maxLength, Allocator.TempJob); MarchingCubesJob marchingCubesJob = new MarchingCubesJob { VoxelData = boundsVoxelData, Isolevel = Isolevel, VertexCountCounter = vertexCountCounter, OutputVertices = outputVertices, OutputTriangles = outputTriangles }; JobHandle jobHandle = marchingCubesJob.Schedule(voxelCount, 128); JobHandleWithData <IMesherJob> jobHandleWithData = new JobHandleWithData <IMesherJob>(); jobHandleWithData.JobHandle = jobHandle; jobHandleWithData.JobData = marchingCubesJob; return(jobHandleWithData); }
/// <summary> /// Moves a chunk to a different coordinate if a chunk doesn't already exist there /// </summary> /// <param name="fromCoordinate">The coordinate of the chunk to move</param> /// <param name="toCoordinate">The coordinate where the chunk should be moved</param> private void MoveChunk(int3 fromCoordinate, int3 toCoordinate) { if (!VoxelWorld.ChunkStore.TryGetChunkAtCoordinate(fromCoordinate, out Chunk chunk)) { Debug.LogWarning($"No chunk at {fromCoordinate.ToString()}, exiting the function"); return; } if (VoxelWorld.ChunkStore.DoesChunkExistAtCoordinate(toCoordinate)) { Debug.LogWarning($"A chunk already exists at {toCoordinate.ToString()}, exiting the function"); return; } Bounds generationBounds = BoundsUtilities.GetChunkBounds(toCoordinate, VoxelWorld.WorldSettings.ChunkSize); JobHandleWithData <IVoxelDataGenerationJob> jobHandleWithData = VoxelWorld.VoxelDataGenerator.GenerateVoxelData(generationBounds); jobHandleWithData.JobHandle.Complete(); VoxelWorld.VoxelDataStore.SetVoxelDataChunk(jobHandleWithData.JobData.OutputVoxelData, toCoordinate); VoxelWorld.ChunkStore.RemoveChunk(fromCoordinate); chunk.Initialize(toCoordinate, VoxelWorld); VoxelWorld.ChunkStore.AddChunk(chunk); }
/// <summary> /// Loads a chunk to a specific coordinate /// </summary> /// <param name="chunkCoordinate">The coordinate of the chunk to load</param> /// <returns>The newly loaded chunk</returns> public Chunk LoadChunkToCoordinate(int3 chunkCoordinate) { int3 worldPosition = chunkCoordinate * VoxelWorld.WorldSettings.ChunkSize; Chunk chunk = Instantiate(VoxelWorld.WorldSettings.ChunkPrefab, worldPosition.ToVectorInt(), Quaternion.identity); Bounds chunkBounds = BoundsUtilities.GetChunkBounds(chunkCoordinate, VoxelWorld.WorldSettings.ChunkSize); JobHandleWithData <IVoxelDataGenerationJob> jobHandleWithData = VoxelWorld.VoxelDataGenerator.GenerateVoxelData(chunkBounds); VoxelWorld.VoxelDataStore.SetVoxelDataJobHandle(jobHandleWithData, chunkCoordinate); chunk.Initialize(chunkCoordinate, VoxelWorld); VoxelWorld.ChunkStore.AddChunk(chunk); return(chunk); }
/// <summary> /// Forces the regeneration of the mesh /// </summary> public void GenerateMeshImmediate(ChunkProperties chunkProperties) { JobHandleWithData <IMesherJob> jobHandleWithData = VoxelWorld.VoxelMesher.CreateMesh(VoxelWorld.VoxelDataStore, VoxelWorld.VoxelColorStore, chunkProperties.ChunkCoordinate); if (jobHandleWithData == null) { return; } IMesherJob job = jobHandleWithData.JobData; Mesh mesh = new Mesh(); SubMeshDescriptor subMesh = new SubMeshDescriptor(0, 0); jobHandleWithData.JobHandle.Complete(); int vertexCount = job.VertexCountCounter.Count * 3; job.VertexCountCounter.Dispose(); mesh.SetVertexBufferParams(vertexCount, MeshingVertexData.VertexBufferMemoryLayout); mesh.SetIndexBufferParams(vertexCount, IndexFormat.UInt16); mesh.SetVertexBufferData(job.OutputVertices, 0, 0, vertexCount, 0, MeshUpdateFlags.DontValidateIndices); mesh.SetIndexBufferData(job.OutputTriangles, 0, 0, vertexCount, MeshUpdateFlags.DontValidateIndices); job.OutputVertices.Dispose(); job.OutputTriangles.Dispose(); mesh.subMeshCount = 1; subMesh.indexCount = vertexCount; mesh.SetSubMesh(0, subMesh); mesh.RecalculateBounds(); chunkProperties.MeshFilter.sharedMesh = mesh; chunkProperties.MeshCollider.sharedMesh = mesh; chunkProperties.MeshCollider.enabled = true; chunkProperties.MeshRenderer.enabled = true; chunkProperties.HasChanges = false; chunkProperties.IsMeshGenerated = true; }
/// <summary> /// Starts generating the voxel data for a specified volume /// </summary> /// <param name="bounds">The volume to generate the voxel data for</param> /// <param name="allocator">The allocator for the new <see cref="VoxelDataVolume"/></param> /// <returns>The job handle and the voxel data generation job</returns> public override JobHandleWithData <IVoxelDataGenerationJob> GenerateVoxelData(Bounds bounds, Allocator allocator) { VoxelDataVolume voxelData = new VoxelDataVolume(bounds.size.ToInt3(), allocator); ProceduralTerrainVoxelDataCalculationJob job = new ProceduralTerrainVoxelDataCalculationJob { WorldPositionOffset = bounds.min.ToInt3(), OutputVoxelData = voxelData, ProceduralTerrainSettings = proceduralTerrainSettings }; JobHandle jobHandle = job.Schedule(voxelData.Length, 256); JobHandleWithData <IVoxelDataGenerationJob> jobHandleWithData = new JobHandleWithData <IVoxelDataGenerationJob>(); jobHandleWithData.JobHandle = jobHandle; jobHandleWithData.JobData = job; return(jobHandleWithData); }
/// <inheritdoc/> public override JobHandleWithData <IVoxelDataGenerationJob> GenerateVoxelData(int3 worldSpaceOrigin, VoxelDataVolume <byte> outputVoxelDataArray) { ProceduralTerrainVoxelDataCalculationJob job = new ProceduralTerrainVoxelDataCalculationJob { WorldPositionOffset = worldSpaceOrigin, OutputVoxelData = outputVoxelDataArray, ProceduralTerrainSettings = proceduralTerrainSettings }; JobHandle jobHandle = job.Schedule(); JobHandleWithData <IVoxelDataGenerationJob> jobHandleWithData = new JobHandleWithData <IVoxelDataGenerationJob> { JobHandle = jobHandle, JobData = job }; return(jobHandleWithData); }
/// <inheritdoc/> public override JobHandleWithData <IMesherJob> CreateMesh(VoxelDataStore voxelDataStore, VoxelColorStore voxelColorStore, int3 chunkCoordinate) { if (!voxelDataStore.TryGetDataChunk(chunkCoordinate, out VoxelDataVolume <byte> boundsVoxelData)) { return(null); } if (!voxelColorStore.TryGetDataChunk(chunkCoordinate, out VoxelDataVolume <Color32> boundsVoxelColors)) { return(null); } NativeCounter vertexCountCounter = new NativeCounter(Allocator.TempJob); int voxelCount = VoxelWorld.WorldSettings.ChunkSize.x * VoxelWorld.WorldSettings.ChunkSize.y * VoxelWorld.WorldSettings.ChunkSize.z; int maxLength = 15 * voxelCount; NativeArray <MeshingVertexData> outputVertices = new NativeArray <MeshingVertexData>(maxLength, Allocator.TempJob); NativeArray <ushort> outputTriangles = new NativeArray <ushort>(maxLength, Allocator.TempJob); MarchingCubesJob marchingCubesJob = new MarchingCubesJob { VoxelData = boundsVoxelData, VoxelColors = boundsVoxelColors, Isolevel = Isolevel, VertexCountCounter = vertexCountCounter, OutputVertices = outputVertices, OutputTriangles = outputTriangles }; JobHandle jobHandle = marchingCubesJob.Schedule(); JobHandleWithData <IMesherJob> jobHandleWithData = new JobHandleWithData <IMesherJob> { JobHandle = jobHandle, JobData = marchingCubesJob }; return(jobHandleWithData); }
/// <inheritdoc/> public override JobHandleWithData <IVoxelDataGenerationJob> GenerateVoxelData(int3 worldSpaceOrigin, VoxelDataVolume <byte> outputVoxelDataArray) { HeightmapTerrainVoxelDataCalculationJob job = new HeightmapTerrainVoxelDataCalculationJob { WorldPositionOffset = worldSpaceOrigin, OutputVoxelData = outputVoxelDataArray, HeightmapData = heightmapWorldGenerator.HeightmapTerrainSettings.HeightmapData, HeightmapWidth = heightmapWorldGenerator.HeightmapTerrainSettings.Width, HeightmapHeight = heightmapWorldGenerator.HeightmapTerrainSettings.Height, Amplitude = heightmapWorldGenerator.HeightmapTerrainSettings.Amplitude, HeightOffset = heightmapWorldGenerator.HeightmapTerrainSettings.HeightOffset }; JobHandle jobHandle = job.Schedule(); JobHandleWithData <IVoxelDataGenerationJob> jobHandleWithData = new JobHandleWithData <IVoxelDataGenerationJob> { JobHandle = jobHandle, JobData = job }; return(jobHandleWithData); }
/// <summary> /// Starts generating the voxel data for a specified volume /// </summary> /// <param name="bounds">The volume to generate the voxel data for</param> /// <param name="allocator">The allocator for the new <see cref="VoxelDataVolume"/></param> /// <returns>The job handle and the voxel data generation job</returns> public override JobHandleWithData <IVoxelDataGenerationJob> GenerateVoxelData(Bounds bounds, Allocator allocator) { VoxelDataVolume voxelData = new VoxelDataVolume(bounds.size.ToInt3(), allocator); HeightmapTerrainVoxelDataCalculationJob job = new HeightmapTerrainVoxelDataCalculationJob { WorldPositionOffset = bounds.min.ToInt3(), OutputVoxelData = voxelData, HeightmapData = heightmapWorldGenerator.HeightmapTerrainSettings.HeightmapData, HeightmapWidth = heightmapWorldGenerator.HeightmapTerrainSettings.Width, HeightmapHeight = heightmapWorldGenerator.HeightmapTerrainSettings.Height, Amplitude = heightmapWorldGenerator.HeightmapTerrainSettings.Amplitude, HeightOffset = heightmapWorldGenerator.HeightmapTerrainSettings.HeightOffset }; JobHandle jobHandle = job.Schedule(voxelData.Length, 256); JobHandleWithData <IVoxelDataGenerationJob> jobHandleWithData = new JobHandleWithData <IVoxelDataGenerationJob>(); jobHandleWithData.JobHandle = jobHandle; jobHandleWithData.JobData = job; return(jobHandleWithData); }