亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

3D空間中的AABB(軸向平行包圍盒, Aixe align bo

系統(tǒng) 2611 0

引言

??????????? 在 前面的一篇文章 中講述了怎樣通過模型的頂點來求的模型的包圍球,而且還講述了基本包圍體除了包圍球之外,還有AABB包圍盒。在這一章,將講述怎樣依據(jù)模型的坐標(biāo)求得它的AABB盒。




表示方法

? ? ? ? ? ?? AABB盒的表示方法有非常多,總結(jié)起來有例如以下的三種情況:

? ? ? ? ? ?? Max-min表示法:使用一個右上角和左下角的點來唯一的定義一個包圍體

? ? ? ? ? ?? Center-radious表示法:我們用center點來表示中點,radious是一個數(shù)組,保存了包圍盒在x方向,y方向,z方向上的半徑。

? ? ? ? ? ??? Min-Width表示方法:我們用min來定義左下角的點,使用width來保存在x,y,z方向上的長度。

????????????? 不同的方法,他們的碰撞檢測算法也會有所不同,而且不同的表示方法也會適用在不同的情形下。所以,大家自己設(shè)計的時候,須要謹(jǐn)慎考慮。

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

      class AABB

{

   ....

public:

    VECTOR3 max ;

   ?VECTOR3 min ;

};


    
??????????? 在這樣的表示方法之下,進(jìn)行碰撞檢測的代碼例如以下所看到的:

      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盒構(gòu)造

??????????? 構(gòu)造AABB盒的方法有非常多種,有的非常easy,有的非常復(fù)雜,這里將介紹兩種主要的構(gòu)造方法,他們也非常的簡單,easy掌握。

???????????? 第一種是固定大小的AABB盒,這樣的AABB盒在構(gòu)造完成之后,無論被包圍的物體怎么樣的旋轉(zhuǎn),都不須要在進(jìn)行又一次構(gòu)造了。

??????????? 另外一種是比較緊湊的一種,利用X,Y和Z軸向上最長和最遠(yuǎn)的點來構(gòu)造一個AABB盒。



固定大小AABB盒

??????????? 正如上面說的那樣,固定大小的AABB盒,它須要被包圍的物體,無論怎么旋轉(zhuǎn),都還在這個包圍體里面。所以,我們先為這個物體構(gòu)造一個包圍球體,然后在這個包圍球體的基礎(chǔ)上構(gòu)建一個AABB盒。這樣就行達(dá)到無論怎么旋轉(zhuǎn),都還在包圍體里面。

??????????? 只是,為這個物體構(gòu)建一個包圍球相同也可以滿足這種要求,所以,就有點雞肋了。可是,在某些限制條件下,你無法使用包圍球,那么就行使用這個方案來構(gòu)建一個固定大小的AABB盒。

??????????? 這個算法的核心是怎樣構(gòu)建一個包圍球體,而這個算法我在前面一章中已經(jīng)講述了,就不再反復(fù),感興趣的讀者能夠去看博客中 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盒的構(gòu)造方法,是從頂點集中獲取X,Y和Z方向上最遠(yuǎn)的和近期的點,然后利用他們來構(gòu)建一個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
    

?????????? 上面一共同擁有兩個函數(shù),第一個函數(shù)就是給用戶調(diào)用的計算AABB盒的方法。用戶僅僅須要將模型的頂點集傳遞進(jìn)來就可以。

?????????? 第二個函數(shù),是獲取在指定的軸向上,哪個點在這個軸向上的投影是最長的和最短的。這個函數(shù)非常easy,僅僅須要調(diào)用一個點積Dot運算就行求出。

????????? 當(dāng)求出了在X,Y和Z軸向上投影最長和最短的6個點之后,我們就分別取他們相應(yīng)的軸向上的坐標(biāo)值來構(gòu)成Max和min,這樣一個AABB盒就構(gòu)造完成了。是不是非常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
    

程序?qū)嵗?

??????????? 以下的兩種圖,各自是使用了第一種和另外一種計算方法計算出來的包圍盒:

?

3D空間中的AABB(軸向平行包圍盒, Aixe align bounding box)的求法


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 中国特黄特级真人毛片 | 99九九精品免费视频观看 | 亚洲视频1区| 国产亚洲精品美女2020久久 | 国产伦精品一区二区三区免 | 香蕉国产精品 | 涩涩视频网 | 奇米网色| 伊人五月天婷婷琪琪综合 | 亚洲欧美在线视频免费 | 国产成人免费观看在线视频 | 久久国| 四虎国产精品永久在线网址 | 中国产一级毛片 | 国产精品一级片 | 夜夜夜夜夜夜爽噜噜噜噜噜噜 | 特黄特级毛片免费视 | 免费看色片网站 | 在线观看日韩欧美 | 99久热在线精品视频播 | 久久久久久久综合狠狠综合 | 亚洲欧美国产日产综合不卡 | 国产精品免费综合一区视频 | 久久夜夜视频 | 男人天堂999| 亚洲精品视频久久 | 国产成人视屏 | 亚洲免费在线观看 | 中国大陆一级毛片 免费 | 九九视频网 | 亚洲毛片免费视频 | 久久嫩草影院免费看夜色 | 九九视频免费 | 成人夜色香网站在线观看 | 国产欧美成人xxx视频 | 日日摸日日 | 欧美日韩在线播放一区二区三区 | 国产精品永久免费10000 | 久久精品伦理 | 首页 动漫 亚洲 欧美 日韩 | 久草网在线观看 |