青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

3D幾何圖元(3)

新建網頁 1


矩形邊界框

另一種常見的用來界定物體的幾何圖元是矩形邊界框,矩形邊界框可以是與軸對齊的或是任意方向的。軸對齊矩形邊界框有一個限制,就是它的邊必須垂直于坐標軸??s寫AABB常用來表示axially aligned bounding box(軸對齊矩形邊界框),OBB用來表示oriented bounding box(方向矩形邊界框)。軸對齊矩形邊界框不僅容易創建,而且易于使用。

一個3D的AABB就是一個簡單的六面體,每一邊都平行于一個坐標平面。矩形邊界框不一定是立方體,它的長、寬、高可以彼此不同。在圖12.10中,畫出了一些簡單的3D物體和它們的AABB。

 

AABB的表達方法

先介紹AABB的一些重要性質和引用這些值時所用到的記法。AABB內的點滿足下列等式:

xmin x xmax

ymin y ymax

zmin z zmax

特別重要的兩個點為:

pmin = [xmin   ymin   zmin ]

pmax = [xmax   ymax   zmax ]

中心點c為:

c = (pmin + pmax) /2

"尺寸向量"s是從pmin指向pmax的向量,包含了矩形邊界的長、寬、高:

s = pmax - pmin

還可以求出矩形邊界框的"半徑向量"r,它是從中心指向pmax的向量:

r = pmax - c = s/2

明確地定義一個AABB只需要pminpmax、cs、r這5個向量中的兩個(除sr不能配對外,它們中的任意兩個都可配對)。在一些情況下,某些配對形式比其他的會更有用。我們建議用pminpmax表示一個邊界框,因為實際應用中,使用它們的頻率遠高于cs、r。當然,由pminpmax計算其余三個中的任意一個都是很容易的。

在我們的C++代碼中,使用下面的類表示AABB,這是一個縮略的代碼清單。

    #ifndef AABB3_H
   
#define AABB3_H
   
    #include "vector3.h"
   
   
class cMatrix4x3;
   
   
    //---------------------------------------------------------------------------
    // Implement a 3D axially aligned bounding box
    //---------------------------------------------------------------------------
   
class cAABB3
    {
   
public:
        cVector3 min, max;
   
   
public:
        
// query for dimentions
   
    cVector3 size() const        { return max - min; }
        
float     x_size()            { return max.x - min.x; }
        
float     y_size()            { return max.y - min.y; }
        
float     z_size()            { return max.z - min.z; }
        cVector3 center() 
const        { return (min + max) * 0.5f; }
   
        
// fetch one of the eight corner points
   
    cVector3 corner(int i) const;
   
        
// "Empty" the box, by setting the values to really large/small numbers.
   
    void empty();
   
        
// add a point to the box
   
    void add(const cVector3& p);
   
        
// add an AABB to the box
   
    void add(const cAABB3& box);
   
        
// return true if the box is empty
   
    bool is_empty() const;
   
        
// return true if the box contains a point
   
    bool contains(const cVector3& p) const;
   
        
// transform the box and compute the new AABB
   
    void set_to_transformed_box(const cAABB3& box, const cMatrix4x3& m);
   
        
// return the clostet point on this box to another point
   
    cVector3 clostet_point_to(const cVector3& p) const;
    };
   
   
#endif

計算AABB

計算一個頂點集合的AABB是非常簡單的,先將最小值和最大值設為"正負無窮大"或任何比實際中用到的數都大或小得多的數。接著,遍歷全部點,并擴展邊界框直到它包含所有點為止。

我們在cAABB類中引入了兩個輔助函數,第一個函數負責"清空"AABB

    //---------------------------------------------------------------------------
    // "Empty" the box, by setting the values to really large/small numbers.
    //---------------------------------------------------------------------------
   
void cAABB3::empty() 
    {
        
const float big_number = 1e37f;
   
        min.x = min.y = min.z = big_number;
        max.x = max.y = max.z = -big_number;
    }

第二個函數將單個點""到AABB中,并在必要的時候擴展AABB以包含每個點:

    //---------------------------------------------------------------------------
    // Add a point to the box
    //---------------------------------------------------------------------------
   
void cAABB3::add(const cVector3& p)
    {
        
// expand the box as necessary to contain the point
   
    if(p.x < min.x)        min.x = p.x;
        
if(p.x > max.x)        max.x = p.x;
        
if(p.y < min.y)        min.y = p.y;
        
if(p.y > max.y)        max.y = p.y;
        
if(p.z < min.z)        min.z = p.z;
        
if(p.z > max.z)        max.z = p.z;
    }

