码农干货系列【1】--方向包围盒(OBB)碰撞检测

2023-10-27

码农干货系列【1】--方向包围盒(OBB)碰撞检测

2012-06-07 11:40 by 【当耐特】, 9251 阅读, 20 评论, 收藏, 编辑

干货

最近一直在删文章,不是要关博洗手什么的,而是被删的文章没有达到“干货”的标准。干货的反义词是水货,比如我们经常吃的注水猪肉,它就是水货,非干货。什么是“干货”。?经过一番搜寻,标准的描述是:实用性比较强的,不含任何吹嘘水分,也没有虚假的成分,所以业内人士通常把这一类分享活动称之为“干货”。

文章是否是干货做如下几点要求:

必备条件:

1.整体样式风格整齐美观;

2.实用性比较强的,逻辑条理清晰;

3.独立性强,一篇文章只写一类东西;

4.码农看完就懂(或者有了search的方向),拿去就能用;

加精条件:

1.图文并茂;

2.在线演示;

3.示例代码下载;

从这篇开始我们的干货之旅~~~~~

简介

包围体是一个简单的几何空间,里面包含着复杂形状的物体。为物体添加包围体的目的是快速的进行碰撞检测或者进行精确的碰撞检测之前进行过滤(即当包围体碰撞,才进行精确碰撞检测和处理)。包围体类型包括球体、轴对齐包围盒(AABB)、有向包围盒(OBB)、8-DOP以及凸壳。如图1所示。

clip_image001

图1 依次是球体、AABB、OBB

可以看到图1是3D包围体,在2D包围体如图2所示:
clip_image003

图2 依次是球体、AABB、OBB

 

OBB

方向包围盒(Oriented bounding box),简称OBB。方向包围盒类似于AABB,但是具有方向性、可以旋转,AABB不能旋转。如图3所示。

clip_image005

图3 矩形和矩形投影检测的四条轴

要计算两个OBB是否碰撞,只需要计算他们在图3上的4个坐标轴上的投影是否有重叠,如果有,则两多边形有接触。这也可以扩展到任意多边形,如图4所示。

clip_image007

图4 矩形和三角形投影检测的五条轴

投影轴来自于多边形自身边的垂线。

判定方式:两个多边形在所有轴上的投影都发生重叠,则判定为碰撞;否则,没有发生碰撞

OBB存在多种的表达方式,这里使用最常用的一种:一个中心点、2个矩形的边长、两个旋转轴(该轴垂直于多边形自身的边,用于投影计算)。代码如下所示:

(function (window) {

    var OBB = function (centerPoint, width, height, rotation) {

        this.centerPoint = centerPoint;
        this.extents = [width / 2, height / 2];
        this.axes = [new Vector2(Math.cos(rotation), Math.sin(rotation)), new Vector2(-1 * Math.sin(rotation), Math.cos(rotation))];

        this._width = width;
        this._height = height;
        this._rotation = rotation;
    }

    window.OBB = OBB;
})(window);

其所依赖的Vector2这个类如下所示:

(function (window) {
    Vector2 = function (x, y) {
        this.x = x || 0;
        this.y = y || 0;
    };

    Vector2.prototype = {
        sub: function (v) {
            return new Vector2(this.x - v.x, this.y - v.y)
        },
        dot: function (v) {
            return this.x * v.x + this.y * v.y;
        }
    };
    window.Vector2 = Vector2;
} (window))

然后基于这个数据结构,进行OBB之间的相交测试。为OBB扩展一个方法,即或者在任意轴上的投影半径:

OBB.prototype = {
    getProjectionRadius: function (axis) {
        returnthis.extents[0] * Math.abs(axis.dot(this.axes[0])) + this.extents[1] * Math.abs(axis.dot(this.axes[1]));
    }
}

这里你可能需要读者了解Vector2.dot的几何意义:若b为单位矢量,则a与b的点积即为a在方向b的投影

有了这些,就可以进行相交检测。由上面的判定方式,可以得出,两个矩形之间的碰撞检测需要判断四次(每个投影轴一次)。完整检测代码如下所示:

(function (window) {

    var CollisionDetector = {

        detectorOBBvsOBB: function (OBB1, OBB2) {
            var nv = OBB1.centerPoint.sub(OBB2.centerPoint);
            var axisA1 = OBB1.axes[0];
            if (OBB1.getProjectionRadius(axisA1) + OBB2.getProjectionRadius(axisA1) <= Math.abs(nv.dot(axisA1))) return false;
            var axisA2 = OBB1.axes[1];
            if (OBB1.getProjectionRadius(axisA2) + OBB2.getProjectionRadius(axisA2) <= Math.abs(nv.dot(axisA2))) return false;
            var axisB1 = OBB2.axes[0];
            if (OBB1.getProjectionRadius(axisB1) + OBB2.getProjectionRadius(axisB1) <= Math.abs(nv.dot(axisB1))) return false;
            var axisB2 = OBB2.axes[1];
            if (OBB1.getProjectionRadius(axisB2) + OBB2.getProjectionRadius(axisB2) <= Math.abs(nv.dot(axisB2))) return false;
            return true;

        }
    }

    window.CollisionDetector = CollisionDetector;
})(window)

这里拿两个OBB的中心点连线在坐标轴上的投影长度和两个矩形投影半径之和进行对比,如果半径之后都小于或者等于中心连线之后才判定为碰撞,否则判定为分离状态。

集成图形化测试接口

为了更加直观的测试OBB碰撞检测方法,使用Easeljs输出碰撞的状态。当两个矩形没有发生碰撞的时候,两矩形呈现蓝色;当两个矩形发生碰撞的时候,两矩形呈现红色。先引入相关的脚本库以及用于显示的canvas画布:

<script src="Vector2.js" type="text/javascript"></script>
<script src="OBB.js" type="text/javascript"></script>
<script src="CollisionDetector.js" type="text/javascript"></script>
<script src="easel.js" type="text/javascript"></script>
<canvas id="testCanvas" width="980" height="580">

然后进行OBB初始化以及碰撞检测:

var OBB1, OBB1x = 100, OBB1y = 150, OBB1w = 30, OBB1h = 140, OBB1r = 30;
var OBB2, OBB2x = 100, OBB2y = 70, OBB2w = 40, OBB2h = 110, OBB2r = 40;
var canvas;
var stage;
var color;

function init() {

    canvas = document.getElementById("testCanvas");
    stage = new Stage(canvas);

    Ticker.addListener(window);
}
     
function tick() {
    stage.removeAllChildren();

    OBB1r += 2;
    OBB2r += 1;
    OBB1 = new OBB(new Vector2(OBB1x, OBB1y), OBB1w, OBB1h, OBB1r * Math.PI / 180);
    OBB2 = new OBB(new Vector2(OBB2x, OBB2y), OBB2w, OBB2h, OBB2r * Math.PI / 180);
    var r = CollisionDetector.detectorOBBvsOBB(OBB1, OBB2);

    color=r?"red":"#00F";
    OBB1 = new Container();
    stage.addChild(OBB1);
    OBB1.x = OBB1x;
    OBB1.y = OBB1y;
    var frame1 = new Shape();
    frame1.graphics.beginFill(color).drawRect(0, 0, OBB1w, OBB1h);
    frame1.rotation = OBB1r;
    frame1.regX = OBB1w / 2;
    frame1.regY = OBB1h / 2;
    OBB1.addChild(frame1);

    OBB2 = new Container();
    stage.addChild(OBB2);
    OBB2.x = OBB2x;
    OBB2.y = OBB2y;
    var frame2 = new Shape();
    frame2.graphics.beginFill(color).drawRect(0, 0, OBB2w, OBB2h);
    frame2.rotation = OBB2r;
    frame2.regX = OBB2w / 2;
    frame2.regY = OBB2h / 2;
    OBB2.addChild(frame2);

    stage.update();
}
init();

以上代码定义了两个旋转的OBB包围盒,当他们发生碰撞则改变绘制的颜色,使其成为红色。运行代码,效果图5和6所示。

clip_image009

图5 未发生碰撞

clip_image011

图6 发生碰撞

这里是2D情况下的OBB碰撞检测,对于3D OBB碰撞检测,更为复杂。需要测试15个分离轴以确定OBB的相交状态,两个OBB的坐标轴各3个,以及垂直于每个轴的9个轴。除了坐标轴个数不一样,其相交测试思路和本文一致,本文不再探讨。

在线演示

更多干货敬请期待~~~~~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

码农干货系列【1】--方向包围盒(OBB)碰撞检测 的相关文章

  • 对齐坐标系

    Let s say I have 2 coordinate systems as it is shown in image attached 如何对齐这个坐标系 我知道我需要将第二个坐标系围绕 X 平移 180 度 然后将其平移到第一个坐标
  • Eclipse 标记 OpenGL 函数无法解析

    我尝试在 Eclipse C C 中使用一些 OpenGL 函数 一些 标准 函数如 GlClear 可以被 eclipse 识别 而其他函数如 glBindBuffer 和 glEnableVertexAttribArray 则不能 它们
  • OpenGL 与 Eclipse CDT + MinGW + GLEW + GLFW:未定义的参考

    Edit 与此同时 我已经弄清楚了这一点 并在下面写了详细的答案 我刚刚尝试在 Win7 上从 Express 版本的 MSVC 10 切换到 Eclipse CDT 在配置时遇到了以下简单 OpenGL 代码的问题 在 Visual St
  • 使用 OpenGL 着色器进行数学计算 (C++)

    我有一个矩阵 例如 100x100 尺寸 我需要对每个元素进行计算 matrix i j tt 8 5例如 我有一个巨大的矩阵 我想使用 OpenGL 着色器来实现该算法 我想使用着色器 例如 uniform float val unifo
  • SDL 鼠标位置调整大小后裁剪

    我在 SDL 中的鼠标位置上遇到了一些奇怪的行为 如果我将窗口大小调整得更大 则任一鼠标事件的 x y 位置似乎都限制为原始窗口的宽度和高度 如果我缺少一些函数调用来告诉 SDL 鼠标区域的大小已增加 应用程序的相关部分 void Resi
  • 如何在 GTX 560 及更高版本上使用 OpenGL 进行立体 3D?

    我正在使用在 Windows 7 上运行的开源触觉和 3D 图形库 Chai3D 我重写了该库以使用 Nvidia nvision 执行立体 3D 我将 OpenGL 与 GLUT 一起使用 并使用 glutInitDisplayMode
  • 使用 C# 截取任何外部应用程序的屏幕截图

    我们有一个 C WPF 应用程序 我们想要在其中截取我们启动的任意应用程序的屏幕截图 即 我们可以引用我们启动的进程 应用程序可能已最小化或位于其他窗口后面 但我们仍然只需要单个应用程序的图像 而不是重叠像素 我知道使用 BitBlt 或的
  • OpenGL - 两个纹理的幂

    OpenGL 使用二次幂纹理 这是因为由于 MipMapping 某些 GPU 只接受 2 的幂纹理 当绘制比实际更大的纹理时 使用这些二次方纹理会导致问题 我想到了一种方法来解决这个问题 即仅在我们使纹理小于实际大小时使用 PO2 比率
  • Visual Studio 2010 中的 SOIL 设置

    我无法得到SOIL http www lonesock net soil html正确使用 Visual Studio 2010 我远非 VS 专家 但据我所知 只需执行以下步骤即可使环境正常运行 属性 gt gt C C gt 常规 gt
  • 未解决的包含:“cocos2d.h” - Cocos2dx

    当我在 Eclipse 中导入 cocos2dx android 项目时 我的头文件上收到此警告 Unresolved inclusion cocos2d h 为什么是这样 它实际上困扰着我 该项目可以正确编译并运行 但我希望这种情况消失
  • 在 Cocos2dx 中使用 CREATE_FUNC

    谁能解释一下为什么我们需要在Cocos2dx中使用CREATE FUNC 我在HelloWorld示例中看到了它 但不太理解它 请告诉我更多细节 谢谢 我们不需要使用它 它是一个扩展为以下内容的辅助宏 define a create fun
  • 如何使用边缘和内部镶嵌因子完成三角形面片镶嵌?

    I am just learning tessellation and i came across with below example for triangle patch tessellation but i am not sure h
  • 在 OpenGL 中只使用纹理的 Alpha 通道?

    嘿 我正在尝试将恒定颜色绘制到帧缓冲区 并使用 RGBA 纹理中的 Alpha 通道将其混合 我一直在研究 glBlendFunc 和 glBlendColor 但似乎无法找到忽略纹理中的 RGB 值的方法 我想我必须自己提取 alpha
  • 编译 GLUI 库,VS2010 给我一个奇怪的命名空间错误

    我有一个针对我所在班级的 OpenGL 项目 它基于 GLUI 提供的 GLUI 库无法工作 这就是我尝试自己编译它的原因 因此 我从 SourceForge 下载了源代码并尝试编译 glui 库 它给了我这个 但我找不到任何相关信息 1
  • 重新创建窗口而不破坏上下文

    这个问题是关于使用 OpenGL 的图形应用程序 当时我正在使用 GLFW 框架 但我考虑更改它 我的目标是让用户 尽可能 在全屏模式和窗口模式之间不断切换 此过程应该花费不到一秒的时间 并且可以在运行时发生 例如 看看游戏 我的世界 用户
  • 纹理映射 C++ OpenGL

    我已经阅读了相关内容 包括 Nehe 和此处的解决方案 但我找不到具体的答案 我正在尝试加载一张名为stars jpg 的照片 我想通过使用 uv 坐标映射它来使其成为场景的背景 方法是 glBegin GL QUADS glTexCoor
  • 如何在 GLSL 1.3 和 OpenGL 2.1 中使用位运算

    我正在尝试编写一个使用许多位操作的着色器 事实上 从 glsl 1 30 开始就支持它们 但我只使用 OpenGL 2 1 有没有办法在我的 OpenGL 版本中使用位运算 所有 SM3 兼容 OpenGL 2 1 硬件支持limited整
  • OpenGL:顶点越多,性能越慢

    我正在开发一个程序的一部分 其中给定 xyz 坐标集合 制作 3D 模型 我已经完成了这张图片所需的所有功能 即平移 旋转 缩放 但是给出的 xyz 坐标越多 程序运行速度就越慢 我的程序在处理 29 000 个坐标时运行得非常流畅 但当我
  • 云或烟雾的粒子系统

    我正在尝试使用 OpenGL 和 CUDA 制作一个简单的用于云和烟雾模拟的粒子系统 如何使粒子系统中的粒子表现得像真正的云或烟雾在低湍流风中的表现 我现在遇到的一些问题是 颗粒聚集成一个大球 粒子扩散到无限远 粒子突然弹射离开 我已经完成
  • Windows下使用GLEW使用OpenGL扩展

    我一直在 Windows 上使用 OpenGL 扩展痛苦的方式 https stackoverflow com questions 14413 using opengl extensions on windows GLEW 是更简单的方法吗

