首页 > 编程语言 >KD树空间划分算法碰撞检测

KD树空间划分算法碰撞检测

时间:2024-07-12 20:19:10浏览次数:20  
标签:node KDNode 划分算法 target KD Vector3 碰撞检测 points

参考:KD树详解-CSDN博客

 

KD树(k-dimensional tree)是一种用于多维空间中点数据的高效存储和检索的数据结构。在游戏开发中,KD树具有多种重要的应用,主要体现在以下几个方面:

1. 空间分区

KD树可以用于将游戏世界划分为多个区域,从而提高碰撞检测、物体查询等操作的效率。通过将空间划分为不同的区域,可以快速确定某个物体位于哪个区域,从而减少需要检查的物体数量。

2. 最近邻搜索

在许多游戏中,需要找到离某个点最近的对象,例如在AI导航、路径规划、物理模拟中。KD树可以高效地进行最近邻搜索,比暴力搜索更快。

示例:

  • AI敌人需要找到离它最近的玩家角色。
  • 在塔防游戏中,塔需要找到最近的敌人目标进行攻击。

3. 碰撞检测

KD树可以用于高效的碰撞检测,尤其是在处理大量物体的场景中。通过使用KD树,可以快速筛选出可能发生碰撞的物体对,减少需要精确检测的物体数量。

示例:

  • 在粒子系统中,粒子之间的碰撞检测。
  • 在大型开放世界游戏中,处理大量物体之间的碰撞。

4. 光线追踪

在光线追踪渲染中,KD树可以用于加速光线与场景中物体的相交测试。通过将场景中的三角形面片组织成KD树,可以快速找到与光线相交的三角形,从而提高渲染速度。

示例:

  • 在光线追踪渲染中,加速光线与场景中物体的相交测试。
  • 在实时渲染中,提高渲染效率。

5. 场景管理

在游戏中,可以使用KD树来管理和组织场景中的静态和动态物体,从而提高渲染和更新效率。KD树可以帮助快速确定哪些物体需要渲染、更新或处理。

示例:

  • 在大型场景中,通过KD树组织物体,以便快速确定可见物体进行渲染。
  • 在复杂的场景中,快速查找和管理物体。

KD树的简单实现示例

下面是一个简单的KD树实现示例,展示如何构建KD树以及进行最近邻搜索。

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

public class KDTree
{
    private class KDNode
    {
        public Vector3 Point;
        public KDNode Left;
        public KDNode Right;

        public KDNode(Vector3 point)
        {
            Point = point;
            Left = null;
            Right = null;
        }
    }

    private KDNode root;

    public KDTree(Vector3[] points)
    {
        root = BuildKDTree(points, 0);
    }

    private KDNode BuildKDTree(Vector3[] points, int depth)
    {
        if (points.Length == 0) return null;

        int axis = depth % 3;
        Array.Sort(points, (a, b) => a[axis].CompareTo(b[axis]));

        int medianIndex = points.Length / 2;
        KDNode node = new KDNode(points[medianIndex]);

        node.Left = BuildKDTree(SubArray(points, 0, medianIndex), depth + 1);
        node.Right = BuildKDTree(SubArray(points, medianIndex + 1, points.Length - medianIndex - 1), depth + 1);

        return node;
    }

    private Vector3[] SubArray(Vector3[] data, int index, int length)
    {
        Vector3[] result = new Vector3[length];
        Array.Copy(data, index, result, 0, length);
        return result;
    }

    public Vector3 FindNearest(Vector3 target)
    {
        return FindNearest(root, target, 0);
    }

    private Vector3 FindNearest(KDNode node, Vector3 target, int depth)
    {
        if (node == null) return Vector3.positiveInfinity;

        int axis = depth % 3;
        KDNode nextNode = (target[axis] < node.Point[axis]) ? node.Left : node.Right;
        KDNode otherNode = (target[axis] < node.Point[axis]) ? node.Right : node.Left;

        Vector3 best = FindNearest(nextNode, target, depth + 1);
        if (Vector3.Distance(target, node.Point) < Vector3.Distance(target, best))
        {
            best = node.Point;
        }

        if (Mathf.Abs(target[axis] - node.Point[axis]) < Vector3.Distance(target, best))
        {
            Vector3 possibleBest = FindNearest(otherNode, target, depth + 1);
            if (Vector3.Distance(target, possibleBest) < Vector3.Distance(target, best))
            {
                best = possibleBest;
            }
        }

        return best;
    }
}

使用示例

public class KDTreeExample : MonoBehaviour
{
    void Start()
    {
        Vector3[] points = {
            new Vector3(1, 2, 3),
            new Vector3(4, 5, 6),
            new Vector3(7, 8, 9),
            new Vector3(2, 3, 4),
            new Vector3(5, 6, 7)
        };

        KDTree kdTree = new KDTree(points);
        Vector3 target = new Vector3(3, 3, 3);
        Vector3 nearest = kdTree.FindNearest(target);

        Debug.Log("Nearest point to " + target + " is " + nearest);
    }
}

 

