Inheritance: IDisposable
        private static void GenerateVertexIndices(OctreeNode node, List <Vector3> verts, List <Vector3> norms)
        {
            if (node == null)
            {
                return;
            }

            if (node.type != OctreeNodeType.NODE_LEAF)
            {
                for (int i = 0; i < 8; i++)
                {
                    GenerateVertexIndices(node.children[i], verts, norms);
                }
            }

            if (node.type != OctreeNodeType.NODE_INTERNAL)
            {
                OctreeDrawInfo drawInfo = node.drawInfo;
                //if (drawInfo == null) {
                //throw new NullReferenceException("Could not add vertex!  DrawInfo was null!");
                //}

                drawInfo.index = verts.Count;
                verts.Add(drawInfo.position);
                norms.Add(drawInfo.normal);
            }
        }
Esempio n. 2
0
    private void GenerateVertexIndices(OctreeNode node, List <Vector3> vertices, List <Vector3> normals, int nodeSize)
    {
        if (node == null)
        {
            return;
        }

        if (node.size > nodeSize)
        {
            if (node.type != OctreeNodeType.Node_Leaf)
            {
                for (int i = 0; i < 8; i++)
                {
                    GenerateVertexIndices(node.children[i], vertices, normals, nodeSize);
                }
            }
        }

        if (node.type != OctreeNodeType.Node_Internal)
        {
            OctreeDrawInfo d = node.drawInfo;
            if (d == null)
            {
                Debug.LogError("Error! Could not add vertex!");
                Application.Quit();
            }

            d.index = vertices.Count;
            vertices.Add(new Vector3(d.position.x, d.position.y, d.position.z));
            normals.Add(new Vector3(d.averageNormal.x, d.averageNormal.y, d.averageNormal.z));
        }
    }
Esempio n. 3
0
    public OctreeNode(OctreeNodeType _type)
    {
        Type     = _type;
        drawInfo = new OctreeDrawInfo();

        Children = new OctreeNode[8];
        for (int i = 0; i < 8; i++)
        {
            Children[i] = null;
        }
    }
Esempio n. 4
0
    public OctreeNode()
    {
        Type     = OctreeNodeType.Node_None;
        drawInfo = new OctreeDrawInfo();

        Children = new OctreeNode[8];
        for (int i = 0; i < 8; i++)
        {
            Children[i] = null;
        }
    }
Esempio n. 5
0
    public OctreeNode(OctreeNodeType _type)
    {
        Type     = _type;
        min      = Vector3.zero;
        size     = 0;
        drawInfo = new OctreeDrawInfo();

        children = new OctreeNode[8];
        for (int i = 0; i < 8; i++)
        {
            children[i] = null;
        }
    }
    protected override void ThreadFunction()
    {
        if (i_Tree != null && i_Count > 0 && i_VoxMins.Length > 0 && i_VoxMaterials.Length > 0 && i_Voxs.Length > 0 && i_Size != 0)
        {

            List<OctreeNode> computedVoxels = new List<OctreeNode>();

            int HIGHEST_VOXEL_RES = 64;
            int voxelSize = HIGHEST_VOXEL_RES / i_Size;
            for (int i = 0; i < i_Count; i++)
            {
                if (i_Voxs[i].numPoints != 0)
                {
                    OctreeNode leaf = new OctreeNode();
                    leaf.type = OctreeNodeType.Node_Leaf;
                    leaf.size = voxelSize;
                    OctreeDrawInfo drawInfo = new OctreeDrawInfo();
                    drawInfo.position = i_Voxs[i].vertPoint;
                    drawInfo.averageNormal = i_Voxs[i].avgNormal;
                    drawInfo.corners = (int) i_VoxMaterials[i];
                    leaf.drawInfo = drawInfo;
                    leaf.min = i_VoxMins[i];
                    computedVoxels.Add(leaf);
                }
            }

            //Debug.Log(computedVoxels.Count);

            if (computedVoxels.Count > 0)
            {
                if (updatingChunk && chunkToUpdate != null)
                    chunkToUpdate.DestroyOctree();
                m_Root = i_Tree.ConstructUpwards(computedVoxels, i_Min, HIGHEST_VOXEL_RES);
                if (m_Root != null)
                {
                    i_Tree.GenerateMeshFromOctree(m_Root, m_Vertices, m_Normals, m_Indices, voxelSize);
                }
            }

            //m_Vertices.TrimExcess();
            //m_Normals.TrimExcess();
            //m_Indices.TrimExcess();

            computedVoxels.Clear();
            computedVoxels = null;

            i_Min = Vector3.zero;
            i_Size = 0;
            i_Count = 0;
            i_Tree = null;
            //Array.Clear(i_VoxMins, 0, i_VoxMins.Length);
            i_VoxMins = null;
            //Array.Clear(i_VoxMaterials, 0, i_VoxMaterials.Length);
            i_VoxMaterials = null;
            //Array.Clear(i_Voxs, 0, i_Voxs.Length);
            i_Voxs = null;

            //Debug.Log ("Finished loading chunk");

            if (!updatingChunk)
                m_Test.informGame();

            if (updatingChunk)
            {
                m_Test.informGame(chunkToUpdate);
                chunkToUpdate = null;
                updatingChunk = false;
            }

        }
    }
