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); } }
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); } }
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); } }
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)); }); } }); }
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); } }
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}"); }
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); }
public bool TryGetReadyChunkAt(Vector3Int p, out CompressedMarchingCubeChunk chunk) => chunkGroup.TryGetReadyChunkAt(VectorExtension.ToArray(p), out chunk);
public bool TryLoadPoints(CompressedMarchingCubeChunk chunk, out float[] loadedPoints) { return(TryGetMipMapAt(chunk.AnchorPos, chunk.ChunkSizePower, out loadedPoints, out bool complete) && complete); }
public bool TryLoadPoints(CompressedMarchingCubeChunk marchingCubeChunk, out float[] loadedPoints) => storageGroup.TryLoadPoints(marchingCubeChunk, out loadedPoints);
protected void ExchangeChunkAsyncParallel(Vector3Int anchorPos, int lodPow, int sizePow, bool allowOveride, Action <CompressedMarchingCubeChunk> onChunkDone) { CompressedMarchingCubeChunk newChunk = GetThreadedChunkObjectAt(anchorPos, lodPow, sizePow, allowOveride); PrepareChunkAsyncFromMeshData(newChunk, onChunkDone); }
public ChunkNeighbourTask(CompressedMarchingCubeChunk chunk, MeshData meshData) { this.chunk = chunk; this.meshData = meshData; maxEntityIndexPerAxis = chunk.MaxEntitiesIndexPerAxis; }
public float[] RequestNoiseForChunk(CompressedMarchingCubeChunk chunk) { return(chunkGPURequest.RequestNoiseForChunk(chunk)); }
protected void ExchangeSingleChunkAsyncParallel(CompressedMarchingCubeChunk from, Vector3Int anchorPos, int lodPow, int sizePow, bool allowOveride) { from.PrepareDestruction(); ExchangeChunkAsyncParallel(anchorPos, lodPow, sizePow, allowOveride, (c) => { FinishAsynchronChunk(from, c); }); }
//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)); }
public int GetFeasibleIncreaseLodForChunk(CompressedMarchingCubeChunk c, int toLodPower) { return(Mathf.Max(toLodPower, c.LODPower - 1)); }
public void SetChunkColliderOf(CompressedMarchingCubeChunk c) { simpleChunkColliderPool.GetItemFromPoolFor(c); }
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); }
protected void SetChunkComponents(CompressedMarchingCubeChunk chunk) { SetDisplayerOfChunk(chunk); SetLODColliderOfChunk(chunk); }
/// <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); }); } }
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); }
protected void SetLODColliderOfChunk(CompressedMarchingCubeChunk chunk) { simpleChunkColliderPool.GetItemFromPoolFor(chunk); }
public ChunkInitializeTask(System.Action <CompressedMarchingCubeChunk> onChunkDone, CompressedMarchingCubeChunk chunk) { this.chunk = chunk; this.onChunkDone = onChunkDone; }