• 售前

  • 售后

热门帖子
入门百科

【Unity】八叉树 优化场景

[复制链接]
永远丶并不远 显示全部楼层 发表于 2022-1-14 09:04:48 |阅读模式 打印 上一主题 下一主题
BStandShaderResources/OcTree1.unitypackage at master · AMikeW/BStandShaderResources (github.com)

 
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEditor;
  4. using UnityEngine;
  5. public class DcTreeManager : MonoBehaviour
  6. {
  7.     public DcTreeNode MainDcTreeNode;
  8.     private Camera camera;
  9.     private Plane[] plane;
  10.     void Start()
  11.     {
  12.         Renderer[] renderers = this.transform.GetComponentsInChildren<Renderer>();
  13.         List<Renderer> rendererList = new List<Renderer>();
  14.         rendererList.AddRange(renderers);
  15.         if (renderers != null && renderers.Length > 0)
  16.         {
  17.             MainDcTreeNode = new DcTreeNode(new Bounds(Vector3.zero, new Vector3(25, 25, 25)), 0);
  18.             MainDcTreeNode.GenerateChildNodes(rendererList, true);
  19.         }
  20.         else
  21.         {
  22.             Debug.LogError("一个renderers都没有");
  23.         }
  24.         camera = Camera.main;
  25.     }
  26.     private void Update()
  27.     {
  28.         MainDcTreeNode.RefreshVisiable((bounds) =>
  29.         {
  30.             plane = GeometryUtility.CalculateFrustumPlanes(this.camera);
  31.             return GeometryUtility.TestPlanesAABB(plane, bounds);
  32.         });
  33.     }
  34.     private void OnDrawGizmos()
  35.     {
  36.         if (UnityEditor.EditorApplication.isPlaying)
  37.         {
  38.             MainDcTreeNode.Draw((bounds) => { Gizmos.DrawWireCube(bounds.center, bounds.size); });
  39.         }
  40.     }
  41. }
复制代码
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. public class DcTreeNode
  6. {
  7.     static Dictionary<int, Vector3> side2Dir = new Dictionary<int, Vector3>()
  8.     {
  9.         [0] = new Vector3(-1, -1, -1).normalized, //lb+ lb代表left bottom左下 +代表正面
  10.         [1] = new Vector3(-1, 1, -1).normalized, //lt+
  11.         [2] = new Vector3(1, -1, -1).normalized, //rb+
  12.         [3] = new Vector3(1, 1, -1).normalized, //rt+
  13.         [4] = new Vector3(-1, -1, 1).normalized, //lb- 左下 背面
  14.         [5] = new Vector3(-1, 1, 1).normalized, //lt-
  15.         [6] = new Vector3(1, -1, 1).normalized, //rb-
  16.         [7] = new Vector3(1, 1, 1).normalized, //rt-
  17.     };
  18.     static Dictionary<int, Color> side2Color = new Dictionary<int, Color>()
  19.     {
  20.         [0] = Color.red, //lb+  同上
  21.         [1] = Color.yellow, //lt+
  22.         [2] = Color.green, //rb+
  23.         [3] = Color.blue, //rt+
  24.         [4] = Color.cyan, //lb-
  25.         [5] = Color.gray, //lt-
  26.         [6] = Color.black, //rb-
  27.         [7] = Color.white, //rt-
  28.     };
  29.     private int side;
  30.     private Bounds nodeBounds;
  31.     private List<DcTreeNode> childNodes;
  32.     private List<Renderer> containRenderers;
  33.     public DcTreeNode(Bounds bounds, int side)
  34.     {
  35.         childNodes = new List<DcTreeNode>();
  36.         nodeBounds = bounds;
  37.         this.side = side;
  38.     }
  39.     public void Draw(Action<Bounds> action)
  40.     {
  41.         Gizmos.color = side2Color[side];
  42.         action(nodeBounds);
  43.         foreach (var v in childNodes)
  44.         {
  45.             v.Draw(action);
  46.         }
  47.     }
  48.     public void RefreshVisiable(Func<Bounds, bool> func)
  49.     {
  50.         bool isOn = func(nodeBounds);
  51.         if (isOn)
  52.         {
  53.             foreach (var v in childNodes)
  54.             {
  55.                 v.RefreshVisiable(func);
  56.             }
  57.         }
  58.         if (containRenderers != null)
  59.         {
  60.             foreach (var v in containRenderers)
  61.             {
  62.                 v.enabled = isOn;
  63.             }
  64.         }
  65.     }
  66.     /// <summary>
  67.     /// 生成8个子节点
  68.     /// </summary>
  69.     public void GenerateChildNodes(List<Renderer> renderers, bool isFirst = false)
  70.     {
  71.         containRenderers = renderers;
  72.         List<Renderer> tempAlreadyAddRenderers = new List<Renderer>();
  73.         float halfSize = this.nodeBounds.size.x * 0.5f;
  74.         float length = new Vector3(halfSize, halfSize, halfSize).magnitude / 2;
  75.         for (int i = 0; i < 8; i++)
  76.         {
  77.             Bounds bounds = new Bounds();
  78.             bounds.size = this.nodeBounds.size * 0.5f;
  79.             bounds.center = this.nodeBounds.center + side2Dir[i] * length;
  80.             List<Renderer> tempNodeRenderers = new List<Renderer>();
  81.             foreach (var v in containRenderers)
  82.             {
  83.                 if (bounds.Contains(v.bounds.min) && bounds.Contains(v.bounds.max))
  84.                 {
  85.                     tempNodeRenderers.Add(v);
  86.                 }
  87.             }
  88.             foreach (var v in tempNodeRenderers)
  89.             {
  90.                 containRenderers.Remove(v);
  91.             }
  92.             DcTreeNode node;
  93.             if (isFirst)
  94.             {
  95.                 node = new DcTreeNode(bounds, i);
  96.             }
  97.             else
  98.             {
  99.                 node = new DcTreeNode(bounds, side);
  100.             }
  101.             childNodes.Add(node);
  102.             if (tempNodeRenderers.Count > 0)
  103.             {
  104.                 node.GenerateChildNodes(tempNodeRenderers);
  105.             }
  106.         }
  107.     }
  108. }
复制代码
实现思路:生成一个适当的Bounds盒子区域进行开始八叉树遍历,每一次切割出等体积的8个子方块,必须满足至少有一个物体AABB盒完全包含在当前八叉树节点Bounds才进行切割8个子节点。
这里的切割方式是最简单无脑的所以很简单,一般都要有一些算法支持 不然会有很多空隙导致搜索变慢。(可自行优化)

来源:https://blog.caogenba.net/qq_39574690/article/details/122463478
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作