現在,從一個點集創建矩形邊界框,可以使用下面的代碼:

    Listing 12.1: Computing the AABB for a set of points
   
   
// Our list of points
   
const int n;
    Vector3 list[n];
   
   
// First, empty the box
   
AABB3 box;
    box.empty();
   
   
// Add each point into the box
   
for (int i = 0 ; i < n ; ++i) 
      box.add(list[i]);

取得AABB的頂點:

    //--------------------------------------------------------------------------------------
    // Return one of the 8 corner points.  The points are numbered as follows:
    //
    //            6                                7
    //              ------------------------------
    //             /|                           /|
    //            / |                          / |
    //           /  |                         /  |
    //          /   |                        /   |
    //         /    |                       /    |
    //        /     |                      /     |
    //       /      |                     /      |
    //      /       |                    /       |
    //     /        |                   /        |
    //  2 /         |                3 /         |
    //   /----------------------------/          |
    //   |          |                 |          |
    //   |          |                 |          |      +Y
    //   |        4 |                 |          | 
    //   |          |-----------------|----------|      |
    //   |         /                  |         /  5    |
    //   |        /                   |        /        |       +Z
    //   |       /                    |       /         |
    //   |      /                     |      /          |     /
    //   |     /                      |     /           |    /
    //   |    /                       |    /            |   /
    //   |   /                        |   /             |  /
    //   |  /                         |  /              | /
    //   | /                          | /               |/
    //   |/                           |/                ----------------- +X
    //   ------------------------------
    //  0                              1
    //
    // Bit 0 selects min.x vs. max.x
    // Bit 1 selects min.y vs. max.y
    // Bit 2 selects min.z vs. max.z
    //--------------------------------------------------------------------------------------
   
cVector3 cAABB3::corner(int i) const
    {
        assert(i >= 0 && i <= 7);    
// make sure index is in range
   

        
return cVector3((i & 1) ? max.x : min.x,
                        (i & 2) ? max.y : min.y,
                        (i & 4) ? max.z : min.z);
    }

其他的相關函數,具體功能詳見注釋:

    //---------------------------------------------------------------------------
    // Add an AABB to the box
    //---------------------------------------------------------------------------
   
void cAABB3::add(const cAABB3& box)
    {
        
// expand the box as necessary
   
    if(box.min.x < min.x)    min.x = box.min.x;
        
if(box.min.x > max.x)    max.x = box.min.x;
        
if(box.min.y < min.y)    min.y = box.min.y;
        
if(box.min.y > max.y)    max.y = box.min.y;
        
if(box.min.z < min.z)    min.z = box.min.z;
        
if(box.min.z > max.z)    max.z = box.min.z;
    }
   
   
//---------------------------------------------------------------------------
    // Return true if the box is empty
    //---------------------------------------------------------------------------
   
bool cAABB3::is_empty() const
    {
        
// check if we're inverted on any axis
   
    return (min.x > max.x) || (min.y > max.y) || (min.z > max.z);
    }
   
   
//---------------------------------------------------------------------------
    // Return true if the box contains a point
    //---------------------------------------------------------------------------
   
bool cAABB3::contains(const cVector3& p) const
    {
        
// check for overlap on each axis
   
    return (p.x >= min.x) && (p.x <= max.x) &&
               (p.y >= min.y) && (p.y <= max.y) &&
               (p.z >= min.z) && (p.z <= max.z);
    }
   
   
//---------------------------------------------------------------------------
    // return the closest point on this box to another point
    //---------------------------------------------------------------------------
   
cVector3 cAABB3::clostet_point_to(const cVector3& p) const
    {
        
// "push" p into the box, on each dimension.
   

        cVector3 r;
   
        
if(p.x < min.x)
            r.x = min.x;
        
else if(p.x > max.x)
            r.x = max.x;
        
else
            r.x = p.x;
   
        
if(p.y < min.y) 
            r.y = min.y;
        
else if(p.y > max.y) 
            r.y = max.y;
        
else
            r.y = p.y;
   
        
if(p.z < min.z)
            r.z = min.z;
        
else if(p.z > max.z)
            r.z = max.z;
        
else
            r.z = p.z;
   
        
return r;
    }

AABB與邊界球

