コード例 #1
0
        public void BuildEmptyChunkAt(Vector3Int pos)
        {
            int[]          posArray       = VectorExtension.ToArray(pos);
            ChunkGroupRoot chunkGroupRoot = chunkGroup.GetOrCreateGroupAtGlobalPosition(posArray);

            if (!chunkGroupRoot.HasLeafAtGlobalPosition(posArray))
            {
                CompressedMarchingCubeChunk chunk = new CompressedMarchingCubeChunk();
                chunk.ChunkHandler   = this;
                chunk.ChunkSizePower = CHUNK_GROUP_SIZE_POWER;
                chunk.ChunkUpdater   = worldUpdater;
                chunk.LODPower       = MAX_CHUNK_LOD_POWER + 1;

                chunk.IsSpawner = true;

                chunkGroupRoot.SetLeafAtPosition(new int[] { pos.x, pos.y, pos.z }, chunk, false);

                simpleChunkColliderPool.GetItemFromPoolFor(chunk);
            }
        }
コード例 #2
0
 protected void CheckChunk(CompressedMarchingCubeChunk chunk, Action <CompressedMarchingCubeChunk> callback, int tryCount, ref Vector3 pos)
 {
     if (chunk.IsEmpty)
     {
         //TODO: maybe just read noise points here and completly remove isSolid or Air
         if (lastChunkWasAir)
         {
             pos.y -= chunk.ChunkSize;
         }
         else
         {
             pos.y += chunk.ChunkSize;
         }
         FindNonEmptyChunkAroundAsync(pos, callback, tryCount);
     }
     else
     {
         hasFoundInitialChunk = true;
         callback(chunk);
     }
 }
コード例 #3
0
        public void IncreaseChunkLod(CompressedMarchingCubeChunk chunk, int toLodPower)
        {
            toLodPower = GetFeasibleIncreaseLodForChunk(chunk, toLodPower);
            int toLod = RoundToPowerOf2(toLodPower);

            if (toLod >= chunk.LOD || chunk.ChunkSize % toLod != 0)
            {
                Debug.LogWarning($"invalid new chunk lod {toLodPower} from lod {chunk.LODPower}");
            }

            chunk.FreeSimpleChunkCollider();
            int newSizePow = DEFAULT_CHUNK_SIZE_POWER + toLodPower;

            if (newSizePow >= chunk.ChunkSizePower || newSizePow == CHUNK_GROUP_SIZE_POWER)
            {
                ExchangeSingleChunkAsyncParallel(chunk, chunk.AnchorPos, toLodPower, chunk.ChunkSizePower, true);
            }
            else
            {
                SplitChunkAndIncreaseLod(chunk, toLodPower, newSizePow);
            }
        }
コード例 #4
0
        public void DispatchAndGetChunkMeshDataAsync(CompressedMarchingCubeChunk chunk, Action <CompressedMarchingCubeChunk> SetChunkComponents, Action <MeshData> onMeshDataDone)
        {
            ChunkGenerationGPUData gpuData       = pipelinePool.GetItemFromPool();
            NoisePipeline          noise         = new NoisePipeline(gpuData, storedNoiseEdits);
            ChunkPipeline          chunkPipeline = new ChunkPipeline(gpuData, minDegreeBufferPool);

            ValidateChunkProperties(chunk);
            noise.TryLoadOrGenerateNoise(chunk);
            chunkPipeline.DispatchPrepareCubesFromNoise(chunk);


            ComputeBufferExtension.GetLengthOfAppendBufferAsync(gpuData.preparedTrisBuffer, gpuData.triCountBuffer, (numTris) =>
            {
                if (numTris <= 0)
                {
                    pipelinePool.ReturnItemToPool(gpuData);
                    onMeshDataDone(new MeshData(null, null, false));
                }
                else
                {
                    //totalTriBuild += numTris;

                    SetChunkComponents(chunk);
                    ComputeBuffer verts;
                    ComputeBuffer colors;
                    chunkPipeline.BuildMeshFromPreparedCubes(chunk, numTris, out verts, out colors);

                    ///read data from gpu
                    ComputeBufferExtension.ReadBuffersAsync <Vector3, Color32>(verts, colors, (vs, cs) =>
                    {
                        verts.Dispose();
                        colors.Dispose();
                        pipelinePool.ReturnItemToPool(gpuData);
                        onMeshDataDone(new MeshData(vs, cs, chunk.UseCollider));
                        //OnDataDone(new GpuAsyncRequestResult(tris));
                    });
                }
            });
        }
コード例 #5
0
        public void BuildEmptyChunkAt(Vector3Int pos)
        {
            IChunkGroupRoot chunkGroup = GetOrCreateChunkGroupAtCoordinate(PositionToChunkGroupCoord(pos));

            if (!chunkGroup.TryGetLeafAtGlobalPosition(pos, out IMarchingCubeChunk chunk))
            {
                chunk = new CompressedMarchingCubeChunk();

                chunk.ChunkHandler   = this;
                chunk.ChunkSizePower = CHUNK_GROUP_SIZE_POWER;
                chunk.ChunkUpdater   = worldUpdater;
                chunk.Material       = chunkMaterial;
                chunk.SurfaceLevel   = surfaceLevel;
                chunk.LODPower       = MAX_CHUNK_LOD_POWER + 1;

                chunk.IsSpawner = true;

                chunkGroup.SetLeafAtPosition(new int[] { pos.x, pos.y, pos.z }, chunk, false);

                simpleChunkColliderPool.GetItemFromPoolFor(chunk);
            }
        }
