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

COLLADA DOM Tutorial

http://www.cnblogs.com/Jedimaster/archive/2007/12/01/979256.html

引言

  COLLADA是一個開放的標準,最初用于3D軟件數(shù)據(jù)交換,由SCEA發(fā)起,現(xiàn)在則被許多著名廠家支持如Autodesk、XSI等。COLLADA不僅僅可以用于建模工具之間交換數(shù)據(jù)之用,也可以作為場景描述語言用于小規(guī)模的實時渲染。因為COLLADA DOM擁有豐富的內(nèi)容用于表現(xiàn)場景中的各種元素,從多邊形幾何體到攝像機無所不包。我們可以通過COLLADA DOM庫來進行場景文件的讀取與處理操作。

提示

  COLLADA DOM的編程方式類似COM

蘇醒

  從這里下載COLLADA DOM

  http://sourceforge.net/projects/collada-dom/

  準備好你的IDE/編譯器,Windows平臺下推薦Visual Studio 8,LINUX/UNIX平臺下看各路英豪自己的了。

  推薦下載安裝包,會省掉不必要的重新編譯的工作。我向來最討厭重新編譯別人的庫,一來是時間寶貴,編譯的時候自己不可能看到任何有意義的東西,二來很多時候編寫這些庫的時候引用了特定版本的其它庫,導致自己還需要去下載其它的庫,非常麻煩。

  安裝好后記得在VC的工程目錄加入COLLADA的頭文件和庫文件文件夾路徑,否則什么都找不到。

開始

  首先在C++源文件中加入COLLADA DOM所需要的頭文件

#include <dae.h>
#include 
<dom/domCOLLADA.h>
  下面寫代碼,打開一個DAE XML文件。
int main(int argc, char** argv)
{
    DAE 
*collada_dom = new DAE();//創(chuàng)建一個DOM解析器
    daeInt error = collada_dom->load("file:///C:/Test/colladaDocument.dae");//打開一個放在C盤Test文件夾下一個名為colladaDocument.dae的文檔
    error = collada_com->unload();//關閉剛才打開的文檔
    return 0;//程序返回
}
一切都是很簡單的。載入文檔,獲得一個根指針,而后一切的操作都是從這個指針開始逐級的向下遍歷、轉(zhuǎn)換。為什么load函數(shù)中不是我們所想象的"C:\\Test\\colladaDocument",而是加了個file前綴。COLLADA DOM支持在處理DAE的時候使用URI直接定位到資源,詳細的可以看附帶的文檔。

  現(xiàn)在來點復雜的,讀取一個幾何體。在實際編碼前,我們需要理解一個概念,就是Shape與Instance的區(qū)別。假如場景中有10000個立方體,那么我們其實只需要儲存8個頂點、向量、三角形索引,然后我們指定這10000個立方體各自的變換、Shader參數(shù)就可以了。使用COLLADA DOM處理場景中幾何體的思路就是,先獲得Geometry(也就是我們所知道的Shape),而后獲得Instance。在對unload()的調(diào)用前增加下面一行代碼,

int geometryElementCount = (int)(collada_dom->getDatabase()->getElementCount(NULL, "geometry", NULL));

  這個時候我們就獲得了幾何體的確切數(shù)目,然后遍歷獲得各自的數(shù)據(jù)。再添加一個循環(huán),

for(int currentGeometry=0;currentGeometry<geometryElementCount;currentGeometry++)
{
    domGeometry 
*thisGeometry = 0;
    m_dae
->getDatabase()->getElement((daeElement**)&thisGeometry,currentGeometry,NULL, "geometry");
    domMesh 
*thisMesh = thisGeometry->getMesh();
}

  先不要繼續(xù)添加代碼,先最好定義一種我們的程序要使用的物體格式。比如,可以這樣,

