关键点:
1. new Float32Array()
2. new THREE.BufferAttribute()
3. geometry.setAttribute()
BoxGeometry
BoxGeometry 有 6 个参数:
width
:x
轴上的大小height
:y
轴上的大小depth
:z
轴上的大小widthSegments
:x
轴上的细分数量heightSegments
: 在y
轴上的细分数量depthSegments
: 在z
轴上的细分数量
细分对应于面由多少个三角形组成。默认情况下,它为 1
,意味着每个面只有 2 个三角形。如果你将细分设置为 2
,每个面将会有 8 个三角形:
const geometry = new THREE.BoxGeometry(1, 1, 1, 2, 2, 2)
// 向 material 中添加 wireframe: true,线框将显示界定每个三角形的线条
const material = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true })
const geometry = new THREE.SphereGeometry(1, 32, 32)
创建自己的缓冲几何体
首先实例化一个空的 BufferGeometry。
// 自定义缓冲几何体
// 1. 创建一个空的 BufferGeometry
const geometry = new THREE.BufferGeometry()
// 2. 使用 Float32Array 添加几何体顶点
// 首先指定第一个顶点的 x、y 和 z,然后是第二个顶点的 x、y 和 z,依此类推
// 方式一
// 创建一个 Float32Array 指定它的长度(比如 9),然后填充它
// const positionArray = new Float32Array(9)
// // First vertice
// positionArray[0] = 0
// positionArray[1] = 0
// positionArray[2] = 0
// // Second vertice
// positionArray[3] = 0
// positionArray[4] = 1
// positionArray[5] = 0
// // Third vertice
// positionArray[6] = 1
// positionArray[7] = 0
// positionArray[8] = 0
// 方式二
const positionArray = new Float32Array([
0,0,0, // First vertice
0,1,0, // Second vertice
1,0,0 // Third vertice
])
// 将其转换为 BufferAttribute,再发送给 BufferGeometry
const positionAttribute = new THREE.BufferAttribute(positionArray, 3)
// 通过使用 setAttribute(...) 方法将这个属性添加到我们的 BufferGeometry ,创建position这个名词的属性
geometry.setAttribute('position', positionAttribute)
// 向 material 中添加 wireframe: true,线框将显示界定每个三角形的线条
const material = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true })
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
创建一堆随机三角形:
// 1. 创建一个空的 BufferGeometry
const geometry = new THREE.BufferGeometry()
// 随机50个三角形(50*9,需要450个顶点)
// 9代表3个顶点位置,也就是3组 x y z
const count = 50
const positionArray = new Float32Array(count * 3 * 3)
for (let i = 0; i < count * 3 * 3; i++) {
positionArray[i] = (Math.random() - 0.5) * 4 // 值在 -2 到接近 2 之间
}
// 将其转换为 BufferAttribute,再发送给 BufferGeometry
const positionAttribute = new THREE.BufferAttribute(positionArray, 3)
// 通过使用 setAttribute(...) 方法将这个属性添加到我们的 BufferGeometry ,创建position这个名词的属性
geometry.setAttribute('position', positionAttribute)
// 向 material 中添加 wireframe: true,线框将显示界定每个三角形的线条
const material = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true })
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
【完整代码】
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
// Canvas
const canvas = document.querySelector('canvas.webgl')
// Scene
const scene = new THREE.Scene()
/**
* Object
*/
// width: x 轴上的大小
// height: y 轴上的大小
// depth: z 轴上的大小
// widthSegments: x 轴上的细分数量
// heightSegments: 在 y 轴上的细分数量
// depthSegments: 在 z 轴上的细分数量
// const geometry = new THREE.BoxGeometry(1, 1, 1)
// const geometry = new THREE.BoxGeometry(1, 1, 1, 2, 2, 2)
// const geometry = new THREE.SphereGeometry(1, 32, 32)
// 自定义缓冲几何体
// 1. 创建一个空的 BufferGeometry
const geometry = new THREE.BufferGeometry()
// 2. 使用 Float32Array 添加几何体顶点
// 首先指定第一个顶点的 x、y 和 z,然后是第二个顶点的 x、y 和 z,依此类推
// 方式一
// 创建一个 Float32Array 指定它的长度(比如 9),然后填充它
// const positionArray = new Float32Array(9)
// // First vertice
// positionArray[0] = 0
// positionArray[1] = 0
// positionArray[2] = 0
// // Second vertice
// positionArray[3] = 0
// positionArray[4] = 1
// positionArray[5] = 0
// // Third vertice
// positionArray[6] = 1
// positionArray[7] = 0
// positionArray[8] = 0
// // 方式二
// const positionArray = new Float32Array([
// 0,0,0, // First vertice
// 0,1,0, // Second vertice
// 1,0,0 // Third vertice
// ])
// 随机50个三角形(50*9,需要450个顶点)
// 9代表3个顶点位置,也就是3组 x y z
const count = 50
const positionArray = new Float32Array(count * 3 * 3)
for (let i = 0; i < count * 3 * 3; i++) {
positionArray[i] = (Math.random() - 0.5) * 4 // 值在 -2 到接近 2 之间
}
// 将其转换为 BufferAttribute,再发送给 BufferGeometry
const positionAttribute = new THREE.BufferAttribute(positionArray, 3)
// 通过使用 setAttribute(...) 方法将这个属性添加到我们的 BufferGeometry ,创建position这个名词的属性
geometry.setAttribute('position', positionAttribute)
// 向 material 中添加 wireframe: true,线框将显示界定每个三角形的线条
const material = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true })
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
/**
* Sizes
*/
const sizes = {
width: window.innerWidth,
height: window.innerHeight
}
/**
* Camera
*/
// 自定义控制
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 1, 1000)
camera.position.z = 3
camera.lookAt(mesh.position)
scene.add(camera)
/**
* Controls
*/
const controls = new OrbitControls(camera, canvas)
controls.enableDamping = true
/**
* Renderer
*/
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
renderer.render(scene, camera)
const tick = () => {
// Update controls
controls.update()
renderer.render(scene, camera)
window.requestAnimationFrame(tick)
}
tick()
window.addEventListener('resize', () => {
// 1. 更新 sizes
sizes.width = window.innerWidth
sizes.height = window.innerHeight
// 2.1 更新 camera aspect 纵横比
camera.aspect = sizes.width / sizes.height
// 2.2 更新 aspect 时要配合更新投影矩阵 updateProjectionMatrix
camera.updateProjectionMatrix()
// 3. 更新 renderer
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})
window.addEventListener('dblclick', () => {
if (!document.fullscreenElement) {
canvas.requestFullscreen();
} else {
document.exitFullscreen();
}
})
项目创建参考