public OctreeNode Update(T obj, OctreeNode node, Vector3 newPos) { if (!OctreeBounds.Contains(newPos)) { throw new System.InvalidOperationException("Attempting to insert out of octree bounds"); } if (node.NodeBounds.Contains(newPos)) { // Update position var ent = Entries[obj]; ent.position = newPos; Entries[obj] = ent; return(node); } var newNode = node.RecursiveUpdate(obj, newPos); OctreeEntry entry = new OctreeEntry(); entry.position = newPos; entry.Node = newNode; Entries[obj] = entry; return(newNode); }
public OctreeEntry <Brick> GetAt(int x, int y, int z) { OctreeEntry <Brick> entry = octree.GetAt(x, y, z); if (entry != null) { return(entry); } return(AddBrickAt(x, y, z)); }
public OctreeEntry <T> SetAtIfNull(int x, int y, int z, T value) { lock (octree) { OctreeEntry <T> stored = GetAt(x, y, z); if (stored == null) { stored = octree.SetAt(x, y, z, value); } return(stored); } }
public OctreeNode Insert(T obj, Vector3 position) { if (!OctreeBounds.Contains(position)) { throw new System.InvalidOperationException("Attempting to insert out of octree bounds"); } var node = Root.RecursiveInsert(obj, position); OctreeEntry entry = new OctreeEntry(); entry.position = position; entry.Node = node; Entries[obj] = entry; return(node); }
public OctreeEntry <T> SetAt(int x, int y, int z, T value) { if (root.Contains(x, y, z)) { OctreeEntry <T> entry = root.SetAt(x, y, z, value); quickieDictionary[Vector3i.Hash(x, y, z)] = entry; return(entry); } // Grow the octree towards the cell GrowTowards(x, y, z); // Attempt to set again return(SetAt(x, y, z, value)); }
public override bool Stroke(Ray ray, BrickTree tree, VoxelMaterial voxelMaterial, VoxelMaterialAtlas materialAtlas, List <byte> blackList, Queue <OctreeEntry <Brick> > outChangedBricks, Bounds bounds) { OctreeEntry <Brick> brickEntry = FirstBrickIntersected(ray, tree, blackList); Brick brick = brickEntry.entry; Vector3 brickPosition = brickEntry.bounds.min; found.Clear(); selector.Select(ray, brick, brickPosition, blackList, found); if (found.Count == 0) { return(false); } Vector3i cell = found.Dequeue(); brick.SetValue(cell.x, cell.y, cell.z, materialAtlas.GetMaterialId(voxelMaterial)); outChangedBricks.Enqueue(brickEntry); if (cell.x == 0) { OctreeEntry <Brick> modified = tree.GetAt(brickEntry.cell.x - 1, brickEntry.cell.y, brickEntry.cell.z); outChangedBricks.Enqueue(modified); } if (cell.y == 0) { OctreeEntry <Brick> modified = tree.GetAt(brickEntry.cell.x, brickEntry.cell.y - 1, brickEntry.cell.z); outChangedBricks.Enqueue(modified); } if (cell.z == 0) { OctreeEntry <Brick> modified = tree.GetAt(brickEntry.cell.x, brickEntry.cell.y, brickEntry.cell.z - 1); outChangedBricks.Enqueue(modified); } return(true); }
protected OctreeEntry <T> SetChild(int index, T node) { if (children[index] != null) { // The entry already exists children[index].entry = node; return(children[index]); } OctreeEntry <T> fish = treeBase.entryPool.Catch(); // Find the new child min int xMinimum, yMinimum, zMinimum; MinOfChildIndex(index, out xMinimum, out yMinimum, out zMinimum); // change the min from local to world space float xWorldMinimum = xMinimum * treeBase.leafDimensions.x; float yWorldMinimum = yMinimum * treeBase.leafDimensions.y; float zWorldMinimum = zMinimum * treeBase.leafDimensions.z; // change the min from local to world space float xWorldMaximum = xWorldMinimum + treeBase.leafDimensions.x; float yWorldMaximum = yWorldMinimum + treeBase.leafDimensions.y; float zWorldMaximum = zWorldMinimum + treeBase.leafDimensions.z; // Initialize the new node with world space bounds fish.Initialize(node, xMinimum, yMinimum, zMinimum, new Vector3(xWorldMinimum, yWorldMinimum, zWorldMinimum), new Vector3(xWorldMaximum, yWorldMaximum, zWorldMaximum)); // Set index to the child children[(int)index] = fish; // Increase the child counter ++childCount; // Set the OctryEnty's value to what was passed children[(int)index].entry = node; return(children[(int)index]); }
private void CreateEntryAtIndex(int index) { if (children[index] != null) { return; } OctreeEntry <T> fish = treeBase.entryPool.Catch(); // Find the new child min int xMinimum, yMinimum, zMinimum; MinOfChildIndex(index, out xMinimum, out yMinimum, out zMinimum); // change the min from local to world space float minX = xMinimum * treeBase.leafDimensions.x; float minY = yMinimum * treeBase.leafDimensions.y; float minZ = zMinimum * treeBase.leafDimensions.z; // Initialize the new node with world space bounds fish.Initialize(default(T), xMinimum, yMinimum, zMinimum, new Vector3(minX, minY, minZ), new Vector3(minX + treeBase.leafDimensions.x, minY + treeBase.leafDimensions.y, minZ + treeBase.leafDimensions.z)); // Set index to the child children[(int)index] = fish; }
protected OctreeEntry <Brick> FirstBrickIntersected(Ray ray, BrickTree tree, List <byte> blackList) { entryPrioirityQueue.Clear(); tree.RaycastFind(ray, entryPrioirityQueue); while (!entryPrioirityQueue.IsEmpty()) { cellPriorityQueue.Clear(); OctreeEntry <Brick> entry = entryPrioirityQueue.Dequeue(); blackListSelector.Select(ray, entry.entry, entry.bounds.min, blackList, cellPriorityQueue); if (cellPriorityQueue.Count > 0) { return(entry); } } return(null); }
public void PaintWithRay(Ray ray, VoxelBrush brush, VoxelMaterial material) { Queue <OctreeEntry <Brick> > changed = new Queue <OctreeEntry <Brick> >(); Bounds bounds = new Bounds(); bounds.SetMinMax(new Vector3(1, 1, 1), new Vector3(maxDimensions.x * voxelTree.BrickDimensionX - 1, maxDimensions.y * voxelTree.BrickDimensionY - 1, maxDimensions.z * voxelTree.BrickDimensionZ - 1)); if (brush.Stroke(ray, voxelTree, material, materialAtlas, materialAtlas.airMaterials, changed, bounds)) { while (changed.Count > 0) { OctreeEntry <Brick> entry = changed.Dequeue(); if (entry == null) { continue; } createBrick(entry.cell.x, entry.cell.y, entry.cell.z); } } }
public override bool Stroke(Ray ray, BrickTree tree, VoxelMaterial voxelMaterial, VoxelMaterialAtlas materialAtlas, List <byte> blackList, Queue <OctreeEntry <Brick> > outChangedBricks, Bounds bounds) { // Find the brick intersected OctreeEntry <Brick> brickEntry = FirstBrickIntersected(ray, tree, blackList); // If we can't find one return if (brickEntry == null) { return(false); } Brick brick = brickEntry.entry; Vector3 brickPosition = brickEntry.bounds.min; dummyVector3.Set(brickEntry.cell.x, brickEntry.cell.y, brickEntry.cell.z); // Make sure the brick is within the legal paining bounds if (!bounds.Contains(dummyVector3)) { // return false; } // Clear the resused found queue found.Clear(); // Find which cells are intersected within the grid selector.Select(ray, brick, brickPosition, blackList, found); if (found.Count == 0) { return(false); } Vector3i firstIntersection = found.Dequeue(); Ray offsetRay = new Ray(new Vector3(ray.origin.x - brickPosition.x, ray.origin.y - brickPosition.y, ray.origin.z - brickPosition.z), ray.direction); float distance; RayEntersCellFromCell(offsetRay, firstIntersection, dummyVector3i, out distance); Vector3i adjacentLocal = dummyVector3i; Vector3i adjacentWorld = adjacentLocal + brickEntry.bounds.min; dummyVector3.Set(adjacentWorld.x, adjacentWorld.y, adjacentWorld.z); if (!bounds.Contains(dummyVector3)) { return(false); } tree.SetVoxelAt(adjacentWorld.x, adjacentWorld.y, adjacentWorld.z, materialAtlas.GetMaterialId(voxelMaterial)); Vector3i cellModified = new Vector3i(adjacentWorld.x / tree.BrickDimensionX, adjacentWorld.y / tree.BrickDimensionY, adjacentWorld.z / tree.BrickDimensionZ); OctreeEntry <Brick> modified = tree.GetAt(cellModified.x, cellModified.y, cellModified.z); outChangedBricks.Enqueue(modified); if (adjacentLocal.x == 0) { modified = tree.GetAt(cellModified.x - 1, cellModified.y, cellModified.z); outChangedBricks.Enqueue(modified); } if (adjacentLocal.y == 0) { modified = tree.GetAt(cellModified.x, cellModified.y - 1, cellModified.z); outChangedBricks.Enqueue(modified); } if (adjacentLocal.z == 0) { modified = tree.GetAt(cellModified.x, cellModified.y, cellModified.z - 1); outChangedBricks.Enqueue(modified); } return(true); }
public void Update() { requestHandlers.Update(); if (Input.GetKeyDown(KeyCode.Alpha1)) { currentBrush = setBrush; currentMaterial = materialAtlas.GetVoxelMaterial(0); } if (Input.GetKeyDown(KeyCode.Alpha2)) { currentBrush = setAdjacentBrush; currentMaterial = materialAtlas.GetVoxelMaterial(1); } if (Input.GetKeyDown(KeyCode.Alpha3)) { currentBrush = setAdjacentBrush; currentMaterial = materialAtlas.GetVoxelMaterial(2); } if (Input.GetKeyDown(KeyCode.Alpha4)) { currentBrush = setAdjacentBrush; currentMaterial = materialAtlas.GetVoxelMaterial(3); } if (!Input.GetMouseButton(0)) { return; } GameObject camera = GameObject.FindGameObjectsWithTag("Player")[0]; Ray ray = camera.GetComponent <Camera>().ScreenPointToRay(Input.mousePosition); Queue <OctreeEntry <Brick> > changed = new Queue <OctreeEntry <Brick> >(); Bounds bounds = new Bounds(); bounds.SetMinMax(new Vector3(0, 0, 0), new Vector3(worldDimensions.x, worldDimensions.y, worldDimensions.z)); if (currentBrush.Stroke(ray, brickTree, currentMaterial, materialAtlas, materialAtlas.airMaterials, changed, bounds)) { while (changed.Count > 0) { OctreeEntry <Brick> entry = changed.Dequeue(); Vector3i cell = new Vector3i((int)entry.bounds.min.x, (int)entry.bounds.min.y, (int)entry.bounds.min.z); Material material = Resources.Load("Materials/TestMaterial", typeof(Material)) as Material; if (chunkDictionary.ContainsKey(cell.GetHashCode())) { chunkPool.Release(chunkDictionary[cell.GetHashCode()]); } ChunkFromOctreeRequest request = extractRequestPool.Catch(); Chunk chunk = request.ReInitialize(brickTree, extractor, material, entry.cell.x, entry.cell.y, entry.cell.z, chunkPool, extractRequestPool); requestHandlers.Grab().QueueRequest(request); int hash = cell.GetHashCode(); if (chunkDictionary.ContainsKey(cell.GetHashCode())) { chunkDictionary[cell.GetHashCode()] = chunk; } else { chunkDictionary.Add(cell.GetHashCode(), chunk); } } } }