对比

  • 维度

    • KD树:适用于任意k维空间(k通常较小)。
    • 八叉树:主要用于三维空间。
  • 空间划分

    • KD树:按维度划分,每次划分一个维度。
    • 八叉树:按立方体划分,每次划分为八个子空间。
  • 适用场景

    • KD树:更适合多维点数据的管理和搜索。
    • 八叉树:更适合三维空间的管理和可视化

标签:node,KDNode,划分算法,target,KD,Vector3,碰撞检测,points
From: https://www.cnblogs.com/jeason1997/p/18299322

相关文章

  • 【Unity】碰撞检测算法及框架实现
    背景硕士期间研究课题是海洋生物数字孪生,基于各类Boids改进的算法里会有大量的海洋鱼类在三维空间中运动,鱼类之间会有互相感知的过程,同一帧里需要对许多行为进行决策判定,例如同伴鱼、食物、捕食者、栖息地等等。因此打算研究下有什么空间加速算法能够避免暴力迭代,减少开销。既然......
  • markdown文件中图片url替换方法
    博客园可以直接通过markdown文件导入成博客,我在本地有一些自己的markdown文件,但是里面的图片都是相对路径,其实我将这些文件都打包好传到gitee了,那其实这些图片也在gitee中,所以我只要把markdown文件中的相对路径换成gitee中的路径就好了,下面是我用python写的一个脚本。importargp......
  • 驻扎初篇(markdown)
    markdown的初级使用语法本片作为开始使用博客的第一篇笔记只为了方便为日后的编辑博客做基础的语言记录以下为markdown的语法标题标题一标题二标题三标题四标题五标题六代码行内代码&代码块行内代码使用代码标识,可嵌入文字中代码块使用4个空格或标识示例//注......
  • markdown 嵌入视频 测试
    【4KIWindows11宣传片】https://www.bilibili.com/video/BV1g64y197mi?vd_source=025a1c967fa95b3dcfb9b276f7348163你的浏览器不支持视频标签。在Markdown中嵌入视频并不是Markdown原生支持的功能,因为Markdown主要被设计用来处理文本格式化,如标题、列表、代码块......
  • 论文分享|KDD2024‘北航|平等对待每种语言:CCRK—1对K对比学习一致提升跨语言跨模态检
    推荐一篇笔者参与的KDD2024工作,面向多语言场景下的图文检索的CCRK。核心创新点可以用下图总结:我们提出了一种新颖的1对K对比学习损失,同时解决了CCR任务中模态内错误传播和模态间优化偏差问题,在训练中平等对待各种语言。我们改进了现有的预训练中M-ITM和M-MLM任务的难负例采......
  • Python潮流周刊的优惠券和精美电子书(EPUB、PDF、Markdown)
    Python潮流周刊从2023.05.13连载至今,本周即将发布第60期,这意味着我们又要达成一个小小的里程碑啦!每周坚持做分享,周复一周,这对自己的精力和意志是一项不小的挑战。于是,为了让自己获得一些仪式感,我给自己定了一个较为合理的时间目标,就是每30期周刊作为一季。划分出“每一季......
  • 如何学习一门新技术,十年 MarkDown 程序员怎么做
    案例源码仓库地址:https://github.com/Rodert/go-demo官方文档:https://etcd.io/视频教程:https://space.bilibili.com/404747369文章目录介绍使用场景安装&搭建搭建ETCD与ETCD交互集群Go+ETCD编码介绍谈使用场景之前,看看他有哪些功能官方定义是这样的:etcd......
  • Bullet 学习笔记之 软体仿真流程(二) 软体碰撞检测与响应
    简述Bullet中软体的碰撞检测与响应算法,仅针对Soft类型,Deformable类型不包含在这篇文章中。1.软体碰撞检测在BulletPhysics中,软体的碰撞检测采用的是“点-面”的方法,即分别用两个软体的m_ndbvt和m_fdbvt做碰撞检测,两个bvh树之间的遍历方法不在此展开,当Node......
  • 【狂神说Java】系列学习笔记01——MarkDown语法
    #MarkDown学习本文为B站老师秦疆【狂神说Java】系列,课堂学习笔记,主要联练习的是MarkDown的使用方法,老师的博客链接我没找到,广告1.标题+加粗2级3级4级5级6级最多七级标题Helloworld!Helloworld!Helloworld!Helloworld!引用-沐风6标题一级标题(#+空格)二......
  • 创建vue2项目执行npm install -g @vue/cli报错 no such file or directory, mkdir '\
    第一步:查看默认全局安装路径。指令:npmconfiggetprefix我这里路径npmconfiggetprefixE:\NVM\nvm\node_global第二步:不存在这个路劲进行更换npmconfigsetprefix"D:\Develop\nodejs"nodejs里面有node_cachenode_globalnode_modules这些文件npmconfiggetpre......