首页 > 其他分享 >Unity3D 八叉树划分空间和可视化

Unity3D 八叉树划分空间和可视化

时间:2024-06-19 14:25:39浏览次数:14  
标签:Unity3D int OctreeNode 八叉树 Vector3 可视化 new root public

也许更好的阅读体验

成果展示

所有层
第一层

第二层

代码

OctreeNode

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OctreeNode
{
    //空间内包含的物体
    public List<GameObject> areaObjects;
    //空间中心
    public Vector3 center;
    //空间大小
    public float size;
    //子节点个数 
    private int kidCount = 8;
    //子节点
    public OctreeNode[] kids;
    //构造函数
    public OctreeNode (Vector3 center, float size)
    {
        this.center = center;
        this.size = size;
        kids = new OctreeNode[kidCount];
        areaObjects = new List<GameObject>();
    }
    #region 八个子节点中心对应的偏移方向
    public static Vector3[] centerOffset = new Vector3[8] {
        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)
    };
    #endregion

    #region 空间和内部物体管理
    //空间内物体树
    public int objectCount => areaObjects.Count;
    //把该空间画出来
    public void DrawGizmos ()
    {
        Gizmos.DrawWireCube(center, Vector3.one * size);
    }
    //判断是否包含某个点
    public bool Contains (Vector3 position)
    {
        float halfSize = size / 2.0f;
        return Mathf.Abs(position.x - center.x) <= halfSize &&
            Mathf.Abs(position.y - center.y) <= halfSize &&
            Mathf.Abs(position.z - center.z) <= halfSize;
    }
    //清理空间内物体
    public void Clear ()
    {
        areaObjects.Clear();
    }
    //添加物体
    public void AddGameObject (GameObject obj)
    {
        areaObjects.Add(obj);
    }
    #endregion

}

Orctree

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Design.Serialization;
using Unity.VisualScripting;
using UnityEngine;

//可视化模式
public enum OctreeDebugMode
{
    AllDepth,
    TargetDepth
}
public class Octree : MonoBehaviour
{

    #region 物体生成和构建八叉树
    //生成物体数
    [Range(0, 500)]
    public int genCount = 500;
    //物体生成范围
    [Range(1, 300)]
    public float range = 100;
    //生成的物体
    public List<GameObject> sceneObjects;
    //Octree最大层数
    [Range(1, 8)]
    public int maxDepth = 3;
    //Octree的根节点
    public OctreeNode root;


    // Start is called before the first frame update
    void Start()
    {
        GenObjects();
        OctreePartition();
    }

    //随机生成一些cube
    private void GenObjects()
    {
        float genRange = range * 0.5f;
        sceneObjects = new List<GameObject>();

        for (int i = 0; i < genCount; ++i)
        {
            GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
            obj.transform.position = new Vector3(Random.Range(-genRange, genRange),
                Random.Range(-genRange, genRange),
                Random.Range(-genRange, genRange));
            obj.hideFlags = HideFlags.HideInHierarchy;
            sceneObjects.Add(obj);
        }
    }
    //进行八叉树划分
    private void OctreePartition ()
    {
        //设定根节点
        Vector3 origin = Vector3.one;
        root = new OctreeNode(Vector3.zero, range);
        root.areaObjects = sceneObjects;
        //往下生成八叉树 根节点层数为1
        GenerateOcetree(root, range, 2);
    }
    //递归往下生成八叉树
    private void GenerateOcetree (OctreeNode root, float range, int depth)
    {
        //depth是当前生成的层数
        if (depth > maxDepth) return;
        //下一层的大小
        float halfRange = range / 2.0f;
        //根节点偏移量
        float rootOffset = halfRange / 2.0f;
        for (int i = 0; i < 8; ++i)
        {
            Vector3 origin = root.center + OctreeNode.centerOffset[i] * rootOffset;
            root.kids[i] = new OctreeNode(origin, halfRange);
        }
        PartitionSceneObjects(root);
        for (int i = 0; i < 8; ++i)
        {
            if (root.kids[i].objectCount >= 2) GenerateOcetree(root.kids[i], halfRange, depth + 1);
        }
    }
    //把空间内物体划分给子节点
    private void PartitionSceneObjects(OctreeNode root)
    {
        foreach (GameObject obj in root.areaObjects)
        {
            foreach (OctreeNode kid in root.kids)
            {
                if (kid.Contains(obj.transform.position))
                {
                    kid.AddGameObject(obj);
                }
            }
        }
    }
    #endregion