Esempio n. 7
0
    private List <OctreeNode> ComputeVoxels(ComputeShader shader, Vector3 min, int octreeSize)
    {
        float gpuStart = Time.realtimeSinceStartup;

        float[] chunkPos = new float[3] {
            min.x, min.y, min.z
        };
        shader.SetFloats("chunkPosition", chunkPos);

        shader.SetInt("resolution", octreeSize);
        shader.SetInt("octreeSize", octreeSize);

        float sqRTRC  = Mathf.Sqrt(octreeSize * octreeSize * octreeSize);
        int   sqRTRes = (int)sqRTRC;

        if (sqRTRC > sqRTRes)
        {
            sqRTRes++;
        }

        ComputeBuffer Perm = new ComputeBuffer(512, sizeof(int));

        Perm.SetData(permutations);

        ComputeBuffer cornCount    = new ComputeBuffer(sqRTRes, sizeof(int));
        ComputeBuffer finalCount   = new ComputeBuffer(1, sizeof(float));
        ComputeBuffer voxMatBuffer = new ComputeBuffer(octreeSize * octreeSize * octreeSize, sizeof(uint));

        float rD8  = octreeSize / 8.0f;
        int   rD8I = (int)rD8;

        if (rD8 > rD8I)
        {
            rD8I++;
        }

        int kernel = shader.FindKernel("ComputeCorners");

        shader.SetBuffer(kernel, "Perm", Perm);
        shader.SetBuffer(kernel, "voxelMaterials", voxMatBuffer);
        shader.Dispatch(kernel, rD8I, rD8I, rD8I);

        /*kernel = shader.FindKernel("ComputeLength");
         * shader.SetBuffer(kernel, "voxelMaterials", voxMatBuffer);
         * shader.SetBuffer(kernel, "cornerCount", cornCount);
         * shader.Dispatch(kernel, 1, 1, 1);*/

        kernel = shader.FindKernel("AddLength");
        shader.SetBuffer(kernel, "cornerCount", cornCount);
        shader.SetBuffer(kernel, "finalCount", finalCount);
        shader.Dispatch(kernel, 1, 1, 1);

        float[] voxelCount = new float[1];
        finalCount.GetData(voxelCount);
        finalCount.SetData(voxelCount);
        int count = (int)voxelCount[0];

        //Debug.Log (count);

        if (count <= 0)
        {
            voxMatBuffer.Dispose();
            cornCount.Dispose();
            finalCount.Dispose();
            Perm.Dispose();
            return(null);
        }

        ComputeBuffer cornerIndexes = new ComputeBuffer(count, sizeof(uint));

        kernel = shader.FindKernel("ComputePositions");
        shader.SetBuffer(kernel, "voxelMaterials", voxMatBuffer);
        shader.SetBuffer(kernel, "cornerCount", cornCount);
        shader.SetBuffer(kernel, "cornerIndexes", cornerIndexes);
        shader.Dispatch(kernel, 1, 1, 1);

        ComputeBuffer voxBuffer      = new ComputeBuffer(count, (sizeof(float) * 6) + sizeof(int));
        ComputeBuffer positionBuffer = new ComputeBuffer(count, sizeof(float) * 3);

        kernel = shader.FindKernel("ComputeVoxels");
        shader.SetBuffer(kernel, "Perm", Perm);
        shader.SetBuffer(kernel, "voxMins", positionBuffer);
        shader.SetBuffer(kernel, "voxelMaterials", voxMatBuffer);
        shader.SetBuffer(kernel, "finalCount", finalCount);
        shader.SetBuffer(kernel, "cornerIndexes", cornerIndexes);
        shader.SetBuffer(kernel, "voxels", voxBuffer);
        //int dispatchCount = count / 10;
        shader.Dispatch(kernel, (count / 128) + 1, 1, 1);

        List <OctreeNode> computedVoxels = new List <OctreeNode>();

        Vector3[] voxelMins = new Vector3[count];
        positionBuffer.GetData(voxelMins);
        positionBuffer.Dispose();

        uint[] voxelMaterials = new uint[count];
        cornerIndexes.GetData(voxelMaterials);
        cornerIndexes.Dispose();

        GPUVOX[] voxs = new GPUVOX[count];
        voxBuffer.GetData(voxs);
        voxBuffer.Dispose();

        voxMatBuffer.Dispose();
        cornCount.Dispose();
        finalCount.Dispose();
        Perm.Dispose();

        float gpuEnd = Time.realtimeSinceStartup;
        //Debug.Log ("GPU time on chunk: " + (gpuEnd - gpuStart));

        int HIGHEST_VOXEL_RES = 64;
        int voxelSize         = HIGHEST_VOXEL_RES / octreeSize;


        for (int i = 0; i < count; i++)
        {
            if (voxs[i].numPoints != 0)
            {
                OctreeNode leaf = new OctreeNode();
                leaf.type = OctreeNodeType.Node_Leaf;
                leaf.size = voxelSize;
                OctreeDrawInfo drawInfo = new OctreeDrawInfo();
                drawInfo.position      = voxs[i].vertPoint;
                drawInfo.averageNormal = voxs[i].avgNormal;
                drawInfo.corners       = (int)voxelMaterials[i];
                leaf.drawInfo          = drawInfo;
                leaf.min = voxelMins[i];
                computedVoxels.Add(leaf);
            }
        }

        //Debug.Log ("CPU Leaf generation time on chunk: " + (Time.realtimeSinceStartup - gpuEnd));
        //Debug.Log (computedVoxels.Count);

        return(computedVoxels);
    }
