Beispiel #1
0
    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);
    }
Beispiel #2
0
    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));
    }
Beispiel #3
0
    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);
        }
    }
Beispiel #4
0
    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);
    }
Beispiel #5
0
    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));
    }
Beispiel #6
0
    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);
    }
Beispiel #7
0
    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]);
    }
Beispiel #8
0
    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;
    }
Beispiel #9
0
    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);
    }
Beispiel #10
0
    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);
    }
Beispiel #12
0
    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);
                }
            }
        }
    }