1. 程式人生 > >【three.js : 3D】【load】threejs:3D模型匯入問題

【three.js : 3D】【load】threejs:3D模型匯入問題

 

轉載:threejs:3D模型匯入問題

想想複雜的模型就交給3D設計師進行創作,而我們開發時只需引入模型檔案,是不是很美滋滋?

當然,如果你時間充裕,又對模型創作感興趣,那你確實可以花時間好好學習3D建模軟體的使用,這樣以後就可以自己建立所需模型,由自己匯出與匯入模型檔案。因為從建模軟體匯出模型的過程中,其實有特別多的坑,一個不小心,匯出的模型可能就大相徑庭。所以依賴於別人匯出的模型檔案,有時你都不知道到底問題出在哪裡。

一、Threejs支援的常見匯出模型的檔案格式有哪些?

JSON(*.js/ *.json):專門為Three.js自己設計的JSON格式,你可以使用它以宣告的方式定義模型,及模型材質和動畫。

OBJ和MTL(*.obj/ *.mtl):OBJ是一種簡單的三維檔案格式,只用來定義物件的幾何體。MTL檔案通常和OBJ檔案一起使用,在一個MTL檔案中,定義物件的材質。

Collada (*.dae):用來定義XML類檔案中數字內容的格式。差不多所有的三維軟體和渲染引擎都支援這個格式。

STL (*.stl):立體成型術 。 廣泛用於快速成型。例如,三維印表機的模型檔案通常是STL檔案。Three.js有一個可定製的STL匯出工具,STLExporter.js。可以將Three.js中的模型匯出到一個STL檔案。

FBX (*.fbx):是FilmBoX這套軟體所使用的格式,其最大的用途是用在諸如在max、maya、softimage等軟體間進行模型、材質、動作和攝影機資訊的互導,因此在建立三維內容的應用軟體之間具有無與倫比的互用性。

CTM (*.ctm):由openCTM建立的格式。可以用來壓縮儲存表示三維網格的三角形面片。

VTK(*.vtk):Visualization Tookit 定義的檔案格式,用來指定頂點和麵。VTK有兩種格式,Three.js支援舊的格式,即Asscii格式。

PDB(*.pdb):特別的資料格式,由 蛋白質資料銀行 場景,用來定義蛋白質的形狀。Three.js可以載入並顯示這種描述格式的蛋白質。

PLY (*.ply):多邊形檔案格式。通常儲存三維掃描器的資料。

二、Threejs中匯入以上外部模型檔案所需的輔助函式是哪些?

threejs中匯入外部檔案所需的輔助函式都在https://github.com/mrdoob/three.js/tree/dev/examples/js/loaders下可以找到。這裡除了JSON模型檔案的匯入外,其餘模型檔案都需要引用其對應名稱的輔助函式。例如:匯入OBJ格式的模型,除了匯入必要的three.js檔案外,還需要在介面中引用OBJLoader.js檔案。而JSONLoader函式整合在three.js中,所以無需再匯入其他輔助檔案!

三、3D軟體匯出的模型檔案可以解析哪些東西呢?

可解析出網格(模型)的有:JSON, STL, OBJ

可解析出模型材質的有:JSON, MTL

可解析出模型動畫的有:FBX, DAE, JSON

理解就是,如:匯出的json檔案既可以存物體的模型,也可以存其材質及動畫資訊。

四、Threejs中幾個常用模型檔案匯入示例

4.1 JSON格式檔案匯入——使用JSONLoader函式

// 例項化一個JSONLoader類
var loader = new THREE.JSONLoader();
// 匯入資源
loader.load(    
   // 匯入的模型檔案所在 URL    
   'models/animated/monster/monster.js',    
    // 資源載入成功後執行的函式       
      //@params geometry  傳入的模型,只能是單個模型,不能是一個場景      
      // @params materials  傳入的材質,是個陣列     
    function ( geometry, materials ) {       
          var material = materials[ 0 ];  
           var object = new THREE.Mesh( geometry, material );     
           scene.add( object );
     });


敲黑板!!!!!前面已經講過,obj格式檔案都是和mtl格式檔案搭配使用,因為obj格式的檔案只能存模型,不能存模型材質和動畫,而材質都存於mtl檔案中。4.2 OBJ格式檔案匯入——使用OBJLoader函式

4.2.1 當只匯入模型,不匯入材質,模型的材質由匯入後用程式碼定義