Esempio n. 8
0
    public static OctreeNode ConstructLeaf(OctreeNode leaf)
    {
        if (leaf == null || leaf.size != 1)
        {
            return(null);
        }

        int corners = 0;

        for (int i = 0; i < 8; i++)
        {
            Vector3 cornerPos = leaf.min + CHILD_MIN_OFFSETS[i];
            float   density   = glm.Density_Func(cornerPos);
            int     material  = density < 0.0f ? MATERIAL_SOLID : MATERIAL_AIR;
            corners |= (material << i);
        }

        if (corners == 0 || corners == 255)
        {
            // voxel is full inside or outside the volume
            //delete leaf
            //setting as null isn't required by the GC in C#... but its in the original, so why not!
            leaf = null;
            return(null);
        }

        // otherwise the voxel contains the surface, so find the edge intersections
        const int MAX_CROSSINGS = 6;
        int       edgeCount     = 0;
        Vector3   averageNormal = Vector3.zero;
        QefSolver qef           = new QefSolver();

        for (int i = 0; i < 12 && edgeCount < MAX_CROSSINGS; i++)
        {
            int c1 = edgevmap[i][0];
            int c2 = edgevmap[i][1];

            int m1 = (corners >> c1) & 1;
            int m2 = (corners >> c2) & 1;

            if ((m1 == MATERIAL_AIR && m2 == MATERIAL_AIR) || (m1 == MATERIAL_SOLID && m2 == MATERIAL_SOLID))
            {
                // no zero crossing on this edge
                continue;
            }

            Vector3 p1 = leaf.min + CHILD_MIN_OFFSETS[c1];
            Vector3 p2 = leaf.min + CHILD_MIN_OFFSETS[c2];
            Vector3 p  = ApproximateZeroCrossingPosition(p1, p2);
            Vector3 n  = CalculateSurfaceNormal(p);
            qef.add(p.x, p.y, p.z, n.x, n.y, n.z);

            averageNormal += n;

            edgeCount++;
        }

        Vector3 qefPosition = Vector3.zero;

        qef.solve(qefPosition, QEF_ERROR, QEF_SWEEPS, QEF_ERROR);

        OctreeDrawInfo drawInfo = new OctreeDrawInfo();

        drawInfo.corners  = 0;
        drawInfo.index    = -1;
        drawInfo.position = new Vector3(qefPosition.x, qefPosition.y, qefPosition.z);
        drawInfo.qef      = qef.getData();

        Vector3 min = leaf.min;
        Vector3 max = new Vector3(leaf.min.x + leaf.size, leaf.min.y + leaf.size, leaf.min.z + leaf.size);

        if (drawInfo.position.x < min.x || drawInfo.position.x > max.x ||
            drawInfo.position.y < min.y || drawInfo.position.y > max.y ||
            drawInfo.position.z < min.z || drawInfo.position.z > max.z)
        {
            drawInfo.position = qef.getMassPoint();
        }

        drawInfo.averageNormal = Vector3.Normalize(averageNormal / (float)edgeCount);
        drawInfo.corners       = corners;

        leaf.Type     = OctreeNodeType.Node_Leaf;
        leaf.drawInfo = drawInfo;

        return(leaf);
    }
