“物体”进阶
1.理解几何体的顶点、UV、法向量属性
geometry:几何体
material:材质
我们知道是由 几何体+材质 成为了我们的 物体 。
在物体的几何体对象中,有一个属性position位置,这个位置指的是顶点位置。
还有一个属性uv,这个我不太懂去百度查了一下,有一个蛮好的解释:模型是立体的,你需要把它的“外皮”剥下,展开到平面上,这样给这层皮上色,画画,就方便很多了。立体的模型有XYZ三个坐标系,精确记录每个顶点的位置,UV则是外皮剥下、展开到平面后,所有点坐标投射到平面上的精确位置 。
像我们小时候,可能会玩过那种用纸叠起来叠成的骰子,也就是把一个立方体拆成一个平面。

意思就是将这个立方体拆开来,详细的在每个面进行描画。
以及一个属性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
})