コード例 #6
0
        public void BuildRelevantChunksFromMeshDataBlockingAround(ChunkNeighbourTask task)
        {
            bool[] dirs = task.HasNeighbourInDirection;
            CompressedMarchingCubeChunk chunk = task.chunk;
            int count = dirs.Length;

            for (int i = 0; i < count; ++i)
            {
                if (!dirs[i])
                {
                    continue;
                }

                Vector3Int v3 = VectorExtension.DirectionFromIndex[i] * (chunk.ChunkSize + 1) + chunk.CenterPos;
                closestNeighbours.Enqueue(0, v3);
                ///for initial neighbours build additional chunks to not just wait for first thread to be done
                ///seems to worsen performance?
                //v3 = 2 * VectorExtension.DirectionFromIndex[i] * (chunk.ChunkSize + 1) + chunk.CenterPos;
                //closestNeighbours.Enqueue(0, v3);

                //v3 = 3 * VectorExtension.DirectionFromIndex[i] * (chunk.ChunkSize + 1) + chunk.CenterPos;
                //closestNeighbours.Enqueue(0, v3);
            }
            if (closestNeighbours.size > 0)
            {
                BuildRelevantChunksFromMeshDataBlockingAround();
            }

            watch.Stop();
            Debug.Log("Total millis: " + watch.Elapsed.TotalMilliseconds);
            if (totalTriBuild >= maxTrianglesLeft)
            {
                Debug.Log("Aborted");
            }
            Debug.Log("Total triangles: " + totalTriBuild);
            OnInitialializationDone();
            // Debug.Log($"Number of chunks: {ChunkGroups.Count}");
        }
コード例 #7
0
        public Vector3Int[] ScanForNonEmptyChunksAround(Vector3 position, int sizePower, int lodPower)
        {
            CompressedMarchingCubeChunk emptyChunk = new CompressedMarchingCubeChunk()
            {
                PointSpacing   = 1,
                LODPower       = lodPower,
                ChunkSizePower = sizePower,
            };
            float offset = emptyChunk.ChunkSize;

            emptyChunk.AnchorPos = VectorExtension.ToVector3Int(position - new Vector3(offset / 2, offset / 2, offset / 2));


            ChunkGenerationGPUData gpuData       = pipelinePool.GetItemFromPool();
            NoisePipeline          noise         = new NoisePipeline(gpuData, storedNoiseEdits);
            ChunkPipeline          chunkPipeline = new ChunkPipeline(gpuData, minDegreeBufferPool);

            noise.DispatchNoiseForChunk(emptyChunk, false);
            chunkPipeline.DispatchFindNonEmptyChunks(emptyChunk);
            Vector3Int[] nonEmptyPositions = ComputeBufferExtension.ReadAppendBuffer <Vector3Int>(ChunkGenerationGPUData.chunkPositionBuffer, gpuData.triCountBuffer);
            pipelinePool.ReturnItemToPool(gpuData);
            return(nonEmptyPositions);
        }
コード例 #8
0
 public bool TryGetReadyChunkAt(Vector3Int p, out CompressedMarchingCubeChunk chunk) => chunkGroup.TryGetReadyChunkAt(VectorExtension.ToArray(p), out chunk);
コード例 #9
0
 public bool TryLoadPoints(CompressedMarchingCubeChunk chunk, out float[] loadedPoints)
 {
     return(TryGetMipMapAt(chunk.AnchorPos, chunk.ChunkSizePower, out loadedPoints, out bool complete) && complete);
 }
コード例 #10
0
 public bool TryLoadPoints(CompressedMarchingCubeChunk marchingCubeChunk, out float[] loadedPoints) => storageGroup.TryLoadPoints(marchingCubeChunk, out loadedPoints);
コード例 #11
0
        protected void ExchangeChunkAsyncParallel(Vector3Int anchorPos, int lodPow, int sizePow, bool allowOveride, Action <CompressedMarchingCubeChunk> onChunkDone)
        {
            CompressedMarchingCubeChunk newChunk = GetThreadedChunkObjectAt(anchorPos, lodPow, sizePow, allowOveride);

            PrepareChunkAsyncFromMeshData(newChunk, onChunkDone);
        }
コード例 #12
0
 public ChunkNeighbourTask(CompressedMarchingCubeChunk chunk, MeshData meshData)
 {
     this.chunk            = chunk;
     this.meshData         = meshData;
     maxEntityIndexPerAxis = chunk.MaxEntitiesIndexPerAxis;
 }
