10 Loaders加载模型到Three.js

2018-10-08 17:19:08 专注前端30年 阅读数 3049更多

分类专栏: 达人课 three.js 基础入门

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/qq_30100043/article/details/80979604

现在市面上的3D模型有上百种,每一种的格式都有不同的用途,不同的功能和复杂程度。尽管Three.js提供了很多的加载器,但选择正确的格式和工作流程将在以后节省时间和成本。而且某些格式难以使用,效率低下或者目前还未完全支持。

推荐使用的模型格式

官方推荐我们使用的3D模型的格式为glTF,由于glTF专注于传输,因此它的传输和解析的速度都很快。glTF模型功能包括:网格,材质,纹理,蒙皮,骨骼,变形动画,骨骼动画,灯光以及相机。

如果当前的首选不是glTF格式,那么推荐Three.js定期维护并且流行的格式FBX,OBJ或者COLLADA格式,Three.js也有自己独有的JSON格式。我们接下来将介绍这五种格式:

Three.js的JSON格式

这里的JSON格式指的是Three.js可以将其转换为场景的3D对象的JSON格式模型。这种格式内部一般必有的四项为:

metadata 当前模型的相关信息以及生成的工具信息

geometries 存储当前模型所使用的几何体的数组

materials 存储当前模型所使用的材质的数组

object 当前模型的结构以及标示所应用到的材质和几何体标示

所有的模型网格,几何体和材质都有一个固定的uuid标识符,JSON格式中都是通过uuid作为引用。

3d对象转成JSON

所有的THREE.Object3D对象都可以转成JSON字符串保存成为文件,我们不能直接将对象转成JSON是因为JSON是无法保存函数的,所以,Three.js给我们提供了一个toJSON()的方法来让我们转换为可存储的JSON格式。

var obj = scene.toJSON(); //将整个场景的内容转换成为json对象

var obj = group.toJSON(); //将一个模型组转成json对象

var obj = mesh.toJSON(); //将一个模型网格转成json对象

var JSONStr = JSON.stringify(obj); //将json对象转换成json字符串

1

2

3

4

按照这种方式,我们就可以将生成的场景模型保存为文件。

使用ObjectLoader加载JSON模型

既然我们能够导入,肯定就可以导入。这里我们将使用到Three.js内置的对象THREE.ObjectLoader来加载模型:

直接加载Three.js生成的JSON对象:

var obj = scene.toJSON(); //将整个场景的内容转换成为json对象

let loader = new THREE.ObjectLoader(); //实例化ObjectLoader对象

let scene = loader.parse(obj); //将json对象再转换成3D对象

1

2

3

4

加载外部的JSON文件:

let loader = new THREE.ObjectLoader(); //实例化ObjectLoader对象

//加载模型,并在回调中将生成的模型对象添加到场景中

loader.load("../js/models/json/file.json", function (group) {

    scene.add(group);

});

1

2

3

4

5

6

案例地址:点击这里

案例的右上角有四个点击事件:

添加模型:将在场景内随机生成一组立方体,每次都不相同。

导出模型:将场景内这一组立方体可以导出到本地json文件。

导入模型:可以将选择的符合JSON文件解析并导入到场景内。

加载模型:将加载服务器上面的一个JSON文件。

案例代码地址:点击这里

glTF格式文件导入

glTF格式的3D格式文件是官方推荐的使用的格式,这种格式的文件我们可以在sketchfab官网下载,这是一个国外比较知名的模型网站,下载地址是:点击这里,我们可以在这里下载一些免费的glTF格式的模型。

这里我在官网上随便找了一个不错的模型做了一个案例:点击这里

模型加载的速度会有些慢,大家可以等待一下便能够看到这个小汽车。

接下来我们便讲解一下加载glTF模型的流程:

首先,将GLTFLoader加载器插件引入到页面,插件在官方包的地址/examples/js/loaders/,一些文件的导入插件都在这一个文件夹内,大家有兴趣可以研究一下:

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

1

然后创建一个加载器:

var loader = new THREE.GLTFLoader();

1

使用加载器去加载模型,并调节一下模型大小在场景内展示:

loader.load('../js/models/gltf/scene.gltf', function (gltf) {

    gltf.scene.scale.set(.1,.1,.1);

    scene.add(gltf.scene);

});

1

2

3

4

我们需要有时候不明白的是,我加载了一个模型,哪一部分是需要导入场景的模型呢?

这里我们可以先将解析的出来的模型对象打印一下,然后通过查看对象属性来了解到底是导入场景内的对象,就比如glTF模型转换出来的对象的scene属性就是需要导入场景的对象,而JSON格式的模型是直接可以导入的对象。

模型加载案例源码:点击这里

FBX模型导入

FBX最大的用途是用在诸如在max、maya、softimage等软件间进行模型、材质、动作和摄影机信息的互导,这样就可以发挥max和maya等软件的优势。可以说,FBX方案是最好的互导方案。

