public bool PostBuild(int lodIndex, Mesh visualMesh, Mesh collisionMesh, ChunkTriggerBounds bounds) { var hasVisualMesh = chunks[lodIndex].PostBuild(visualMesh, collisionMesh, bounds); if (LODCount > 1) { lodGroup.RecalculateBounds(); } return(hasVisualMesh); }
public void Load() { Utils.Profiler.BeginSample("VoxelChunk.Load"); // Feed heights again in case they have been modified FeedHeights(digger, voxelPosition, ref heightArray); FeedAlphamaps(); var path = digger.GetPathVoxelFile(chunkPosition, false); var rawBytes = Utils.GetBytes(path); if (rawBytes == null) { if (voxelArray == null) { // If there is no persisted voxels but voxel array is null, then we fallback and (re)generate them. GenerateVoxels(digger, heightArray, voxelPosition.y, ref voxelArray); digger.EnsureChunkWillBePersisted(this); } Utils.Profiler.EndSample(); return; } ReadVoxelFile(sizeVox, rawBytes, ref voxelArray); var hScale = digger.HeightmapScale; var metadataPath = digger.GetPathVoxelMetadataFile(chunkPosition, false); rawBytes = Utils.GetBytes(metadataPath); if (rawBytes == null) { Debug.LogError($"Could not read metadata file of chunk {chunkPosition}"); Utils.Profiler.EndSample(); return; } using (Stream stream = new MemoryStream(rawBytes)) { using (var reader = new BinaryReader(stream, Encoding.Default)) { bounds = new ChunkTriggerBounds( reader.ReadBoolean(), new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()), new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()), hScale, sizeOfMesh); } } Utils.Profiler.EndSample(); }
public void DoKernelOperation(ActionType action, float intensity, Vector3 position, float radius, bool cutDetails, int textureIndex) { Utils.Profiler.BeginSample("[Dig] VoxelChunk.DoKernelOperation"); voxelArrayBeforeSmooth = new Voxel[voxelArray.Length]; Array.Copy(voxelArray, voxelArrayBeforeSmooth, voxelArray.Length); var voxels = new NativeArray <Voxel>(voxelArray, Allocator.TempJob); var voxelsOut = new NativeArray <Voxel>(voxelArray, Allocator.TempJob); var heights = new NativeArray <float>(heightArray, Allocator.TempJob); #if UNITY_2019_3_OR_NEWER var chunkHoles = new NativeArray <int>(sizeOfMesh * sizeOfMesh, Allocator.TempJob); #else var toCut = new NativeCollections.NativeQueue <CutEntry>(Allocator.TempJob); var toTriggerBounds = new NativeCollections.NativeQueue <float3>(Allocator.TempJob); #endif var tData = digger.Terrain.terrainData; var hScale = digger.HeightmapScale; var holeScale = digger.HoleMapScale; var cutSizeX = Math.Max(1, (int)(hScale.x / holeScale.x)); var cutSizeZ = Math.Max(1, (int)(hScale.z / holeScale.z)); var jobData = new VoxelKernelModificationJob { SizeVox = sizeVox, SizeVox2 = sizeVox * sizeVox, SizeOfMesh = sizeOfMesh, LowInd = sizeVox - 3, Action = action, HeightmapScale = digger.HeightmapScale, Voxels = voxels, VoxelsOut = voxelsOut, Intensity = intensity, Center = position, Radius = radius, RadiusWithMargin = radius + Math.Max(Math.Max(digger.CutMargin.x, digger.CutMargin.y), digger.CutMargin.z), ChunkAltitude = voxelPosition.y, Heights = heights, CutSize = new int2(cutSizeX, cutSizeZ), #if UNITY_2019_3_OR_NEWER Holes = chunkHoles, #else WorldPosition = worldPosition, ToCut = toCut.ToConcurrent(), TerrainRelativePositionToHolePosition = new float2(1f / tData.size.x * tData.alphamapWidth, 1f / tData.size.z * tData.alphamapHeight), ToTriggerBounds = toTriggerBounds.ToConcurrent(), #endif NeighborVoxelsLBB = LoadVoxels(digger, chunkPosition + new Vector3i(-1, -1, -1)), NeighborVoxelsLBF = LoadVoxels(digger, chunkPosition + new Vector3i(-1, -1, +1)), NeighborVoxelsLB_ = LoadVoxels(digger, chunkPosition + new Vector3i(-1, -1, +0)), NeighborVoxels_BB = LoadVoxels(digger, chunkPosition + new Vector3i(+0, -1, -1)), NeighborVoxels_BF = LoadVoxels(digger, chunkPosition + new Vector3i(+0, -1, +1)), NeighborVoxels_B_ = LoadVoxels(digger, chunkPosition + new Vector3i(+0, -1, +0)), NeighborVoxelsRBB = LoadVoxels(digger, chunkPosition + new Vector3i(+1, -1, -1)), NeighborVoxelsRBF = LoadVoxels(digger, chunkPosition + new Vector3i(+1, -1, +1)), NeighborVoxelsRB_ = LoadVoxels(digger, chunkPosition + new Vector3i(+1, -1, +0)), NeighborVoxelsL_B = LoadVoxels(digger, chunkPosition + new Vector3i(-1, +0, -1)), NeighborVoxelsL_F = LoadVoxels(digger, chunkPosition + new Vector3i(-1, +0, +1)), NeighborVoxelsL__ = LoadVoxels(digger, chunkPosition + new Vector3i(-1, +0, +0)), NeighborVoxels__B = LoadVoxels(digger, chunkPosition + new Vector3i(+0, +0, -1)), NeighborVoxels__F = LoadVoxels(digger, chunkPosition + new Vector3i(+0, +0, +1)), NeighborVoxelsR_B = LoadVoxels(digger, chunkPosition + new Vector3i(+1, +0, -1)), NeighborVoxelsR_F = LoadVoxels(digger, chunkPosition + new Vector3i(+1, +0, +1)), NeighborVoxelsR__ = LoadVoxels(digger, chunkPosition + new Vector3i(+1, +0, +0)), NeighborVoxelsLUB = LoadVoxels(digger, chunkPosition + new Vector3i(-1, +1, -1)), NeighborVoxelsLUF = LoadVoxels(digger, chunkPosition + new Vector3i(-1, +1, +1)), NeighborVoxelsLU_ = LoadVoxels(digger, chunkPosition + new Vector3i(-1, +1, +0)), NeighborVoxels_UB = LoadVoxels(digger, chunkPosition + new Vector3i(+0, +1, -1)), NeighborVoxels_UF = LoadVoxels(digger, chunkPosition + new Vector3i(+0, +1, +1)), NeighborVoxels_U_ = LoadVoxels(digger, chunkPosition + new Vector3i(+0, +1, +0)), NeighborVoxelsRUB = LoadVoxels(digger, chunkPosition + new Vector3i(+1, +1, -1)), NeighborVoxelsRUF = LoadVoxels(digger, chunkPosition + new Vector3i(+1, +1, +1)), NeighborVoxelsRU_ = LoadVoxels(digger, chunkPosition + new Vector3i(+1, +1, +0)), }; // Schedule the job var handle = jobData.Schedule(voxels.Length, 64); // Wait for the job to complete handle.Complete(); jobData.DisposeNeighbors(); voxels.Dispose(); voxelsOut.CopyTo(voxelArray); voxelsOut.Dispose(); heights.Dispose(); #if UNITY_2019_3_OR_NEWER var cutter = (TerrainCutter20193)digger.Cutter; cutter.Cut(chunkHoles, voxelPosition, chunkPosition); chunkHoles.Dispose(); #else UpdateCut(cutDetails, toCut); var triggerBounds = new ChunkTriggerBounds(digger.HeightmapScale, digger.SizeOfMesh); while (toTriggerBounds.Count > 0) { triggerBounds.ExtendIfNeeded(toTriggerBounds.Dequeue()); } toTriggerBounds.Dispose(); bounds = triggerBounds; #endif #if UNITY_EDITOR RecordUndoIfNeeded(); #endif digger.EnsureChunkWillBePersisted(this); Utils.Profiler.EndSample(); }
public void DoOperation(BrushType brush, ActionType action, float intensity, Vector3 position, float radius, float coneHeight, bool upsideDown, int textureIndex, bool cutDetails, bool isTargetIntensity) { if (action == ActionType.Smooth || action == ActionType.BETA_Sharpen) { DoKernelOperation(action, intensity, position, radius, cutDetails, textureIndex); return; } Utils.Profiler.BeginSample("[Dig] VoxelChunk.DoOperation"); var heights = new NativeArray <float>(heightArray, Allocator.TempJob); var voxels = new NativeArray <Voxel>(voxelArray, Allocator.TempJob); #if UNITY_2019_3_OR_NEWER var chunkHoles = new NativeArray <int>(sizeOfMesh * sizeOfMesh, Allocator.TempJob); #else var toCut = new NativeCollections.NativeQueue <CutEntry>(Allocator.TempJob); var toTriggerBounds = new NativeCollections.NativeQueue <float3>(Allocator.TempJob); #endif var tData = digger.Terrain.terrainData; var hScale = digger.HeightmapScale; var holeScale = digger.HoleMapScale; var cutSizeX = Math.Max(1, (int)(hScale.x / holeScale.x)); var cutSizeZ = Math.Max(1, (int)(hScale.z / holeScale.z)); var jobData = new VoxelModificationJob { SizeVox = sizeVox, SizeVox2 = sizeVox * sizeVox, SizeOfMesh = sizeOfMesh, Brush = brush, Action = action, HeightmapScale = digger.HeightmapScale, ChunkAltitude = voxelPosition.y, Voxels = voxels, Heights = heights, Intensity = intensity, IsTargetIntensity = isTargetIntensity, Center = position, Radius = radius, ConeHeight = coneHeight, UpsideDown = upsideDown, RadiusWithMargin = radius + Math.Max(Math.Max(digger.CutMargin.x, digger.CutMargin.y), digger.CutMargin.z), TextureIndex = (uint)textureIndex, CutSize = new int2(cutSizeX, cutSizeZ), #if UNITY_2019_3_OR_NEWER Holes = chunkHoles #else ToCut = toCut.ToConcurrent(), WorldPosition = worldPosition, TerrainRelativePositionToHolePosition = new float2(1f / tData.size.x * tData.alphamapWidth, 1f / tData.size.z * tData.alphamapHeight), ToTriggerBounds = toTriggerBounds.ToConcurrent(), #endif }; jobData.PostConstruct(); // Schedule the job var handle = jobData.Schedule(voxels.Length, 64); // Wait for the job to complete handle.Complete(); voxels.CopyTo(voxelArray); voxels.Dispose(); heights.Dispose(); #if UNITY_2019_3_OR_NEWER var cutter = (TerrainCutter20193)digger.Cutter; if (action != ActionType.Reset) { cutter.Cut(chunkHoles, voxelPosition, chunkPosition); } else { cutter.UnCut(chunkHoles, voxelPosition, chunkPosition); } chunkHoles.Dispose(); #else UpdateCut(cutDetails, toCut); var triggerBounds = new ChunkTriggerBounds(digger.HeightmapScale, digger.SizeOfMesh); while (toTriggerBounds.Count > 0) { triggerBounds.ExtendIfNeeded(toTriggerBounds.Dequeue()); } toTriggerBounds.Dispose(); bounds = triggerBounds; #endif #if UNITY_EDITOR RecordUndoIfNeeded(); #endif digger.EnsureChunkWillBePersisted(this); Utils.Profiler.EndSample(); }
public bool PostBuild(Mesh visualMesh, Mesh collisionMesh, ChunkTriggerBounds bounds) { Utils.Profiler.BeginSample("[Dig] Chunk.PostBuild"); if (filter.sharedMesh && !isStatic) { if (Application.isEditor && !Application.isPlaying) { DestroyImmediate(filter.sharedMesh, true); } else { #if UNITY_EDITOR if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(filter.sharedMesh.GetInstanceID()))) #endif Destroy(filter.sharedMesh); } } var hasVisualMesh = false; if (!ReferenceEquals(visualMesh, null) && visualMesh.vertexCount > 0) { filter.sharedMesh = visualMesh; meshRenderer.enabled = true; hasVisualMesh = true; } else { filter.sharedMesh = null; meshRenderer.enabled = false; } if (hasCollider) { #if !UNITY_2019_3_OR_NEWER if (!bounds.IsVirgin) { var b = bounds.ToBounds(); holeCollider.center = b.center; holeCollider.size = b.size + Vector3.one * 2; holeCollider.enabled = true; } else { holeCollider.enabled = false; } #endif if (meshCollider.sharedMesh) { if (Application.isEditor && !Application.isPlaying) { DestroyImmediate(meshCollider.sharedMesh, true); } else { #if UNITY_EDITOR if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(meshCollider.sharedMesh.GetInstanceID()))) #endif Destroy(meshCollider.sharedMesh); } } if (!ReferenceEquals(collisionMesh, null) && collisionMesh.vertexCount > 0) { if (!Application.isEditor) { meshCollider.cookingOptions = MeshColliderCookingOptions.EnableMeshCleaning; } meshCollider.sharedMesh = collisionMesh; meshCollider.enabled = true; } else { meshCollider.sharedMesh = null; meshCollider.enabled = false; } } Utils.Profiler.EndSample(); return(hasVisualMesh); }