1. 程式人生 > >threejs第五篇【一條龍測試之四 threejs 給obj模型貼圖】

threejs第五篇【一條龍測試之四 threejs 給obj模型貼圖】

由於OBJ沒有紋理資訊, 需要threejs來載入外部貼圖,來指定給模型!

//模型需要紋理Texture
        var texture = new THREE.Texture();
        var loader = new THREE.ImageLoader( manager );
        loader.load( 'knotTex.png', function ( image ) {
            texture.image = image;
            texture.needsUpdate = true;
        } );
        //obj載入的類如圖:


        //obj載入,建構函式的引數是LoadingManager
        var loader = new THREE.OBJLoader(manager);
        //載入方法有4個引數,分別是obj檔案路徑,載入完畢回撥,載入進度回撥,錯誤回撥。
        //我們先把幾個回撥寫好
        //載入完畢回撥如下,載入完畢,我們做的就是把模型載入到場景中
        var onLoad = function(object){
            //載入模型如何指定Texture呢?            
            object.traverse( function ( child ) {
                if ( child instanceof THREE.Mesh ) {
                    child.material.map = texture;
                }
            } );
            scene.add( object);    
        }

我們給個載入進度吧,

使用CSS做2個塊樣式,頁面頂部div progress,顯示載入進度百分比。

<style type="text/css">
              #progress{
                margin:0; 
                line-height:40px; 
                font-weight:bold;
                color:#fff; 
                text-align:center;
                background-color:#ff0000;
            }
        </style>

主體視窗div canvas3d 顯示3D場景

<style type="text/css">
            #canvas3d{
                margin:0;
                /*border:1px solid red;*/
                width:100%;              
                height:600px;
            }
          
        </style>

另外,網頁視窗變化,3D場景比例也要適配:

//視窗變化時,3D視窗也會動態適配
    window.onresize = function(){
        var w = document.getElementById("canvas3d").clientWidth;
        var h = document.getElementById("canvas3d").clientHeight;
         
        camera.aspect = w/h;
        camera.updateProjectionMatrix();
        renderer.setSize(w,h); 
    }


完整程式碼:

<!DOCTYPE html> 
<html lang="zh-cn">
    <head>
        <meta charset="utf-8">
        <script src="../build/three.js" type="text/javascript" ></script>
        <script src="../examples/js/Detector.js" type="text/javascript" ></script>
        <script src="../examples/js/loaders/OBJLoader.js" type="text/javascript" ></script>
        <style type="text/css">
            #canvas3d{
                margin:0;
                /*border:1px solid red;*/
                width:100%;              
                height:600px;
            }
          
        </style>
        <style type="text/css">
              #progress{
                margin:0; 
                line-height:40px; 
                font-weight:bold;
                color:#fff; 
                text-align:center;
                background-color:#ff0000;
            }
        </style>
    </head>
    <body>
    <div id="canvas3d">
        <div id = "progress">
             <p></p>
        </div>       
    </div>
    <script type="text/javascript">



    if(Detector.webgl){
        //alert('瀏覽器支援');
        //瀏覽器支援,我們就做初始化工作。不然js處理半天,瀏覽器不支援也白搭
        
        init();
        animate();


    }else{
        alert('瀏覽器不支援');
    }


    var scene,camera,renderer;
   


    //初始化
    function init(){
        var w = document.getElementById("canvas3d").clientWidth;
        var h = document.getElementById("canvas3d").clientHeight;


        scene = new THREE.Scene();
        
        camera = new THREE.PerspectiveCamera(45,w/h,0.1,1000);
        camera.position.z= 250;
        var directionalLight = new THREE.DirectionalLight( 0xffeedd );
        directionalLight.position.set( 0, 0, 1 );
        scene.add( directionalLight );
        renderer = new THREE.WebGLRenderer();
        //下面setSize()可以不寫,畫面也會顯示預設指定300*150的大小,很小。所以肯定要手動設定一下大小
        
        renderer.setSize(w,h);
        renderer.setClearColor(0xf0f0f0);
        //別忘記了這個要寫滴...不然就真看不見畫面。
        document.getElementById('canvas3d').appendChild(renderer.domElement);


        //開始模型匯入的一些工作
        //我們看看官方提供的OBJLoad.js指令碼的建構函式
        //建構函式的引數是一個manager,這是什麼呀?看到圖中他是整合自THREE.DefaultLoadingManager,
        //
        //然後我們去three.js裡面DefaultLoadingManager看看是什麼?看到了,是LoadingManager物件;
        //
        //裡面搜了一遍,沒有找到LoadingManager的類,我們再看看three.module.js
        //在這裡發現了function LoadingManager( onLoad, onProgress, onError ) {...}
        //這個管理器有
        //接下來我們宣告一個LoadingManager
        var manager = new THREE.LoadingManager();     
        
        //模型需要紋理Texture
        var texture = new THREE.Texture();
        var loader = new THREE.ImageLoader( manager );
        loader.load( 'knotTex.png', function ( image ) {
            texture.image = image;
            texture.needsUpdate = true;
        } );
        //obj載入的類如圖:


        //obj載入,建構函式的引數是LoadingManager
        var loader = new THREE.OBJLoader(manager);
        //載入方法有4個引數,分別是obj檔案路徑,載入完畢回撥,載入進度回撥,錯誤回撥。
        //我們先把幾個回撥寫好
        //載入完畢回撥如下,載入完畢,我們做的就是把模型載入到場景中
        var onLoad = function(object){
            //載入模型如何指定Texture呢?            
            object.traverse( function ( child ) {
                if ( child instanceof THREE.Mesh ) {
                    child.material.map = texture;
                }
            } );
            scene.add( object);    
        }
        //載入過程,可以顯示進度值
        var onProgress = function ( xhr ) {
            if ( xhr.lengthComputable ) {
                var percentComplete = xhr.loaded / xhr.total * 100;
                console.log( Math.round(percentComplete, 2) + '% downloaded' );
                document.getElementById('progress').innerText= Math.round(percentComplete, 2) + '%下載' ;
            }
        };
        //錯誤回撥,因為網頁除錯有報錯,這裡可以不做處理
        var onError = function ( xhr ) {


        };
        //回撥寫好了,現在可以用載入的方法載入模型了。
        loader.load('knot.obj',onLoad,onProgress,onError);           
    }
    
    //視窗變化時,3D視窗也會動態適配
    window.onresize = function(){
        var w = document.getElementById("canvas3d").clientWidth;
        var h = document.getElementById("canvas3d").clientHeight;
         
        camera.aspect = w/h;
        camera.updateProjectionMatrix();
        renderer.setSize(w,h); 
    }
    // 渲染
    function render(){
        renderer.render(scene,camera);
    }
    //迴圈渲染
    function animate() {
        requestAnimationFrame( animate );
        render();
    }


    </script>
    </body>
</html>