====================================================||

欢迎讨论技术的可以相互加微信:windgs (请备注csdn+xx职业)

====================================================||

目录

目录

欢迎讨论技术的可以相互加微信:windgs (请备注csdn+xx职业)

Bounds(包围盒)概述与应用

1.包围盒描述(摘至百度百科):

1.1 什么是包围盒?

1.2 包围盒的类型:

1.2.1 AABB包围盒(Axis-aligned bounding box)

1.2.2 包围球(Sphere)

1.2.3 OBB方向包围盒(Oriented bounding box)

1.2.4 FDH固定方向凸包(Fixed directions hulls或k-DOP)

2.AABB包围盒在Unity中的拓展

3.例子,关于上面拓展方法的使用


球形包围盒的碰撞检测,生成原理: 
生成方法是均值法,Ritter方法 
均值法简单,快速,但是不准确,生成的包围盒不是特别贴近模型 
Ritter方法步骤更多,要慢一些,但是包围盒更准确,更贴近模型 
http://blog.csdn.net/i_dovelemon/article/details/32904251

AABB碰撞检测: 
http://www.it165.net/pro/html/201409/22717.html

OBB碰撞检测: 
一般用 Seperating Axie Theorem(分离轴定理) 来检测的原理 
http://www.cnblogs.com/iamzhanglei/archive/2012/06/07/2539751.html 
http://blog.csdn.net/i_dovelemon/article/details/31420749 
http://www.2cto.com/kf/201410/339595.html
---------------------

任何实时三维交互式程序,如果没有碰撞检测,都是没有价值,甚至无法使用的。游戏中最常用的碰撞检测技术莫过于包围盒(bounding volume)碰撞检测。对于以60pfs运行的游戏来说,处理每一帧数据的时间只有0.0167s左右,对于不同的游戏,碰撞检测大概需要占10~30%的时间,也就是说,所有碰撞检测必须在0.002~0.005s内完成,非常巨大的挑战。因此,任何包围盒都应该满足以下特性:

1. 快速的碰撞检测
2. 能紧密覆盖所包围的对象
3. 包围盒应该非常容易计算
4. 能方便的旋转和变换坐标
5. 低内存占用

最常见的包围盒有:Sphere,AABB,OBB等,外加一个比较特殊的frustum。Sphere能很好的满足1,3,4,5条,但通常包含了太多无用的空间,容易导致错误的碰撞结果。AABB应该是sphere与obb之间的解决方案,同时兼顾了效率和空间覆盖范围。OBB是三者中精度最高的,但检测代价也是最高的。
   
最终使用哪一种包围盒,是一个非常痛苦的过程,我们需要在效率和精度之间做出权衡取舍。前几天刚好完成了基本的碰撞检测函数,以下是我的一些测试数据,在一定程度上可以作为参考。纯C#代码实现,没有任何GPU加速,单线程在Q6600上运行。

Sphere-Sphere:100万次测试,大约有16000次碰撞,耗时0.016s。

AABB-AABB:100万次测试,1000次碰撞,耗时0.014s。

OBB-OBB: 使用传统的separate axis算法,100万次测试,30万次碰撞,耗时0.160s左右。对于没有碰撞的情况,几乎在前6条轴的检测中,就能结束检测,也就是说大约50万次(50%)测试都在检测第七条轴之前结束。

Vertical-agliened OBB - Vertical-agliened OBB:普通OBB的特殊版本,只能绕Y轴旋转。100w次测试,同样30万次碰撞,耗时0.08s,几乎比普通OBB快了一倍。

最后Frustum-AABB:使用<<Optimized View Frustum Culling Algorithms for Bounding Boxes>>中的算法,100w次测试,6万次碰撞,耗时0.096s。目前我计算n-vertex和p-vertex的方法是瓶颈,大约0.016s的时间花在计算这两个点上。 相比XNA中的BoundingFrustum.Intersects,同样的测试需要0.5s左右。
(以上均为对随机数据的测试,因此不同包围盒之间的实际碰撞次数并没有可比性,也不代表不同类型间的精度)

