private void CreateALLNodes(COTNode root, int maxDepth) { if (maxDepth == 0) return; Vector3 parentCenter = root.center; float parentHalfWidth = root.aabb.maxExtent.x - parentCenter.x; float parentHalfHeight = root.aabb.maxExtent.y- parentCenter.y; float parentHalfDepth = root.aabb.maxExtent.z - parentCenter.z; Vector3 minExtent, maxExtent; root.childs[0] = new COTNode(); minExtent = new Vector3(parentCenter.x - parentHalfWidth, parentCenter.y - parentHalfHeight, parentCenter.z - parentHalfDepth); maxExtent = parentCenter; root.childs[0].center = (maxExtent + minExtent) / 2; root.childs[0].size = maxExtent - minExtent; root.childs[0].aabb.MakeAABB(minExtent, maxExtent); CreateALLNodes(root.childs[0], maxDepth -1); root.childs[1] = new COTNode(); minExtent = new Vector3(parentCenter.x, parentCenter.y - parentHalfHeight, parentCenter.z - parentHalfDepth); maxExtent = new Vector3(parentCenter.x + parentHalfWidth, parentCenter.y, parentCenter.z); root.childs[1].center = (maxExtent + minExtent) / 2; root.childs[1].size = maxExtent - minExtent; root.childs[1].aabb.MakeAABB(minExtent, maxExtent); CreateALLNodes(root.childs[1], maxDepth - 1); root.childs[2] = new COTNode(); minExtent = new Vector3(parentCenter.x, parentCenter.y, parentCenter.z - parentHalfDepth); maxExtent = new Vector3(parentCenter.x + parentHalfWidth, parentCenter.y + parentHalfHeight, parentCenter.z); root.childs[2].center = (maxExtent + minExtent) / 2; root.childs[2].size = maxExtent - minExtent; root.childs[2].aabb.MakeAABB(minExtent, maxExtent); CreateALLNodes(root.childs[2], maxDepth - 1); root.childs[3] = new COTNode(); minExtent = new Vector3(parentCenter.x - parentHalfWidth, parentCenter.y, parentCenter.z - parentHalfDepth); maxExtent = new Vector3(parentCenter.x, parentCenter.y + parentHalfHeight, parentCenter.z); root.childs[3].center = (maxExtent + minExtent) / 2; root.childs[3].size = maxExtent - minExtent; root.childs[3].aabb.MakeAABB(minExtent, maxExtent); CreateALLNodes(root.childs[3], maxDepth - 1); root.childs[4] = new COTNode(); minExtent = new Vector3(parentCenter.x - parentHalfWidth, parentCenter.y - parentHalfHeight, parentCenter.z); maxExtent = new Vector3(parentCenter.x, parentCenter.y, parentCenter.z + parentHalfDepth); root.childs[4].center = (maxExtent + minExtent) / 2; root.childs[4].size = maxExtent - minExtent; root.childs[4].aabb.MakeAABB(minExtent, maxExtent); CreateALLNodes(root.childs[4], maxDepth - 1); root.childs[5] = new COTNode(); minExtent = new Vector3(parentCenter.x, parentCenter.y - parentHalfHeight, parentCenter.z); maxExtent = new Vector3(parentCenter.x + parentHalfWidth, parentCenter.y, parentCenter.z + parentHalfDepth); root.childs[5].center = (maxExtent + minExtent) / 2; root.childs[5].size = maxExtent - minExtent; root.childs[5].aabb.MakeAABB(minExtent, maxExtent); CreateALLNodes(root.childs[5], maxDepth - 1); root.childs[6] = new COTNode(); minExtent = new Vector3(parentCenter.x, parentCenter.y, parentCenter.z); maxExtent = new Vector3(parentCenter.x +parentHalfWidth, parentCenter.y + parentHalfHeight, parentCenter.z + parentHalfDepth); root.childs[6].center = (maxExtent + minExtent) / 2; root.childs[6].size = maxExtent - minExtent; root.childs[6].aabb.MakeAABB(minExtent, maxExtent); CreateALLNodes(root.childs[6], maxDepth - 1); root.childs[7] = new COTNode(); minExtent = new Vector3(parentCenter.x - parentHalfWidth, parentCenter.y, parentCenter.z); maxExtent = new Vector3(parentCenter.x, parentCenter.y + parentHalfHeight, parentCenter.z + parentHalfDepth); root.childs[7].center = (maxExtent + minExtent) / 2; root.childs[7].size = maxExtent - minExtent; root.childs[7].aabb.MakeAABB(minExtent, maxExtent); CreateALLNodes(root.childs[7], maxDepth - 1); }
/// <summary> /// 전체 지형를 감싸는 바운딩박스의 Min, MaxExtent로 Octree의 초기화를 합니다. /// </summary> /// <param name="_minBound"></param> /// <param name="_maxBound"></param> public void Init(Vector3 _minBound, Vector3 _maxBound) { // 실제 월드에 존재하는 각 블록들의 렌더링 되는 시작점에서 해당 오프셋을 빼준다. _minBound += offset; _maxBound += offset; Vector3 center = (_maxBound + _minBound) /2; root = new COTNode(); root.center = center; root.size = _maxBound - _minBound; root.aabb.MakeAABB(_minBound, _maxBound); }
private void AddNode(Vector3 pos, COTNode root) { Vector3 parentCenter = root.center; float parentHalfWidth = root.aabb.maxExtent.x - parentCenter.x; float parentHalfHeight = root.aabb.maxExtent.y - parentCenter.y; float parentHalfDepth = root.aabb.maxExtent.z - parentCenter.z; Vector3 minExtent, maxExtent; if (root.center == pos) { return; } else if ((root.center.x > pos.x) && (root.center.y > pos.y) && (root.center.z > pos.z)) { // 0번 노드. if(root.childs[0] != null) { AddNode(pos, root.childs[0]); }else { root.childs[0] = new COTNode(); minExtent = new Vector3(parentCenter.x - parentHalfWidth, parentCenter.y - parentHalfHeight, parentCenter.z - parentHalfDepth); maxExtent = parentCenter; root.childs[0].center = (maxExtent + minExtent) / 2; root.childs[0].size = maxExtent - minExtent; root.childs[0].aabb.MakeAABB(minExtent, maxExtent); AddNode(pos, root.childs[0]); } } else if ((root.center.x < pos.x) && (root.center.y > pos.y) && (root.center.z > pos.z)) { // 1번 노드. if (root.childs[1] != null) { AddNode(pos, root.childs[1]); } else { root.childs[1] = new COTNode(); minExtent = new Vector3(parentCenter.x, parentCenter.y - parentHalfHeight, parentCenter.z - parentHalfDepth); maxExtent = new Vector3(parentCenter.x + parentHalfWidth, parentCenter.y, parentCenter.z); root.childs[1].center = (maxExtent + minExtent) / 2; root.childs[1].size = maxExtent - minExtent; root.childs[1].aabb.MakeAABB(minExtent, maxExtent); AddNode(pos, root.childs[1]); } } else if ((root.center.x < pos.x) && (root.center.y < pos.y) && (root.center.z > pos.z)) { // 2번 노드. if (root.childs[2] != null) { AddNode(pos, root.childs[2]); } else { root.childs[2] = new COTNode(); minExtent = new Vector3(parentCenter.x, parentCenter.y, parentCenter.z - parentHalfDepth); maxExtent = new Vector3(parentCenter.x + parentHalfWidth, parentCenter.y + parentHalfHeight, parentCenter.z); root.childs[2].center = (maxExtent + minExtent) / 2; root.childs[2].size = maxExtent - minExtent; root.childs[2].aabb.MakeAABB(minExtent, maxExtent); AddNode(pos, root.childs[2]); } } else if ((root.center.x > pos.x) && (root.center.y < pos.y) && (root.center.z > pos.z)) { // 3번 노드. if (root.childs[3] != null) { AddNode(pos, root.childs[3]); } else { root.childs[3] = new COTNode(); minExtent = new Vector3(parentCenter.x - parentHalfWidth, parentCenter.y, parentCenter.z - parentHalfDepth); maxExtent = new Vector3(parentCenter.x, parentCenter.y + parentHalfHeight, parentCenter.z); root.childs[3].center = (maxExtent + minExtent) / 2; root.childs[3].size = maxExtent - minExtent; root.childs[3].aabb.MakeAABB(minExtent, maxExtent); AddNode(pos, root.childs[3]); } } else if ((root.center.x > pos.x) && (root.center.y > pos.y) && (root.center.z < pos.z)) { // 4번 노드. if (root.childs[4] != null) { AddNode(pos, root.childs[4]); } else { root.childs[4] = new COTNode(); minExtent = new Vector3(parentCenter.x - parentHalfWidth, parentCenter.y - parentHalfHeight, parentCenter.z); maxExtent = new Vector3(parentCenter.x, parentCenter.y, parentCenter.z + parentHalfDepth); root.childs[4].center = (maxExtent + minExtent) / 2; root.childs[4].size = maxExtent - minExtent; root.childs[4].aabb.MakeAABB(minExtent, maxExtent); AddNode(pos, root.childs[4]); } } else if ((root.center.x < pos.x) && (root.center.y > pos.y) && (root.center.z < pos.z)) { //5번 노드. if (root.childs[5] != null) { AddNode(pos, root.childs[5]); } else { root.childs[5] = new COTNode(); minExtent = new Vector3(parentCenter.x, parentCenter.y - parentHalfHeight, parentCenter.z); maxExtent = new Vector3(parentCenter.x + parentHalfWidth, parentCenter.y, parentCenter.z + parentHalfDepth); root.childs[5].center = (maxExtent + minExtent) / 2; root.childs[5].size = maxExtent - minExtent; root.childs[5].aabb.MakeAABB(minExtent, maxExtent); AddNode(pos, root.childs[5]); } } else if ((root.center.x < pos.x) && (root.center.y < pos.y) && (root.center.z < pos.z)) { // 6번 노드. if (root.childs[6] != null) { AddNode(pos, root.childs[6]); } else { root.childs[6] = new COTNode(); minExtent = new Vector3(parentCenter.x, parentCenter.y, parentCenter.z); maxExtent = new Vector3(parentCenter.x + parentHalfWidth, parentCenter.y + parentHalfHeight, parentCenter.z + parentHalfDepth); root.childs[6].center = (maxExtent + minExtent) / 2; root.childs[6].size = maxExtent - minExtent; root.childs[6].aabb.MakeAABB(minExtent, maxExtent); AddNode(pos, root.childs[6]); } } else if ((root.center.x > pos.x) && (root.center.y < pos.y) && (root.center.z < pos.z)) { // 7번 노드. if (root.childs[7] != null) { AddNode(pos, root.childs[7]); } else { root.childs[7] = new COTNode(); minExtent = new Vector3(parentCenter.x - parentHalfWidth, parentCenter.y, parentCenter.z); maxExtent = new Vector3(parentCenter.x, parentCenter.y + parentHalfHeight, parentCenter.z + parentHalfDepth); root.childs[7].center = (maxExtent + minExtent) / 2; root.childs[7].size = maxExtent - minExtent; root.childs[7].aabb.MakeAABB(minExtent, maxExtent); AddNode(pos, root.childs[7]); } } }
private void DeleteNode(Vector3 pos, COTNode root) { if (root.center == pos) { for (int i = 0; i < 8; i++) root.childs[i] = null; root.isCanDelete = true; return; } else if ((root.center.x > pos.x) && (root.center.y > pos.y) && (root.center.z > pos.z)) { // 0번 노드. if (root.childs[0] != null) { DeleteNode(pos, root.childs[0]); if (root.childs[0].isCanDelete) root.childs[0] = null; } } else if ((root.center.x < pos.x) && (root.center.y > pos.y) && (root.center.z > pos.z)) { // 1번 노드. if (root.childs[1] != null) { DeleteNode(pos, root.childs[1]); if (root.childs[1].isCanDelete) root.childs[1] = null; } } else if ((root.center.x < pos.x) && (root.center.y < pos.y) && (root.center.z > pos.z)) { // 2번 노드. if (root.childs[2] != null) { DeleteNode(pos, root.childs[2]); if (root.childs[2].isCanDelete) root.childs[2] = null; } } else if ((root.center.x > pos.x) && (root.center.y < pos.y) && (root.center.z > pos.z)) { // 3번 노드. if (root.childs[3] != null) { DeleteNode(pos, root.childs[3]); if (root.childs[3].isCanDelete) root.childs[3] = null; } } else if ((root.center.x > pos.x) && (root.center.y > pos.y) && (root.center.z < pos.z)) { // 4번 노드. if (root.childs[4] != null) { DeleteNode(pos, root.childs[4]); if (root.childs[4].isCanDelete) root.childs[4] = null; } } else if ((root.center.x < pos.x) && (root.center.y > pos.y) && (root.center.z < pos.z)) { //5번 노드. if (root.childs[5] != null) { DeleteNode(pos, root.childs[5]); if (root.childs[5].isCanDelete) root.childs[5] = null; } } else if ((root.center.x < pos.x) && (root.center.y < pos.y) && (root.center.z < pos.z)) { // 6번 노드. if (root.childs[6] != null) { DeleteNode(pos, root.childs[6]); if (root.childs[6].isCanDelete) root.childs[6] = null; } } else if ((root.center.x > pos.x) && (root.center.y < pos.y) && (root.center.z < pos.z)) { // 7번 노드. if (root.childs[7] != null) { DeleteNode(pos, root.childs[7]); if (root.childs[7].isCanDelete) root.childs[7] = null; } } }
/// <summary> /// Octree 중에 광선과 충돌하는 노드를 찾습니다. /// </summary> /// <param name="ray"></param> /// <param name="root"></param> private void CollideNodeWithRay(Ray ray, COTNode root) { if (root == null) return; CollideInfo info; info.isCollide = false; info.hitBlockCenter = new Vector3(0, 0, 0); if(root.size == blockMinSize) { info.isCollide = true; info.hitBlockCenter = root.center; collideCandidate.Add(info); } for(int i = 0; i < 8; i++) { if ((root.childs[i] != null) && (CustomRayCast.InterSectWithAABB(ray, root.childs[i].aabb))) { CollideNodeWithRay(ray, root.childs[i]); } } }
/// <summary> /// Octree 중에 특정 AABB와 충돌하는 노드를 찾습니다. /// </summary> /// <param name="other"></param> /// <param name="root"></param> private CollideInfo CollideNodeWithAABB(CustomAABB other, COTNode root) { CollideInfo info; info.isCollide = false; info.hitBlockCenter = new Vector3(0, 0, 0); if(root.size == blockMinSize) { info.isCollide = true; info.hitBlockCenter = root.center; return info; } for (int i = 0; i < 8; i++) { if ((root.childs[i] != null) && (root.childs[i].aabb.IsInterSectAABB(other))) { return CollideNodeWithAABB(other, root.childs[i]); } } return info; }
private void DrawAllNodes(COTNode node) { Gizmos.color = Color.yellow; if (node.size == blockMinSize) Gizmos.DrawWireCube(node.center, node.size); for (int i = 0; i < 8; i++) { if (node.childs[i] == null) continue; if (node.size == blockMinSize) Gizmos.DrawWireCube(node.childs[i].center, node.childs[i].size); DrawAllNodes(node.childs[i]); } }