unity3D 中关于网格八叉树的实现

      八叉树是一种3D数据结构,最适合用于根据3D位置存储对象。它们被用于许多非常酷的技术中,并成为像Voxel渲染器这样的主干。我们将致力于实现Octree的通用形式,我们可以将其用于任何解决方案。有了这个,我们将能够设计各种有趣的东西。效果如下:

unity3D 中关于网格八叉树的实现_第1张图片

 

代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum OctreeIndex
{
    BottomLeftFront = 0, //000,
    BottomRightFront = 2, //010,
    BottomRightBack = 3, //011,
    BottomLeftBack = 1, //001,
    TopLeftFront = 4, //100,
    TopRightFront = 6, //110,
    TopRightBack = 7, //111,
    TopLeftBack = 5, //101,
}

public class Octree
{
    private OctreeNode node;
    private int depth;

    public Octree(Vector3 position, float size, int depth)
    {
        node = new OctreeNode(position, size);
        node.Subdivide(depth);
    }

    public class OctreeNode
    {
        Vector3 position;
        float size;
        OctreeNode[] subNodes;
        IList value;

        public OctreeNode(Vector3 pos, float size)
        {
            position = pos;
            this.size = size;
        }

        public IEnumerable> Nodes
        {
            get { return subNodes; }
        }

        public Vector3 Position
        {
            get { return position; }
        }

        public float Size
        {
            get { return size; }
        }

        public void Subdivide(int depth = 0)
        {
            subNodes = new OctreeNode[8];
            for (int i = 0; i < subNodes.Length; ++i)
            {
                Vector3 newPos = position;
                if ((i & 4) == 4)
                {
                    newPos.y += size * 0.25f;
                }
                else
                {
                    newPos.y -= size * 0.25f;
                }

                if ((i & 2) == 2)
                {
                    newPos.x += size * 0.25f;
                }
                else
                {
                    newPos.x -= size * 0.25f;
                }

                if ((i & 1) == 1)
                {
                    newPos.z += size * 0.25f;
                }
                else
                {
                    newPos.z -= size * 0.25f;
                }

                subNodes[i] = new OctreeNode(newPos, size * 0.5f);
                if (depth > 0)
                {
                    subNodes[i].Subdivide(depth - 1);
                }
            }
        }

        public bool IsLeaf()
        {
            return subNodes == null;
        }
    }

    private int GetIndexOfPosition(Vector3 lookupPosition, Vector3 nodePosition)
    {
        int index = 0;

        index |= lookupPosition.y > nodePosition.y ? 4 : 0;
        index |= lookupPosition.x > nodePosition.x ? 2 : 0;
        index |= lookupPosition.z > nodePosition.z ? 1 : 0;

        return index;
    }

    public OctreeNode GetRoot()
    {
        return node;
    }
}

 

using System.Collections;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using UnityEngine;

public class OctreeComponent : MonoBehaviour
{

    public float size = 5;
    public int depth = 2;

    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }

    void OnDrawGizmos()
    {
        var octree = new Octree(this.transform.position, size, depth);

        DrawNode(octree.GetRoot());
    }

    private Color minColor = new Color(1, 1, 1, 1f);
    private Color maxColor = new Color(0, 0.5f, 1, 0.25f);

    private void DrawNode(Octree.OctreeNode node, int nodeDepth = 0)
    {
        if (!node.IsLeaf())
        {
            foreach (var subnode in node.Nodes)
            {
                DrawNode(subnode, nodeDepth + 1);
            }
        }
        Gizmos.color = Color.Lerp(minColor, maxColor, nodeDepth / (float)depth);
        Gizmos.DrawWireCube(node.Position, Vector3.one * node.Size);
    }
}
 

转自:https://www.youtube.com/watch?v=m0guE7804to

你可能感兴趣的:(unity3D 中关于网格八叉树的实现)