首页 前端知识 【Three.js】Layers图层的使用

【Three.js】Layers图层的使用

2024-06-22 01:06:11 前端知识 前端哥 142 43 我要收藏

目录

前言

创建图层对象

启用图层

关闭图层

其他


前言

Layers 对象为Object3D对象分配了1-32个图层,编号为0-31。在内部实现上,每个图层对象被存储为一个bit mask, 默认所有 Object3D 对象都存储在第 0 个图层上

图层对象可以用于控制对象的显示,和相机处于同一个图层的物体才可以被显示出来。

每个继承自 Object3D 的对象都有一个 Object3D.layers 对象。Mesh、Camera、Group等都继承自基类 Object3D,所以它们都有一个 layers 属性。

创建图层对象

通过构造函数 Layers() 可以创建一个新的图层对象,该对象默认与第 0 图层关联。

每个图层都被存储为一个32位的BitMask(掩码),启用了哪个图层,哪个位置的比特位就为1,其余为0。可以同时启用多个图层。

  const layers = new THREE.Layers()
  console.log(`默认图层0, mask值为: ${layers.mask} ---> 对应二进制:${layers.mask.toString(2)}`)

  for (let i = 0; i < 10; ++i) {
    layers.set(i)
    console.log(`layers.set(${i}) -> layers.mask: ${layers.mask} ---> 对应二进制:${layers.mask.toString(2)}`)
  }
  layers.set(0)

  layers.enableAll()
  console.log(`layers.enableAll() -> layers.mask: ${layers.mask} ---> 对应二进制:${layers.mask.toString(2)}`)

  layers.disableAll()
  console.log(`layers.disableAll() -> layers.mask: ${layers.mask} ---> 对应二进制:${layers.mask.toString(2)}`)

  layers.enable(2)
  console.log(`layers.enable(2) -> layers.mask: ${layers.mask} ---> 对应二进制:${layers.mask.toString(2)}`)
  layers.disable(2)
  console.log(`layers.disable(2) -> layers.mask: ${layers.mask} ---> 对应二进制:${layers.mask.toString(2)}`)

  for (let i = 0; i < 3; ++i) {
    layers.toggle(i)
    console.log(`layers.toggle(${i}) -> layers.mask: ${layers.mask} ---> 对应二进制:${layers.mask.toString(2)}`)
  }

打印结果:

启用图层

.enable(layerNum) 增加一个layerNum图层的显示

.set(layerNum) 删除原来设置的图层,启用layerNum图层

.toggle(layerNum) 切换图层,开启或关闭layerNum图层

.enableAll() 启用全部图层

<template>
  <div class="app">
    <div id="three"></div>
    <div class="btns">
      <button @click="setLayer(0)">layers.set(0)</button>
      <button @click="setLayer(1)">layers.set(1)</button>
      <button @click="setLayer(2)">layers.set(2)</button>
      <br>
      <button @click="enableLayer(0)">layers.enable(0)</button>
      <button @click="enableLayer(1)">layers.enable(1)</button>
      <button @click="enableLayer(2)">layers.enable(2)</button>
      <br>
      <button @click="toggleLayer(0)">layers.toggle(0)</button>
      <button @click="toggleLayer(1)">layers.toggle(1)</button>
      <button @click="toggleLayer(2)">layers.toggle(2)</button>
      <br>
      <button @click="enableAll">layers.enableAll()</button>
      <button @click="reset">重置</button>
    </div>
  </div>
</template>
 
<script setup>
import { onMounted, ref } from 'vue'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

