public ReadyChunkExchange(List <IMarchingCubeChunk> old, IMarchingCubeChunk chunks) { this.old = old; this.chunks = new List <IMarchingCubeChunk>() { chunks }; }
public ReadyChunkExchange(IMarchingCubeChunk old, List <IMarchingCubeChunk> chunks) { this.old = new List <IMarchingCubeChunk>() { old }; this.chunks = chunks; }
private void OnTriggerEnter(Collider other) { IMarchingCubeChunk chunk = other.GetComponent <ChunkLodCollider>()?.chunk; if (chunk != null) { chunk.TargetLODPower = Mathf.Min(chunk.TargetLODPower, lod); } }
public void RemoveLowerLodChunk(IMarchingCubeChunk c) { if (isInDecreasingChunkIteration) { removedLowerChunkLodsBuffer.Add(c); } else { lowerChunkLods.Remove(c); } }
protected void SetDisplayerOfChunk(IMarchingCubeChunk c) { if (c is IMarchingCubeInteractableChunk interactableChunk) { interactableChunk.AddDisplayer(GetNextInteractableMeshDisplayer(interactableChunk)); } else { c.AddDisplayer(GetNextMeshDisplayer()); } }
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); }
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); }
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); }
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)); } }); }
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); } }
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); }
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); } }
//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); }
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}"); }
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); }
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); } } } }
public float[] RequestNoiseForChunk(IMarchingCubeChunk chunk) { return(RequestNoiseFor(chunk.ChunkSizePower, chunk.PointsPerAxis, chunk.LOD, chunk.AnchorPos)); }
//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); }
public bool TryGetReadyChunkAt(Vector3Int p, out IMarchingCubeChunk chunk, out Vector3Int relativePositionInChunk) { return(TryGetChunkAtPosition(p, out chunk, out relativePositionInChunk) && chunk.IsReady); }
public int RequestCubesFromNoise(IMarchingCubeChunk chunk, int lod, int triCount = -1) { ComputeCubesFromNoise(chunk.ChunkSize, chunk.AnchorPos, lod); return(ReadCurrentTriangleData(out tris, triCount)); }
public TriangleBuilder[] GenerateCubesFromNoise(IMarchingCubeChunk chunk, int triCount, float[] noise) { pointsBuffer.SetData(noise); RequestCubesFromNoise(chunk, chunk.LOD, triCount); return(tris); }
public void SetChunkColliderOf(IMarchingCubeChunk c) { simpleChunkColliderPool.GetItemFromPoolFor(c); }
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); })); }
//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)); }
public int GetFeasibleReducedLodForChunk(IMarchingCubeChunk c, int toLodPower) { return(Mathf.Min(toLodPower, c.LODPower + 1)); }
public void AccumulateCubesFromNoise(IMarchingCubeChunk chunk, int offest) { ComputeCubesFromNoise(chunk.ChunkSize, chunk.AnchorPos, chunk.LOD, false); ComputeBuffer.CopyCount(triangleBuffer, triCountBuffer, offest * 4); }
/// <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); }
public bool TryGetChunkAtPosition(Vector3Int p, out IMarchingCubeChunk chunk) { Vector3Int _; return(TryGetChunkAtPosition(p, out chunk, out _)); }
public int GetFeasibleIncreaseLodForChunk(IMarchingCubeChunk c, int toLodPower) { return(Mathf.Max(toLodPower, c.LODPower - 1)); }