Beispiel #1
0
 public ReadyChunkExchange(List <IMarchingCubeChunk> old, IMarchingCubeChunk chunks)
 {
     this.old    = old;
     this.chunks = new List <IMarchingCubeChunk>()
     {
         chunks
     };
 }
Beispiel #2
0
 public ReadyChunkExchange(IMarchingCubeChunk old, List <IMarchingCubeChunk> chunks)
 {
     this.old = new List <IMarchingCubeChunk>()
     {
         old
     };
     this.chunks = chunks;
 }
Beispiel #3
0
        private void OnTriggerEnter(Collider other)
        {
            IMarchingCubeChunk chunk = other.GetComponent <ChunkLodCollider>()?.chunk;

            if (chunk != null)
            {
                chunk.TargetLODPower = Mathf.Min(chunk.TargetLODPower, lod);
            }
        }
Beispiel #4
0
 public void RemoveLowerLodChunk(IMarchingCubeChunk c)
 {
     if (isInDecreasingChunkIteration)
     {
         removedLowerChunkLodsBuffer.Add(c);
     }
     else
     {
         lowerChunkLods.Remove(c);
     }
 }
Beispiel #5
0
 protected void SetDisplayerOfChunk(IMarchingCubeChunk c)
 {
     if (c is IMarchingCubeInteractableChunk interactableChunk)
     {
         interactableChunk.AddDisplayer(GetNextInteractableMeshDisplayer(interactableChunk));
     }
     else
     {
         c.AddDisplayer(GetNextMeshDisplayer());
     }
 }
Beispiel #6
0
        public float[] RequestNoiseAndEditAtPosition(IMarchingCubeChunk chunk, Vector3 editPoint, Vector3Int start, Vector3Int end, float delta, float maxDistance)
        {
            int pointsPerAxis = chunk.PointsPerAxis;

            float[] result = new float[pointsPerAxis * pointsPerAxis * pointsPerAxis];
            GenerateNoise(chunk.ChunkSizePower, pointsPerAxis, chunk.LOD, chunk.AnchorPos);
            ApplyNoiseEditing(pointsPerAxis, editPoint, start, end, delta, maxDistance);
            pointsBuffer.GetData(result, 0, 0, result.Length);
            Store(chunk.AnchorPos, result);
            return(result);
        }
Beispiel #7
0
        protected void CreateChunkParallelAt(Vector3 pos, Vector3Int coord)
        {
            int  lodPower;
            int  chunkSizePower;
            bool careForNeighbours;

            GetSizeAndLodPowerForChunkPosition(pos, out chunkSizePower, out lodPower, out careForNeighbours);

            IMarchingCubeChunk chunk = GetThreadedChunkObjectAt(Vector3Int.FloorToInt(pos), coord, lodPower, chunkSizePower, false);

            BuildChunkParallel(chunk, careForNeighbours);
        }
Beispiel #8
0
 public bool TryGetOrCreateChunkAt(Vector3Int p, out IMarchingCubeChunk chunk)
 {
     if (!TryGetChunkAtPosition(p, out chunk))
     {
         chunk = CreateChunkWithProperties(p, PositionToChunkGroupCoord(p), 0, DEFAULT_CHUNK_SIZE_POWER, false, false);
     }
     if (chunk != null && !chunk.IsReady)
     {
         Debug.LogWarning("Unfinished chunk next to requested chunk. may lead to holes in mesh!");
     }
     return(chunk != null);
 }
Beispiel #9
0
        public void MergeAndReduceChunkBranch(IMarchingCubeChunk chunk, int toLodPower)
        {
            List <IMarchingCubeChunk> oldChunks = new List <IMarchingCubeChunk>();

            chunk.Leaf.parent.PrepareBranchDestruction(oldChunks);

            ExchangeChunkParallel(chunk.CenterPos, toLodPower, chunk.ChunkSizePower + 1, false, true, (c) =>
            {
                lock (exchangeLocker)
                {
                    worldUpdater.readyExchangeChunks.Push(new ReadyChunkExchange(oldChunks, c));
                }
            });
        }
Beispiel #10
0
        public void SpawnEmptyChunksAround(IMarchingCubeChunk c)
        {
            bool[] dirs  = c.HasNeighbourInDirection;
            int    count = dirs.Length;

            for (int i = 0; i < count; i++)
            {
                if (!dirs[i])
                {
                    continue;
                }
                Vector3Int v3 = VectorExtension.GetDirectionFromIndex(i) * (c.ChunkSize + 1) + c.CenterPos;
                BuildEmptyChunkAt(v3);
            }
        }