const camera = ref(null)
onMounted(() => {
  const threeContainer = document.getElementById('three')
  // 创建场景
  const scene = new THREE.Scene()
  // 创建相机
  camera.value = new THREE.PerspectiveCamera( 75, threeContainer.offsetWidth / threeContainer.offsetHeight, 0.1, 1000 )
  // const camera = new THREE.OrthographicCamera(
  //   -5*threeContainer?.offsetWidth / threeContainer?.offsetHeight, 
  //   5*threeContainer?.offsetWidth / threeContainer?.offsetHeight, 
  //   5, -5, 
  //   0.1, 
  //   1000 
  // ) //正交视角
  // 设置相机位置
  camera.value.position.set(0, 0, 10)
  // 将相机添加到场景中
  scene.add(camera.value)

  // 创建渲染器
  const renderer = new THREE.WebGLRenderer({
    antialias: true //开启抗锯齿
  })
  // 设置渲染的尺寸和大小
  renderer.setSize(threeContainer.offsetWidth, threeContainer.offsetHeight)
  // 将webgl渲染的canvas内容添加到DOM容器
  threeContainer.appendChild(renderer.domElement)
 

  /*创建几何体*/ 
  const cubeGeometry = new THREE.BoxGeometry(1, 1, 1) //几何体对象
  const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 }) //材质
  const cube = new THREE.Mesh(cubeGeometry, cubeMaterial) //根据几何体和材质创建物体
  // 将几何体添加到场景当中
  scene.add(cube)
  cube.layers.set(0)

  const cubeGeometry1 = new THREE.BoxGeometry(1, 1, 1) //几何体对象
  const cubeMaterial1 = new THREE.MeshBasicMaterial({ color: 'hotpink' }) //材质
  const cube1 = new THREE.Mesh(cubeGeometry1, cubeMaterial1) //根据几何体和材质创建物体
  // 将几何体添加到场景当中
  scene.add(cube1)
  cube1.position.set(1,0,0)
  cube1.layers.set(1)

  const cubeGeometry2 = new THREE.BoxGeometry(1, 1, 1) //几何体对象
  const cubeMaterial2 = new THREE.MeshBasicMaterial({ color: 'skyblue' }) //材质
  const cube2 = new THREE.Mesh(cubeGeometry2, cubeMaterial2) //根据几何体和材质创建物体
  // 将几何体添加到场景当中
  scene.add(cube2)
  cube2.position.set(2,0,0)
  cube2.layers.set(2)

  // 添加坐标轴辅助器
  const axesHelper = new THREE.AxesHelper(5)
  scene.add(axesHelper)
  axesHelper.layers.enableAll()

  // 轨道控制器
  const controls  = new OrbitControls(camera.value, renderer.domElement)
  // 循环渲染
  function animate() {
    requestAnimationFrame(animate)
    renderer.render(scene, camera.value)
    controls.update()
  }
  animate()

  window.addEventListener("resize", () => {
    // 更新摄像头
    camera.value.aspect = threeContainer.offsetWidth / threeContainer.offsetHeight
    //   更新摄像机的投影矩阵
    camera.value.updateProjectionMatrix()
    //   更新渲染器
    renderer.setSize(threeContainer.offsetWidth, threeContainer.offsetHeight)
    //   设置渲染器的像素比
    renderer.setPixelRatio(threeContainer.devicePixelRatio)
  })
})

const setLayer = (num) => {
  camera.value.layers.set(num)
}
const enableLayer = (num) => {
  camera.value.layers.enable(num)
}
const toggleLayer = (num) => {
  camera.value.layers.toggle(num)
}
const enableAll = () => {
  camera.value.layers.enableAll()
}
const reset = () => {
  camera.value.layers.disableAll()
  camera.value.layers.set(0)
}
</script>
 
<style lang="scss" scoped>
.app{
  width: 100vw;
  height: 100vh;
  position: relative;
  #three{
    width: 100%;
    height: 100%;
    background-color: skyblue;
  }
  .btns{
    position: absolute;
    top: 10px;
    right: 20px;
    button{
      cursor: pointer;
      margin-right: 10px;
      margin-top: 10px;
    }
  }
}
</style>

上述代码设置三个物体的图层分别为0、1、2,然后通过控制相机所在图层来控制物体显示和隐藏。 

关闭图层

.disable(layerNum) 删除layerNum图层

.disableAll() 关闭所有图层

    <div class="btns">
      <button @click="enableAll">layers.enableAll()</button>
      <br>
      <button @click="hideLayer(0)">layers.disable(0)</button>
      <button @click="hideLayer(1)">layers.disable(1)</button>
      <button @click="hideLayer(2)">layers.disable(2)</button>
      <br>
      <button @click="disableAll">layers.disableAll()</button>
    </div>
const enableAll = () => {
  camera.value.layers.enableAll()
}
const hideLayer = (num) => {
  camera.value.layers.disable(num)
}
const disableAll = () => {
  camera.value.layers.disableAll()
}

其他

.test(layers) 如果传入图层对象与当前对象属于相同的一组图层,则返回 true,否则返回 false。 

.isEnabled(layerNum) 如果layerNum层已启用,则返回true。

console.log('cube&&camera', cube.layers.test(camera.value.layers));
console.log('cube1&&camera', cube1.layers.test(camera.value.layers));
console.log('cube2&&camera', cube2.layers.test(camera.value.layers));

/*
打印结果:
cube&&camera true
cube1&&camera false
cube2&&camera false
*/
const enableAll = () => {
  camera.value.layers.enableAll()
  console.log(
    camera.value.layers.isEnabled(0),
    camera.value.layers.isEnabled(1),
    camera.value.layers.isEnabled(2),
    camera.value.layers.isEnabled(3),
    camera.value.layers.isEnabled(31)
  ); //true true true true true 
}

转载请注明出处或者链接地址:https://www.qianduange.cn//article/13208.html
标签
webglthreejs
评论
发布的文章

JQuery中的load()、$

2024-05-10 08:05:15

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!