Threejs入门之二十:使用InstancedMesh(实例化网格)批量创建物体

2023-05-19 09:31:32 浏览数 (1)

InstancedMesh(实例化网格)是Threejs提供的一种特殊的网格Mesh,它可以批量创建具有相同几何体和材质的物体;

构造函数

InstancedMesh( geometry : BufferGeometry, material : Material, count : Integer ) 要创建一个InstancedMesh,需要三个参数,几何体(BufferGeometry类型),材质(Material类型)和要创建的总数(Integer 类型)

属性

.count : Integer 实例的数量。被传入到构造函数中的count表示mesh实例数量的最大值。 可以在运行时改变这个数值到 [0, count] 区间的一个整数 .instanceColor : InstancedBufferAttribute 代表所有实例的颜色。默认情况下null。 如果通过.setColorAt()修改实例化数据,则必须将它的needsUpdate标志设置为 true .instanceMatrix : InstancedBufferAttribute 表示所有实例的本地变换。 如果你要通过 .setMatrixAt() 来修改实例数据,你必须将它的 needsUpdate 标识为 true .isInstancedMesh : Boolean 只读属性,判断一个对象是否是InstancedMesh类型

方法

.dispose () 释放实例的内部资源 .getColorAt ( index : Integer, color : Color ) 获取实例的颜色,它有两个参数, index:实例索引,取值范围为0~count color:已定义的颜色对象 .getMatrixAt ( index : Integer, matrix : Matrix4 ) 获得已定义实例的本地变换矩阵,它有两个参数 index: 实例的索引。值必须在 [0, count] 区间 matrix: 该4x4矩阵将会被设为已定义实例的本地变换矩阵 .setColorAt ( index : Integer, color : Color ) 将给定的颜色设置为定义的实例,它包含两个参数 index:实例索引,取值范围为0~count color:单个实例的颜色 这里需要注意 确保在使用setColorAt 更新所有颜色后将.instanceColor.needsUpdate设置为true .setMatrixAt ( index : Integer, matrix : Matrix4 ) 设置给定的本地变换矩阵到已定义的实例,需要两个参数 index: 实例的索引。值必须在 [0, count] 区间 matrix: 一个4x4矩阵,表示单个实例本地变换 这里需要注意 确保在使用setMatrixAt 更新所有矩阵后将 .instanceMatrix.needsUpdate 设置为true

InstancedMesh实例应用

使用InstancedMesh实现Threejs案例中的instancing / raycast 效果 引入Threejs并创建场景

代码语言:javascript复制
import * as THREE from 'three' 
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
// 场景
const scene = new THREE.Scene()
scene.background = new THREE.Color(0x808080)

创建几何体 这里使用Threejs提供的IcosahedronGeometry来创建几何体 IcosahedronGeometry是二十面缓冲几何体,用于生成一个二十面体,其构造函数如下: IcosahedronGeometry(radius : Float, detail : Integer) 它包含两个参数 radius — 二十面体的半径,默认为1。 detail — 默认值为0。将这个值设为一个大于0的数将会为它增加一些顶点,使其不再是一个二十面体。当这个值大于1的时候,实际上它将变成一个球体

代码语言:javascript复制
const geometry = new THREE.IcosahedronGeometry(0.5,5) 

创建材质

代码语言:javascript复制
const material = new THREE.MeshPhongMaterial({color:0xffffff})

创建物体 这里使用InstancedMesh来批量创建物体

代码语言:javascript复制
let amount = 10
let count = Math.pow(amount,3) //amount 的三次方,1000个
const meshes = new THREE.InstancedMesh(geometry,material,count) //InstancedMesh 创建多个形状材质相同的物探,count 数量

循环设置meshes中每一个小球的位置和颜色 我们首先定义一个变量index作为每一个小球的索引ID,初始值为0 定义一个变量white,用于存放Threejs中的颜色 定义一个offset,用于存放偏移量,即两个小球之间的间隔 定义一个四维矩阵用于存放物体的位置 然后通过三层for循环遍历每一个小球,并设置其位置和颜色

代码语言:javascript复制
// 定义每个小球的id索引,作为小球的标识
let index = 0 
// 定义颜色
let white = new THREE.Color().setHex(0xffffff)
// 定义每个小球位置的偏移量
const offset = (amount -1 ) / 2 //4.5,即每个小球间隔4.5
// 转换矩阵,
const matrix = new THREE.Matrix4()
for(let i = 0 ; i < amount; i  ) {
  for(let j = 0; j < amount; j  ) {
    for(let k = 0; k < amount; k  ) {
      // 设置matrix的位置,根据偏移量
      matrix.setPosition(offset - i, offset - j, offset - k) //-4.5 ~ 4.5
      // 将index和matrix赋值给meshes
      meshes.setMatrixAt(index,matrix)  
      // 设置每个小球的颜色
      meshes.setColorAt(index,white)
      index = index   1
    }
  }
}
scene.add(meshes)

创建光、辅助轴和相机

代码语言:javascript复制
// 辅助轴
const axesHelper = new THREE.AxesHelper(50)
scene.add(axesHelper)
// 灯光
const light = new THREE.HemisphereLight(0xffffff,0x888888)
light.position.set(0,1,0)
scene.add(light)
// 相机
const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,1,1000)
camera.position.set(20,20,20)

创建渲染器

代码语言:javascript复制
// 渲染器
const renderer = new THREE.WebGLRenderer()
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth,window.innerHeight)

document.body.appendChild(renderer.domElement)

添加轨道控制器使用鼠标控制相机

代码语言:javascript复制
const control = new OrbitControls(camera,renderer.domElement)

创建循环渲染函数并调用

代码语言:javascript复制
function render() {
  requestAnimationFrame(render)
  renderer.render(scene,camera)
}
render()

刷新浏览器查看效果

可以通过随机函数使每个小球的颜色都随机显示不同的颜色 将上面定义的颜色变量white修改为如下代码,即可实现随机颜色效果

代码语言:javascript复制
//let white = new THREE.Color().setHex(0xffffff)
let white = new THREE.Color().setHex(Math.random() * 0xffffff))

OK,今天就先到这里吧,下次我们来实现这个有小球组成的立方体与鼠标的交互效果,仿照Threejs案例中的效果来实现当鼠标滑过某个小球时,使某个小球变色的效果。喜欢的关注点赞收藏哦

0 人点赞