方向包围盒OBB(oriented bounding box)

2023-11-15

制造几何仿真中的碰撞检测通常视为针对刚体对象间的碰撞检测,这样的话可以把非刚体即软体的建模和变形算法对碰撞检测的影响减少到最小。常见成熟的基于包围盒的碰撞检测(box intersection test)算法如:
1)沿坐标轴的包围盒AABB(axis-aligned bounding boxes)在碰撞检测的研究历史中使用得最久最广, 一个给定对象的AABB被定义为包含该对象且各边平行于坐标轴的最小的六面体。
AABB间的相交测试也比较简单,两个AABB相交当且仅当它们在三个坐标轴上的投影区间均重叠。定义AABB的六个最大最小值分别确定了它在三个坐标轴上的投影区间,因此AABB间的相交测试最多只需要六次比较运算。 
2)包围球类似于AABB,也是简单性好紧密性差的一类包围盒,包围球被定义为包含该对象的最小的球体,计算给定对象E的包围球,首先需确定包围球的球心c,再由球心与三个最大值坐标所确定的点间的距离计算半径r。包围球的计算时间略多于AABB,但存储一个包围球只需两个浮点数。
3)方向包围盒OBB(oriented bounding box)是比较著名的一个包围盒类型。一个给定对象的OBB被定义为包含该对象且相对于坐标轴方向任意的最小的长方体。OBB最大特点是它的方向的任意性,这使得它可以根据被包围对象的形状特点尽可能紧密地包围对象,但同时也使得它的相交测试变得复杂。 OBB间的相交测试基于分离轴理论(separating axis test)。若两个OBB在一条轴线上(不一定是坐标轴)上的投影不重叠,则这条轴称为分离轴。若一对OBB间存在一条分离轴,则可以判定这两个OBB不相交。对任何两个不相交的凸三维多面体,其分离轴要么垂直于任何一个多面体的某一个面,要么同时垂直于每个多面体的某一条边。因此,对一对OBB,只需测试15条可能是分离轴的轴(每个OBB的3个面方向再加上每个OBB的3个边方面的两两组合),只要找到一条这样的分离轴,就可以判定这两个OBB是不相交的,如果这15条轴都不能将这两个OBB分离,则它们是相交的。 

可以在运动过程中使用OBB进行初次碰撞检测,如果没有碰撞,则忽略进行下一个检测,如果发生碰撞,则调用更精细的碰撞检测。作者定义的包围盒(bounding box)和实现如下: 


class Point3D 
{
public:
    double x;
    double y;
    double z;
public:
    Point3D();
    Point3D(double X, double Y, double Z);
    virtual ~Point3D();
public:
    //两个向量的交叉乘积(矩阵形式)用于就法向量
    Point3D operator^(Point3D pt);叉乘cross product
    Point3D operator-(Point3D pt);
    Point3D operator+(Point3D pt);
    double operator*(Point3D pt);//点乘dot product
    Point3D operator*(double k);
    void Normalize();
    float VecMod();
};

class CboundingBox
{
public:
    CBoundingBox();
    virtual ~CBoundingBox();
    void SetBendRelation(double bendDim, double dim, double cen[3]);
    void GetBoxCenter(double cen[3]);
    void GetMinMax(double* min_x, double* min_y, double* min_z, double* max_x, double* max_y, double* max_z);
    void TranslatedBox(double xOffset,double yOffset,double zOffset);
    void RotateBox(double angle, double x, double y, double z);
    void InitBoundingBox(Point3D Vertex[8]);
    void UpdateBoundingBox(Point3D Vertex[8]);//更新包围盒
public:
    //定义8个顶点,
    Point3D m_Vertex[8];
public:
    //Jorbin edited[2/8/2008]
    int BoxIntersectTest(CBoundingBox * box);
    void GetInterval(CBoundingBox * box, Point3D axis, float &min, float &max);
    float Dot(Point3D axis, Point3D pt);
    Point3D GetFaceDir(int indexID);   //取面方向
    Point3D GetEdgeDir(int indexID); //取边方向
};

//点在该轴上投影值
float CBoundingBox:ot(Point3D axis, Point3D pt)
{
    return (float)((axis * pt) / axis.VecMod());
}
void CBoundingBox::GetInterval(CBoundingBox * box, Point3D axis, float &min, float &max) 
{
    float value;
    min = max = Dot(axis, box->m_Vertex[0]);
    for(int i=1; i<8; i++)
    {
        value = Dot(axis, box->m_Vertex);
        min = Min(min, value);
        max = Max(max, value);
    }
}

