关于web模型,这是个很难讲的主题,因为它跨了比较多的领域,之前也在文章中吐槽过:

然而,当时并没有很好的去解释3d模型的原理,原因主要是模型经手的并不多,并没有形成很好的方法论,只能大致说一下当时项目中的处理的个例。
不过现在依然没有形成很好的方法论,只能说,可以处理的模型范围比之前广了一点。
在这之前我们可以先来了解一下为什么模型导出对我们来说这么困难。
首先,对前端的同学来说:

你们看得懂这个界面吗?

而对于看得懂这个界面的3d美术同学来说:

你们看得懂这个东西吗?

啥?你两个都很熟?
……
那你点进这篇文章干p啊!

好了,进入正题,我们先从模型开始讲:
在这里按导出难度来区分,模型大致可以分为无动画模型和带动画模型两种。
因为目前3dsmax的模型接触的比较多,所以下面的3d软件都以3dsmax为例进行演示。
3dsmax导出前需要先安装插件,在threejs完整包里,你可以在utils\exporters\max下面看到这样3个文件

配置3dsmax中的系统路径


然后插件管理器里把这个勾上


之后,每次启动3dsmax时就会出现这些插件的界面:



————————————————————————————
另外,上面那些步骤都不做也没关系,等到想要导出时,点一下

找到对应脚本,确认就行了……

接下来我们就可以开始导出模型了
我们先说说无动画模型,或者说
一、导出不带动画的模型数据
比如这样一个模型

你只要选中它


点击一下 导出 就完成了:

然后把这个模型放到web页面里:

因为导出的是个纯模型,为了不让大家产生误解,我稍微调了下代码里的颜色。而模型里看起来的“棱角分明”也是threejs代码设置的结果。
至此一个不带动画的3d模型已经完成了。
SO……So easy?

是的,不带动画的3d模型相对来说是简单很多,但是为了之后更好的理解带动画的模型,我们先来过一遍无动画模型的代码。

metadata:
模型里信息概要
sourceFile:源文件,比如model.obj,obj.max。
generatedBy: 转换的插件名称
formatVersion: 版本
vertices: 顶点数
normals: 与顶点对应的法线向量
colors: 与顶点对应的颜色值
uvs: uv映射
triangles: 三角形
materials: 材质
materials:
模型的材质,一个模型可同时包含多个材质,上图由于是用3dsmax里直接绘制的茶壶进行导出,所以基本上没有材质信息,而材质信息是一个模型里很重要并且略繁杂的信息,这里列一下比较常见的材质的属性:
DbgIndex: 材质索引
DbgName: 材质名称
colorDiffuse:漫射颜色
colorSpecular: 镜面颜色
opacity:透明度
colorDiffuse:镜面系数
mapDiffuse: 漫射贴图
vertexColors:顶点颜色
一般情况下,贴图模型导出后只需要把mapDiffuse里的贴图路径设置好就行,而其他的属性可以通过手动调整,来优化模型在web中显示的效果。(直接导出,web端的呈现效果多少会和软件中显示的效果有出入,因为web端的灯光之类的处理是由我们手动控制)
vertices:
顶点数据,这个数据是一个一维数组,每3个值组成一个点的位置,[x1,y1,z1,x2,y2,z2,x3...]

normals:
顶点法线向量,配合顶点颜色,用来计算不同角度光照时的漫反射光的显示,同样是xyz循环的一维数组
colors:
顶点颜色,rgb循环的一维数组,与normals配合可以实现多种顶点颜色分布,这个涉及到着色器。

uvs:
uv映射,就是模型与贴图的对应关系,uvs并不是一维数组,基本上就是下图的数据化。

faces:
这个是threejs内的类型,存储了顶点vertices的索引,详情可参考https://threejs.org/docs/index.html#api/core/Face3在模型上的面(三角形)如下图

