美文网首页Three.jsThree.jsWEB前端开发技术杂谈
THREE.js中加载不同格式的模型及动画(fbx、json和o

THREE.js中加载不同格式的模型及动画(fbx、json和o

作者: hotyann | 来源:发表于2017-10-17 17:06 被阅读1149次

    注:本文章内容基于 Three.js 88dev 实现

    作为刚接触three.js的小萌新,励志将自己开荒历程记录下来,希望对后来人有所帮助。
    网上有很多demo,文档却不多。每次都是,照搬别人的数据没问题,换成自己的模型/动画总会报错! (╯‵□′)╯︵┻━┻
    多次踩坑后,总结出三种常用格式的加载方法。

    1、fbx文件

    three.js有官方的fbx插件,可以直接将模型加载至网页,并且支持动画数据,代码量也是最少的。
    但是,该格式存在很大弊端:插件对文件格式的规范很严格,换言之,插件支持性不太好。从网上下载的fbx动画,十有八九会加载失败。

    首先需要引入FBXLoader.js插件,如果报错 “Error: THREE.FBXLoader: External library Inflate.min.js required, obtain or import from https://github.com/imaya/zlib.js,则还需引入inflate.min.js文件。

    var fbx_loader = new THREE.FBXLoader(manager);
    

    1.1、静态模型

    fbx_loader.load('./models/miku/miku.fbx', function(object) {
        object.scale.multiplyScalar(.1);    // 缩放模型大小
        scene.add(object);
    }, onProgress, onError);
    
    fbx静态模型

    1.2、动画

    fbx_loader.load('./models/gf/run.fbx', function(object) {
        object.mixer = new THREE.AnimationMixer(object);
        mixers.push(object.mixer);
        var action = object.mixer.clipAction(object.animations[0]);
        action.play();
        object.scale.multiplyScalar(.5);
        scene.add(object);
    }, onProgress, onError);
    
    fbx动画
    1、如果遇到报错 “URIError: URI malformed”,说明fbx文件格式不符合插件要求。可能是fbx版本过低导致的。

    检测方法:
    新版blender导入该fbx文件,如果提示 “Version xxxx unsupported, must be xxxx or later”,说明你的模型文件版本太低。

    解决方案有俩:
    (1)导入3dmax,再重新导出成fbx文件,将低版本转换为最新版本。经实践,虽然在3dmax和blender中动画显示正常,但是载入网页后模型变得支离破碎。可能是坐标丢失,目前还在寻找原因及解决办法。


    fbx低版本转高版本后,坐标丢失

    (2)用官方提供的插件将fbx文件转换成json动画数据。

    2、如果遇到报错 “TypeError: Cannot read property 'has' of undefined”,同样是因为模型文件不符合规范。

    检测方法:
    Chrome Devtools断点调试,你会发现很多参数都是undefined。

    解决方案:
    同上二。

    2、json文件

    three.js自带了加载json的方法,所以不需要额外引用插件。

    Three.js展示模型问题总结 中讲到:

    现在的JSON格式有两个类型,一个是Geometry类型,需要JSONLoader加载;一个是Object类型,需要ObjectLoader加载。

    用错loader.js的话,会报错 “THREE.ObjectLoader: Can't load xxx.json. Use THREE.JSONLoader instead.” 或者 “THREE.JSONLoader: xxx.json should be loaded with THREE.ObjectLoader instead.”

    2.1、静态模型

    2.1.1、Geometry类型
    var js_loader = new THREE.JSONLoader(manager);
    
    js_loader.load('./models/hmj/frame001.json', function(geometry, materials) {
        var material = new THREE.MultiMaterial(materials);    // 多个纹理
        var mesh = new THREE.Mesh(geometry, material);
        mesh.scale.multiplyScalar(.06);
        scene.add(mesh);
    }, onProgress, onError);
    
    json静态模型 - Geometry类型
    2.1.2、Object类型
    var object_loader = new THREE.ObjectLoader(manager);
    
    object_loader.load('./models/teapot-claraio.json', function(object) {
        object.scale.multiplyScalar(5);
        scene.add(object);
    });
    
    json静态模型 - Object类型

    下面给出两种数据类型的区别:


    Geometry类型
    Object类型

    2.2、动画

    var js_loader = new THREE.JSONLoader(manager);
    
    js_loader.load('./models/body/climb.js', function(geometry, materials) {
        for(var i = 0; i < materials.length; i++) {
            materials[i].skinning = true;
        }
        var material = new THREE.MultiMaterial(materials);
        var mesh = new THREE.SkinnedMesh(geometry, material);    // 划重点啊!!!
        var mixer = new THREE.AnimationMixer(mesh);
        mixer.clipAction(geometry.animations[0]).play();
        mixers.push(mixer);
        mesh.scale.multiplyScalar(.05);
        mesh.lookAt(new THREE.Vector3(0, 0, 0));
        scene.add(mesh);
    }, onProgress, onError);
    
    json动画

    说到json格式动画,一把辛酸泪(╥﹏╥)。从动画制作到maya导出,再到网页载入,无不有坑。

    1、由于不了解three.js的数据需求,动画制作方用maya插件advancedSkeleton进行绑骨,导致动画可以展示,数据却导出不来,只能自掏腰包重做。
      制作动画时,切记要做成能导出fbx格式的。

    2、用maya做动画,虽然官方有提供maya转three.js的插件,不过导出数据时,还是碰到了不少问题。
      maya2016用官方插件报错 “IOError: file C:\Program Files\Autodesk\Maya2016\bin\python27.zip\shutil.py line 82: 2”Maya 导出动画到THREE.js 的博主给出修改后的插件,亲测可以使用。然而还是不可避免地掉了坑。
      Maya导出动画到THREE.js(补充) 对修改后的插件进行了总结,其中隐藏网格和报错 “More than 4 influences on a vertex in xxx” 的问题我这边也遇到了。

    当然,以上两个bug最直接有效的解决办法是,在做动画时就让设计师删除隐藏网格并导出可用的fbx文件。

    3、json动画载入网页时,报错 “THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.”,google了好久才查出,是因为自己创建的不是骨骼蒙皮网格对象(代码划重点部分)。
      从3dMax导出供threeJS使用的带动作... 里 “代码中如何加载动态模型” 有具体讲解。

    3、obj文件

    obj格式文件不支持动画数据存储,只用于静态模型。

    首先需要引入OBJLoader.js插件,如果纹理贴图是tga或dds格式的,则还需要另外引入TGALoader.js或DDSLoader.js(纹理贴图问题同样适用于其他模型格式)。

    var obj_loader = new THREE.OBJLoader(manager);
    obj_loader.setPath('./models/mooncake/');    // 设置文件路径
    

    自己总结了两种加载方法。

    3.1、外部载入纹理

    官方文档 - MeshPhongMaterial

    var tga_loader = new THREE.TGALoader();
    var material = new THREE.MeshPhongMaterial({
        map: tga_loader.load('./models/mooncake/Diffuse.tga'),
        normalMap: tga_loader.load('./models/mooncake/Normal.tga'),
        specularMap: tga_loader.load('./models/mooncake/S.tga'),
        bumpMap: tga_loader.load('./models/mooncake/Bump.tga')
    });    // 存在多个纹理材质,具体参数查看[官方文档 - MeshPhongMaterial]
    
    obj_loader.load('mooncake.obj', function(group) {
        var geometry = group.children[0].geometry;
        geometry.attributes.uv2 = geometry.attributes.uv;
        geometry.center();
        var mesh = new THREE.Mesh(geometry, material);
        mesh.scale.multiplyScalar(.1);
        scene.add(mesh);
    }, onProgress, onError);
    
    obj静态模型 - 外部载入纹理

    3.2、obj+mtl

    需要额外引用MTLLoader.js文件

    THREE.Loader.Handlers.add(/\.tga$/i, new THREE.TGALoader());    // 划重点!
    var mtl_loader = new THREE.MTLLoader();
    mtl_loader.setPath('./models/mooncake/');
    
    mtl_loader.load('mooncake.mtl', function(materials) {
        materials.preload();
        obj_loader.setMaterials(materials);
    
        obj_loader.load('mooncake.obj', function(object) {
            object.scale.multiplyScalar(.1);
            scene.add(object);
        }, onProgress, onError);
    });
    
    obj静态模型 - obj+mtl
    一开始打算用obj+mtl方法加载obj模型,但由于项目是tga格式贴图,参考大佬的代码,却怎么都显示不了纹理,最后放弃转而琢磨出第一种方法来。
    后来偶然看到THREE.Loader.Handlers.add(/\.tga$/i, new THREE.TGALoader());这句代码。经实践,果然能载入某些不常用格式的纹理材质。




    以上就是自己总结的一些经验,欢迎小伙伴留言讨论ε=ε=(ノ≧∇≦)ノ

    相关文章

      网友评论

      • Simon_s:楼主大大,你的坐标丢失的问题,目前解决了吗?遇到同样的问题了
        hotyann:用fbx_converter_2013把旧版本的fbx转成可支持的fbx文件,我目前是这样做的

      本文标题:THREE.js中加载不同格式的模型及动画(fbx、json和o

      本文链接:https://www.haomeiwen.com/subject/zrjduxtx.html