    #region 可视化
    //是否显示八叉树
    public bool showOctree = true;
    //可视化类型
    public OctreeDebugMode octreeDebugMode;
    //可视化层数
    [Range(0, 8)]
    public int displayDepth = 3;
    //不同深度的可视化颜色
    public Color[] displayColor;
    private void OnDrawGizmos()
    {
        if (root == null) return;
        if (showOctree && displayDepth <= maxDepth)
        {
            //显示所有深度的空间范围
            if (octreeDebugMode == OctreeDebugMode.AllDepth)
            {
                DrawNode(root, 1);
            }
            //显示指定深度的空间范围(第displayDepth层)
            else if (octreeDebugMode == OctreeDebugMode.TargetDepth)
            {
                if (displayDepth > 0 && displayColor.Length >= displayDepth) 
                {
                    Color color = displayColor[displayDepth - 1];
                    color.a = 0.5f;
                    Gizmos.color = color;
                    DrawTargetDepth(root, displayDepth);
                }
            }
        }
    }
    //绘制所有节点 当前深度为depth
    private void DrawNode(OctreeNode root, int depth)
    {
        if (root == null || depth > maxDepth) return;
        Color color = displayColor[depth - 1];
        color.a = 0.5f;
        Gizmos.color = color;
        root.DrawGizmos();
        foreach (OctreeNode kid in root.kids)
        {
            DrawNode(kid, depth + 1);
        }
    }
    //绘制指定层
    private void DrawTargetDepth (OctreeNode root, int targetDepth)
    {
        --targetDepth;
        if (root == null || targetDepth < 0) return;
        Debug.Log(targetDepth);
        if (targetDepth == 0)
        {
            root.DrawGizmos();
            return;
        }
        foreach (OctreeNode kid in root.kids)
        {
            DrawTargetDepth(kid, targetDepth);
        }
    }
    #endregion
}

标签:Unity3D,int,OctreeNode,八叉树,Vector3,可视化,new,root,public
From: https://www.cnblogs.com/Morning-Glory/p/18256138

相关文章

  • Unity3D 用贝塞尔曲线进行弹道追踪
    usingSystem.Collections;usingSystem.Collections.Generic;usingUnity.Collections.LowLevel.Unsafe;usingUnityEngine;usingUnityEngine.UI;publicclassBulletLogic:MonoBehaviour{//Startiscalledbeforethefirstframeupdate//飞行速度最大......
  • 【名词解释】Unity3D物理射线(Physics Ray)含义及其用法
    Unity3D是一款流行的游戏开发引擎,它提供了一套强大的工具和功能来帮助开发者创建交互式3D内容。在Unity中,"物理射线"(PhysicsRay)通常指的是使用射线检测(Raycasting)来检测物体之间的碰撞或者检测射线与物体的交点。这在游戏开发中非常常见,用于实现如射击、视线检测、物体碰撞检......
  • (slam工具)5 绘画可视化
       https://github.com/Dongvdong/v1_1_slam_tool  #!/usr/bin/python#-*-coding:UTF-8-*-importmathfrompyechartsimportLine3DfrompyechartsimportLineimportmatplotlib.pyplotaspltfrommpl_toolkits.mplot3dimportaxes3dimportnump......
  • 前端使用 Konva 实现可视化设计器(16)- 旋转对齐、触摸板操作的优化
    这一章解决两个缺陷,一是调整一些快捷键,使得Mac触摸板可以正常操作;二是修复一个Issue,使得即使素材节点即使被旋转之后,也能正常触发磁贴对齐效果,有个小坑需要注意。请大家动动小手,给我一个免费的Star吧~大家如果发现了Bug,欢迎来提Issue哟~github源码gitee源码示例地址......
  • 基于springboot的南门桥社区疫情防疫系统-48138(免费领源码+数据库)可做计算机毕业设计J
    Springboot南门桥社区疫情防疫系统的设计与实现摘 要信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对南门桥社区疫情防疫系统等问题,对南门桥社区......
  • 数据可视化是如何在智慧水利中应用的?
    数据可视化是如何在智慧水利中应用的?在现代水利管理中,面对复杂的水资源数据和动态变化的水文情况,数据可视化技术通过将繁杂的数据转化为直观、易理解的图表和图形,极大地提升了水利管理的效率和决策的科学性。智慧水利利用数据可视化技术,实现了对水资源的全面监控、精确管理和优化......
  • 数据可视化在智慧物流中发挥了什么作用?
    数据可视化在智慧物流中发挥了至关重要的作用,成为优化物流管理、提升效率和改善客户体验的关键工具。在现代物流行业中,面对海量数据的挑战,数据可视化技术通过将复杂数据转化为直观的图表、图形和仪表盘,帮助企业和管理者更有效地理解、分析和利用信息,从而做出更明智的决策。首先,......
  • 风光储一体化园区 | 图扑新能源可视化
    随着全球能源结构转型加速,可再生能源成为能源发展的重要方向。风能、太阳能作为清洁、绿色的能源,得到了广泛的开发和应用。与此同时,储能技术的发展为解决风能和太阳能发电的间歇性和波动性问题提供了有效途径。风光储园区作为整合风电、光伏发电及储能技术的新型能源基地,在提高能......
  • ETL可视化工具 DataX -- 简介( 一)
    引言DataX系列文章:ETL可视化工具DataX–安装部署(二)1.1DataX1.1.1DataX概览DataX是阿里云DataWorks数据集成的开源版本,在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。DataX实现了包括MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS、Hive、A......
  • 【EMC专题】ESD可视化设备对比宽地线和窄地线对ESD性能的影响
    ESD可视化设备        ESD可视化设备是一种通过用非接触磁场探针自动扫描ESD电流来实现ESD电流可视化的设备。如下所示磁场探针可以测量电场强度,结合不同位置移动进行扫描,通过反复施加ESD并测量,得到PCB整体的电场强度数据。 实验解析实验目的        利......