コード例 #13
0
 public float[] RequestNoiseForChunk(CompressedMarchingCubeChunk chunk)
 {
     return(chunkGPURequest.RequestNoiseForChunk(chunk));
 }
コード例 #14
0
 protected void ExchangeSingleChunkAsyncParallel(CompressedMarchingCubeChunk from, Vector3Int anchorPos, int lodPow, int sizePow, bool allowOveride)
 {
     from.PrepareDestruction();
     ExchangeChunkAsyncParallel(anchorPos, lodPow, sizePow, allowOveride, (c) => { FinishAsynchronChunk(from, c); });
 }
コード例 #15
0
        //public int ComputeCubesFromNoise(CompressedMarchingCubeChunk chunk, int lod, bool resetCounter = true)
        //{
        //    int pointsPerAxis = DispatchCubesFromNoise(chunk, lod, resetCounter);
        //    int numTris = ComputeBufferExtension.GetLengthOfAppendBuffer(trianglesToBuild, triCountBuffer);
        //    totalTriBuild += numTris;

        //    BuildPreparedCubes(chunk, lod, pointsPerAxis, numTris);

        //    return numTris;
        //}


        public int GetFeasibleReducedLodForChunk(CompressedMarchingCubeChunk c, int toLodPower)
        {
            return(Mathf.Min(toLodPower, c.LODPower + 1));
        }
コード例 #16
0
 public int GetFeasibleIncreaseLodForChunk(CompressedMarchingCubeChunk c, int toLodPower)
 {
     return(Mathf.Max(toLodPower, c.LODPower - 1));
 }
コード例 #17
0
 public void SetChunkColliderOf(CompressedMarchingCubeChunk c)
 {
     simpleChunkColliderPool.GetItemFromPoolFor(c);
 }
コード例 #18
0
        protected void ApplyBuildGenericTrianglesForChunkProperties(ComputeShader forShader, CompressedMarchingCubeChunk chunk, int numTris)
        {
            bool storeMinDegree = chunk.MinDegreeBuffer != null;

            forShader.SetBool("storeMinDegrees", storeMinDegree);

            if (storeMinDegree)
            {
                forShader.SetBuffer(0, "minDegreeAtCoord", chunk.MinDegreeBuffer);
            }
            else
            {
                forShader.SetBuffer(0, "minDegreeAtCoord", ChunkGPUDataRequest.emptyMinDegreeBuffer);
            }

            Vector4 anchor        = VectorExtension.ToVector4(chunk.AnchorPos);
            int     pointsPerAxis = chunk.NoisePointsPerAxis;

            forShader.SetVector("anchor", anchor);
            forShader.SetFloat("spacing", chunk.LOD);
            forShader.SetInt("numPointsPerAxis", pointsPerAxis);
            forShader.SetInt("length", numTris);

            forShader.SetInt("pointSpacing", chunk.PointSpacing);
        }
コード例 #19
0
 protected void SetChunkComponents(CompressedMarchingCubeChunk chunk)
 {
     SetDisplayerOfChunk(chunk);
     SetLODColliderOfChunk(chunk);
 }
コード例 #20
0
        /// <summary>
        /// returns true if the chunk was created
        /// </summary>
        /// <param name="p"></param>
        /// <param name="editPoint"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="delta"></param>
        /// <param name="maxDistance"></param>
        /// <param name="chunk"></param>
        /// <returns></returns>
        public void CreateChunkWithNoiseEdit(Vector3Int p, Vector3 editPoint, Vector3Int start, Vector3Int end, float delta, float maxDistance, out CompressedMarchingCubeChunk chunk)
        {
            bool hasChunkAtPosition = chunkGroup.TryGetGroupItemAt(VectorExtension.ToArray(p), out chunk);

            if (!hasChunkAtPosition || !chunk.HasStarted)
            {
                if (chunk != null)
                {
                    ///current chunk is marks border of generated chunks, so destroy it
                    chunk.DestroyChunk();
                }
                chunk = CreateChunkWithProperties(p, 0, DEFAULT_CHUNK_SIZE_POWER, false,
                                                  (b) => {
                    ApplyNoiseEditing(b, editPoint, start, end, delta, maxDistance);
                });
            }
        }
コード例 #21
0
        protected void CreateChunkWithPropertiesAsync(Vector3Int pos, int lodPower, int chunkSizePower, bool allowOverride, Action <CompressedMarchingCubeChunk> callback, Action WorkOnNoise = null)
        {
            CompressedMarchingCubeChunk chunk = GetThreadedChunkObjectAt(pos, lodPower, chunkSizePower, allowOverride);

            BuildChunkAsyncFromMeshData(chunk, callback);
        }
コード例 #22
0
 protected void SetLODColliderOfChunk(CompressedMarchingCubeChunk chunk)
 {
     simpleChunkColliderPool.GetItemFromPoolFor(chunk);
 }
コード例 #23
0
 public ChunkInitializeTask(System.Action <CompressedMarchingCubeChunk> onChunkDone, CompressedMarchingCubeChunk chunk)
 {
     this.chunk       = chunk;
     this.onChunkDone = onChunkDone;
 }