從3dMax導出供threeJS使用的帶動作模型與加載


評論區發現的建議,最近沒空測試,先貼這

 

 還有好多人說找不到插件的 https://pan.baidu.com/s/1Q5g0... 密碼:b43e 。 應該是他們現在只是維護blender,只有這個的插件,不如改用blender?

在自己做的一個小玩意中,發現要從3dMax中導出js文件供給threeJS使用,真是太多坑了!所以打算詳細記錄一下方法,好像開發會3dMax的比較少,但是至少可以幫助開發與美工更好的溝通與交流。在文末,我會附上一個可加載的js模型,方便學習~

導出文件類型選型

在《THREE.JS開發指南》2015年第一印第一版中提及的支持的模型主要有一下幾種

 圖中的確是一些常見格式,我們可以通過這個表格對常見格式做一些了解,但是我們從Three.js的官方實例的Loaders包中可以看到,發現他現在提供了各種加載器來支持文件加載,我們可以根據我們的需求來選擇我們需要的加載方式

與3dmax自帶的導出選擇相比較,可以導出.FBX,Collada,STL,OBJ和MTL等文件,然后使用對應的Loader進行加載。我們可以選擇自己熟悉的工具,熟悉的格式進行模型的導出,但是也正是由於他的多樣性,導致無從下手,在嘗試了Blender導出動作模型,與DDS素材轉換等等工具之后,最終決定采用,我較為熟悉3dMax為建模工具,來導出我最熟悉的js文件來完成模型的導出與加載

下面是我經過實驗后對一些常見格式的記錄與分析大致統計出的一些選型分析

 

如果不需要做那么多選型的話,直接導出js好了~各方面都比較合適。

如何導出動態模型的js文件

安裝3dMax導出插件

 .OBJ導出來的僅僅是模型,.MTL導出來的僅僅是材質,那動作呢?js在Three.js中支持的動作導出,在3dmax,maya,blender中並沒有直接導出js的方法,慶幸的是大牛已經給我們開發了越來越豐富的插件了。在utils中的export中包含了這些插件(文件目錄.\three.js-master\three.js-master\utils\exporters\max),我們需要將這些插件直接復制到3dmax的plugin文件夾中,如果都是需要導出包含動作的,只需要安裝ThreeJSAnimationExporter.ms這一個文件就夠了,重啟3dmax后打開就可以看到這個插件了。(如下圖)

如何獲取一個可加載模型(以一個簡單的圓柱體為例)

  1. 首先你的模型必須是一個整體,比如你的模型是熊貓吃竹子,如果你的熊貓和竹子要一塊導出,那么你的熊貓和竹子必須是一個整體
  2. 貼圖只能有一張,且貼圖是png格式
  3. 給bone(骨骼)認真命名,js導出后你可能會發現骨骼有點偏移與錯位,嚴格的命名有助於你在建模或者導出的時候進行修改,不過對開發來說這點會比較麻煩,這點也不是必須的。
  4. 模型的每一個點都必須賦予權重,如果發生破面行為,那么非常有可能是加了動作的模型卻有的店沒有權重
  5. 骨骼測試可用的有bone和CS骨骼,如果采用其他骨骼最好進行測試
  6. 導出的時候你的模型必須是一個Mesh,非常重要!這就意味着你不能導出一個可編輯多邊形或者其他形式,在我們添加skin修改器的時候,先添加一個EditMesh修改器在我們的物體上,如果你已經是一個editable mesh,那這就不需要了。最好再使用Unwrap, UVW,中途出現warning點確定就好。

 導出的時候選擇模型就好,不要選擇骨骼,如果把骨骼一起選擇導出會出現如下錯誤

 

 添加一個XForm修改器於你的模型當你開始導出之前,他會重置你物件的位置,轉向等等,將它變為初始那樣,最小化在導出時可能遇到的問題

 

  1. 如果發生錯誤,修復完畢后需要重新啟動3dmax才能正常使用導出插件
  2. 可以先驗證模型導出的數據量和點格式的正確與否再進行加載,一般導出文件的貼圖地址會與你的地址不同,需要打開導出文件(如下圖)修改貼圖對應地址

  1. 加載過程中你有可能看不見模型,那么很有可能是你的模型過大或者過小,可以直接在代碼中用scale函數進行調整測試
  2. 如果還有問題,建議在重復以上幾點查看一遍

代碼中如何加載動態模型

在程序中主要是這幾個步驟

下面是代碼的部分節選,其實官方的教程例子寫的很完整,之后把一個完整可運行的實例傳在GIt上~

/**
 * @method animateModel
 * @description 
 *  一個創建帶動畫模型的方法
 * @param {object} object.g 幾何體 object.m 材質  object.name 名字
 */
