Published on

THREE.js 知识: 创建 Mesh

Authors
  • avatar
    Name
    王凯
    Twitter

 

1. 线

曲线类名说明
Line线段
LineLoop自闭合线段
LineCurveTHREE.Line 用于“可视化显示线段”,THREE.LineCurve 用于“数学定义路径”
LineCurve3三维 THREE.LineCurve
QuadraticBezierCurve二维二次贝塞尔曲线
CubicBezierCurve二维三次贝塞尔曲线
QuadraticBezierCurve3三维二次贝塞尔曲线
CubicBezierCurve3三维三次贝塞尔曲线
ArcCurve圆弧
EllipseCurve椭圆
CatmullRomCurve3平滑连接多个三维点的曲线(常用于轨迹)
SplineCurve平滑连接二维点的样条曲线
// Line & LineLoop
const points = [
  new THREE.Vector3(0, 60, 0),
  new THREE.Vector3(0, 0, 60),
  new THREE.Vector3(60, 0, 0),
  new THREE.Vector3(0, 60, 0), // LineLoop 不需要此点,即可完成合并
]
const geometry = new THREE.BufferGeometry()
const material = new THREE.LineBasicMaterial({ color: '#ffffff' })
geometry.setFromPoints(points)
scene.add(new THREE.Line(geometry, material))
// scene.add(new THREE.LineLoop(geometry, material))

const getLineMesh = (path) => {
  const geometry = new THREE.BufferGeometry().setFromPoints(path.getPoints(100))
  const material = new THREE.LineBasicMaterial({ color: 0xffffff })
  return new THREE.Line(geometry, material)
}

// LineCurve
const path = new THREE.CurvePath<THREE.Vector2>()
path.add(new THREE.LineCurve(new THREE.Vector2(0, 60), new THREE.Vector2(60, 0)))
scene.add(getLineMesh(path))

// LineCurve3
const path = new THREE.CurvePath<THREE.Vector3>()
path.add(
  new THREE.LineCurve3(new THREE.Vector3(60, 0, 0), new THREE.Vector3(0, 0, 60))
)
scene.add(getLineMesh(path))

// QuadraticBezierCurve
const curve = new THREE.QuadraticBezierCurve(
  new THREE.Vector2(0, 0),
  new THREE.Vector2(50, 100),
  new THREE.Vector2(100, 0)
)
scene.add(getLineMesh(curve))

// QuadraticBezierCurve3
const curve = new THREE.QuadraticBezierCurve3(
  new THREE.Vector3(0, 0, 20),
  new THREE.Vector3(-50, 100, 20),
  new THREE.Vector3(-100, 0, 20)
)
scene.add(getLineMesh(curve))

// CubicBezierCurve
const curve = new THREE.CubicBezierCurve(
  new THREE.Vector2(0, 0),
  new THREE.Vector2(50, 100),
  new THREE.Vector2(80, 10),
  new THREE.Vector2(150, 0)
)
scene.add(getLineMesh(curve))

// CubicBezierCurve3
const curve = new THREE.CubicBezierCurve3(
  new THREE.Vector3(0, 0, 20),
  new THREE.Vector3(-50, 100, 20),
  new THREE.Vector3(-80, 10, 20),
  new THREE.Vector3(-150, 0, 20)
)
scene.add(getLineMesh(curve))

// ArcCurve
const curve = new THREE.ArcCurve(0, 0, 60, 0, Math.PI)
scene.add(getLineMesh(curve))

// EllipseCurve
const curve = new THREE.EllipseCurve(0, 0, 100, 60, 0, Math.PI)
scene.add(getLineMesh(curve))

 

2. 规则几何体

几何体构造函数参数说明
立方体BoxGeometry也可传入段数
球体SphereGeometry经常用于星球
圆柱体CylinderGeometry圆锥体也可以通过 top/bottom 调整
圆锥体ConeGeometry底部圆形、顶部尖
圆形CircleGeometry用于基础面片
平面PlaneGeometry常用于地面或背景
环形RingGeometry用于圆环等
圆环体(甜甜圈)TorusGeometry中空圆体
圆环结(拓扑结)TorusKnotGeometry特别适合做动画或展示
四面体TetrahedronGeometry金字塔型几何
八面体OctahedronGeometry正八面体
十二面体DodecahedronGeometry正十二面体
二十面体IcosahedronGeometry用于建模多面体
const getMesh = (
  geometry,
  materialParameters: THREE.MeshBasicMaterialParameters = {}
) => {
  const material = new THREE.MeshBasicMaterial(materialParameters)
  return new THREE.Mesh(geometry, material)
}

scene.add(getMesh(new THREE.BoxGeometry(40, 40, 40)))
scene.add(getMesh(new THREE.SphereGeometry(40)))
// radiusTop: 60, radiusBottom: 60, height: 60
scene.add(getMesh(new THREE.CylinderGeometry(60, 60, 60)))
// radius: 60, height: 60
scene.add(getMesh(new THREE.ConeGeometry(60, 60)))
scene.add(getMesh(new THREE.CircleGeometry(60)))
scene.add(getMesh(new THREE.PlaneGeometry(60, 60), { side: THREE.DoubleSide }))
// innerRadius: 60, outerRadius: 66
scene.add(getMesh(new THREE.RingGeometry(60, 66)))
// radius: 60, tube: 16
scene.add(getMesh(new THREE.TorusGeometry(60, 16)))
scene.add(getMesh(new THREE.TorusKnotGeometry(60, 16), { wireframe: true }))
scene.add(getMesh(new THREE.TetrahedronGeometry(80), { wireframe: true }))
scene.add(getMesh(new THREE.OctahedronGeometry(80), { wireframe: true }))
scene.add(getMesh(new THREE.DodecahedronGeometry(80), { wireframe: true }))
scene.add(getMesh(new THREE.IcosahedronGeometry(80), { wireframe: true }))

 

3. 不规则几何体

几何体类型类名说明
凸包几何体ConvexGeometry根据一组点生成凸包几何体
Shape 几何体ShapeGeometry根据 2D Shape 生成 3D 表面
拉伸几何体ExtrudeGeometry根据二维轮廓拉伸出三维形状
旋转几何体LatheGeometry将二维点旋转生成三维体(如酒杯、花瓶)
管道几何体TubeGeometry沿曲线路径生成管道模型
参数曲面ParametricGeometry通过自定义函数生成任意表面形状
Text 几何体TextGeometry将文字变成三维模型(需加载字体)
// 凸包几何体
const points: THREE.Vector3[] = [
  new THREE.Vector3(0, 0, 0),
  new THREE.Vector3(60, 0, 0),
  new THREE.Vector3(0, 60, 0),
  new THREE.Vector3(0, 0, 60),
]
const geometry = new ConvexGeometry(points)
const material = new THREE.MeshBasicMaterial({ wireframe: true })
scene.add(new THREE.Mesh(geometry, material))

// Shape / 拉伸几何体
const shape = new THREE.Shape()
shape.moveTo(0, 0)
shape.lineTo(0, 60)
shape.lineTo(60, 60)
shape.lineTo(60, 0)
const path = new THREE.Path()
path.arc(30, 30, 20, 0, Math.PI * 4, false)
shape.holes.push(path)
// const geometry = new THREE.ShapeGeometry(shape)
const geometry = new THREE.ExtrudeGeometry(shape, { depth: 12 })
const material = new THREE.MeshLambertMaterial({ wireframe: true })
scene.add(new THREE.Mesh(geometry, material))

// 旋转几何体
const points = [
  new THREE.Vector2(0, 0),
  new THREE.Vector2(50, 20),
  new THREE.Vector2(40, 40),
  new THREE.Vector2(20, 60),
  new THREE.Vector2(0, 80),
]
const geometry = new THREE.LatheGeometry(points, 20)
const material = new THREE.MeshLambertMaterial({ wireframe: true })
scene.add(new THREE.Mesh(geometry, material))

// 管道几何体
const points = [
  new THREE.Vector3(-100, 50, 50),
  new THREE.Vector3(50, 150, 0),
  new THREE.Vector3(100, 0, 100),
  new THREE.Vector3(100, 50, -50),
]
const curve = new THREE.CubicBezierCurve3(...points)
const geometry = new THREE.TubeGeometry(curve, 100, 20, 20)
const material = new THREE.MeshBasicMaterial({ wireframe: true })
scene.add(new THREE.Mesh(geometry, material))

// 参数曲面
const func = (u, v, target) => {
  const _u = u * Math.PI
  const _v = v * 2 * Math.PI
  const x = Math.sin(_u) * Math.cos(_v)
  const y = Math.sin(_u) * Math.sin(_v)
  const z = Math.cos(_u)
  target.set(x * 60, y * 60, z * 60)
}
const geometry = new ParametricGeometry(func, 50, 50)
const material = new THREE.MeshNormalMaterial()
scene.add(new THREE.Mesh(geometry, material))