Maya教程 :用MEL匯出3D模型
阿新 • • 發佈:2019-02-01
前面已經寫過一個Hello EGL的練習程式,手工設計和推算3D座標是非常累,非常沒有效率的,實際上我們應該使用專業的三維建模工具來製作模型。
Maya是我最喜歡的三維製作軟體,除了操作介面非常符合我的直覺外,它強大而開放的MEL及SDK也是非常重要的因素。前些日子偶遇一個在好萊塢混過三維製作的朋友說,最強悍而又符合程式設計師思維的工具是Houdini,不過還沒學習過,目前Maya是我會用的最好的3D製作工具了。可惜曾經3D高階的代名詞SGI把它賣給Autodesk了,這讓我心裡多少有些鬱悶。
Maya內部對3D場景有一個相當優美的描述,由結點連線而成的網路,這個網路可以MEL指令碼來訪問和控制,當然更可以通過SDK來利用和增強。
由於OpenGL|ES 1.x不支援QUADE,所以在為這類應用轉換模型之前,注意先將模型表面三角化:
在MEL中轉換模型的要點如下:
- 獲取當前選中的物體清單,對每個物體分別進行轉換和匯出
- string $objs[] = `ls -sl`
- for( $obj in $objs ) { ... }
- 讀取一個物體的所有的面
- string $f2v[]=`polyInfo -faceToVertex`
- 注意:這條命令在PSE版本里是不支援的,如果你是在使用這個版本學習建模的話,可能需要找一個有正式版本的朋友幫你匯出模型。
- 這條命令的結果包含很多個字串,每個字串描述一個面,其內容類似於"FACE 0: 88 64 85",如果是沒有三角化的模型,還會多出一個數字來(預設使用四邊形)。
- FACE id:後面的數字是形成該面的頂點的索引
- int $faceCount = `size $f2v`
- 對於每一個面的字串進行分析,讀取構成面的頂點索引
- for ( int $i = 0; $i < $faceCount; $i++ )
- string oneFace[]
- tokenize($f2v[$i], $oneFace)
- (int) $oneFace[2,3,4] 就得到了頂點索引 (a,b,c)
- string $f2v[]=`polyInfo -faceToVertex`
- 讀取物體所有的頂點
- int vc[] = `polyEvaluate -vertex`
- [0]是vertexCount
- 對於每一個頂點,讀取其座標
- for ( int $i = 0; $i < $faceCount; $i++ )
- string $point = $obj.vtx[$i]
- float v[] = `$pointPosition -l $point`
- ([0], [1], [2])就是(x, y, z)
- 讀取法向座標
- 對於每一個面 (參考2.2)
- 對於面的每一個頂點
- string $v = $obj.vtxFace[$f2v[$i*3 + 0,1,2]][$i]
- $i 是面的索引
- $f2v[$i*3 + 0,1,2] 分別取出第$i個面的三個頂點索引
- $obj.vtxFace[vertex][face]是一個關聯陣列或者說偽陣列
- 比較有意思的是我在Maya聯機文件裡並沒有找到這個vtxFace的說明,在網上倒有些討論,感興趣的可以之為關鍵字google之。
- string $v = $obj.vtxFace[$f2v[$i*3 + 0,1,2]][$i]
- 選中該頂點
- select -r $v
- 計算其法向
- float n[] = `polyNormalPerVertex -q -xyz`
- 取得的n[0],[1],[2]就是該頂點法向的(x,y,z)
- 恢復最初的選中狀態
- select -r $objs;
- 讀取UV座標
- 對於每一個面 (參考2.2)
- 對於面上的每一個頂點 (參考4.2)
- 選中該頂點
- 分析UV座標
- string u[] = `polyListComponentConversion -fromVertexFace -toUV`
- 如果返回陣列長度為0,則未指定UV座標
- 否則可獲取UV座標
- float uv[] = `polyEditUV -q u[0]`
- [0],[1]就是(u,v)
- 將讀取的資料寫入檔案
- 開啟檔案 int $fid = `fopen $fname "w"`
- 寫入資料 fwrite $fid $data
- 可寫入MEL能識別的各種資料型別
- string寫入後尾部會跟一個0(BYTE)
- int寫入成32位
- float寫入成64位,對應C語言裡的double
- vector將寫入三個float
- 關閉檔案 fclose $fid
有經驗的程式設計師都知道合理的程式碼重用是提高效率的好辦法,自己重頭寫一個對於掌握以上要點是有好處的,但直接找一個現成的指令碼來用顯然可以節省大量的時間,要知道,指令碼程式的除錯可是非常麻煩的。
可以直接修改MEL以輸出自己想要的格式,也可以修改程式適應匯出格式,不過我覺得兩者都太麻煩,還是再寫一個轉換程式將MEL輸出格式轉成自己認為使用較為檔案格式比較爽。