至此,整个无动画模型的基础数据格式我们都了解了,threejs内有多种加载器,但是,最后threejs要解析的就是这样的json格式数据。
当然,对于这些数据,我们能手动修改的地方不多,如果模型出了问题,还是要在3d软件内进行调整。

二、导出带动画的模型数据

之前导出模型只要点一下就行了吧,居然要拆开2段来讲,导出带动画的模型也只要点一下就行了吧?

叮

叮

叮


懂了没?带动画的模型和不带动画的模型导出不是一个概念。
我们先看个视频,了解一下3dsmax中的简易动画模型的制作,以及导出threejs格式的过程。
threejs动画模型导出_腾讯视频
动画导出比不带动画的模型导出要严格很多,各种奇葩的情况都会在这个时候出现。
那么,模型里增加了动画,到底是增加了什么?
以视频里的圆柱体为例。
首先,增加了骨骼

其次,增加蒙皮

最后,增加动画帧

反应在导出的json代码上就是多了这几个属性

bones:
骨骼,是一个包含每段骨骼数据的数组

parent:骨骼的父节点(实际作用类似于骨骼节点索引)
name:骨骼名称
pos:骨骼位置(xyz)
scl:骨骼缩放(xyz)
rotq:骨骼旋转(四元)
skinIndices:
蒙皮索引
skinWeights:
蒙皮权重,蒙皮的概念如下图


每块骨骼进行变换的时候,控制的顶点数即受到蒙皮权重的影响。
不懂也没关系,反正就算懂了,真遇到蒙皮问题,我们还是要求助美术大佬~

animations:
通过时间控制每组骨骼状态。一般情况下,一个模型对应一组骨骼动画,但有些模型里,可能会同时存在多组骨骼动画,这也是动画模型事故多发地段。动画帧在软件里的呈现。

动画转换后的代码

name:动画名称
fps:帧频
hierarchy:骨骼层级,包含各个骨骼的信息的数组
length:总时长
parent:骨骼父节点
keys:动画帧,每一帧都有当前骨骼的信息
pos:骨骼位置(xyz)
scl:骨骼缩放(xyz)
rotq:骨骼旋转(四元)
time:当前帧的时间(取决于导出时的帧频)
模型动画由animations开始,动画随着时间不断调整每个骨骼的属性,而骨骼通过蒙皮控制对应的顶点进行计算,而顶点上附着的颜色与法向量也相应的进行重新计算,因此整个模型就产生动画的联动。
那么,为什么增加这些东西后,模型导出就失败了呢?
1)首先,要导出动画模型,必须选中对应几何体,而且不能选到骨骼,否则就会出现这个错误

2)导出的动画模型必须是可编辑网格,而大部分模型其实是可编辑多边形。因为可编辑多边形比可编辑网格屌很多,但是threejs的导出插件比较弱鸡,所以只能导出可编辑网格。



怎么转换呢?我也是折腾了几天后,最后通过给大佬们递茶,才了解到转换方法,所以我才不会告诉你们。想知道的同学,关注一下我的公众号SignACG,不过,这个公众号跟这个文章没半毛钱关系。

3)模型的蒙皮权重必须与整体骨骼保持一致,否则就会鬼畜(在3d模型里是不会有问题,但是threejs里不行),解决方法是把所有的几何体合并成同一个,并重新绑定骨骼动画。
这个没招了,去给美术大佬们递茶,让他们帮忙调整吧。

4)还有个很常见的情况,就是动画模型里为了方便绘制角色的运动轨迹,通常会为角色添加一个 根节点,这个节点没有对应信息的绑定,会导致导出的模型的初始位置就出错
这里需要把当作质点的节点断开链接

找到容器资源管理器

找到根节点

选择根节点的下级节点,断开其与根节点的链接

三、小结
可能上面列的这些情况还是没法罗列出所有动画模型导出时的会出现的问题,坑还是那个坑,走过的人还是要踩。
没了。
网友评论