日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

八叉树 ( 1 )

發(fā)布時間:2024/5/15 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 八叉树 ( 1 ) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
?

1、對Octree的描述

Octree的定義是:若不為空樹的話,樹中任一節(jié)點的子節(jié)點恰好只會有八個,或零個,也就是子節(jié)點不會有08以外的數(shù)目。那么,這要用來做什么?想象一個立方體,我們最少可以切成多少個相同等分的小立方體?答案就是8個。再想象我們有一個房間,房間里某個角落藏著一枚金幣,我們想很快的把金幣找出來,聰明的你會怎么做?我們可以把房間當成一個立方體,先切成八個小立方體,然后排除掉沒有放任何東西的小立方體,再把有可能藏金幣的小立方體繼續(xù)切八等份….如此下去,平均在Log8(房間內(nèi)的所有物品數(shù))的時間內(nèi)就可找到金幣。因此,Octree就是用在3D空間中的場景管理,可以很快地知道物體在3D場景中的位置,或偵測與其它物體是否有碰撞以及是否在可視范圍內(nèi)。

2、實現(xiàn)Octree的原理

(1). 設定最大遞歸深度

(2). 找出場景的最大尺寸,并以此尺寸建立第一個立方體

(3). 依序?qū)挝辉貋G入能被包含且沒有子節(jié)點的立方體

(4). 若沒有達到最大遞歸深度,就進行細分八等份,再將該立方體所裝的單位元元素全部分擔給八個子立方體

(5). 若發(fā)現(xiàn)子立方體所分配到的單位元元素數(shù)量不為零且跟父立方體是一樣的,則該子立方體停止細分,因為跟據(jù)空間分割理論,細分的空間所得到的分配必定較少,若是一樣數(shù)目,則再怎么切數(shù)目還是一樣,會造成無窮切割的情形。

(6). 重復3,直到達到最大遞歸深度。

3、Octree的存貯結(jié)構(gòu)

本例中Octree的存貯結(jié)構(gòu)用一個有(若干+八)個字段的記錄來表示樹中的每個結(jié)點。其中若干字段用來描述該結(jié)點的特性(本例中的特性為:節(jié)點的值和節(jié)點坐標),其余的八個字段用來作為存放指向其八個子結(jié)點的指針。此外,還有線性存儲和1托8式存儲。

4BSP Tree和Octree對比

a) BSP Tree將場景分割為1個面,而Octree分割為3個面。

b) BSP Tree每個節(jié)點最多有2個子結(jié)點,而Octree最多有8個子結(jié)點

因此BSP Tree可以用在不論幾唯的場景中,而Octree則常用于三維場景

5、本例實現(xiàn)Octree的若干關(guān)鍵技術(shù)及截圖

A、主界面:

Main函數(shù)中使用while(true)產(chǎn)生類似Trinigy引擎中的渲染循環(huán)效果,等待用戶輸入操作。通過IF判斷用戶的輸入并進行相應的操作。

[Copy to clipboard] [-] View CodeCPP
1234567891011 cin>>choiced; while(true){ if(choiced == 0) return 0; else if(choiced == 1) {………… } …………}

B、創(chuàng)建八叉樹界面,需要用戶輸入遞歸次數(shù)和外包盒在三維場景中的坐標

本例使用3層深度,外包盒坐標為(1,100,1,100,1,100)

[Copy to clipboard] [-] View CodeCPP
12345678910111213 template<class T>struct OctreeNode{T data; //節(jié)點數(shù)據(jù) T xmin,xmax; //節(jié)點坐標,即六面體個頂點的坐標 T ymin,ymax; T zmin,zmax; OctreeNode <T> *top_left_front,*top_left_back; //該節(jié)點的8個子結(jié)點,即個子六面體 OctreeNode <T> *top_right_front,*top_right_back; OctreeNode <T> *bottom_left_front,*bottom_left_back;OctreeNode <T> *bottom_right_front,*bottom_right_back;…………};

樹的結(jié)構(gòu)圖:

C、創(chuàng)建成功后先序遍歷此八叉樹。

[Copy to clipboard] [-] View CodeCPP
12345678910111213141516171819 void createOctree(OctreeNode<T> * &root,int maxdepth,double xmin,double xmax,double ymin,double ymax,double zmin,double zmax){ maxdepth=maxdepth-1; //每遞歸一次就將最大遞歸深度-1 if(maxdepth>=0) { root=new OctreeNode<T>(); root->xmin=xmin; //為節(jié)點坐標賦值 root->xmax=xmax;……………… double xm=(xmax-xmin)/2; double ym=(ymax-ymin)/2; double zm=(ymax-ymin)/2; //計算節(jié)點3個維度上的半邊長 //遞歸創(chuàng)建子樹,根據(jù)每一個節(jié)點所處(是幾號節(jié)點)的位置決定其子結(jié)點的坐標。 createOctree(root->top_left_front,maxdepth,xmin,xmax-xm,ymax-ym,ymax,zmax-zm,zmax); createOctree(root->top_left_back,maxdepth,xmin,xmax-xm,ymin,ymax-ym,zmax-zm,zmax); ……………… //8個子結(jié)點 }}

共產(chǎn)生了73個節(jié)點,由于比較多,沒有截出全部結(jié)果。

D、查看此樹的深度

即查找1號節(jié)點的個數(shù)。

[Copy to clipboard] [-] View CodeCPP
1234567891011121314 int i=1;template <class T>void preOrder( OctreeNode<T> * & p){ if(p) { cout<<i<<".當前節(jié)點的值為:"<<p->data<<"/n坐標為:"; cout<<" xmin: "<<p->xmin<<" xmax: "<<p->xmax;………… i+=1; preOrder(p->top_left_front); preOrder(p->top_left_back);……………… }}

E、查找點,需要用戶輸入坐標,本例使用坐標(80,80,80)

如果用戶輸入的點在場景外,則提示沒有找到。如(200,2,200)

根據(jù)用戶定義的最大遞歸深度和場景的坐標,計算一下該場景被分割后的最小6面體各邊的邊長,然后判斷用戶輸入的坐標是在當前節(jié)點的哪一個子結(jié)點中并循環(huán)搜索,直到達到葉子節(jié)點。(代碼較多,詳情請見下面的源代碼)

6、源代碼

八叉樹節(jié)點類的定義:

[Copy to clipboard] [-] View CodeCPP
12345678 template<class T>int depth(OctreeNode<T> *& p){ if(p == NULL) return -1; int h = depth(p->top_left_front); return h+1;}

創(chuàng)建節(jié)點的函數(shù):

/

總結(jié)

以上是生活随笔為你收集整理的八叉树 ( 1 )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。