struct CObject
{
    string m_sName;
    size_t m_iVertexNum;
    size_t m_iNormalNum;
    float* m_pVertices;
    float* m_pNormals;
    size_t m_iTriangleNum;
};

  我們就可以直接調(diào)用glDrawArrays去繪制這個物體。以后為了提高效率甚至可以把所有頂點都上傳到Vertex Buffer Object中,這樣就不需要每次繪制的時候把頂點、向量、紋理坐標都上傳一遍了。下面繼續(xù)補全代碼,

std::vector<CObject*> ObjectShapes;
for(int currentGeometry=0;currentGeometry<geometryElementCount;currentGeometry++)
{
    CObject
* pShape = new CObject;
    domGeometry 
*thisGeometry = 0;
    m_dae
->getDatabase()->getElement((daeElement**)&thisGeometry,currentGeometry,NULL, "geometry"); //逐個的找到每個Geometry Shape
    domMesh *thisMesh = thisGeometry->getMesh();//取得Mesh
    domListOfFloats vertexArray = thisMesh->getSource_array()[0]->getFloat_array()->getValue();//取得儲存頂點的數(shù)組
    domListOfFloats normalArray = thisMesh->getSource_array()[1]->getFloat_array()->getValue();//取得儲存向量的數(shù)組
    domListOfUInts indexArray = thisMesh->getTriangles_array()[0]->getP()->getValue();//取得三角形索引
    pShape->m_iTriangleNum = indexArray.getCount() / 6;//看下面的解釋
    pShape->m_iVertexNum = vertexArray.getCount() / 3;//每個頂點由3個數(shù)字組成
    pShape->m_iNormalNum = normalArray.getCount() / 3;//每個向量也由3個數(shù)字組成
    printf("%u %u %u\n", pShape->m_iTriangleNum, pShape->m_iVertexNum, pShape->m_iNormalNum);//再次打印一下
    ObjectShapes.push_back(pShape);
}

Exporter

 

  我們知道從MAYA導出的OBJ格式可以不是三角形,通過COLLADA插件導出的物體也一樣,我們可以選擇三角化或者保持原樣。假如我們不選擇三角化,那么對于一個簡單的CUBE來說,它的表示可能是這樣的,

<polylist material="initialShadingGroup" count="6">
  
<input semantic="VERTEX" source="#pCubeShape1-vertices" offset="0"/>
  
<input semantic="NORMAL" source="#pCubeShape1-normals" offset="1"/>
  
<vcount>4 4 4 4 4 4</vcount>
  
<p>0 0 1 1 3 2 2 3 2 4 3 5 5 6 4 7 4 8 5 9 7 10 6 11 6 12 7 13 1 14 0 15 1 16 7 17 5 18 3 19 6 20 0 21 2 22 4 23</p>
</polylist>

  這里vcount的意思是每個POLYGON由多少個頂點向量對組成,列表可以讓大家明白的更容易一些,

Polygon Vertex Index Normal Index
0 0 1 3 2 0 1 2 3
1 2 3 5 4 4 5 6 7

  也就是說,索引數(shù)值遵照“頂點 向量 頂點 向量”這樣的順序排列,即使有了UV也一樣。

<triangles material="initialShadingGroup" count="12">
  
<input semantic="VERTEX" source="#pCubeShape1-vertices" offset="0"/>
  
<input semantic="NORMAL" source="#pCubeShape1-normals" offset="1"/>
  
<p>0 0 1 1 2 3 1 1 3 2 2 3 2 4 3 5 4 7 3 5 5 6 4 7 4 8 5 9 6 11 5 9 7 10 6 11 6 12 7 13 0 15 7 13 1 14 0 15 1 16 7 17 3 19 7 17 5 18 3 19 6 20 0 21 4 23 0 21 2 22 4 23</p>
</triangles>

 

  三角化后一切看似都變多了,其實原理依舊,

Triangle Vertex Index Normal Index
0 0 1 2 0 1 3
1 1 3 2 1 2 3

  了解了這個之后,讓我們再次把代碼補全,將所有三角化后幾何體按照順序儲存到數(shù)組里去讓OpenGL直接渲染。

std::vector<CObject*> ObjectShapes;