Esempio n. 9
0
    public static OctreeNode SimplifyOctree(OctreeNode node, float threshold)
    {
        if (node == null)
        {
            return(null);
        }

        if (node.Type != OctreeNodeType.Node_Internal)
        {
            // can't simplify!
            return(node);
        }

        QefSolver qef = new QefSolver();

        int[] signs = new int[8] {
            -1, -1, -1, -1, -1, -1, -1, -1
        };
        int  midsign       = -1;
        int  edgeCount     = 0;
        bool isCollapsible = true;

        for (int i = 0; i < 8; i++)
        {
            node.children[i] = SimplifyOctree(node.children[i], threshold);

            if (node.children[i] != null)
            {
                OctreeNode child = node.children[i];

                if (child.Type == OctreeNodeType.Node_Internal)
                {
                    isCollapsible = false;
                }
                else
                {
                    qef.add(child.drawInfo.qef);

                    midsign  = (child.drawInfo.corners >> (7 - i)) & 1;
                    signs[i] = (child.drawInfo.corners >> i) & 1;

                    edgeCount++;
                }
            }
        }

        if (!isCollapsible)
        {
            // at least one child is an internal node, can't collapse
            return(node);
        }

        Vector3 qefPosition = Vector3.zero;

        qef.solve(qefPosition, QEF_ERROR, QEF_SWEEPS, QEF_ERROR);
        float error = qef.getError();

        // convert to glm vec3 for ease of use
        Vector3 position = new Vector3(qefPosition.x, qefPosition.y, qefPosition.z);

        // at this point the masspoint will actually be a sum, so divide to make it the average
        if (error > threshold)
        {
            // this collapse breaches the threshold
            return(node);
        }

        if (position.x < node.min.x || position.x > (node.min.x + node.size) ||
            position.y < node.min.y || position.y > (node.min.y + node.size) ||
            position.z < node.min.z || position.z > (node.min.z + node.size))
        {
            position = qef.getMassPoint();
        }

        // change the node from an internal node to a 'psuedo leaf' node
        OctreeDrawInfo drawInfo = new OctreeDrawInfo();

        drawInfo.corners = 0;
        drawInfo.index   = -1;

        for (int i = 0; i < 8; i++)
        {
            if (signs[i] == -1)
            {
                // Undetermined, use centre sign instead
                drawInfo.corners |= (midsign << i);
            }
            else
            {
                drawInfo.corners |= (signs[i] << i);
            }
        }

        drawInfo.averageNormal = Vector3.zero;
        for (int i = 0; i < 8; i++)
        {
            if (node.children[i] != null)
            {
                OctreeNode child = node.children[i];
                if (child.Type == OctreeNodeType.Node_Psuedo ||
                    child.Type == OctreeNodeType.Node_Leaf)
                {
                    drawInfo.averageNormal += child.drawInfo.averageNormal;
                }
            }
        }

        drawInfo.averageNormal = drawInfo.averageNormal.normalized;
        drawInfo.position      = position;
        drawInfo.qef           = qef.getData();

        for (int i = 0; i < 8; i++)
        {
            DestroyOctree(node.children[i]);
            node.children[i] = null;
        }

        node.Type     = OctreeNodeType.Node_Psuedo;
        node.drawInfo = drawInfo;

        return(node);
    }
