three.js学习(5)

96 阅读4分钟

“物体”进阶

1.理解几何体的顶点、UV、法向量属性

geometry:几何体

material:材质

我们知道是由 几何体+材质 成为了我们的 物体

物体几何体对象中,有一个属性position位置,这个位置指的是顶点位置

还有一个属性uv,这个我不太懂去百度查了一下,有一个蛮好的解释:模型是立体的,你需要把它的“外皮”剥下,展开到平面上,这样给这层皮上色,画画,就方便很多了。立体的模型有XYZ三个坐标系,精确记录每个顶点的位置,UV则是外皮剥下、展开到平面后,所有点坐标投射到平面上的精确位置

像我们小时候,可能会玩过那种用纸叠起来叠成的骰子,也就是把一个立方体拆成一个平面。

img

意思就是将这个立方体拆开来,详细的在每个面进行描画。

以及一个属性normal法向量,使用在例如光反射的角度等等。

2.BufferGeometry设置顶点创建矩形

之前我们设置一个物体是这样子

 const cubeGeometry = new THREE.BoxGeometry(1, 1, 1) //几何体
 const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 }) //材质
     
 const cube = new THREE.Mesh(cubeGeometry, cubeMaterial)//根据几何体和材质去创建物体

我们这次自己来设置几何体的顶点

 const geometry = new THREE.BufferGeometry() //缓冲区几何体
 //设置顶点数组,使用32位的浮点数数组进行创建
 const vertices = new Float32Array([//一维数组,每三个值作为一个顶点
     -1.0,1.0,1.0,
     1.0,1.0,1.0,
     1.0,-1.0,1.0,
     -1.0,1.0,1.0,
     -1.0,-1.0,1.0,
     1.0,-1.0,1.0,
 ])//对于数学不错的小聪明来说,应该很容易能理解这个。
 //设置属性->创建一个缓冲区属性对象,传入这个一维数组,并且告诉它每3个值为一个坐标
 geometry.setAttribute('position',new THREE.BufferAttribute(vertices,3))
 
 const material = new THREE.MeshBasicMaterial({ color: 0xffff00 }) //材质
     //根据几何体和材质去创建物体
     //设置我们的物体
 const mesh = new THREE.Mesh(geometry,material)
 scene.add(mesh)

这个时候画出来的图,让我懵圈。。居然有一半是显示的,一半是背面才显示的,而要整个正方形显示必须是这样

 [
     -1.0, -1.0, 1.0,
     1.0, -1.0, 1.0,
     1.0, 1.0, 1.0,
     1.0, 1.0, 1.0,
     -1.0, 1.0, 1.0,
     -1.0, -1.0, 1.0,
 ]

让我思考思考:只显示一般的代码中,正面显示的图形的位置是

 [
     -1.0,1.0,1.0,
     -1.0,-1.0,1.0,
     1.0,-1.0,1.0,
 ]

原来如此,逆时针画成的图形就会在正面显示!!!

3.生成酷炫三角形科技物体

那我们试着生成50个三角形,然后让他坐标都随机就好了。三角形的话需要三个点,每个点有需要xyz三个坐标,所以

 for (let i = 0; i < 50; i++) {
     const geometry = new THREE.BufferGeometry()
     const vertices = new Float32Array(9) //这里要告诉它,我们需要九个坐标,否则会报错
     for (let j = 0; j < 9; j++) { //随机打出九个坐标
         vertices[j] = Math.random() * 5 //0~5
     }
     geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
     let color = new THREE.Color(Math.random(), Math.random(), Math.random()) //这里我们也来随机颜色
     const material = new THREE.MeshBasicMaterial({ color: color }) //材质
     const mesh = new THREE.Mesh(geometry, material)
     scene.add(mesh)
 }

当然我们可以在材质上稍微加一点点微调,比如透明度,但是在材质里面必须把transparent设置为true,才能修改。

 const material = new THREE.MeshBasicMaterial({ color: color, transparent: true, opacity: 0.5 }) //材质
 //然后让图形基本上位于原点的位置吧,就让坐标的范围变成-5~5好了
 for (let j = 0; j < 9; j++) { //随机打出九个坐标
         vertices[j] = Math.random() * 10-5 //-5~5
     }

4.常用网格几何体Geometry

这个的话最好是去文档里面学习。

BoxGeometry 立方缓冲几何体

CircleGeometry 圆形缓冲几何体:细分得越多越圆

ConeGeometry 圆锥缓冲几何体:底部细分得越多越圆,甚至可以去掉底部圆底

CylinderGeometry 圆柱缓冲几何体:底部细分得越多越圆,可以去掉两边圆底

TextGeometry 文本缓冲几何体:用得比较多

主要还是根据情况去文档里面寻找需要的几何体。

5.初识材质与纹理

在前面我们用到了一个就普通的材质:

基础网格材质 MeshBasicMaterial:它不受任何光照的影响

先一样创建一个最基本的立方体

 //几何体
 const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1)
     //材质
 const basicMaterial = new THREE.MeshBasicMaterial({
     color: "#ffff00"
 })
 const cube = new THREE.Mesh(cubeGeometry, basicMaterial)
 scene.add(cube)

那下面我们可以加入一些纹理,我们用到 threejs 官方提供的一个纹理加载器 ,实际上就是一个图片的加载器

 //导入纹理
 const textureLoader = new THREE.TextureLoader()
 const stoneColorTexture = textureLoader.load("./textures/stone.jpg")

这里要注意的是,这个纹理文件的位置。应该放到 dist 里面,打包好的文件。因为实际上我们打包好之后,我们执行的文件是dist/index.html这个位置。

所以我们自己可以找想要贴的图案,我找了石头的图案有点像是我的世界哈哈。在dist下建了一个文件夹textures,把图片放到里面。

然后再将纹理放到材质里面即可。

 const basicMaterial = new THREE.MeshBasicMaterial({
     map: stoneColorTexture
 })