接下来我们看一下FBX模型导入的案例,这是我在网上随便下载的一个FBX格式的模型,导入到场景内的效果,案例查看地址:点击这里

实现过程:

首先我们需要导入FBXLoader插件,并且还需要额外增加一个解析二进制文件的插件inflate.min.js,不导入这个文件的话,除了一些字符串存储的FBX格式,别的格式都会报错:

<script src="../js/loaders/inflate.min.js"></script>

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

1

2

创建FBX加载器

var loader = new THREE.FBXLoader();

1

修改模型大小,并设置每个模型网格可以投射阴影:

loader.load('../js/models/fbx/file.fbx', function (fbx) {

    fbx.scale.set(.1,.1,.1);

    fbx.traverse(function (item) {

      if(item instanceof THREE.Mesh){

          item.castShadow = true;

          item.receiveShadow = true;

      }

    });

    scene.add(fbx);

});

1

2

3

4

5

6

7

8

9

10

这样就实现了FBX模型的导入。

案例源码地址:点击这里

OBJ格式模型导入

OBJ文件是3D模型文件格式。由Alias|Wavefront公司为3D建模和动画软件"Advanced Visualizer"开发的一种标准,适合用于3D软件模型之间的互导,也可以通过Maya读写。

OBJ文件是一种文本文件,可以直接用写字板打开进行查看和编辑修改,但不包含动画、材质特性、贴图路径、动力学、粒子等信息。

OBJ文件的导出通常会和MTL格式一同导出,MTL作为OBJ文件的附属文件,却有着OBJ文件需要贴图材质,所以,我们通常使用时,将它们两个文件一同导入。

这是我使用官网提供的一个模型制作的一个案例,查看地址:点击这里

实现导入的过程:

首先,我们需要将OBJLoader插件和MTLLoader插件引入页面:

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

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

1

2

实例化MTLLoader:

//创建MTL加载器

var mtlLoader = new THREE.MTLLoader();

//设置文件路径

mtlLoader.setPath('../js/models/obj/');

1

2

3

4

如果有需要,我们还可以设置纹理文件夹地址:

//设置纹理文件路径

mtlLoader.setTexturePath('../js/models/obj/');

1

2

加载MTL文件,并在文件加载成功后,创建OBJLoader并设置对象应用当前的材质:

//加载mtl文件

mtlLoader.load('female02.mtl', function (material) {

    //创建OBJ加载器

    var objLoader = new THREE.OBJLoader();

    //设置当前加载的纹理

    objLoader.setMaterials(material);

    objLoader.setPath('../js/models/obj/');

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

        //添加阴影

        object.traverse(function (item) {

            if(item instanceof THREE.Mesh){

                item.castShadow = true;

                item.receiveShadow = true;

            }

        });

        //缩放

        object.scale.set(.3,.3,.3);

        scene.add(object);

    })

});

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

我们再去加载OBJ文件,加载成功的文件就是可以导入到场景内的3D对象。

案例源码查看地址:点击这里

COLLADA模型导入

COLLADA是一个开放的标准,最初用于3D软件数据交换,由SCEA发起,现在则被许多著名厂家支持如Autodesk、XSI等。COLLADA不仅仅可以用于建模工具之间交换数据之用,也可以作为场景描述语言用于小规模的实时渲染。因为COLLADA DOM拥有丰富的内容用于表现场景中的各种元素,从多边形几何体到摄像机无所不包。我们可以通过COLLADA DOM库来进行场景文件的读取与处理操作。

上面是我写的一个模型导入案例,案例地址:点击这里

实现步骤,首先引入ColladaLoader插件:

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

1

接着实例化ColladaLoader对象:

var loader = new THREE.ColladaLoader();

1

最后加载文件并调整文件大小,添加到场景内:

loader.load('../js/models/collada/elf.dae', function (collada) {

    //添加阴影

    collada.scene.traverse(function (item) {

        if(item instanceof THREE.Mesh){

            item.castShadow = true;

            item.receiveShadow = true;

        }

    });

    //缩放

    collada.scene.scale.set(5,5,5);

    scene.add(collada.scene);

});

1

2

3

4

5

6

7

8

9

10

11

12

13

案例源码查看:点击这里

注意事项

如何知道,加载完成的模型需要将哪部分导入到场景?

一般情况下都是将自身导入,比如FBX,OBJ,JSON等,还有一种,会在里面生成一个可导入scene属性,如:glTF和COLLADA文件。如果导入的你无法确定,你就把模型对象打印到控制台查看,然后尝试往场景内导入。

导入到场景内的模型无法查看,而且也没有报错

这种会有可能有多种情况造成的,一般情况下都是下面两种情况造成的:

模型太小或者太大,这种情况可以尝试放大一千倍或者缩小一千倍来查看效果。

模型的位置太偏,根本不在相机照射范围内,这种问题我们可以将模型居中到相机照射的焦点位置查看,如何居中我们将在后面的章节中讲解。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容