Esempio n. 10
0
        public static OctreeNode SimplifyOctree(OctreeNode node, double threshold)
        {
            if (node == null)
            {
                return(null);
            }

            if (node.Type != OctreeNodeType.Node_Internal)
            {
                // can't simplify!
                return(node);
            }

            var qef = new QefSolver();

            int[] signs = new int[8] {
                -1, -1, -1, -1, -1, -1, -1, -1
            };
            int  midsign       = -1;
            int  edgeCount     = 0;
            bool isCollapsible = true;

            for (int i = 0; i < 8; i++)
            {
                node.Children[i] = SimplifyOctree(node.Children[i], threshold);

                if (node.Children[i] != null)
                {
                    OctreeNode child = node.Children[i];

                    if (child.Type == OctreeNodeType.Node_Internal)
                    {
                        isCollapsible = false;
                    }
                    else
                    {
                        qef.Add(child.drawInfo.qefData);

                        midsign  = (child.drawInfo.corners >> (7 - i)) & 1;
                        signs[i] = (child.drawInfo.corners >> i) & 1;

                        edgeCount++;
                    }
                }
            }

            if (!isCollapsible)
            {
                // at least one child is an internal node, can't collapse
                return(node);
            }

            Vector3 position = qef.Solve(QEF_ERROR, QEF_SWEEPS, QEF_ERROR);
            double  error    = qef.GetError();

            // at this point the masspoint will actually be a sum, so divide to make it the average
            if (error > threshold)
            {
                // this collapse breaches the threshold
                return(node);
            }

            if (position.X < node.Min.X || position.X > (node.Min.X + node.Size.X) ||
                position.Y < node.Min.Y || position.Y > (node.Min.Y + node.Size.Y) ||
                position.Z < node.Min.Z || position.Z > (node.Min.Z + node.Size.Z))
            {
                position = qef.GetMassPoint();
            }

            // change the node from an internal node to a 'psuedo leaf' node
            var drawInfo = new OctreeDrawInfo();

            drawInfo.corners = 0;
            drawInfo.index   = -1;

            for (int i = 0; i < 8; i++)
            {
                if (signs[i] == -1)
                {
                    // Undetermined, use center sign instead
                    drawInfo.corners |= (midsign << i);
                }
                else
                {
                    drawInfo.corners |= (signs[i] << i);
                }
            }

            drawInfo.averageNormal = Vector3.Zero;
            for (int i = 0; i < 8; i++)
            {
                if (node.Children[i] != null)
                {
                    OctreeNode child = node.Children[i];
                    if (child.Type == OctreeNodeType.Node_Psuedo ||
                        child.Type == OctreeNodeType.Node_Leaf)
                    {
                        drawInfo.averageNormal += child.drawInfo.averageNormal;
                    }
                }
            }

            drawInfo.averageNormal = drawInfo.averageNormal.GetNormal();
            drawInfo.position      = position;
            drawInfo.qefData       = qef.QefData;

            for (int i = 0; i < 8; i++)
            {
                DestroyOctree(node.Children[i]);
                node.Children[i] = null;
            }

            node.Type     = OctreeNodeType.Node_Psuedo;
            node.drawInfo = drawInfo;

            return(node);
        }