Beispiel #11
0
        protected IMarchingCubeChunk GetChunkObjectAt(IMarchingCubeChunk chunk, Vector3Int position, Vector3Int coord, int lodPower, int chunkSizePower, bool allowOverride)
        {
            ///Pot racecondition
            IChunkGroupRoot chunkGroup = GetOrCreateChunkGroupAtCoordinate(coord);

            chunk.ChunkHandler   = this;
            chunk.ChunkSizePower = chunkSizePower;
            chunk.ChunkUpdater   = worldUpdater;
            chunk.Material       = chunkMaterial;
            chunk.SurfaceLevel   = surfaceLevel;
            chunk.LODPower       = lodPower;

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

            return(chunk);
        }
Beispiel #12
0
        public void IncreaseChunkLod(IMarchingCubeChunk 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}");
            }

            int newSizePow = DEFAULT_CHUNK_SIZE_POWER + toLodPower;

            if (newSizePow == chunk.ChunkSizePower || newSizePow == CHUNK_GROUP_SIZE_POWER)
            {
                ExchangeSingleChunkParallel(chunk, chunk.AnchorPos, toLodPower, chunk.ChunkSizePower, false, true);
            }
            else
            {
                SplitChunkAndIncreaseLod(chunk, toLodPower, newSizePow);
            }
        }
Beispiel #13
0
        //TODO: Maybe remove pooling theese -> could reduce size of buffer for faster reads
        protected TriangleChunkHeap[] DispatchMultipleChunks(IMarchingCubeChunk[] chunks)
        {
            triangleBuffer.SetCounterValue(0);
            int chunkLength = chunks.Length;

            for (int i = 0; i < chunkLength; i++)
            {
                IMarchingCubeChunk c = chunks[i];
                GenerateNoise(c.ChunkSizePower, c.PointsPerAxis, c.LOD, c.AnchorPos);
                AccumulateCubesFromNoise(c, i);
            }
            int[] triCounts = new int[chunkLength];

            for (int i = 0; i < chunkLength; i++)
            {
                //TODO:check if this reduces wait time from gpu
                SetDisplayerOfChunk(chunks[i]);
                simpleChunkColliderPool.GetItemFromPoolFor(chunks[i]);
            }

            triCountBuffer.GetData(triCounts, 0, 0, chunkLength);
            TriangleChunkHeap[] result  = new TriangleChunkHeap[chunkLength];
            TriangleBuilder[]   allTris = new TriangleBuilder[triCounts[triCounts.Length - 1]];
            triangleBuffer.GetData(allTris, 0, 0, allTris.Length);
            int last = 0;

            for (int i = 0; i < chunkLength; i++)
            {
                int current = triCounts[i];
                int length  = current - last;
                result[i] = new TriangleChunkHeap(allTris, last, length);
                last      = current;

                if (length == 0)
                {
                    chunks[i].FreeSimpleChunkCollider();
                }
            }
            return(result);
        }