随机推荐

  • spring中的控制反转和依赖注入之间的关系

    Spring中的控制反转 把new这一个过程交给了spring容器去处理 控制反转就是将new对象这一个过程交给外部去做 即Spring 而不是自己去创建 图中的1 控制正转 并没有这个名词 只是为了更好的理解什么是控制反转 图2中并没有n
  • hexo博客主题diaspora的gitalk配置(多图预警)

    前提 已装好git hexo环境 首先 在github上注册 如下图所示 进入设置 开发者设置 新建OAuth App 注册 注册完成 注意事项均在图中标出 现在完成了第一步 然后去主题页下载主题 也可以在你的hexo文件夹下右键打开git
  • java快速对接微信支付分(一)

    1 微信支付分产品介绍 维信支付分是对个人的身份特质 支付行为 使用历史等情况的综合计算分值 旨在为用户提供更简单便捷的生活方式 1 用户可在具体应用场景中 开通威信支付分 此为最常见的开通方法 开通后 用户可以在 微信 gt 我 gt 服
  • Windows安装ElasticSearch

    Linux买了个最小配的服务器 内存玩不起 window实验一下 准备工作 第一步 安装java 下载链接 进去下个最新版的就行 https www oracle com technetwork java javase downloads
  • 实现简单的栈与队列

    前言 前面已经详细地介绍了基本的顺序表和链表 这次要介绍的是数据结构中的栈与队列 从本质上来说 二者是特殊的线性表 是依赖于顺序表或链表来实现的 所以只要能够很好地掌握顺序表和链表 再了解清楚栈与队列的概念及基本结构 就可以很好地将二者实现
  • python编写递归函数、计算n!(n=10)_十、Python函数递归(带实例演示)

    在一个函数体内调用它自身 被称为函数递归 函数递归包含了一种隐式的循环 它会重复执行某段代码 但这种重复执行无须循环控制 例如有如下数学题 己知有一个数列 f 0 1 f 1 4 f n 2 2 f n 1 f n 其中 n 是大于 0 的
  • 初步使用openEuler华为欧拉Linux系统

    使用openEuler 1 下载镜像文件 2 启动虚拟机软件安装虚拟机 3 开始配置系统 4 开始使用 5 安装桌面 5 1 安装必备的字体 5 2设置桌面图形化界面 5 3安装ukui 5 4重启 6 整体评价 参考文献 1 下载镜像文件
  • Html+css(第一天)

    基础认识 1 五大浏览器有哪些 IE浏览器 火狐浏览器 Firefox 谷歌浏览器 Chrome Safari浏览器 欧朋浏览器 Opera 2 相同的网页在不同浏览器中显示效果会完全一致吗 因为不同浏览器渲染引擎不同 解析的效果会存在差异
  • 编程思想:面向对象和面向过程

    何谓面向对象 何谓面向过程 对于这编程界的两大思想 一直贯穿在我们学习和工作当中 我们知道面向过程和面向对象 但要让我们讲出来个所以然 又感觉是不知从何说起 最后可能也只会说出一句就是那样啦 你知道啦 而这种茫然 其实就是对这两大编程思想的
  • linux系统在当前目录下创建子目录,linux根目录下一级子目录

    linux上每一个文件都必须是在根文件系统下的某个路径或者是从根文件系统才可以访问 文件系统中只分为目录和文件 所有文件都是存放在目录下 root根目录用 表示 ls 查看根目录下的一级子目录 boot 存放系统启动相关的文件 如内核文件
  • 地址解析中文乱码

    function Params var pattern w a zA Z0 9 u4e00 u9fa5 ig params 定义正则表达式和一个空对象 decodeURIComponent window location href true
  • 【数据结构】包装类&简单认识泛型

    文章目录 1 包装类 1 1 基本数据类型和对应的包装类 1 2 装箱和拆箱 2 什么是泛型 3 引出泛型 3 1 语法 4 泛型类的使用 4 1 语法 4 2 示例 4 3 类型推导 Type Inference 5 泛型的上界 5 1
  • E9流程表单中动态自定义添加button js代码

  • 发现一款专为.NET WinForms开发的数据可视化图表库

    FastReport是快捷 轻量级报表工具 使用简单 功能丰富 性价比高 适合个人 中小型企业和项目使用 FastReport近期推出了全新专为 NET WinForms开发的数据可视化图表库FastReport Business Grap
  • echarts水波球特效(附带外边框进度条)

    echarts水波球特效 附带外边框进度条 1 话不多说先上效果图 2 这里用到了echarts的liquidFill图表 需要加载liquidFill插件 npm i echarts liquidFill save 3 在main js入
  • c++ vector容器函数说明

    构造函数 vector 默认构造函数 创建一个空的 vector 对象 vector size type n 创建一个包含 n 个元素的 vector 对象 每个元素的值都是类型的默认值 vector size type n const v
  • yii2-admin扩展自定义目录

    yii2 admin文件如下 仓库地址 https github com mdmsoft yii2 admin tree master 复制yii2 admin文件至自定义目录 比如我就复制到了common rbac目录 在配置文件comm
  • 如何动态调试Python的第三方库

    注意 本文方法仅限于调试安装时附带py源码的库 如sklearn 引入 用sklearn中的sklearn feature extraction text TfidfTransformer来获取TF特征 但发现sklearn的计算结果与我手
  • 使用变量时,单引号、双引号、反向单引号的区别

    单引号 双引号 反向单引号的区别 1 单引号 当变量内容用单引号 时 对里面的命令echo和变量USER都无法识别 只识别成字符串本身 称之为强引用 2 双引号 当变量内容用双引号 时 是不能识别出里面的命令echo的 但可识别出里面的变量
  • 码农干货系列【1】--方向包围盒(OBB)碰撞检测

    码农干货系列 1 方向包围盒 OBB 碰撞检测 2012 06 07 11 40 by 当耐特 9251 阅读 20 评论 收藏 编辑 干货 最近一直在删文章 不是要关博洗手什么的 而是被删的文章没有达到 干货 的标准 干货的反义词是水货