Esempio n. 11
0
        public static OctreeNode ConstructLeaf(Func <Vector3, double> f, OctreeNode leaf)
        {
            if (leaf == null || leaf.Level != 1)
            {
                return(null);
            }

            int corners = 0;

            for (int i = 0; i < 8; i++)
            {
                Vector3 cornerPos = leaf.Min + CHILD_MIN_OFFSETS[i] * leaf.Size;
                double  density   = f(cornerPos);
                int     material  = density < 0.0f ? MATERIAL_SOLID : MATERIAL_AIR;
                corners |= (material << i);
            }

            if (corners == 0 || corners == 255)
            {
                // voxel is full inside or outside the volume
                //delete leaf
                return(null);
            }

            // otherwise the voxel contains the surface, so find the edge intersections
            const int MAX_CROSSINGS = 6;
            int       edgeCount     = 0;
            Vector3   averageNormal = Vector3.Zero;
            var       qefSolver     = new QefSolver();
            var       debugError    = .1;
            bool      is5Ish        = false;

            for (int i = 0; i < 12 && edgeCount < MAX_CROSSINGS; i++)
            {
                int c1 = edgevmap[i][0];
                int c2 = edgevmap[i][1];

                int m1 = (corners >> c1) & 1;
                int m2 = (corners >> c2) & 1;

                if ((m1 == MATERIAL_AIR && m2 == MATERIAL_AIR) || (m1 == MATERIAL_SOLID && m2 == MATERIAL_SOLID))
                {
                    // no zero crossing on this edge
                    continue;
                }

                Vector3 p1       = leaf.Min + CHILD_MIN_OFFSETS[c1] * leaf.Size;
                Vector3 p2       = leaf.Min + CHILD_MIN_OFFSETS[c2] * leaf.Size;
                Vector3 position = ApproximateZeroCrossingPosition(f, p1, p2);

                is5Ish  = Math.Abs(Math.Abs(position[0]) - 5) < debugError;
                is5Ish |= Math.Abs(Math.Abs(position[1]) - 5) < debugError;
                is5Ish |= Math.Abs(Math.Abs(position[2]) - 5) < debugError;

                if (!is5Ish)
                {
                    int a = 0;
                }
                Vector3 normal = CalculateSurfaceNormal(f, position);
                qefSolver.Add(position, normal);

                averageNormal += normal;

                edgeCount++;
            }

            Vector3 qefPosition = qefSolver.Solve(QEF_ERROR, QEF_SWEEPS, QEF_ERROR);

            is5Ish  = Math.Abs(Math.Abs(qefPosition[0]) - 5) < debugError;
            is5Ish |= Math.Abs(Math.Abs(qefPosition[1]) - 5) < debugError;
            is5Ish |= Math.Abs(Math.Abs(qefPosition[2]) - 5) < debugError;

            if (!is5Ish)
            {
                int a = 0;
            }

            var drawInfo = new OctreeDrawInfo();

            drawInfo.corners  = 0;
            drawInfo.index    = -1;
            drawInfo.position = new Vector3(qefPosition.X, qefPosition.Y, qefPosition.Z);
            drawInfo.qefData  = qefSolver.QefData;

            Vector3 min = leaf.Min;
            var     max = min + leaf.Size;

            if (drawInfo.position.X < min.X || drawInfo.position.X > max.X ||
                drawInfo.position.Y < min.Y || drawInfo.position.Y > max.Y ||
                drawInfo.position.Z < min.Z || drawInfo.position.Z > max.Z)
            {
                drawInfo.position = qefSolver.GetMassPoint();
            }

            drawInfo.averageNormal = Vector3.Normalize(averageNormal);
            drawInfo.corners       = corners;

            leaf.Type     = OctreeNodeType.Node_Leaf;
            leaf.drawInfo = drawInfo;

            return(leaf);
        }
    protected override void ThreadFunction()
    {
        if (i_Tree != null && i_Count > 0 && i_VoxMins.Length > 0 && i_VoxMaterials.Length > 0 && i_Voxs.Length > 0 && i_Size != 0)
        {
            List <OctreeNode> computedVoxels = new List <OctreeNode>();


            int HIGHEST_VOXEL_RES = 64;
            int voxelSize         = HIGHEST_VOXEL_RES / i_Size;
            for (int i = 0; i < i_Count; i++)
            {
                if (i_Voxs[i].numPoints != 0)
                {
                    OctreeNode leaf = new OctreeNode();
                    leaf.type = OctreeNodeType.Node_Leaf;
                    leaf.size = voxelSize;
                    OctreeDrawInfo drawInfo = new OctreeDrawInfo();
                    drawInfo.position      = i_Voxs[i].vertPoint;
                    drawInfo.averageNormal = i_Voxs[i].avgNormal;
                    drawInfo.corners       = (int)i_VoxMaterials[i];
                    leaf.drawInfo          = drawInfo;
                    leaf.min = i_VoxMins[i];
                    computedVoxels.Add(leaf);
                }
            }

            //Debug.Log(computedVoxels.Count);

            if (computedVoxels.Count > 0)
            {
                if (updatingChunk && chunkToUpdate != null)
                {
                    chunkToUpdate.DestroyOctree();
                }
                m_Root = i_Tree.ConstructUpwards(computedVoxels, i_Min, HIGHEST_VOXEL_RES);
                if (m_Root != null)
                {
                    i_Tree.GenerateMeshFromOctree(m_Root, m_Vertices, m_Normals, m_Indices, voxelSize);
                }
            }

            //m_Vertices.TrimExcess();
            //m_Normals.TrimExcess();
            //m_Indices.TrimExcess();

            computedVoxels.Clear();
            computedVoxels = null;

            i_Min   = Vector3.zero;
            i_Size  = 0;
            i_Count = 0;
            i_Tree  = null;
            //Array.Clear(i_VoxMins, 0, i_VoxMins.Length);
            i_VoxMins = null;
            //Array.Clear(i_VoxMaterials, 0, i_VoxMaterials.Length);
            i_VoxMaterials = null;
            //Array.Clear(i_Voxs, 0, i_Voxs.Length);
            i_Voxs = null;

            //Debug.Log ("Finished loading chunk");

            if (!updatingChunk)
            {
                m_Test.informGame();
            }

            if (updatingChunk)
            {
                m_Test.informGame(chunkToUpdate);
                chunkToUpdate = null;
                updatingChunk = false;
            }
        }
    }