很多情況下,AABB比邊界球更適合于做定界球:

(1)計算一個點集的AABB,在編程上更容易實現,并能在較短的時間內完成。計算邊界球則困難得多。

(2)對實際世界里的許多物體,AABB提供了一種"更緊湊"的邊界。當然,對于某些物體,邊界球更好(設想一個本身就是球形的物體)。在極端情況下,AABB的體積可能僅相當于邊界球體積的1/2,大部分時候邊界球的體積會比矩形框的體積大得多,比較一下電線桿的邊界球和AABB就知道了。圖12.11所示為不同物體的AABB與邊界球的比較。

邊界球的根本問題是它的形狀只有一個自由度----半徑,而AABB卻有三個自由度----長、寬、高。因此,它可以調節這些自由度以適應不同物體。對圖12.11中的大部分物體,除了右上角的星形體外,AABB都比邊界球小。對這顆星,邊界球也僅比AABB略小一些。通過圖12.11,我們可以注意到AABB對物體的方向很敏感。比較下面兩支槍的AABB,圖中槍的大小都是相同的,只是方向不同而已;還應注意到在這一情況下邊界球大小相同,因為邊界球對物體方向不敏感。

 

變換AABB

當物體在虛擬世界中移動時,它的AABB也需要隨之移動。此時我們有兩個選擇----用變換后的物體來重新計算AABB,或者對AABB做和物體同樣的變換。所得到的結果不一定是軸對齊的(如果物體旋轉),也不一定是盒狀的(如果物體發生了扭曲)。不過,通過"變換后的AABB"進行計算要比通過"經過變換后的物體"計算AABB快得多,因為AABB只有8個頂點。

通過"變換后的AABB"計算不能只是簡單地變換8個頂點,也不能通過轉換原pminpmax來得到新的pminpmax ----這樣可能會導致xmin > xmax。為了計算新的AABB,必須先變換8個頂點,再從這8個頂點中計算一個新的AABB。

根據變換的不同,這種方法可能使新邊界框比原邊界框大許多。例如,在2D中,45度的旋轉會大大增加邊界框的尺寸,如圖12.12所示:

比較圖12.12中原AABB(灰色框)和新AABB(右邊較大的方框),它是通過旋轉后的AABB計算的,新AABB幾乎是原來的兩倍。注意,如果從旋轉后的物體而不是通過旋轉后的AABB來計算新AABB,它的大小將和原來的AABB相同。

可以利用AABB的結構來加快新的AABB的計算速度,而不必先變換8個頂點,再從這8個頂點中計算新AABB。

讓我們簡單回顧一下3x3矩陣變換一個3D點的過程:

設原邊界框為xmin,xmax,ymin...,新邊界框計算將得到x'min,x'max,y'min...?,F在我們的任務就是想辦法加快計算x'min的速度,換句話說,我們希望找到m11x+m21y+m31z的最小值,其中[x, y, z]是原8個頂點中的任意一個,我們所要做的就是找出這些點經過變換后誰的x坐標最小??吹谝粋€乘積:m11x,為了最小化乘積,必須決定是用xmin還是xmax來代換其中的x。顯然,如果m11>0,用xmin能得到最小化乘積;如果m11<0,則用xmax能得到最小化乘積。比較方便的是,不管xminxmax中哪個被用來計算xmin,都可以用另外一個來計算xmax??梢詫仃?個元素中的每個都應用這個計算過程,如下列代碼所示:

    //---------------------------------------------------------------------------
    // Transform the box and compute the new AABB.  Remember, this always
    // results in an AABB that is at least as big as the origin, and may be
    // considerably bigger.
    //---------------------------------------------------------------------------
   
