using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; //定义一个八叉树 ?二叉树对应于一维得数组(参考满二叉树) // 那么 四叉树 对应于 二维得数组 ?八叉树显然对应于三维数组 // 因此我们也从1维世界转到2维世界最后来到三维. public class OcTree? { ? ? //程序需要定义一个最小的空间半径 下面的值可以自己指定(通过读配置==动态设置亦可) ? ? // 但是一定要有所限制防止构建的死递归 ? ? public static float m_minRadius = 0.5f; // 比0.5还小的空间已经没有什么意义了太小了 ? ? public static float m_maxLayer = 0; ? ? public float m_radius = 0f; // 半径? ? ? public Vector3 m_center = Vector3.zero; // 八叉树的中心 ? ? public OcTree[] m_child = new OcTree[8]; ? ? public int m_nLayer = 1; ? ? public int m_id = 0;? ? ? public static Vector3[] releave_center_direction = new Vector3[] ? ? { ? ? ? ? new Vector3(-1,1,1), //上帝视角第一个盒子 ? ? ? ? new Vector3(1,1,1), // 第一个盒子的右侧盒子 ? ? ? ? new Vector3(-1,1,-1), // 第一个盒子下面的盒子 ? ? ? ? new Vector3(1,1,-1), // 第二个盒子的下面的盒子? ? ? ? ? new Vector3(-1,-1,1), // 下层空间的第一个盒子? ? ? ? ? new Vector3(1,-1,1), // 下层第一个盒子的右侧盒子 ? ? ? ? new Vector3(-1,-1,-1), // 下层第一个盒子的下面的盒子 ? ? ? ? new Vector3(1,-1,-1),// 下层第二个盒子的下面的盒子 ? ? };
? ? public OcTree(float r, Vector3 center,int layer = 1,int id = 0) ? ? { ? ? ? ? m_radius = r; ? ? ? ? m_center = center; ? ? ? ? m_nLayer = layer; ? ? ? ? m_id = id; ? ? ? ? Create(); // 构造函数天生的适合做递归 这是一个感悟点 ? ? }
? ? public void Create() //这个函数看不到递归却一直在递归似的执行 这就是编程手法 ? ? { ? ? ? ? if(m_radius <= m_minRadius || m_nLayer > m_maxLayer) ? ? ? ? { ? ? ? ? ? ? return; ? ? ? ? } ? ? ? ? Vector3 offSet = Vector3.zero; ? ? ? ? float halfRadius = m_radius / 2; ? ? ? ? for(int i = 0; i < 8; i++) ? ? ? ? { ? ? ? ? ? ? offSet ?= releave_center_direction[i] * halfRadius; ? ? ? ? ? ? int tmpId = ((m_nLayer-1) << 3) + (i+1); ? ? ? ? ? ? m_child[i] = new OcTree(halfRadius, m_center + offSet,m_nLayer + 1, tmpId); ? ? ? ? } ? ? } ? ? public void Draw() ? ? { ? ? ? ? if(m_radius == 0f) ? ? ? ? { ? ? ? ? ? ? return; ? ? ? ? } ? ? ? ? //一些绘制代码 ? ? ? ? DrawCube(m_radius, m_center); ? ? ? ? for (int i = 0; i < 8; i++) ? ? ? ? { ? ? ? ? ? ? if (m_child[i] != null) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? m_child[i].Draw(); ? ? ? ? ? ? } ? ? ? ? } ? ? }
? ? public ?int IsInCube( Vector3 pos) ? ? { ? ? ? ? Vector3 left = m_center - m_radius * Vector3.one; ? ? ? ? Vector3 right =m_center + m_radius * Vector3.one; ? ? ? ?? ? ? ? ? if (pos.x >= left.x && pos.x <= right.x && pos.y >= left.y && pos.y <= right.y && pos.z >= left.z &&? ? ? ? ? ? ? pos.z <= right.z) ? ? ? ? { ? ? ? ? ? ? return 1; ? ? ? ? } ? ? ? ? return -1; ? ? }
? ? public static int GetId(OcTree tree,Vector3 pos) ? ? { ? ? ? ? for(int i = 0; i < 8; i++) ? ? ? ? { ? ? ? ? ? ? if(tree.m_child[i] != null) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? int nRst = tree.m_child[i].IsInCube(pos); ? ? ? ? ? ? ? ? if (nRst > 0) ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? return GetId(tree.m_child[i], pos); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? } ? ? ? ? return tree.m_id; ? ? } ? ? ? ?
? ? void DrawLineFunc(Vector3 one, Vector3 two) ? ? { ? ? ? ? Debug.DrawLine(one, two, Color.yellow); ? ? }
? ? public void DrawCube(float r,Vector3 center) ? ? { ? ? ? ?? ? ? ? ? Vector3 offSet = Vector3.zero; ? ? ? ? Vector3[] vecArray = new Vector3[8]; ? ? ? ? for (int i = 0; i < 8;i++) ? ? ? ? { ? ? ? ? ? ? offSet = releave_center_direction[i] * m_radius; ? ? ? ? ? ? vecArray[i] = m_center + offSet; ? ? ? ? } ? ? ? ? for(int i = 0; i < 2; i++) ? ? ? ? { ? ? ? ? ? ? DrawLineFunc(vecArray[4 * i ], vecArray[4 * i + 1]); ? ? ? ? ? ? DrawLineFunc(vecArray[4 * i ], vecArray[4 * i + 2]); ? ? ? ? ? ? DrawLineFunc(vecArray[4 * i + 2], vecArray[4 * i + 3]); ? ? ? ? ? ? DrawLineFunc(vecArray[4 * i + 3], vecArray[4 * i + 1]); ? ? ? ? } ? ? ? ? DrawLineFunc(vecArray[0], vecArray[4]); ? ? ? ? DrawLineFunc(vecArray[1], vecArray[5]); ? ? ? ? DrawLineFunc(vecArray[2], vecArray[6]); ? ? ? ? DrawLineFunc(vecArray[3], vecArray[7]);
? ? } }
using UnityEngine; using System.Collections; using UnityEditor; [CustomEditor(typeof(Game))] public class GameEditor : Editor { ? ? Game self; ? ? public void Awake() ? ? { ? ? ? ? self = target as Game; ? ? }
? ? public override void OnInspectorGUI() ? ? { ? ? ? ? base.OnInspectorGUI(); ? ? ? ? if(GUILayout.Button("draw")) ? ? ? ? { ?? ? ? ? ? ? ? if(self.needDraw) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? self.CreateOcTree(); ? ? ? ? ? ? } ? ? ? ? ? ? else ? ? ? ? ? ? { ? ? ? ? ? ? ? ?self.needDraw = true; ? ? ? ? ? ? } ? ? ? ? ? ?? ? ? ? ? } ? ? ? ? if(GUILayout.Button("nodraw")) ? ? ? ? { ? ? ? ? ? ? self.needDraw = false; ? ? ? ? } ? ? ? ? if(GUILayout.Button("找到点所在的八叉树位置")) ? ? ? ? { ? ? ? ? ? ? if(self.m_ocTree.IsInCube(self.findPos) > 0) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? var id = ?OcTree.GetId(self.m_ocTree, self.findPos); ? ? ? ? ? ? ? ? Debug.Log(id); ? ? ? ? ? ? } ? ? ? ? } ? ? } }
public class Game : MonoBehaviour { ? ? public int layer = 2; ? ? public float minRadius = 0.5f; ? ? [HideInInspector] ? ? public OcTree m_ocTree = null; ? ? public Vector3 center = Vector3.zero; ? ? public float m_radius =10f; ? ? public bool needDraw = false; ? ? public static Game Instance = null; ? ? public Vector3 findPos = new Vector3(0, 0, 0); ? ? void Start() ? ? { ? ? ? ? Instance = this; ? ? ? ? CreateOcTree(); ? ? } ? ? public void CreateOcTree() ? ? { ? ? ? ? OcTree.m_maxLayer = layer; ? ? ? ? OcTree.m_minRadius = minRadius; ? ? ? ? m_ocTree = new OcTree(m_radius, center); ? ? } ? ? public void Draw() ? ? { ? ? ? ? if (!needDraw) return; ? ? ? ? if(m_ocTree != null) ? ? ? ? { ? ? ? ? ? ? m_ocTree.Draw(); ? ? ? ? } ? ? }
? ? void Update() ? ? { ? ? ? ? Draw(); ? ? }
} ?
|