Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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();
        }
Esempio n. 3
0
        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();
        }
Esempio n. 4
0
        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();
        }
Esempio n. 5
0
        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);
        }