void cAABB3::set_to_transformed_box(const cAABB3& box, const cMatrix4x3& m)
    {
        
// if we're empty, then bail.
   
    if(box.is_empty())
        {
            empty();
            
return;
        }
   
        
// start with the translation portion
   
    min = max = get_translation(m);
   
        
// examine each of the 9 matrix elements and compute the new AABB
   

        
if(m.m11 > 0.0f)
        {
            min.x += m.m11 * box.min.x;
            max.x += m.m11 * box.max.x;
        }
        
else
        {
            min.x += m.m11 * box.max.x;
            max.x += m.m11 * box.min.x;
        }
   
        
if(m.m21 > 0.0f)
        {
            min.x += m.m21 * box.min.y; 
            max.x += m.m21 * box.max.y;
        }
        
else
        {
            min.x += m.m21 * box.max.y; 
            max.x += m.m21 * box.min.y;
        }
   
        
if(m.m31 > 0.0f)
        {
            min.x += m.m31 * box.min.z; 
            max.x += m.m31 * box.max.z;
        }
        
else
        {
            min.x += m.m31 * box.max.z; 
            max.x += m.m31 * box.min.z;
        }
   
        
if(m.m12 > 0.0f) 
        {
            min.y += m.m12 * box.min.x; 
            max.y += m.m12 * box.max.x;
        }
        
else
        {
            min.y += m.m12 * box.max.x; 
            max.y += m.m12 * box.min.x;
        }
   
        
if(m.m22 > 0.0f)
        {
            min.y += m.m22 * box.min.y; 
            max.y += m.m22 * box.max.y;
        }
        
else
        {
            min.y += m.m22 * box.max.y; 
            max.y += m.m22 * box.min.y;
        }
   
        
if(m.m32 > 0.0f)
        {
            min.y += m.m32 * box.min.z; 
            max.y += m.m32 * box.max.z;
        }
        
else
        {
            min.y += m.m32 * box.max.z; 
            max.y += m.m32 * box.min.z;
        }
   
        
if(m.m13 > 0.0f) 
        {
            min.z += m.m13 * box.min.x; 
            max.z += m.m13 * box.max.x;
        }
        
else
        {
            min.z += m.m13 * box.max.x; 
            max.z += m.m13 * box.min.x;
        }
   
        
if(m.m23 > 0.0f)
        {
            min.z += m.m23 * box.min.y; 
            max.z += m.m23 * box.max.y;
        }
        
else
        {
            min.z += m.m23 * box.max.y; 
            max.z += m.m23 * box.min.y;
        }
   
        
if(m.m33 > 0.0f)
        {
            min.z += m.m33 * box.min.z; 
            max.z += m.m33 * box.max.z;
        }
        
else
        {
            min.z += m.m33 * box.max.z; 
            max.z += m.m33 * box.min.z;
        }
    }

posted on 2008-02-23 12:25 lovedday 閱讀(2657) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品综合色区在线观看| 在线一区二区三区做爰视频网站 | 午夜一区二区三区不卡视频| 欧美韩国日本一区| 久久aⅴ国产欧美74aaa| 日韩视频永久免费观看| 国产欧美视频一区二区| 欧美网站大全在线观看| 欧美国产一区二区三区激情无套| 亚洲欧美另类国产| 9色国产精品| 欧美一二三区精品| 久久影音先锋| 亚洲欧美视频| 韩曰欧美视频免费观看| 久久天天躁夜夜躁狠狠躁2022| 欧美综合二区| 亚洲欧美日本在线| 欧美大尺度在线观看| 亚洲视频二区| 亚洲色图自拍| 一区二区在线不卡| 国产综合色在线| 激情校园亚洲| 亚洲人午夜精品| 一区二区三区导航| 亚洲欧美精品| 久久精品中文字幕一区| 美女精品在线| 日韩亚洲不卡在线| 亚洲制服丝袜在线| 久久精品二区亚洲w码| 噜噜噜久久亚洲精品国产品小说| 欧美国产日韩二区| 国产精品v欧美精品v日韩精品 | 免费h精品视频在线播放| 亚洲第一页自拍| 亚洲精品一区在线观看| 亚洲自拍偷拍视频| 蜜臀91精品一区二区三区| 欧美日韩三级电影在线| 国内精品久久久久久影视8| 亚洲第一页自拍| 在线午夜精品自拍| 久久狠狠亚洲综合| 亚洲日本免费| 欧美制服第一页| 欧美人与禽猛交乱配| 国产亚洲欧美一级| 国产精品欧美一区喷水| 亚洲成色www久久网站| 亚洲免费小视频| 欧美高清视频一区二区| 亚洲视频一二三| 欧美日韩你懂的| 99视频在线精品国自产拍免费观看| 91久久极品少妇xxxxⅹ软件| 久久久久久久波多野高潮日日| 正在播放欧美视频| 欧美一区二区三区免费视| 欧美日韩精品高清| 亚洲国产精品成人精品| 国产亚洲精品激情久久| 可以免费看不卡的av网站| 亚洲免费av电影| 欧美三级电影一区| 免费视频一区二区三区在线观看| 一区二区毛片| 91久久精品美女高潮| 一本一本久久a久久精品综合妖精| 免费一级欧美片在线播放| 国产精品欧美在线| 久久午夜精品| 国产精品免费看| 亚洲欧美视频一区| 亚洲国产岛国毛片在线| 亚洲卡通欧美制服中文| 欧美精品免费在线观看| 一区二区三区日韩欧美| 久久国产黑丝| 蜜桃久久精品一区二区| 免费日韩av片| 羞羞色国产精品| 久久女同互慰一区二区三区| 亚洲影院免费观看| 欧美精品日韩三级| 在线播放日韩专区| 欧美一区二区视频在线观看2020 | 久热这里只精品99re8久| 国产欧美日韩综合一区在线观看 | 亚洲欧美日韩成人高清在线一区| 亚洲激情女人| 久久精品国产精品亚洲精品| 国产伦精品一区二区三区高清版| 亚洲欧美韩国| 中文日韩电影网站| 欧美另类久久久品| 欧美日韩国产色视频| 免费看成人av| 在线观看日韩av电影| 久久久久久久欧美精品| 亚洲欧美日韩精品久久奇米色影视 | 欧美一区二区三区四区高清| 亚洲视频欧美视频| 国产精品久久久久久久久久直播| 艳妇臀荡乳欲伦亚洲一区| 亚洲人成免费| 久久一本综合频道| 久久精品人人爽| 激情欧美一区二区| 裸体一区二区| 久久精品一区二区三区中文字幕 | 欧美岛国激情| 亚洲精选中文字幕| 亚洲精品在线视频观看| 欧美日韩高清在线播放| 亚洲色图制服丝袜| 日韩午夜黄色| 国产精品久久久久9999高清 | 亚洲一区二区三区精品在线观看 | 亚洲欧美日韩中文视频| 中文亚洲视频在线| 国产精品久久7| 欧美在线999| 亚洲一区二区三区中文字幕| 国产精品一区毛片| 久久蜜桃资源一区二区老牛| 久久不射2019中文字幕| 亚洲国产精品国自产拍av秋霞 | 欧美激情欧美狂野欧美精品| 一区二区三区国产在线| 在线视频日韩| 国产亚洲成年网址在线观看| 老牛影视一区二区三区| 欧美成人有码| 亚洲视频中文| 亚洲免费视频网站| 国语自产精品视频在线看一大j8| 免费视频最近日韩| 久久中文字幕导航| 欧美日韩国产综合视频在线观看中文| 一区二区三区在线观看视频| 亚洲第一在线| 欧美性猛交99久久久久99按摩| 香蕉久久一区二区不卡无毒影院| 校园激情久久| 91久久精品www人人做人人爽 | 亚洲一区不卡| 狠狠色丁香婷婷综合久久片| 欧美国产视频在线观看| 欧美激情精品久久久久久大尺度| 亚洲欧美三级在线| 久久亚洲综合网| 亚洲视频大全| 欧美专区在线播放| 亚洲精品中文字幕有码专区| 亚洲一级黄色片| 亚洲经典三级| 亚洲一区二区成人| 亚洲第一在线视频| 亚洲午夜未删减在线观看| 尤物yw午夜国产精品视频| 99re66热这里只有精品4| 好看的日韩av电影| 99精品99久久久久久宅男| 国产日韩一区欧美| 亚洲经典自拍| 韩国福利一区| 夜夜嗨av一区二区三区四季av| 国产专区欧美专区| 91久久午夜| 韩国成人福利片在线播放| 一区二区电影免费观看| 亚洲国产成人av| 欧美肥婆bbw| 国产午夜精品久久久| 亚洲美女在线国产| 一区二区三区在线免费观看| 亚洲午夜一区二区三区| 日韩视频在线观看国产| 欧美自拍偷拍午夜视频| 亚洲一区中文| 欧美国产成人在线| 久久偷看各类wc女厕嘘嘘偷窃| 国产精品福利久久久| 亚洲精品乱码久久久久久日本蜜臀 | 欧美一区久久| 亚洲国产日韩欧美| 欧美 日韩 国产 一区| 欧美在线一区二区三区| 羞羞色国产精品| 亚洲精品免费在线观看| 欧美综合国产| 久久精品免费| 欧美日韩免费视频| 欧美一级二区| 欧美精品一区二区三区四区| 欧美一区二区三区免费看| 欧美日韩1区2区| 亚洲国产视频一区|