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

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并创建场景

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的时候,实际上它将变成一个球体

const geometry = new THREE.IcosahedronGeometry(0.5,5) 

创建材质

const material = new THREE.MeshPhongMaterial({color:0xffffff})

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

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循环遍历每一个小球,并设置其位置和颜色

// 定义每个小球的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)

创建光、辅助轴和相机

// 辅助轴
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)

创建渲染器

// 渲染器
const renderer = new THREE.WebGLRenderer()
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth,window.innerHeight)

document.body.appendChild(renderer.domElement)

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

const control = new OrbitControls(camera,renderer.domElement)

创建循环渲染函数并调用

function render() {
  requestAnimationFrame(render)
  renderer.render(scene,camera)
}
render()

刷新浏览器查看效果
在这里插入图片描述
可以通过随机函数使每个小球的颜色都随机显示不同的颜色
将上面定义的颜色变量white修改为如下代码,即可实现随机颜色效果

//let white = new THREE.Color().setHex(0xffffff)
let white = new THREE.Color().setHex(Math.random() * 0xffffff))

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

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九仞山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值