显然,AABB是性价比最高的,OBB虽然有较高精度,但相对其计算代价来说,并不划算,可以考虑用多个AABB来近似OBB,或者使用代价相对较低的Vertical-agliened OBB。Sphere看起来简单,但计算涉及到开方(虽然Math.Sqrt会直接编译为fsqrt指令),因此仍然没有AABB快(只需要6条逻辑比较指令)


Bounds(包围盒)概述与应用

1.包围盒描述(摘至百度百科):

1.1 什么是包围盒?

包围盒算法是一种求解离散点集最优包围空间的方法。
    基本思想是用体积稍大且特性简单的几何体(称为包围盒)来近似地代替复杂的几何对象。
    最常见的包围盒算法有

AABB包围盒(Axis-aligned bounding box),
    包围球(Sphere), 
    方向包围盒OBB(Oriented bounding box)
    固定方向凸包FDH(Fixed directions hulls或k-DOP)。

1.2 包围盒的类型:

1.2.1 AABB包围盒(Axis-aligned bounding box)

AABB是应用最早的包围盒。它被定义为包含该对象,且边平行于坐标轴的最小六面体
    。故描述一个AABB,仅需六个标量。AABB构造比较简单,存储空间小,但紧密性差,尤其
    对不规则几何形体,冗余空间很,当对象旋转时,无法对其进行相应的旋转。处理对象
    是刚性并且是凸的,不适合包含软体变形复杂虚拟环境情况。
        AABB也是比较简单的一类包围盒。但对于沿斜对角方向放置的瘦长形对象,其紧密性
    较差。由于AABB相交测试的简单性及较好的紧密性,因此得到了广泛的应用,还可以
    用于软体对象的碰撞检测。

1.2.2 包围球(Sphere)

包围球被定义为包含该对象的最小的球体。确定包围球,首先需分别计算组成对象的
    基本几何元素集合中所有元素的顶点的x,y,z坐标的均值以确定包围球的球心,再由球心
    与三个最大值坐标所确定的点间的距离确定半径r。包围球的碰撞检测主要是比较两球间半
    径和与球心距离的大小。

1.2.3 OBB方向包围盒(Oriented bounding box)

OBB是较为常用的包围盒类型。它是包含该对象且相对于坐标轴方向任意的最小的长方
    体
。OBB最大特点是它的方向的任意性,这使得它可以根据被包围对象的形状特点尽可能紧
    密的包围对象
,但同时也使得它的相交测试变得复杂。OBB包围盒比AABB包围盒和包围球
    加紧密
地逼近物体,能比较显著地减少包围体的个数,从而避免了大量包围体之间的相交
    检测。但OBB之间的相交检测比AABB或包围球体之间的相交检测更费时。

1.2.4 FDH固定方向凸包(Fixed directions hulls或k-DOP)

FDH(k-DOP)是一种特殊的凸包,继承了AABB简单性的特点,但其要具备良好的空间
    紧密度,必须使用足够多的固定方向。被定义为包含该对象且它的所有面的法向量都取自
    一个固定的方向(k个向量)集合的凸包。FDH比其他包围体更紧密地包围原物体,创建的层
    次树也就有更少的节点,求交检测时就会减少更多的冗余计算,但相互间的求交运算较为复杂。

2.AABB包围盒在Unity中的拓展