Point3D CBoundingBox::GetEdgeDir(int indexID)
{
    Point3D pt;
    Line3D tmpLine;
    switch(indexID) 
    {
        case 0://edge in parallel with x axis
            pt = tmpLine.Normalize(m_Vertex[0]), m_Vertex[1]);
            break;
        case 1://edge in parallel with y axis
            pt = tmpLine.Normalize(m_Vertex[0], m_Vertex[4]);
            break;
        case 2://edge in parallel with z axis
            pt = tmpLine.Normalize(m_Vertex[0], m_Vertex[3]);
            break;
    }
    return pt;
}



Point3D CBoundingBox::GetFaceDir(int indexID) {
    Point3D vFace;
    Plane3D tmpPlane;
    switch(indexID)
    {
        case 0://front and back
            vFace = tmpPlane.NormLine((m_Vertex[2], m_Vertex[3], m_Vertex[6]);
            break;
        case 1://left and right
            vFace = tmpPlane.NormLine((m_Vertex[1], m_Vertex[2], m_Vertex[5]);
            break;
        case 2://top and bottom
            vFace = tmpPlane.NormLine((m_Vertex[0], m_Vertex[1], m_Vertex[2]);
            break;
    }

    return vFace;
}
 
int CBoundingBox::BoxIntersectTest(CBoundingBox * box)
{
    int flag = 20;
    int i, j;
    float min1, max1, min2, max2;
    for (i=0; i<3; i++)
    {             
        GetInterval(this, this->GetFaceDir(i), min1, max1);              
        GetInterval(box, this->GetFaceDir(i), min2, max2);              
        if (max1 < min2 || max2 < min1) return 0;               
    } 
    for (i=0; i<3; i++)
    {             
        GetInterval(this, box->GetFaceDir(i), min1, max1);              
        GetInterval(box, box->GetFaceDir(i), min2, max2);              
        if (max1 < min2 || max2 < min1)    return 0;             
    }
    Point3D axis;
    for (i=0; i<3; i++)            
        for (j=0; j<3; j++) 
        {         
            axis = (this->GetEdgeDir(i)) ^ (box->GetEdgeDir(j));//cross product
            GetInterval(this, axis, min1, max1);                      
            GetInterval(box, axis, min2, max2);                      
            if (max1 < min2 || max2 < min1)    return 0;            
        }
    return flag;
}

 

cYq3g5wd.jpg (117.89 KB, 下载次数: 8)

下载附件  保存到相册

OBB包围盒和实现

1970-1-1 08:00 上传


参考文献:
魏迎梅. 虚拟环境中碰撞检测问题的研究. 工学博士学位论文. 国防科学技术大学. 2000.10
申玉斌,蔡勇,华才建. 虚拟环境中的碰撞检测技术的研究与应用. 交通与计算机.2005.1
吴强,基于OBB碰撞检测算法的研究.硕士学位论文. 郑州大学.2007
http://www.gamasutra.com/features/19991018/Gomez_1.htm
http://www.gamasutra.com/features/19991018/Gomez_2.htm
http://www.gamasutra.com/features/19991018/Gomez_5.htm
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

方向包围盒OBB(oriented bounding box) 的相关文章

  • 如何渲染精美3D PCB图

    简介 现在网上大部分PCB渲染方法都比较麻烦 并且会有丝印不清晰 或者走线与铜皮不显现问题 现在分享一种简单有效的PCB渲染方法 图为渲染效果图 工具或材料 AD keyshot 一个带3D封装图的PCB文件 具体步骤 1 AD端操作 在P
  • 写出你所知道的测试工具,并写出他们的用途和优缺点

    写出你所知道的测试工具 并写出他们的用途和优缺点 Jmeter Apache JMeter是Apache组织开发的基于Java的压力测试工具 Apache jmeter 可以用于对静态的和动态的资源 文件 Servlet Perl脚本 ja
  • XXL-JOB详细说明

    XXL JOB 常见任务调度 单机 Timer ExectorService spring scheduled 分布式 xxl job quartz elastic job 原生定时任务的先天缺陷 XXL JOB简介 由调度中心和执行器组成
  • fabric环境

    1 1环境配置链接 https www jianshu com p 6ef2e8425087 https studygolang com articles 17546 Fabric chaincode测试 开发者模式和单元测试 https
  • 计算机网络 传输层的作用,端口,UDP协议,其他传输层协议

    传输层的作用 传输层定义 IP首部中有一个协议字段 用来标识网络层 IP 的 上一层所采用的是哪一种传输层协议 根据这个字段的协议号 就可以识别IP传 输的数据部分究竟是TCP的内容 还是UDP的内容 同样 传输层的TCP和UDP 为了识别
  • 参与 2023 第一季度官方 Flutter 开发者调查

    Flutter 3 7 已经正式发布 每个季度一次的 Flutter 开发者调查也如约而至 邀请社区的各位成员们填写 调查表链接 https flutter cn urls 2023q1wx 本次调研将会涉及既有的对 Flutter 整体和
  • 【李宏毅深度强化学习笔记】—7、Sparse Reward

    原文链接 https blog csdn net ACL lihan article details 104103873 李宏毅深度强化学习笔记 1 策略梯度方法 Policy Gradient 李宏毅深度强化学习笔记 2 Proximal
  • 24个K8S常用场景使用命令(推荐收藏)!

    kubectl是K8S中的一个命令行工具 主要用于管理和操作K8S集群 kubectl通过向K8S API发送REST请求 允许用户与K8S集群中的各种资源进行交互 列如Pod service Deployment等 kubectl提供了一
  • 【数据结构学习笔记】18:线段树(建树、单点修改、区间查询)

    1 线段树上的操作 push up int u 由子节点的信息去计算父节点的信息 例如两个子节点的区间和 加起来就是父节点表示的区间和 其中u是当前节点编号 表示用u的左右两个子节点来算一下自己这个节点的信息 push down 将父节点的
  • 数据爆炸,Python一键获取阿里法拍的爆款商品数据,并保存到数据库!

    目录 前言 获取数据代码实现 步骤1 获取目标网址 步骤2 向目标网址发送请求并获取响应内容 步骤3 解析网页内容并提取商品信息 步骤4 将商品信息保存到DataFrame中 将商品信息保存到数据库中 步骤1 安装MySQL Connect
  • Spring Boot的自动配置与自定义配置(附配置优先级表)

    相比于Spring MVC Spring Boot省去了繁琐的配置 提供了大部分场景下的默认配置 用户可以在不做任何配置的情况下使用Spring Boot框架进行开发 如果默认的参数并不能满足用户的需求 也只需创建一个配置文件并加上自定义的
  • JetBrains Rider 连接MySQL失败 解决方案

    JetBrains Rider 连接MySQL失败 解决方案 解决JetBrains Rider连接数据库失败 解决方案 设置MySQL时区 time zone 错误界面 Rider 连接mysql 用户名 密码 Port 全都配置好了 点

随机推荐

  • _萌新 web3

  • QFile清空原来文件内容的方法

    QFile清空原来文件内容的方法 Qt 清空文件方法 Qt 清空文件方法 方法一 void DataOperate clearFileInfos QString fileName QFile file fileName file resiz
  • LeetCode1823.找出游戏的胜利者

    共有 n 名小伙伴一起做游戏 小伙伴们围成一圈 按 顺时针顺序 从 1 到 n 编号 确切地说 从第 i 名小伙伴顺时针移动一位会到达第 i 1 名小伙伴的位置 其中 1 lt i lt n 从第 n 名小伙伴顺时针移动一位会回到第 1 名
  • 机器学习之加州房价预测(一)

    加州房价预测实例 任务 基于加州房价数据集建立一个预测模型 使之可以在给定的条件下 预测加州任何地点的房价的中位数 一 定义问题 1 公司要如何利用我的模型 模型的输出将作为另一个机器学习算法的输入 该算法在综合考虑其他因素之后 决定是否值
  • 推荐一本书——《The Scientist and Engineer's Guide to Digital Signal Processing》

    突然在国外的网站上看到一本非常好的数字信号处理的书籍 讲解简介明白 清晰易懂 书籍为免费电子版 地址为 http www dspguide com pdfbook htm
  • day05-编程题

    知识点 方法 题目1 训练 定义一个方法 该方法能够找出两个小数中的较小值并返回 在主方法中调用方法进行测试 训练提示 根据方法的功能描述 方法的参数应该是两个小数 要返回两个小数的较小值 所以返回值类型也是小数类型 解题方案 操作步骤 定
  • QT中学习Opengl---(GLSL简单的使用)

    前言 本文的代码是 LearnOpenGL 中对应代码 这里提供学习 大家喜欢的可去官方网站去看看 https learnopengl cn readthedocs io zh latest https learnopengl cn rea
  • C++的模板特例化template<>

    C 的模板特例化是指当我们定义了一个通用的模板类或模板函数时 如果特定输入参数类型或值需要进行不同的处理 我们可以为这些特定情况提供单独的实现 这就是模板特例化 下面我们将详细介绍C 的模板特例化 假设我们有以下的一个模板类 templat
  • java自学笔记12:java中的集合框架(下)List

    一 学生选课 判断List中课程是否存在 思考 在课程序列中 如何判断是否包含某门或者某几门课程 如果课程序列包含某门课程 如何判断该课程的索引位置 在学生映射表中 如何判断是否包含某个学生ID 又该如何判断是否包含某个学生对象 如果想把课
  • 解读随着教育改革的深入steam教育

    STEAM鼓励孩子勇于创新和探索 打破思维的第三面墙 自古以来 大家都是教育孩子纠正错误 而STEAM可以让孩子们通过与小组实践学习 探索讨论 交流思想和相互帮助 来发现自己的缺点和不足 通过团队合作来弥补自己的劣势 可以说 STEAM是一
  • Pandas 返回Nan值的行索

    Pandas 返回Nan值的行索 通过np where函数查找 gt gt gt df Out 1 0 1 0 0 450319 0 062595 1 0 673058 0 156073 2 0 871179 0 118575 3 0 59
  • Mysql大小写敏感设置(Docker版)

    应用场景 本人由于项目前期使用windows版国产数据库开发 默认就是大小写不敏感的 加上代码规范约束不够 导致代码中SQL大小写不统一 后期有需求要更换数据库 改用Mysql 因为在Linux系统中Mysql默认是大小写敏感的 所以需要对
  • java多线程同步的实现方式

    java多线程同步的实现方式 1 什么时候会出现线程安全问题 2 使用synchronized关键字 2 1修饰方法 2 2 修饰代码块 3 使用重入锁实现线程同步 4 wait与notify方法 5 使用原子变量实现线程同步 关于vola
  • vmospro启动黑屏_VMOS Pro,安卓手机上的虚拟机

    应用名称 VMOS Pro 应用包名 com vmos pro 应用版本 1 1 26 应用大小 28 0MB 适用平台 Android 5 1 版本说明 1 优化电量同步问题 2 优化游戏断触问题 3 设备信息修改加入随机按钮 4 增加横
  • Docker导入导出镜像(镜像迁移)

    打包现有镜像 docker images 命令查看已有镜像列表 docker save命令打包镜像 docker save使用说明 o 选项 用来指定输出文件 将alpine ffmpeg 3 15打包 docker save o alpi
  • Linux定时任务

    Linux定时任务 at命令 语法 at 选项 日期时间 选项 f 指定包含具体指令的任务文件 q 指定新任务的队列名称 l 显示待执行任务的列表 d 删除指定的待执行任务 m 任务执行完成后向用户发送 E mail 日期时间 指定任务执行
  • 通过XSD文件生成JAVA对象

    c Program Files Java jdk1 8 0 101 bin gt xjc exe p io xsd xml encoding UTF 8 xsdTOxml MyField xsd d xsdTOxml Picked up J
  • 如何在uni中实现一个路由守卫

    在uni app中实现路由守卫 可以使用全局的router beforeEach方法来拦截路由导航 以下是一个简单的示例 展示了如何在uni app中实现路由守卫 在上述代码中 我们通过监听beforeRouterEnter事件来实现路由守
  • java.util.LinkedHashMap cannot be cast to Entity

    前后端数据传输转换问题 java util LinkedHashMap cannot be cast to Entity 问题场景 项目前端使用json传输方式 后台接收后对象变成了LinkedHashMap ResponseBody Re
  • 方向包围盒OBB(oriented bounding box)

    制造几何仿真中的碰撞检测通常视为针对刚体对象间的碰撞检测 这样的话可以把非刚体即软体的建模和变形算法对碰撞检测的影响减少到最小 常见成熟的基于包围盒的碰撞检测 box intersection test 算法如 1 沿坐标轴的包围盒AABB