var zz;
var animateModel = function(config) {
    var geometry = config.g;
    var materials = config.m;
    for (var i = 0; i < materials.length; i++) {
        var m = materials[i];
        m.skinning = true
    }

    // 創建材質,由於材質是多面材質,由材質數組組成故要調用MultiMaterial方法來創建一個新的材質
    var material = new THREE.MultiMaterial(materials);
    //創建出一個骨骼帶蒙皮的網格對象
    var mesh = new THREE.SkinnedMesh(geometry, material);
    //給這個網格模型增加他的屬性
    mesh.name = config.name;
    // 初始化模型位置
    mesh.position.set(0, 0, 0);
    mesh.geometry.computeVertexNormals();

    //用你的網格模型去創建一個骨骼幫助器 
    var skeletonHelper = new THREE.SkeletonHelper(mesh)
    skeletonHelper.material.linewidth = 3;
    // 我們可以打開skeletonHelper,這樣可以看到骨骼,便於調整
    skeletonHelper.visible = true;
    //將骨骼添加到場景
    scene.add(skeletonHelper);

    // AnimationMixer 動畫混合器 理解為這個動畫各方面的一個管理者吧
    var mixer = new THREE.AnimationMixer(mesh);
    // 骨骼動畫的動作片段保存在geometry中 下面是讀取第一個動畫的方式,所以animationFirst是一個AnimationClip
    var firstAnimation = geometry.animations[0];
    // AnimationAction是動作的schedule,之所以叫schedule是因為他可以控制着動畫開始 結束 停止 這些流程
    var action = mixer.clipAction(firstAnimation);

    // 接下來可以為這個動畫配置一些細節了
    action.clampWhenFinished = false;
//  0會停止,這里設置為0默認停止,不停要注意其他的地方是否有設置這個值,值越大越快
    action.setEffectiveTimeScale(0);
    action.play();
    mesh.mixer = mixer;
    mesh.action = action;
    mesh.skeletonHelper = skeletonHelper;
    return mesh;
}

//加載模型數據
var loader = new THREE.JSONLoader();
loader.load("static/img/model/czz3.js", function(geometry, materials) {
    var config = { name: "zz", g: geometry, m: materials };
                zz = animateModel(config);
                zz.status = 1;
                zz.action.time = 0;
                zz.action.setEffectiveTimeScale(0.7);
                zz.rotation.set(-26, 0, 0);
                zz.scale.set(7, 7, 7)
                zz.visible = true;
                scene.add(zz);
                addAnimateModel.animate();
                console.log(TWEEN.Tween)
                var zz_tween = new TWEEN.Tween(jichan.position).to({ z: 20 }, 10000)
                zz_tween.repeat(Infinity);
                zz_tween.start()
});
//主要理解render和animate這兩個函數,模型能載入,缺動不起來主要都是這個袁術
var clock = new THREE.Clock();
function render() {
    // if (animation) animation.update(delta);
    var r = Date.now() * 0.0005;
    var delta = clock.getDelta();
    zz.mixer.update(delta);
    zz.skeletonHelper.update();
    stats.update();
    renderer.render(scene, camera);
}
function animate() {
    render();
    requestAnimationFrame(animate);
    trackBallControl.update();
}

靜態模型的導出與加載

靜態模型的導出,對我而言用3dmax直接導出obj最簡單了,用導出OBJ和MTL格式,如果只要選擇導出不帶貼圖的模型,那么在Material這一欄的Create mat-library則不用勾選.

require('OBJLoader.js')
require('MTLLoader.js')

/**
 * 加載一個有貼圖模型
 */
const createMtlObj = argv => {

    THREE.Loader.Handlers.add(/\.dds$/i, new THREE.DDSLoader());
    //創建材質加載器
    let mtlLoader = new THREE.MTLLoader();
    // 設置材質加載路徑 (相對路徑)
    mtlLoader.setPath(argv.mtlPath);

    mtlLoader.load(argv.mtlFileName, function(materials) {
        materials.preload();
        let objLoader = new THREE.OBJLoader();
        objLoader.setMaterials(materials);
        objLoader.setPath(argv.objPath);
        objLoader.load(argv.objFileName, function(object) {
                // 加載模型完成后的回調函數
                if (typeof argv.completeCallback === 'function') {
                    argv.completeCallback(object);
                }
            },

            // 加載中
            function(xhr) {
                if (xhr.lengthComputable) {
                    var percentComplete = xhr.loaded / xhr.total * 100;
                    console.log(Math.round(percentComplete, 2) + '% downloaded');
                }
            },
            function(error) { console.log('error:' + error) }
        );
    });

}

一個js動態模型文件——一頭不嚇人的蜘蛛

太長了,鏈接: https://pan.baidu.com/s/1boI98hL 密碼: ethr

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM