引言

前面的一篇文章中讲述了怎样通过模型的顶点来求的模型的包围球,而且还讲述了基本包围体除了包围球之外,还有AABB包围盒。在这一章,将讲述怎样依据模型的坐标求得它的AABB盒。

表示方法

AABB盒的表示方法有非常多,总结起来有例如以下的三种情况:

Max-min表示法:使用一个右上角和左下角的点来唯一的定义一个包围体

Center-radious表示法:我们用center点来表示中点,radious是一个数组,保存了包围盒在x方向,y方向,z方向上的半径。

Min-Width表示方法:我们用min来定义左下角的点,使用width来保存在x,y,z方向上的长度。

不同的方法,他们的碰撞检測算法也会有所不同,而且不同的表示方法也会适用在不同的情形下。所以,大家自己设计的时候,须要谨慎考虑。

在本文中,将会使用的是Max-min表示方法,例如以下所看到的:

class AABB
{
....
public:
VECTOR3 max ;
 VECTOR3 min ;
};

在这样的表示方法之下,进行碰撞检測的代码例如以下所看到的:

bool AABB::isCollided(AABB* a)
{
if(max.x < a->min.x || min.x > a->max.x) return false ;
if(max.y < a->min.y || min.y > a->max.y) return false ;
if(max.z < a->min.z || min.z > a->min.z) return false ; return true ;
}// end for isCollided

AABB盒构造

构造AABB盒的方法有非常多种,有的非常easy,有的非常复杂,这里将介绍两种主要的构造方法,他们也非常的简单,easy掌握。

第一种是固定大小的AABB盒,这样的AABB盒在构造完成之后,无论被包围的物体怎么样的旋转,都不须要在进行又一次构造了。

另外一种是比較紧凑的一种,利用X,Y和Z轴向上最长和最远的点来构造一个AABB盒。

固定大小AABB盒

正如上面说的那样,固定大小的AABB盒,它须要被包围的物体,无论怎么旋转,都还在这个包围体里面。所以,我们先为这个物体构造一个包围球体,然后在这个包围球体的基础上构建一个AABB盒。这样就行达到无论怎么旋转,都还在包围体里面。

只是,为这个物体构建一个包围球相同也可以满足这种要求,所以,就有点鸡肋了。可是,在某些限制条件下,你无法使用包围球,那么就行使用这个方案来构建一个固定大小的AABB盒。

这个算法的核心是怎样构建一个包围球体,而这个算法我在前面一章中已经讲述了,就不再反复,感兴趣的读者能够去看博客中3D空间包围球(Bounding Sphere)的求法的文章。

在有了包围球之后,我们通过例如以下的方法就行计算出固定大小的AABB盒了:

void AABB::computeFixedAABB(Sphere *s)
{
max.x = s->center.x + s->radious ;
max.y = s->center.y + s->radious ;
max.z = s->center.z + s->radious ;
min.x = s->center.x - s->radious ;
min.y = s->center.y - s->radious ;
min.z = s->center.z - s->radious ;
}// end for computeFixedAABB

紧凑点的AABB盒

这个AABB盒的构造方法,是从顶点集中获取X,Y和Z方向上最远的和近期的点,然后利用他们来构建一个AABB盒。这样的方法也非常easy。我直接上代码来给大家解说:

void AABB::computeAABBFromOriginalPointSet(VECTOR3* vertices, unsigned int vertex_num)
{
unsigned int minX_i = 0 , maxX_i = 0 ;
extrameDistanceAlongDir(MAKE_VECTOR3(1,0,0), vertices, vertex_num, &minX_i, &maxX_i);
min.x = vertices[minX_i].x ;
max.x = vertices[maxX_i].x ; unsigned int minY_i = 0 , maxY_i = 0;
extrameDistanceAlongDir(MAKE_VECTOR3(0,1,0),vertices, vertex_num, &minY_i, &maxY_i);
min.y = vertices[minY_i].y ;
max.y = vertices[maxY_i].y ; unsigned int minZ_i = 0 , maxZ_i = 0;
extrameDistanceAlongDir(MAKE_VECTOR3(0,0,1),vertices, vertex_num, &minZ_i, &maxZ_i);
min.z = vertices[minZ_i].z ;
max.z = vertices[maxZ_i].z ;
}// end for computeAABBFromOriginalPointSet void AABB::extrameDistanceAlongDir(VECTOR3 dir, VECTOR3* vertices, unsigned int vertex_num, unsigned int* min, unsigned int*max)
{
float maxProj = FLT_MIN , minProj = FLT_MAX ;
for(unsigned int i = 0 ; i < vertex_num ; i ++)
{
float proj = 0 ;
Vec3Dot(proj, vertices[i], dir); if(proj > maxProj)
{
maxProj = proj ;
*max = i ;
} if(proj < minProj)
{
minProj = proj ;
*min = i ;
}
}// end for
}// end for extrameDistanceAlongDir

