ThreeJs入门23-加载模型过程的问题

1,466 阅读3分钟

「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战

示例代码采用three.js-r73版本: cdnjs.cloudflare.com/ajax/libs/t…

yuque_diagram.jpg

上一节我们已经成功地加载了模型,但是对加载模型过程使用的材质和loader方法没有做太多介绍。下面我们来看一下。

Lambert网格材质

  • 我们加载模型时使用MeshLambertMaterial材质
var material = new THREE.MeshLambertMaterial({ color: 0xffffff, side: THREE.DoubleSide });

side属性解析

  • 这里我们创建了一个基础材质(粗糙的平面),使用了side属性,这个属性有三个值
THREE.FrontSide = 0;  // 绘制前面
THREE.BackSide = 1; // 绘制后面
THREE.DoubleSide = 2; // 两面绘制
  • 我们展示模型的时候,是有正面后面之分的,如果只绘制一面,当我们旋转的时候,可能就看不到另一个面了,所以我们这里使用了两面绘制。
  • 比如我们有一个三角形,它有正反两面,我们只绘制正面,那么能看到的就只有正面,只绘制反面同理。

image.png

  • 放到我们的模型上,我们把摄像机位置设置小一些,就可以进入到兔子的肚子中
camera.position.z = 0.001;

image.png

  • 现在我们看到的其实是兔子里面
  • 当我们设置side为THREE.FrontSide时,我们就看不到里面了,只能通过缩放看到兔子外面

外面.gif

  • 当我们把摄像机拉远,设置side为THREE.BackSide时,只能看到兔子的里面
  camera.position.z = 0.2;

里面.gif

  • 所以我们既想看到里面又想看到外面,就要设置side为THREE.DoubleSide,这个还是比较神奇的,只有自己操作过才能体会出来

材质问题

  • 我们现在使用的是MeshLambertMaterial材质,这种材质可以均匀的反射光,所以要有灯光
  • 如果我们使用MeshBasicMaterial材质的话,就不需要光了,但是只能进行简单的着色,我们的模型会展示称如下样子

image.png

  • 所以材质的选择也很重要

VTKLoader

  • 我们加载vtk模型文件,使用了VTKLoader,目前使用了urlonLoad回调函数,其实它还有两个参数
    • url: 资源路径
    • onLoad: 加载完成回调函数,返回geometry
    • onProgress:加载进度
    • onError:加载错误提示

不同版本可能也有些许差别,目前使用的是r73版本。

geometry法线

loader.load("../../static/models/vtk/bunny.vtk", function (geometry) {
    geometry.computeVertexNormals();
    var mesh = new THREE.Mesh(geometry, material);
    mesh.position.setY(- 0.09);
    scene.add(mesh);
});
  • 我们获取到了模型资源的geometry,需要通过geometry.computeVertexNormals()来计算每个顶点的法线
  • 因为MeshLambertMaterial是有光照的材质,当光照射到geometry上要有法线才能反射光照。如果不计算法向量,就看不到物体了。

模型位置问题

  • 我们加载完模型,创建网格,给网格设置了一个位置
  mesh.position.setY(- 0.09);
  • 如果不设置这个位置,我们的模型会展示在场景上方

image.png

  • 这是因为,建模时,模型位置并没有在(0,0,0)点,而是选择了往上一点,所以有的时候我们拿到的模型并不一定是在原点,也有可能在别的地方或者被旋转过等等

总结

这一节我们主要讲了以下内容:

  • Lambert网格材质
    • side属性解析
    • 材质问题
  • VTKLoader属性方法介绍
  • 模型位置问题