//圖片載入loader

var texture = new THREE.Texture();

var loader = new THREE.ImageLoader( );

    //匯入資源

    loader.load(

           //材質圖片所在url

            'textures/UV_Grid_Sm.jpg',

              function ( image ) {

                    texture.image = image;

                    texture.needsUpdate = true;

        } );

//obj檔案載入loader

var loader = new THREE.OBJLoader( );

 //匯入資源

  loader.load(

 //obj模型所在url

              'obj/male02/male02.obj',

 // 資源載入成功後執行的函式

               //@params object 傳入的模型,只能是單個模型,也可能是一個group,視構建的model而定

               function ( object ) {

//taverse函式為遍歷object的每個子mesh,傳入的child為每個mesh

                //該示例中的object為一個group,有多個mesh組成

            object.traverse( function ( child ) {

               if ( child instanceof THREE.Mesh ) {

                       child.material.map = texture;

                 }

            } );

            object.position.y = - 95;

            scene.add( object );

        });

4.2.2 當既匯入模型,又匯入材質時

 

//當mtl中引用了dds型別的圖片時,還需匯入DDSLoader檔案。

//這裡的src路徑視實際開發而定

<script src="js/loaders/DDSLoader.js"></script>

<script src="js/loaders/MTLLoader.js"></script>

<script src="js/loaders/OBJLoader.js"></script>





THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );



var mtlLoader = new THREE.MTLLoader();

//設定路徑,也可不是設定,在load中載入完整路徑也可

    mtlLoader.setPath( 'obj/male02/' );

    mtlLoader.load( 'male02_dds.mtl',

 // 資源載入成功後執行的函式

             //@params materials THREE.MTLLoader.MaterialCreator

                      function( materials ) {

                materials.preload();

                var objLoader = new THREE.OBJLoader();

                    objLoader.setMaterials( materials );

                    objLoader.setPath( 'obj/male02/' );

                    objLoader.load( 'male02.obj', function ( object ) {

                        object.position.y = - 95;

                        scene.add( object );

                    });

                });

https://threejs.org/examples/ 中的loader/*部分4.3 其他模型檔案匯入類似,具體可參考官網examples

五、常見問題

模型匯出為obj格式後,檔案太大,想將其轉化為json格式以減少檔案大小。那麼該怎樣操作呢?

threejs R86版本中,有convert-to-threejs.py這樣一個python檔案,該檔案的作用是將模型檔案(.fbx,.dae, .obj, .3ds)轉換成json格式。詳細地轉換操作可參考以下連結文章:

convert_to_threejs.py 使用配置

注意事項:

對以上鍊接文章做個小補充,這裡箭頭所引入的python版本最好一致,反正我當時不一致好像最後轉化出bug了。

雖然threejs R86仍然保留convert-to-threejs.py,但是該檔案作者已很久沒維護,處於已過時的檔案。所以即便成功將obj轉換成json檔案,仍有存在json檔案不可用的情況(就問你絕不絕望??)。筆者在開發的過程中,就遇到該問題:成功轉換成json檔案後,用JSONLoader匯入該檔案後報錯,因為轉換後的json檔案中“type“型別為”scene“,因此既不符合JSONLoader,也不符合ObjectLoader的匯入格式要求。查詢相關資料,發現有許多小夥伴也遇到過這種bug,暫時沒找到解決方法。如果有大大發現,請務必分享下解決方案,萬分感謝!

2. 如何用Threejs匯入基於JSON格式的場景檔案?

所謂場景檔案,也就是檔案中列出了各個物體和變換層級,以及所有的材質,紋理,相機和光源資訊。講道理,如果成功匯入一個場景檔案後,進行基本渲染就可以檢視整個3D場景了。之前threejs的版本中進行場景渲染呼叫THREE.SceneLoader即可,不過現在threejs R86版本已用THREE.ObjectLoader替代。

給個簡單示例:

//@params url  場景檔案所在路徑

new THREE.ObjectLoader().load( url, function ( loadedScene ) {

                scene = loadedScene;

// If the loaded file contains a perspective camera, use it with adjusted aspect ratio...

        scene.traverse( function ( sceneChild ) {

                if ( sceneChild.type === 'PerspectiveCamera' ) {

                    camera = sceneChild;

                    camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;

                    camera.updateProjectionMatrix();

                    }

                } );