上面一共同拥有两个函数,第一个函数就是给用户调用的计算AABB盒的方法。用户仅仅须要将模型的顶点集传递进来就可以。

第二个函数,是获取在指定的轴向上,哪个点在这个轴向上的投影是最长的和最短的。这个函数非常easy,仅仅须要调用一个点积Dot运算就行求出。

当求出了在X,Y和Z轴向上投影最长和最短的6个点之后,我们就分别取他们相应的轴向上的坐标值来构成Max和min,这样一个AABB盒就构造完成了。是不是非常easy??

AABB类

以下是AABB的完整类:

//--------------------------------------------------------------------------------------------------
// declaration : Copyright (c), by XJ , 2014 . All right reserved .
// brief : This file will define the Axie aligned bounding box.
// author : XJ
// date : 2014 / 6 / 22
// file : AABB.h
// version : 1.0
//---------------------------------------------------------------------------------------------------
#pragma once
#include"XJMath.h"
#include"Sphere.h" namespace XJCollision
{
/**
* brief : We use the Max-min representation
*/
class AABB
{
public:
AABB();
AABB(VECTOR3 min, VECTOR3 max); public:
/**
* Compute the fixed AABB
*/
void computeFixedAABB(Sphere* s); /**
* Compute the AABB from the original point set
*/
void computeAABBFromOriginalPointSet(VECTOR3 *vertices, unsigned int vertex_num); /**
* Collision Detection between two AABB
*/
bool isCollided(AABB* a); private:
/**
* Compute the least and most distance along the specific direction
*/
void extrameDistanceAlongDir(VECTOR3 dir, VECTOR3 * vertices, unsigned int vertex_num, unsigned int * min, unsigned int * max); public:
VECTOR3 max ;
VECTOR3 min ;
};
};
#include"AABB.h"
#include<cmath>
#include<float.h>
using namespace XJCollision ; AABB::AABB()
:max(),
min()
{ } AABB::AABB(VECTOR3 _max, VECTOR3 _min)
{
max.x = _max.x ; max.y = _max.y ; max.z = _max.z ;
min.x = _min.x ; min.y = _min.y ; min.z = _min.z ;
} void AABB::computeFixedAABB(Sphere *s)
{
max.x = s->center.x + s->radious ;
max.y = s->center.y + s->radious ;
max.z = s->center.z + s->radious ;
min.x = s->center.x - s->radious ;
min.y = s->center.y - s->radious ;
min.z = s->center.z - s->radious ;
}// end for computeFixedAABB void AABB::computeAABBFromOriginalPointSet(VECTOR3* vertices, unsigned int vertex_num)
{
unsigned int minX_i = 0 , maxX_i = 0 ;
extrameDistanceAlongDir(MAKE_VECTOR3(1,0,0), vertices, vertex_num, &minX_i, &maxX_i);
min.x = vertices[minX_i].x ;
max.x = vertices[maxX_i].x ; unsigned int minY_i = 0 , maxY_i = 0;
extrameDistanceAlongDir(MAKE_VECTOR3(0,1,0),vertices, vertex_num, &minY_i, &maxY_i);
min.y = vertices[minY_i].y ;
max.y = vertices[maxY_i].y ; unsigned int minZ_i = 0 , maxZ_i = 0;
extrameDistanceAlongDir(MAKE_VECTOR3(0,0,1),vertices, vertex_num, &minZ_i, &maxZ_i);
min.z = vertices[minZ_i].z ;
max.z = vertices[maxZ_i].z ;
}// end for computeAABBFromOriginalPointSet void AABB::extrameDistanceAlongDir(VECTOR3 dir, VECTOR3* vertices, unsigned int vertex_num, unsigned int* min, unsigned int*max)
{
float maxProj = FLT_MIN , minProj = FLT_MAX ;
for(unsigned int i = 0 ; i < vertex_num ; i ++)
{
float proj = 0 ;
Vec3Dot(proj, vertices[i], dir); if(proj > maxProj)
{
maxProj = proj ;
*max = i ;
} if(proj < minProj)
{
minProj = proj ;
*min = i ;
}
}// end for
}// end for extrameDistanceAlongDir bool AABB::isCollided(AABB* a)
{
if(max.x < a->min.x || min.x > a->max.x) return false ;
if(max.y < a->min.y || min.y > a->max.y) return false ;
if(max.z < a->min.z || min.z > a->min.z) return false ; return true ;
}// end for isCollided

程序实例

以下的两种图,各自是使用了第一种和另外一种计算方法计算出来的包围盒:

3D空间中的AABB(轴向平行包围盒, Aixe align bounding box)的求法的更多相关文章

  1. 3D空间中射线与轴向包围盒AABB的交叉检测算法【转】

    引言 在上一节中,我讲述了如何实现射线与三角形的交叉检测算法.但是,我们应该知道,在游戏开发中,一个模型有很多的三角形构成,如果要对所有的物体,所有的三角形进行这种检测,就算现在的计算机运算能力,也是 ...

  2. 3D空间中射线与轴向包围盒AABB的交叉检测算法 【转】

    http://blog.csdn.net/i_dovelemon/article/details/38342739 引言 在上一节中,我讲述了如何实现射线与三角形的交叉检测算法. 但是,我们应该知道, ...

  3. JAVA智能设备基于OpenGL的3D开发技术 之AABB碰撞检测算法论述

    摘要:无论是PC机的3D还是智能设备应用上,碰撞检测始终是程序开发的难点,甚至可以用碰撞检测作为衡量3D引擎是否完善的标准.现有许多3D碰撞检测算法,其中AABB碰撞检测是一种卓有成效而又经典的检测算 ...

  4. Oracle导入dmp备份文件到不同的表空间中

    原文链接:http://www.2cto.com/database/201211/171081.html 将DMP导入到不同的表空间中 1,用imp导出数据    cmd进入orcle安装目录bin下 ...

  5. Delphi接口的底层实现(接口在内存中仍然有其布局,它依附在对象的内存空间中,有汇编解释)——接口的内存结构图,简单清楚,深刻 good

    引言 接口是面向对象程序语言中一个很重要的元素,它被描述为一组服务的集合,对于客户端来说,我们关心的只是提供的服务,而不必关心服务是如何实现的:对于服务端的类来说,如果它想实现某种服务,实现与该服务相 ...

  6. 三维空间中xoy平面上特定抛物线的正等测投影解析解的一种求法

    背景 背景:为锻炼代同学,老师给了她一个反向工程微信"跳一跳"小游戏的任务,希望做一个一样的出来.跳一跳中,有方块,有小人,小人站在方块上. 这个游戏的玩法是,用手指按住手机屏幕, ...

  7. 浅析Linux用户空间中的Mmap

    一.MMap基础概念 mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系.实现这样的映射关系后,进程就可以采 ...

  8. cad二次开发--添加对象到模型空间中

    通过实体名来将实体加入到模型空间 AcDbObjectId PostToModelSpace(AcDbEntity *pEnt){ //打开块表 AcDbBlockTable *pBlockTable ...

  9. oracle表空间中PCTFREE, PCTUSED, INITRANS, MAXTRANX参数的解释

    1. PCTFREE 要形容一个 BLOCK 的运作,我们可以把一个 BLOCK 想成一个水杯.侍者把水倒入放在我们面前的水杯,要多满呢,我们要求他倒 9 分满好了,这时候 PCTFREE 代表着设定 ...

随机推荐

  1. hibernate学习——Set集合配置

    Set集合的配置 数据表的创建:表关系一个员工拥有多个身份 create table EMPLOYEE ( id INT NOT NULL auto_increment, first_name VAR ...

  2. hibernate操作数据库总结

    这篇文章用于总结hibernate操作数据库的各种方法 一.query方式 1.hibernate使用原生态的sql语句执行数据库查询 有些时候有些开发人员总觉得用hql语句不踏实,程序出现了错误,就 ...

  3. WPF MediaElement播放器2

    在此问个问题,MediaElement播放本地和http上的视频没问题,但是ftp的怎么在本例中播放不了 若高手了解,请不吝赐教 using System; using System.Collecti ...

  4. mysql多实例的配置(转)

    1.创建多实例的目录: mkdir -p /data/mysql/mysql_3307/{data,tmp,logs} mkdir -p /data/mysql/mysql_3308/{data,tm ...

  5. OpenCV在MFC图像控件内显示图像

    1.依照文章<OpenCV+MFC显示图像>,完毕配置. 2.创建对应的图像控件,button控件. 3.进行类型转换. 在当前OpenCV2版本号内,图像格式为cv::Mat ,而该格式 ...

  6. Dictionary带来的一种隐式内存泄漏

    当心Dictionary带来的一种隐式内存泄漏 最近在看Dictionary的源代码的时候, 突然想到Dictionary的不当使用中有一种隐含内存泄漏的可能. 简化使用场景 小A正在写一个简单的图书 ...

  7. JTable demo

    简单讲就是在没有使用layout manager的时候用setSize,在使用了layout manager 的时候用setPreferredSize 并且setPreferredSize通常和set ...

  8. Mean Shift简介

    Mean Shift,我们 翻译“平均漂移”. 其集群,图像平滑. 图像分割和跟踪已广泛应用.因为我现在认为追踪,因此推出Mean Shift该方法用于目标跟踪.从而MeanShift較全面的介绍. ...

  9. (五岁以下儿童)NS3样本演示:桥模块演示样品csma-bridge.cc凝视程序

    (五岁以下儿童)NS3:桥模块演示样品csma-bridge.cc凝视程序 1.Ns3 bridge模csma-bridge.cc演示示例程序的目光 // Network topology // // ...

  10. ZOJ 1203 Swordfish 旗鱼 最小生成树,Kruskal算法

    主题链接:problemId=203" target="_blank">ZOJ 1203 Swordfish 旗鱼 Swordfish Time Limit: 2 ...