以下这段代码可以添加到静态类中作为Transform的拓展方法可以直接使用
这段代码可以直接获取模型的包围盒数据,不论是几个层级的模型,都可以直接获取最大的包围盒
详细计算可以见代码,就不详细讲解了,看不懂可私信我/// <summary>
/// 获取模型包围盒的中心点
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public static Vector3 CENTER( this Transform model )
{Vector3 result = Vector3.zero;int counter = 0;calculateCenter(model,ref result,ref counter);return result / counter;
}/// <summary>
/// 获取模型包围盒
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public static Bounds BOUNDS( this Transform model )
{Vector3 oldPos = model.position;model.position = Vector3.zero;Bounds resultBounds = new Bounds(model.CENTER() , Vector3.zero);calculateBounds(model , ref resultBounds);model.position = oldPos;Vector3 scalueValue = scaleValue(model); ;resultBounds.size = new Vector3(resultBounds.size.x / scalueValue.x , resultBounds.size.y / scalueValue.y , resultBounds.size.z / scalueValue.z);return resultBounds;
}private static void calculateCenter( Transform model , ref Vector3 result , ref int counter )
{if (model.childCount.Equals(0)){if(!model.GetComponent<Renderer>())return;result += model.center();counter++;return;}List<Transform> childModels = model.GetComponentsInChildrenNoSelf<Transform>();for (int i = 0; i < childModels.Count; i++, ++counter)calculateCenter(childModels[i] , ref result , ref counter);
}private static Vector3 scaleValue( Transform model )
{Vector3 result = model.localScale;return calculateScale(model,ref result);
}private static Vector3 calculateScale( Transform model ,ref Vector3 value)
{if (model.parent){Vector3 scale = model.parent.localScale;value = new Vector3(value.x * scale.x , value.y * scale.y , value.z * scale.z);calculateScale(model.parent,ref value);}return value;
}private static void calculateBounds( Transform model , ref Bounds bounds )
{if (model.childCount.Equals(0)){if (!model.GetComponent<Renderer>())return;bounds.Encapsulate(model.bounds());return;}List<Transform> childModels = model.GetComponentsInChildrenNoSelf<Transform>();for (int i = 0; i < childModels.Count; i++)calculateBounds(childModels[i],ref bounds);
}

3.例子,关于上面拓展方法的使用

1.添加碰撞器
AddCollider这个拓展方法可以为模型添加一个最大的Box碰撞器,可以在游戏中需要添加碰撞器的地方使用,省去为每一个模型添加碰撞器带来的性能损耗。public static Bounds AddCollider( this Transform model )
{Bounds bounds = model.BOUNDS();BoxCollider collider = model.gameObject.AddComponent<BoxCollider>();collider.center = bounds.center;collider.size = bounds.size;return bounds;
}2.定位模型
在某些设计中可能需要对模型定位,但是每一个模型的位置会因建模带来误差,因此直接利用模型的位置定位的体验很不好,相机的位置和角度都不好固定,这里我们就可以用包围盒来定位,计算出包围盒,我们可以得到包围盒上的很多点位置,可以利用这些点固定相机的位置,角度也可以利用朝向包围盒的中心来固定public static void SetPosition()
{//todo 详细的定位代码在理解以上内容之后根据自己的需求编写//todo 比如你可以把相机的位置固定在上下左右,以及包围盒八个顶点
}3.更多其他方法...

Bounds(包围盒)详解-【AABB包围盒、Sphere包围球、OBB方向包围盒、FDH固定方向凸包】相关推荐

  1. ❤️UNITY实战进阶-OBB包围盒详解-6

    ❤️UNITY实战进阶-三维AABB包围盒详解-6_欲望如海水,越喝越渴.-CSDN博客前言 碰撞检测问题在虚拟现实.计算机辅助设计与制造.游戏.机器人等方面都有着广泛的应用,而包围盒算法是进行碰撞检 ...

  2. Bounds(包围盒)概述与AABB包围盒应用

    Bounds(包围盒)概述与应用 ==转载标明出处== 1.包围盒描述(摘至百度百科): 1.1 什么是包围盒?包围盒算法是一种求解离散点集最优包围空间的方法.基本思想是用体积稍大且特性简单的几何体( ...

  3. hls之m3u8、ts流格式详解

    HLS,Http Live Streaming 是由Apple公司定义的用于实时流传输的协议,HLS基于HTTP协议实现,传输内容包括两部分,一是M3U8描述文件,二是TS媒体文件. 1.M3U8文件 ...

  4. 欢乐球吃球服务器维护中是什么意思,欢乐球吃球进阶攻略:活动中心详解

    原标题:欢乐球吃球进阶攻略:活动中心详解 活动中心是为了球球成长专门开设的一个功能,在活动中心中可以查看各种已经开始或即将开始的活动,参与活动可以获得海量游戏内道具,还有机会获得实物奖励. 活动中心的 ...

  5. bgp通告四原则_BGP选路原则详解

    <BGP选路原则详解>由会员分享,可在线阅读,更多相关<BGP选路原则详解(112页珍藏版)>请在人人文库网上搜索. 1.BGP选路原则详解,BGP路由选路原则详解,技术培训中 ...

  6. java I/O流详解

    目录 一. I/O(Input/Output)流是什么? 什么是流? 输入输出如何理解? 流的分类? 二. 字节流.字符流.缓冲流. 字节流.字符流能做什么? 字节流读取文件? 字节流写出文件? 字节 ...

  7. html5 游戏 算法,JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法详解【圆形情况】...

    JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法详解[圆形情况] 发布时间:2020-10-10 13:42:43 来源:脚本之家 阅读:95 作者:krapnik 本文实例讲述了JS/HTML ...

  8. 计算机图形几何算法详解勘误

    一直在看<计算机图形几何算法详解>这本书,但是在用的过程中发现了一些错误,一直以为是自己的错误,后来在网上找到了这本书的勘误信息,不过是英文原版的,但是还是想贴出来,以便查找 07 Jul ...

  9. Unity UGUI Batches合批规则详解(含源码)

    Unity UGUI Batches合批规则详解 在处理UGUI DrawCall问题的时候,我们经常遇到各式各样的问题. 问题1:在处理UGUI合批的时候,发现了一个面板父节点发生旋转,底下的UI合 ...

  10. Clipper库中文文档详解

    Clipper库中文文档详解 简介 Clipper Library(以下简称为Clipper库或ClipperLib或Clipper)提供了对线段和多边形的裁剪(Clipping)以及偏置(offse ...

最新文章

  1. 写一篇C语言入门第一讲
  2. 衡量机器学习模型的三大指标:准确率、精度和召回率
  3. 网络缓存 峰值 linux,Linux Page Cache调优在Kafka中的应用
  4. ios php ide,最好的PHP IDE for Mac? (最好免费!)
  5. Android studio 导入module方法
  6. 分布式协议学习笔记(一) Raft 选举
  7. 新华三的背景_开放融合创新:新华三全力支撑运营商5G赋能百业
  8. 更强大的技术团队和更雄厚的预算,海外高频巨头抢占中国市场,不少本土团队淘汰出局
  9. python实现组合优化
  10. 前端开发面试题及答案整理
  11. 如何测试微信的点赞功能
  12. 在线文章生成-自动文章生成
  13. windows getLastError 错误码大全
  14. 图-154飞机简直就是杀人凶器
  15. 【硬核】 ROS Navigation 局部路径规划常见算法
  16. DC故障,在使用缓存登录的错误理解的解释
  17. 狂奔与内卷并存,自嗨锅、莫小仙们如何寻找“破局之道”?
  18. 蠎周刊 188: Jays
  19. 国内排名前几的客流统计系统公司有哪些?
  20. django 第一个web页面

热门文章

  1. PFC离散元软件快捷操作方式
  2. matlab 信号去直流,Speex中的近端信号去直流和预加重操作
  3. SQL的连接查询——内连接、左连接、右连接、自连接(重要)
  4. python题目-奇偶数调用函数
  5. android 拷贝大文件,不用数据线,手机和电脑互传大文件
  6. opencv修改像素值
  7. 什么叫无纸化会议系统?有哪些实用功能
  8. \x75\x73\x65\x20\x73\x74\x72\x69\x63\x74解码
  9. IGBTMOS管的工作原理及检测方法
  10. 绘制函数z = x2 + y2所表示的三维网格图