第一次使用threejs到实际项目中,开始的时候心情有点小激动,毕竟是第一次嘛,然而做着做着就感受到这玩意水好深,满满的都是坑,填都填不过来。经过老板20天惨无人道的摧残,终于小有成就。
因为第一次搞这玩意,相对的遇到的问题也是大把的,让我来一一诉说一路上遇到的各种问题。
开发使用: C4D、Blender2.75、[threejs-r72]()
万事开头难,第一个问题就是怎么才能把3d软件中做好的模型显示在浏览器中。
一、模型在软件中的导入与导出。
这个项目中涉及到单个模型和动画模型,而不同模型的导入导出有差异,下面就告诉大家我是如何将坑填平的。
1、单个模型:
因为自己不会使用3D软件建模,只能求助公司大神设计师来一起搞。刚开始的想法是直接用3d软件建模然后直接导出obj格式来用,然后设计师用C4D做好了一个测试模型,发现模型数量少的话网页的大小还可以接受,但是由于项目的模型数量比较多,然后粗算了一下模型总的大小,发现超出了预想,所以得另寻它法。
接着在网上搜索发现Blender这玩意,由于设计师对C4D情有独钟不会Blender软件,所以决定用C4D做好模型然后导出obj格式接着再导入到Blender里面,再经由Blender导出需要的格式。
因为是第一次倒腾这个软件,所以并不会导出。然后就在网上搜素了怎么用Blender导出的json、js文件。经过测试js文件导出比较大,最后果断选择json。
在软件中如何导入导出如图所示:
图一 (左边为导入obj,右边导出json)
2、动画模型:
由于设计师出一个动画模型也没有这么快,就没法进行导出测试。于是看到threejs官网里有demo中使用的动画模型,我就拿过来进行测试,发现动画模型跟单个模型导出选择有差异然后发现更单个模型的导出有出入,经过反复的测试,得到导动画模型需要注意的几点,
(1)选择好动画的帧数,如果没选择,导出的json文件会有空帧。并且文件也会相对增大。
(2)选择好导出选项中Animation,一般就选择Morph Animation、Embed Animation选项。
单个模型以及动画模型导出选项如下图所示:
图二 (左边为导出单个模型,右边导出动画模型)
注:导出单个带材质模型需要在导出选项的时候需要在shading选项中选择Face Materials。
拿着设计师做好的动画模型导出json格式后碰到了一些问题,虽然json格式的大小相比obj格式的要小一点,不过项目中有人物的动画模型导出的json格式大小还是太大。然后为了解决这个问题,跟设计师进行讨论,然后得到以下解决方案:
(1)将模型的面和顶点在不影响正常显示的情况下进行删减
(2)对动画模型的帧数、面、顶点也进行删减
经过反复的修改和测试终于将动画模型控制在500-1000KB左右,单个模型控制在100K左右。
模型的导出问题解决了然后是对模型进行导入到页面中去。
二、模型加载到页面
在threejs官网上看到利用obj格式加载的demo比较多,所以就直接使用的是obj的格式模型进行加载,根据demo利用THREE.OBJLoader()、THREE.OBJMTLLoader()进行加载。然后设计大神给了我一个带材质的模型让我进行测试,发现两问题:
(1)模型材质丢失
(2)模型的大小太大(模型量少大小还可以接受,考虑到此次项目中的模型量多,估算了一下大概有70-80M左右)
由于模型大小太大所以放弃。所以改选用THREE.JSONLoader()进行加载。
在这一步由于是直接导出带材质的json格式,材质对应到模型的各个面是一个问题。然后在官网的demo上看到THREE.MeshFaceMaterial()方法,查看了一下文档,然后迅速解决这个了这个问题。
另外threejs提供了各种模型的加载方法具体可去查询。
虽然解决了模型加载和面的问题,但是模型在网页的表现与软件中渲染的差别太大。刚开始以为是模型方面以及导入导出的方式不对,于是和设计师进行各种修改然后反复的测试,发现没什么变化。然后求助stackoverflow找到了答案。是由于模型的shading的原因造成的,然后根据网上提供的解决方案在材质中加上materials.shading = THREE.FlatShading来解决。不过有些Android手机上会出现材质无法解析的错误。而且在r72的版本中MeshLambertMaterial已经移除了shading这个属性。
下图就是在网页中渲染的结果对比。
图三 (左边为未加shading,右边加了shading)
静态模型的导入没有问题了,然后是动画模型的导入,参考官网demo,直接套用基本的动画没有太大问题,只是项目中有一个人物运球的动画模型比较难折腾,刚开始的时候直接是按照动画模型的导出直接导,然后同步到页面中发现只能导出一个动画,另外一个丢失了,定位了一下问题好像是Blender不能同时导出多个动画(具体是不是待研究)。最后想了一个办法就是采取分开导出再创建一个obj包裹两个动画,操作这个obj。来解决多个动画问题(如有更好的办法求大神指导)。
至此将模型放到页面中的准备工作都做完了。接着就是模型上的事件与动画,模型上的各种事件整的头都大了,然而到现在我还是有一些东西没有弄清楚原理还得继续研究。
三、模型的圆周运动
刚开始项目中有个需求就是进入页面中模型需要做一个圆周运动,圆周运动以前在数学中学过,但是一直没用所以就忘了,然后就在网上找有关圆周运动计算的方法。这里不做过多的解释,用下面一张图来完整解释怎么来计算圆周运动。
图四 (圆周运动计算)
在页面中测试的结果如下图所示:
图五 (圆周运动测试结果)
功能代码如下:
time = clock.getElapsedTime() * 1; loadMesh.position.x = Math.cos( time ) * 10; loadMesh.position.y = Math.sin( time ) * 10;