Three.js - 几何体(五)

871 阅读4分钟

「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战

几何体

  • three.js中如球体、立方体、平面、狗、猫、人、树、建筑等物体,都是几何体。它们都是根据大量顶点参数生成。
  • three.js中内置了许多基本几何体,也提供了自定义几何体的方法。在开发中常见的做法是让美术在 3D 建模软件中创建 3D 模型,在由开发人员进行交互开发。

常见几何体

BoxGeometry 盒子

  • 分段数简单理解,就是每多一个分段,在对应面的轴上添加两个顶点,增加组成这个面三角形的数量。分段数越多面就越精细,性能消耗也会变大。
      const width = 8 // 宽度
      const height = 8 // 高度
      const depth = 8 // 深度
      const widthSegments = 4 // ui: 宽度的分段数
      const heightSegments = 4 // ui: 高度的分段数
      const depthSegments = 4 // ui: 深度的分段数
      const boxGeometry = new THREE.BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)

image.png

SphereGeometry 球

  • SphereGeometry是通过扫描并计算围绕着Y轴和X轴的顶点来创建的。我们可以通过修改水平、垂直扫描角度的大来实现球体切片。
      const radius = 8 // 球体半径
      const widthSegments = 32 // 水平分段数
      const heightSegments = 16 // 垂直分段数
      const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments)

      // 网格
      const mesh = new THREE.Mesh(geometry, material)
      mesh.position.x = 10
      scene.add(mesh)

      {
        const radius = 8 // 球体半径
        const widthSegments = 32 // 水平分段数
        const heightSegments = 16 // 垂直分段数
        const phiStart = Math.PI * 0.25 // 水平(经线)起始角度
        const phiLength = Math.PI * 2 // 水平(经线)扫描角度的大小
        const thetaStart = Math.PI * 0.25 // 垂直(纬线)起始角度
        const thetaLength = Math.PI * 0.5 // 垂直(纬线)扫描角度大小
        const geometry1 = new THREE.SphereGeometry(
          radius,
          widthSegments,
          heightSegments,
          phiStart,
          phiLength,
          thetaStart,
          thetaLength
        )

        // 网格
        const mesh1 = new THREE.Mesh(geometry1, material)
        mesh1.position.x = -10
        scene.add(mesh1)
      }

image.png

PlaneGeometry 平面几何体

      const width = 8 // 宽度
      const height = 8 // 高度
      const widthSegments = 2 //  宽度的分段数
      const heightSegments = 2 // 高度的分段数
      const geometry = new THREE.PlaneGeometry(width, height, widthSegments, heightSegments)

image.png

BufferGeometry 自定义几何体

  • BufferGeometry是面片、线或点几何体的有效表述。通过顶点位置、法相量、颜色值、UV 坐标等值来绘制几何体
  • 使用BufferGeometry可以有效减少向 GPU 传输顶点数据所需的开销。
  1. 定义面的顶点位置,法线坐标(法线是面朝向的信息)。一个面是两个三角形组成,所以需要6个顶点,一个立方体就需要36个顶点信息。
      const vertices = [
        // front
        { pos: [-1, -1, 1], norm: [0, 0, 1] },
        { pos: [1, -1, 1], norm: [0, 0, 1] },
        { pos: [-1, 1, 1], norm: [0, 0, 1] },

        { pos: [-1, 1, 1], norm: [0, 0, 1] },
        { pos: [1, -1, 1], norm: [0, 0, 1] },
        { pos: [1, 1, 1], norm: [0, 0, 1] },
        // right
        { pos: [1, -1, 1], norm: [1, 0, 0] },
        { pos: [1, -1, -1], norm: [1, 0, 0] },
        { pos: [1, 1, 1], norm: [1, 0, 0] },

        { pos: [1, 1, 1], norm: [1, 0, 0] },
        { pos: [1, -1, -1], norm: [1, 0, 0] },
        { pos: [1, 1, -1], norm: [1, 0, 0] },
        // back
        { pos: [1, -1, -1], norm: [0, 0, -1] },
        { pos: [-1, -1, -1], norm: [0, 0, -1] },
        { pos: [1, 1, -1], norm: [0, 0, -1] },

        { pos: [1, 1, -1], norm: [0, 0, -1] },
        { pos: [-1, -1, -1], norm: [0, 0, -1] },
        { pos: [-1, 1, -1], norm: [0, 0, -1] },
        // left
        { pos: [-1, -1, -1], norm: [-1, 0, 0] },
        { pos: [-1, -1, 1], norm: [-1, 0, 0] },
        { pos: [-1, 1, -1], norm: [-1, 0, 0] },

        { pos: [-1, 1, -1], norm: [-1, 0, 0] },
        { pos: [-1, -1, 1], norm: [-1, 0, 0] },
        { pos: [-1, 1, 1], norm: [-1, 0, 0] },
        // top
        { pos: [1, 1, -1], norm: [0, 1, 0] },
        { pos: [-1, 1, -1], norm: [0, 1, 0] },
        { pos: [1, 1, 1], norm: [0, 1, 0] },

        { pos: [1, 1, 1], norm: [0, 1, 0] },
        { pos: [-1, 1, -1], norm: [0, 1, 0] },
        { pos: [-1, 1, 1], norm: [0, 1, 0] },
        // bottom
        { pos: [1, -1, 1], norm: [0, -1, 0] },
        { pos: [-1, -1, 1], norm: [0, -1, 0] },
        { pos: [1, -1, -1], norm: [0, -1, 0] },

        { pos: [1, -1, -1], norm: [0, -1, 0] },
        { pos: [-1, -1, 1], norm: [0, -1, 0] },
        { pos: [-1, -1, -1], norm: [0, -1, 0] }
      ]
      const positions = []
      const normals = []
      // 以数组形式获取 数据
      for (const vertex of vertices) {
        positions.push(...vertex.pos)
        normals.push(...vertex.norm)
      }
  1. 通过.setAttribute()设置定义好的顶点信息。这里需要注意的是.BufferAttribute()第二个参数是确认,数组中连续的几个值组合为一组信息。
      const geometry = new THREE.BufferGeometry()
      const positionNumComponents = 3 // 3个一组 为一个顶点
      const normalNumComponents = 3 // 3个一组 为一个顶点
      geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents))
      geometry.setAttribute('normal', new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents))

image.png

  • 自定义几何体的优势是它和GPU传输的数度快,缺点是顶点信息难以修改,在开发中需要根据需求判断是否使用。

总结

  • three.js中内置的几何体非常的多,需要深入了解的需要到官网上查看。本节简单的介绍了几何体是什么。
  • 在创建几何体时需要注意,分段数的大小要控制好。细分的越少,运行的越流畅,使用的内存也会更少。细分的越多,动画越精细,运行的越不流畅。