for(int currentGeometry=0;currentGeometry<geometryElementCount;currentGeometry++)
{
    CObject
* pShape = new CObject;
    domGeometry 
*thisGeometry = 0;
    m_dae
->getDatabase()->getElement((daeElement**)&thisGeometry,currentGeometry,NULL, "geometry"); //逐個的找到每個Geometry Shape
    domMesh 
*thisMesh = thisGeometry->getMesh();//取得Mesh
    domListOfFloats vertexArray 
= thisMesh->getSource_array()[0]->getFloat_array()->getValue();//取得儲存頂點的數(shù)組
    domListOfFloats normalArray 
= thisMesh->getSource_array()[1]->getFloat_array()->getValue();//取得儲存向量的數(shù)組
    domListOfUInts indexArray 
= thisMesh->getTriangles_array()[0]->getP()->getValue();//取得三角形索引

    pShape
->m_iTriangleNum = indexArray.getCount() / 6;//看下面的解釋
    pShape->m_iVertexNum = vertexArray.getCount() / 3;//每個頂點由3個數(shù)字組成
    pShape->m_iNormalNum = normalArray.getCount() / 3;//每個向量也由3個數(shù)字組成
    printf("%u %u %u\n", pShape->m_iTriangleNum, pShape->m_iVertexNum, pShape->m_iNormalNum);//再次打印一下
    pShape->m_pVertices = new float[pShape->m_iTriangleNum*3*3];
    pShape
->m_pNormals = new float[pShape->m_iTriangleNum*3*3];

    ObjectShapes.push_back(pShape);

    size_t _V[
3],_N[3];
   
for( size_t i = 0; i < cube.m_iTriangleNum; i++ ){
        size_t offset 
= i*6;
        _V[
0= indexArray.get(offset+0);
        _N[
0= indexArray.get(offset+1);
        _V[
1= indexArray.get(offset+2);
        _N[
1= indexArray.get(offset+3);
        _V[
2= indexArray.get(offset+4);
        _N[
2= indexArray.get(offset+5);

        offset 
= i*3*3;
        for( size_t j=0; j < 3; j++ ){
            pShape
->m_pVertices[offset+0= vertexArray.get(_V[0]*3+0);
            pShape
->m_pVertices[offset+1= vertexArray.get(_V[0]*3+1);
            pShape
->m_pVertices[offset+2= vertexArray.get(_V[0]*3+2);
            pShape
->m_pVertices[offset+3= vertexArray.get(_V[1]*3+0);
            pShape
->m_pVertices[offset+4= vertexArray.get(_V[1]*3+1);
            pShape
->m_pVertices[offset+5= vertexArray.get(_V[1]*3+2);
            pShape
->m_pVertices[offset+6= vertexArray.get(_V[2]*3+0);
            pShape
->m_pVertices[offset+7= vertexArray.get(_V[2]*3+1);
            pShape
->m_pVertices[offset+8= vertexArray.get(_V[2]*3+2);
            pShape
->m_pNormals[offset+0= normalArray.get(_N[0]*3+0);
            pShape
->m_pNormals[offset+1= normalArray.get(_N[0]*3+1);
            pShape
->m_pNormals[offset+2= normalArray.get(_N[0]*3+2);
            pShape
->m_pNormals[offset+3= normalArray.get(_N[1]*3+0);
            pShape
->m_pNormals[offset+4= normalArray.get(_N[1]*3+1);
            pShape
->m_pNormals[offset+5= normalArray.get(_N[1]*3+2);
            pShape
->m_pNormals[offset+6= normalArray.get(_N[2]*3+0);
            pShape
->m_pNormals[offset+7= normalArray.get(_N[2]*3+1);
            pShape
->m_pNormals[offset+8= normalArray.get(_N[2]*3+2);
        }
    }
}

  這樣,我們就可以使用OpenGL渲染了,

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
forint i=0; i<ObjectShapes.size(); i++ ){
    glVertexPointer(
3,GL_FLOAT,0,ObjectShapes[i]->m_pVertices);
    glNormalPointer(GL_FLOAT,
0,ObjectShapes[i]->m_pNormals);
    glDrawArrays(GL_TRIANGLES,
0,ObjectShapes[i]->m_iTriangleNum*3);
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);

  在這里可能會有疑問,為什么不使用索引的方式繪制,而是把所有的三角形全部分開,因為導出的場景向量與頂點的數(shù)目、位置都不統(tǒng)一,導致索引“顧此失彼”全然無序,雖然說可以修正,但是那樣代碼量就多了起來,而且無法應用OOCSX的方法簡化復雜幾何體。

關于調(diào)試方法

  COLLADA DOM在操作過程中幾乎都是與指針打交道,在開始不熟悉的情況下頻頻訪問違規(guī)出錯等等是很正常的,只要注意老老實實的調(diào)用getElementName()、getTypeName()、getCount()查看當前操作對象的名稱和元素數(shù)據(jù),而后逐步的找到自己需要的資源。

性能建議

  COLLADA DOM的底層使用的是SAX進行XML文件的訪問操作,構(gòu)建于LibXML2庫之上,所以我推薦從DAE文件頭開始依次處理Geometry、Visual Scene等等,減少運行庫在來回搜索的損耗。默認COLLADA DOM是靜態(tài)庫,導致鏈接后的程序著實非常巨大,所以推薦使用動態(tài)鏈接。

posted on 2008-08-28 13:39 zmj 閱讀(1102) 評論(0)  編輯 收藏 引用


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


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美va天堂va视频va在线| 欧美va天堂在线| 国产精品一二三视频| 亚洲欧美激情在线视频| 亚洲午夜久久久久久久久电影院| 亚洲国产欧美一区| 久久天堂国产精品| 91久久精品日日躁夜夜躁欧美 | 红桃视频亚洲| 欧美成人一区二区| 欧美精品一区二区高清在线观看| 一区二区三区免费在线观看| 亚洲天堂黄色| 国语自产在线不卡| 亚洲第一在线| 欧美性猛交一区二区三区精品| 亚洲一区二区在线免费观看视频| 亚洲图片在线观看| 一区二区三区自拍| 亚洲欧洲精品天堂一级| 国产精品久久国产三级国电话系列| 亚洲在线第一页| 久久激情婷婷| av成人免费在线观看| 亚洲尤物视频网| 亚洲国产一区二区在线| 一二三区精品| 亚洲福利视频免费观看| 羞羞漫画18久久大片| 久久国产精品色婷婷| 99re6这里只有精品| 亚洲在线不卡| 日韩视频在线一区二区三区| 亚洲免费一在线| 91久久在线观看| 午夜一级久久| 一本大道久久a久久精二百| 亚洲欧美日韩精品久久久久| 亚洲国产另类 国产精品国产免费| 日韩一级精品| 亚洲国产日韩欧美| 午夜精品久久久久久99热软件| 亚洲人人精品| 久久久久久欧美| 亚洲欧美一区二区三区久久| 欧美激情视频网站| 久久综合九色综合久99| 欧美图区在线视频| 亚洲国产99| 在线观看日韩精品| 牛牛国产精品| 国产偷久久久精品专区| 日韩一区二区高清| 亚洲欧洲日本国产| 久久久久久久久久久久久9999| 亚洲欧美日韩在线综合| 欧美美女喷水视频| 欧美高清在线播放| 精品99视频| 性18欧美另类| 性欧美暴力猛交另类hd| 国产精品福利片| 99国产精品久久久久老师| 亚洲精品永久免费| 欧美国产成人精品| 欧美成人免费在线| 在线观看成人小视频| 久久国产精品色婷婷| 久久精品人人做人人爽电影蜜月| 国产精品欧美精品| 亚洲视频在线观看| 亚洲欧美国产77777| 国产精品国产自产拍高清av王其| 亚洲麻豆视频| 亚洲午夜精品网| 国产精品日产欧美久久久久| 亚洲午夜激情网站| 欧美一区二区三区电影在线观看| 国产精品视频免费观看www| 亚洲午夜精品在线| 欧美一区二区三区免费看| 国产女主播视频一区二区| 亚洲永久精品大片| 久久免费观看视频| 亚洲高清网站| 欧美日韩国产综合网| 一区二区三区精品在线 | 国产自产高清不卡| 欧美在线资源| 欧美激情视频一区二区三区不卡| 亚洲精品123区| 欧美日韩国产一区| 亚洲欧美不卡| 欧美α欧美αv大片| 亚洲精品黄色| 国产精品乱码久久久久久| 亚洲欧美中文日韩v在线观看| 久久久久国色av免费看影院 | 国产精品一区二区你懂得| 亚洲男人的天堂在线aⅴ视频| 久久久久久久国产| 亚洲肉体裸体xxxx137| 国产精品毛片| 免费欧美日韩| 亚洲图片激情小说| 久久综合狠狠| 亚洲视屏一区| 国产色综合久久| 欧美第十八页| 午夜性色一区二区三区免费视频| 免费一区视频| 亚洲图色在线| 在线精品视频一区二区| 欧美日韩亚洲国产一区| 欧美一区二区免费观在线| 亚洲二区视频在线| 久久精品国产精品亚洲| 一本色道久久综合狠狠躁篇的优点| 国产日韩欧美一区在线| 欧美国产亚洲精品久久久8v| 欧美在线视频免费| 99re国产精品| 欧美激情偷拍| 久久艳片www.17c.com| 亚洲愉拍自拍另类高清精品| 亚洲日本欧美天堂| 红桃视频欧美| 国产乱码精品一区二区三区不卡| 欧美精品日韩| 免费观看国产成人| 久久九九热免费视频| 亚洲一区在线免费| 一区二区欧美日韩| 亚洲精品视频一区二区三区| 欧美成人首页| 另类尿喷潮videofree| 欧美在线3区| 亚洲欧美国产va在线影院| 在线亚洲电影| 一区二区三区久久| 一本一本a久久| 99日韩精品| 亚洲精品一区在线观看香蕉| 亚洲国内在线| 亚洲黄色免费电影| 亚洲国产一区二区三区在线播| 国产自产2019最新不卡| 国产午夜精品一区二区三区欧美| 国产精品久久二区二区| 欧美视频中文字幕在线| 欧美日韩亚洲另类| 欧美三级乱码| 国产精品伦一区| 国产欧美不卡| 韩日视频一区| 在线观看亚洲一区| 91久久视频| 一区二区三区av| 亚洲中午字幕| 久久激情综合网| 欧美成人免费va影院高清| 欧美高清视频www夜色资源网| 欧美激情第10页| 亚洲日本在线视频观看| av成人免费观看| 亚洲视频免费看| 亚洲大黄网站| 亚洲人被黑人高潮完整版| 亚洲毛片在线| 亚洲资源在线观看| 久久久久久久尹人综合网亚洲| 免费视频最近日韩| 欧美肉体xxxx裸体137大胆| 国产精品久久久久久久一区探花| 国产香蕉久久精品综合网| 在线看片欧美| 亚洲天堂第二页| 久久久精品日韩欧美| 亚洲国产精品第一区二区| 亚洲亚洲精品在线观看| 久久免费国产| 欧美日韩国产成人在线91| 国产精品亚洲美女av网站| 在线观看亚洲一区| 亚洲淫性视频| 免费在线观看一区二区| 99热这里只有精品8| 久久黄色网页| 欧美午夜精品久久久久久久| 伊人成人在线视频| 午夜精品久久久久久久99热浪潮| 老牛影视一区二区三区| 日韩系列在线| 六月婷婷久久| 国产免费观看久久| 亚洲免费精品| 久久综合狠狠综合久久综青草| 一区二区三区日韩欧美精品| 免费欧美日韩国产三级电影| 国产欧美视频在线观看|