Beispiel #14
0
        public void BuildRelevantChunksParallelBlockingAround(IMarchingCubeChunk chunk)
        {
            bool[] dirs  = chunk.HasNeighbourInDirection;
            int    count = dirs.Length;

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

                Vector3Int v3 = VectorExtension.GetDirectionFromIndex(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.GetDirectionFromIndex(i) * (chunk.ChunkSize + 1) + chunk.CenterPos;
                //closestNeighbours.Enqueue(0, v3);

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

            watch.Stop();
            Debug.Log("Total millis: " + watch.Elapsed.TotalMilliseconds);
            if (totalTriBuild >= maxTrianglesLeft)
            {
                Debug.Log("Aborted");
            }
            Debug.Log("Total triangles: " + totalTriBuild);

            // Debug.Log($"Number of chunks: {ChunkGroups.Count}");
        }
Beispiel #15
0
        public bool TryGetChunkAtPosition(Vector3Int p, out IMarchingCubeChunk chunk, out Vector3Int positionInOtherChunk)
        {
            Vector3Int      coord = PositionToChunkGroupCoord(p);
            IChunkGroupRoot chunkGroup;

            if (chunkGroups.TryGetValue(coord, out chunkGroup))
            {
                if (chunkGroup.HasChild)
                {
                    if (/*chunkGroup.HasChild && */ chunkGroup.TryGetLeafAtGlobalPosition(p, out chunk))
                    {
                        positionInOtherChunk = p - chunk.AnchorPos;
                        return(true);
                    }
                }
                else
                {
                    Debug.LogWarning("Chunk is nt set yet -> may loose neighbours");
                }
            }
            chunk = null;
            positionInOtherChunk = default;
            return(false);
        }
Beispiel #16
0
        protected void OnParallelChunkDoneCallBack(IMarchingCubeChunk chunk)
        {
            channeledChunks--;

            chunk.SetChunkOnMainThread();
            if (chunk.IsEmpty)
            {
                chunk.DestroyChunk();
            }
            else
            {
                Vector3Int v3;
                bool[]     dirs  = chunk.HasNeighbourInDirection;
                int        count = dirs.Length;
                for (int i = 0; i < count; ++i)
                {
                    if (!dirs[i])
                    {
                        continue;
                    }

                    v3 = VectorExtension.GetDirectionFromIndex(i) * (chunk.ChunkSize + 1) + chunk.CenterPos;
                    float sqrDist = (startPos - v3).sqrMagnitude;

                    if (sqrDist <= buildAroundSqrDistance &&
                        !HasChunkAtPosition(v3))
                    {
                        closestNeighbours.Enqueue(sqrDist, v3);
                    }
                    else
                    {
                        BuildEmptyChunkAt(v3);
                    }
                }
            }
        }
Beispiel #17
0
 public float[] RequestNoiseForChunk(IMarchingCubeChunk chunk)
 {
     return(RequestNoiseFor(chunk.ChunkSizePower, chunk.PointsPerAxis, chunk.LOD, chunk.AnchorPos));
 }
Beispiel #18
0
        //public MarchingCubeChunkNeighbourLODs GetNeighbourLODSFrom(IMarchingCubeChunk chunk)
        //{
        //    MarchingCubeChunkNeighbourLODs result = new MarchingCubeChunkNeighbourLODs();
        //    Vector3Int[] coords = VectorExtension.GetAllAdjacentDirections;
        //    for (int i = 0; i < coords.Length; ++i)
        //    {
        //        MarchingCubeNeighbour neighbour = new MarchingCubeNeighbour();
        //        Vector3Int neighbourPos = chunk.CenterPos + chunk.ChunkSize * coords[i];
        //        if (!TryGetChunkAtPosition(neighbourPos, out neighbour.chunk))
        //        {
        //            //change name to extectedLodPower
        //            neighbour.estimatedLodPower = GetLodPowerAt(neighbourPos);
        //        }
        //        result[i] = neighbour;
        //    }

        //    return result;
        //}

        //TODO:Remove keep points
        protected void BuildChunk(IMarchingCubeChunk chunk, bool careForNeighbours, Action WorkOnNoise = null)
        {
            TriangleChunkHeap ts = DispatchAndGetShaderData(chunk, careForNeighbours, WorkOnNoise);

            chunk.InitializeWithMeshData(ts);
        }
Beispiel #19
0
 public bool TryGetReadyChunkAt(Vector3Int p, out IMarchingCubeChunk chunk, out Vector3Int relativePositionInChunk)
 {
     return(TryGetChunkAtPosition(p, out chunk, out relativePositionInChunk) && chunk.IsReady);
 }
Beispiel #20
0
 public int RequestCubesFromNoise(IMarchingCubeChunk chunk, int lod, int triCount = -1)
 {
     ComputeCubesFromNoise(chunk.ChunkSize, chunk.AnchorPos, lod);
     return(ReadCurrentTriangleData(out tris, triCount));
 }
Beispiel #21
0
 public TriangleBuilder[] GenerateCubesFromNoise(IMarchingCubeChunk chunk, int triCount, float[] noise)
 {
     pointsBuffer.SetData(noise);
     RequestCubesFromNoise(chunk, chunk.LOD, triCount);
     return(tris);
 }
Beispiel #22
0
 public void SetChunkColliderOf(IMarchingCubeChunk c)
 {
     simpleChunkColliderPool.GetItemFromPoolFor(c);
 }
Beispiel #23
0
 protected IMarchingCubeChunk ExchangeSingleChunkParallel(IMarchingCubeChunk from, Vector3Int anchorPos, int lodPow, int sizePow, bool careForNeighbours, bool allowOveride)
 {
     from.PrepareDestruction();
     return(ExchangeChunkParallel(anchorPos, lodPow, sizePow, careForNeighbours, allowOveride, (c) => { FinishParallelChunk(from, c); }));
 }
Beispiel #24
0
        //TODO: Inform about Mesh subset and mesh set vertex buffer
        //Subset may be used to only change parts of the mesh -> dont need multiple mesh displayers with submeshes?
        protected TriangleChunkHeap DispatchAndGetShaderData(IMarchingCubeChunk chunk, bool careForNeighbours, Action WorkOnNoise = null)
        {
            int lod       = chunk.LOD;
            int chunkSize = chunk.ChunkSize;

            if (chunkSize % lod != 0)
            {
                throw new Exception("Lod must be divisor of chunksize");
            }

            int numVoxelsPerAxis = chunkSize / lod;
            int pointsPerAxis    = numVoxelsPerAxis + 1;
            int pointsVolume     = pointsPerAxis * pointsPerAxis * pointsPerAxis;

            GenerateNoise(chunk.ChunkSizePower, pointsPerAxis, lod, chunk.AnchorPos);

            bool storeNoise = false;

            if (WorkOnNoise != null)
            {
                WorkOnNoise?.Invoke();
                storeNoise = true;
            }

            ComputeCubesFromNoise(chunk.ChunkSize, chunk.AnchorPos, lod);

            ///Do work for chunk here, before data from gpu is read, to give gpu time to finish

            SetDisplayerOfChunk(chunk);
            simpleChunkColliderPool.GetItemFromPoolFor(chunk);

            ///read data from gpu

            numTris = ReadCurrentTriangleData(out tris);

            if (numTris == 0)
            {
                chunk.FreeSimpleChunkCollider();
                chunk.GiveUnusedDisplayerBack();
            }
            //else if(lod == 1)
            //{
            //    grass.ComputeGrassFor(new Bounds(chunk.CenterPos, Vector3.one * chunk.ChunkSize), numTris, triangleBuffer);
            //}

            if (storeNoise || (numTris == 0 && !hasFoundInitialChunk) || careForNeighbours)
            {
                if (careForNeighbours || storeNoise)
                {
                    pointsArray = new float[pointsVolume];
                }
                else
                {
                    pointsArray = new float[1];
                }
                pointsBuffer.GetData(pointsArray, 0, 0, pointsArray.Length);
                chunk.Points = pointsArray;
                if (storeNoise)
                {
                    Store(chunk.AnchorPos, pointsArray);
                }
            }
            return(new TriangleChunkHeap(tris, 0, numTris));
        }
Beispiel #25
0
 public int GetFeasibleReducedLodForChunk(IMarchingCubeChunk c, int toLodPower)
 {
     return(Mathf.Min(toLodPower, c.LODPower + 1));
 }
Beispiel #26
0
 public void AccumulateCubesFromNoise(IMarchingCubeChunk chunk, int offest)
 {
     ComputeCubesFromNoise(chunk.ChunkSize, chunk.AnchorPos, chunk.LOD, false);
     ComputeBuffer.CopyCount(triangleBuffer, triCountBuffer, offest * 4);
 }
Beispiel #27
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 bool CreateChunkWithNoiseEdit(Vector3Int p, Vector3 editPoint, Vector3Int start, Vector3Int end, float delta, float maxDistance, out IMarchingCubeChunk chunk)
        {
            bool createdChunk       = false;
            bool hasChunkAtPosition = TryGetChunkAtPosition(p, out chunk);

            if (!hasChunkAtPosition || !chunk.HasStarted)
            {
                if (chunk != null)
                {
                    chunk.DestroyChunk();
                }
                chunk = CreateChunkWithProperties(p, PositionToChunkGroupCoord(p), 0, DEFAULT_CHUNK_SIZE_POWER, false, false,
                                                  () => {
                    ApplyNoiseEditing(33, editPoint, start, end, delta, maxDistance);
                });
                createdChunk = true;
            }
            return(createdChunk);
        }
Beispiel #28
0
        public bool TryGetChunkAtPosition(Vector3Int p, out IMarchingCubeChunk chunk)
        {
            Vector3Int _;

            return(TryGetChunkAtPosition(p, out chunk, out _));
        }
Beispiel #29
0
 public int GetFeasibleIncreaseLodForChunk(IMarchingCubeChunk c, int toLodPower)
 {
     return(Mathf.Max(toLodPower, c.LODPower - 1));
 }