threejs 层级模型

467 阅读3分钟

一、Vector3与模型位置、缩放属性

Group层级模型(树结构)

const mesh = new THREE.Mesh(geometry, material)
const mesh1 = new THREE.Mesh(geometry, material)

mesh1.translateX(50)

const group = new THREE.Group()

group.add(mesh)
group.add(mesh1)

add方法

scene、group、mesh的add方法都是来自于他们的基类Object3D

add方法可以传入多个子对象

group.add(mesh, mesh1)

add方法返回值也是一个group对象,可以继续调用add

group.add(mesh).add(mesh1)

父对象平移、缩放、旋转时,子对象会跟着变化

group.translateY(50)
group.scale.set(2, 2, 2)
group.rotateY(Math.PI / 6)

Object3D当做Group使用

const group = new THREE.Object3D()const group = new THREE.Group()的效果一样,Group更语义化

mesh也能添加mesh子对象

mesh.add(mesh1)

二、遍历模型树结构,查询模型节点

组命名和模型命名,通过name

const group1 = new THREE.Group()
group1.name = '高层'
for (let i = 0; i < 5; i++) {
  const geometry = new THREE.BoxGeometry(20, 60, 10)
  const material = new THREE.MeshLambertMaterial({ color: 'deepskyblue' })
  const mesh = new THREE.Mesh(geometry, material)
  mesh.position.x = i * 30
  group1.add(mesh)
  mesh.name = i + 1 + '号楼'
}
group1.position.y = 30

const group2 = new THREE.Group()
group2.name = '洋房'
for (let i = 0; i < 5; i++) {
  const geometry = new THREE.BoxGeometry(20, 30, 10)
  const material = new THREE.MeshLambertMaterial({ color: 'yellow' })
  const mesh = new THREE.Mesh(geometry, material)
  mesh.position.x = i * 30
  group2.add(mesh)
  mesh.name = i + 6 + '号楼'
}
group2.position.z = 50
group2.position.y = 15

const model = new THREE.Group()
model.name = '光明小区'
model.add(group1, group2)
model.position.set(-50, 0, -25)

递归遍历

可以遍历出所有的组和模型对象

model.traverse(function (obj) {
  console.log('obj',obj)
  if (obj.isMesh) {
    obj.material.color.set('red')
  }
})

查找某个具体的模型

const mesh = model.getObjectByName('2号楼')
mesh.material.color.set('yellow')

三、本地(局部)坐标和世界坐标

模型在三维空间中的坐标会受自己的position属性和父级position属性共同影响

const geometry = new THREE.BoxGeometry(20, 20, 20)
const material = new THREE.MeshLambertMaterial({
  color: 'pink'
})
const mesh = new THREE.Mesh(geometry, material)
mesh.position.set(20, 0, 0)

const group = new THREE.Group()
group.add(mesh)
group.position.set(20, 0, 0)

本地坐标(局部坐标):模型自身的position

世界坐标:模型自身的position和所有父级的position累加的坐标

getWorldPosition方法获取世界坐标

const worldPosition = new THREE.Vector3()
mesh.getWorldPosition(worldPosition)

console.log('世界坐标', worldPosition)
console.log('本地坐标', mesh.position)

image.png

给子对象添加一个局部坐标系

const meshAxesHelper = new THREE.AxesHelper(50)
mesh.add(meshAxesHelper)
image.png

四、改变模型局部坐标原点位置

const geometry = new THREE.BoxGeometry(20, 20, 20)
const material = new THREE.MeshLambertMaterial({
  color: 'pink'
})
const mesh = new THREE.Mesh(geometry, material)
geometry.translate(10, 0, 0)
mesh.rotateY(45) // rotateY默认绕几何体中心旋转,经过平移后,rotateY是绕长方体面上一条线旋转

五、移除对象方法remove

场景对象(scene)、组对象(group)、模型对象(mesh)都有add方法,同样拥有remove方法,继承于共同的父类Object3D

场景中移除光源scene.remove(ambient)

组对象移除模型group.remove(mesh)

模型对象移除自身的坐标轴mesh.remove(meshAxesHelper)

同样地,remove方法也可以一次移除多个对象

六、隐藏或显示属性visible

创建2个模型

const geometry = new THREE.BoxGeometry(20, 20, 20)
const material = new THREE.MeshLambertMaterial({
  color: 'pink'
})
const mesh = new THREE.Mesh(geometry, material)
const mesh1 = new THREE.Mesh(geometry, material)

mesh1.translateX(30)

const group = new THREE.Group()
group.add(mesh, mesh1)

模型隐藏mesh.visible = false

组隐藏group.visible = false

材质属性隐藏mesh.material.visible = false 如果多个模型使用的是同一个材质,其中一个模型将材质的visible设置为false,那么所有的模型都会隐藏

如果希望当前模型设置visible属性时只作用于当前模型,可以在设置visible属性前克隆一下:

mesh.material = material.clone()
mesh.material.visible = false