第三篇:几何体入门:内置几何体全解析

发布于:2025-08-02 ⋅ 阅读:(10) ⋅ 点赞:(0)

第三篇:几何体入门:内置几何体全解析

引言

几何体是Three.js世界的基石,它们定义了3D物体的形状和结构。Three.js提供20+种内置几何体,从基础立方体到复杂多面体,覆盖90%的3D建模需求。本文将深入解析12种核心几何体,并通过Vue3实现交互式参数调节面板,助你掌握几何造型的核心技术。


在这里插入图片描述

1. 几何体核心概念
1.1 顶点(Vertex)与面(Face)

几何体由两大基本元素构成:

几何体
顶点
位置坐标
连接顶点的三角形
  • 顶点(Vertex):3D空间中的点,包含(x,y,z)坐标
  • 面(Face):由三个顶点组成的三角形(Three.js仅支持三角面)
  • 示例:立方体有8个顶点和12个面(6个面×2个三角形)
1.2 几何体类型对比
几何体名称 顶点数 面数 主要参数 应用场景
BoxGeometry 8 12 宽/高/深 建筑/家具
SphereGeometry 482 960 半径/分段数 星球/粒子
CylinderGeometry 136 240 顶径/底径/高度 柱体/管道
TorusGeometry 800 1600 半径/管道径/分段数 圆环/轮胎
IcosahedronGeometry 12 20 半径/细节层级 低模球体

2. 12大核心几何体详解
2.1 立方体(BoxGeometry)
<script setup>
import { ref } from 'vue';

const boxParams = ref({
  width: 1,
  height: 1,
  depth: 1,
  widthSegments: 1,
  heightSegments: 1,
  depthSegments: 1
});

// 创建立方体
const createBox = () => {
  return new THREE.BoxGeometry(
    boxParams.value.width,
    boxParams.value.height,
    boxParams.value.depth,
    boxParams.value.widthSegments,
    boxParams.value.heightSegments,
    boxParams.value.depthSegments
  );
};
</script>

参数解析

  • widthSegments:宽度分段数(影响表面细分)
  • 当分段数>1时,可用于变形动画或曲面效果
2.2 球体(SphereGeometry)
const sphere = new THREE.SphereGeometry(
  1,    // 半径
  32,   // 经度分段数(水平细分数)
  16,   // 纬度分段数(垂直细分数)
  0,    // 水平起始角度(0-Math.PI*2)
  Math.PI * 2, // 水平覆盖角度
  0,    // 垂直起始角度(0-Math.PI)
  Math.PI      // 垂直覆盖角度
);

分段数影响

2.3 圆柱体(CylinderGeometry)
const cylinder = new THREE.CylinderGeometry(
  0.5,  // 顶部半径
  1,    // 底部半径
  2,    // 高度
  16,   // 径向分段数
  4,    // 高度分段数
  false // 是否开启顶盖/底盖
);

特殊形态

  • 圆锥:顶部半径=0
  • 棱柱:分段数=4/6/8
  • 圆台:顶部半径≠底部半径
2.4 圆环(TorusGeometry)
const torus = new THREE.TorusGeometry(
  1,    // 圆环半径
  0.3,  // 管道半径
  16,   // 径向分段数
  100,  // 管道分段数
  Math.PI * 2 // 圆弧角度(缺省为整圆)
);

应用场景:行星环、戒指、管道弯曲


3. 其他实用几何体
3.1 平面(PlaneGeometry)
const plane = new THREE.PlaneGeometry(
  10,   // 宽度
  10,   // 高度
  10,   // 宽度分段
  10    // 高度分段
);

用途:地面、水面、公告板

3.2 圆环缓冲(TorusKnotGeometry)
const knot = new THREE.TorusKnotGeometry(
  1,    // 半径
  0.3,  // 管道半径
  100,  // 管道分段
  16,   // 交叉分段
  2,    // P值(控制缠绕次数)
  3     // Q值(控制围绕轴旋转次数)
);

数学原理:通过参数方程生成复杂拓扑结构

3.3 二十面体(IcosahedronGeometry)
const ico = new THREE.IcosahedronGeometry(
  1,    // 半径
  2     // 细节层级(0=基础,每+1细分4倍面数)
);

特点:最接近球体的多面体,常用于低模风格


4. Vue3实战:几何体参数调节器
4.1 项目结构
src/
  ├── components/
  │    ├── GeometryController.vue  // 参数控制面板
  │    ├── GeometryViewer.vue      // 3D显示组件
  │    └── ParamSlider.vue         // 通用滑动条
  └── App.vue
4.2 核心代码实现
<!-- GeometryController.vue -->
<script setup>
import { ref, watch } from 'vue';

// 支持的几何体类型
const GEOMETRY_TYPES = {
  BOX: 'Box',
  SPHERE: 'Sphere',
  CYLINDER: 'Cylinder',
  TORUS: 'Torus'
};

const currentType = ref(GEOMETRY_TYPES.BOX);

// 几何体参数响应式对象
const params = ref({
  // 立方体参数
  [GEOMETRY_TYPES.BOX]: {
    width: 2, height: 1, depth: 1,
    widthSegments: 1, heightSegments: 1, depthSegments: 1
  },
  // 球体参数
  [GEOMETRY_TYPES.SPHERE]: {
    radius: 1, widthSegments: 32, heightSegments: 16,
    phiStart: 0, phiLength: Math.PI * 2,
    thetaStart: 0, thetaLength: Math.PI
  },
  // 圆柱体参数
  [GEOMETRY_TYPES.CYLINDER]: {
    radiusTop: 0.5, radiusBottom: 1, height: 2,
    radialSegments: 32, heightSegments: 8
  },
  // 圆环参数
  [GEOMETRY_TYPES.TORUS]: {
    radius: 1, tube: 0.3, radialSegments: 100, tubularSegments: 16
  }
});

// 生成当前几何体的配置项
const currentParams = computed(() => ({
  type: currentType.value,
  ...params.value[currentType.value]
}));

// 发射更新事件
const emit = defineEmits(['update']);
watch(currentParams, (val) => {
  emit('update', val);
}, { deep: true });
</script>

<template>
  <div class="controller">
    <select v-model="currentType">
      <option v-for="(type, key) in GEOMETRY_TYPES" :value="type" :key="key">
        {{ type }}
      </option>
    </select>
    
    <template v-if="currentType === GEOMETRY_TYPES.BOX">
      <ParamSlider label="宽度" v-model="params.BOX.width" :min="0.1" :max="5" :step="0.1"/>
      <ParamSlider label="高度" v-model="params.BOX.height" :min="0.1" :max="5" :step="0.1"/>
      <ParamSlider label="深度" v-model="params.BOX.depth" :min="0.1" :max="5" :step="0.1"/>
      <!-- 其他参数 -->
    </template>
    
    <!-- 其他几何体参数控制 -->
  </div>
</template>
4.3 几何体动态更新
<!-- GeometryViewer.vue -->
<script setup>
import { ref, watch } from 'vue';
import * as THREE from 'three';

const props = defineProps(['geometryParams']);
let geometry = ref(null);
let mesh = ref(null);

// 根据参数创建几何体
const createGeometry = (params) => {
  switch(params.type) {
    case 'Box':
      return new THREE.BoxGeometry(...Object.values(params));
    case 'Sphere':
      return new THREE.SphereGeometry(...Object.values(params));
    // 其他几何体...
  }
};

// 监听参数变化
watch(() => props.geometryParams, (newParams) => {
  // 释放旧几何体内存
  if (geometry.value) geometry.value.dispose();
  
  // 创建新几何体
  geometry.value = createGeometry(newParams);
  
  // 更新网格
  if (mesh.value) {
    mesh.value.geometry = geometry.value;
  } else {
    const material = new THREE.MeshNormalMaterial();
    mesh.value = new THREE.Mesh(geometry.value, material);
    scene.add(mesh.value);
  }
}, { immediate: true });
</script>
4.4 性能优化:几何体复用
// 使用BufferGeometryUtils合并几何体
import { mergeBufferGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils';

const geometries = [];
for (let i = 0; i < 100; i++) {
  const box = new THREE.BoxGeometry(0.2, 0.2, 0.2);
  box.translate(Math.random()*10-5, Math.random()*10-5, Math.random()*10-5);
  geometries.push(box);
}

// 合并为单个几何体(减少Draw Call)
const mergedGeometry = mergeBufferGeometries(geometries);
const mesh = new THREE.Mesh(mergedGeometry, material);
scene.add(mesh);

5. 几何体操作进阶技巧
5.1 顶点修改:创建波浪平面
const plane = new THREE.PlaneGeometry(10, 10, 50, 50);
const positions = plane.attributes.position.array;

// 遍历顶点添加波浪效果
for (let i = 0; i < positions.length; i += 3) {
  const x = positions[i];
  const z = positions[i+2];
  
  // 使用正弦函数生成高度
  positions[i+1] = Math.sin(x * 0.5) * Math.cos(z * 0.5) * 1.5;
}

// 通知Three.js更新
plane.attributes.position.needsUpdate = true;
5.2 UV坐标操作:纹理映射
const geometry = new THREE.BoxGeometry(2, 2, 2);
const uvs = geometry.attributes.uv.array;

// 修改UV坐标实现特殊纹理映射
for (let i = 0; i < uvs.length; i += 2) {
  uvs[i] *= 2;   // U坐标拉伸
  uvs[i+1] *= 2; // V坐标拉伸
}

geometry.attributes.uv.needsUpdate = true;

// 应用纹理
const texture = new THREE.TextureLoader().load('brick.jpg');
const material = new THREE.MeshBasicMaterial({ map: texture });
5.3 法线重计算
geometry.computeVertexNormals(); // 自动计算法线

// 手动修改法线
const normals = geometry.attributes.normal.array;
for (let i = 0; i < normals.length; i += 3) {
  normals[i] = 0;   // X分量
  normals[i+1] = 1; // Y分量(指向正上方)
  normals[i+2] = 0; // Z分量
}
geometry.attributes.normal.needsUpdate = true;

6. 性能优化指南
6.1 几何体选择策略
graph TD
    A[选择几何体] --> B{需要变形?}
    B -->|是| C[高分段几何体]
    B -->|否| D{静态物体?}
    D -->|是| E[使用BufferGeometry]
    D -->|否| F[使用基础几何体]
6.2 内存管理最佳实践
  1. 几何体复用:相同物体共享几何体

    const boxGeometry = new THREE.BoxGeometry();
    const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
    
    const mesh1 = new THREE.Mesh(boxGeometry, material);
    const mesh2 = new THREE.Mesh(boxGeometry, material.clone());
    
  2. 及时释放内存

    // 组件卸载时
    onUnmounted(() => {
      geometry.dispose();
      material.dispose();
    });
    
  3. 避免每帧创建:在动画循环外创建几何体

6.3 实例化渲染(InstancedMesh)
const geometry = new THREE.BoxGeometry(0.2, 0.2, 0.2);
const material = new THREE.MeshBasicMaterial();
const instances = new THREE.InstancedMesh(geometry, material, 1000);

// 设置每个实例的位置和旋转
const matrix = new THREE.Matrix4();
for (let i = 0; i < 1000; i++) {
  matrix.setPosition(
    Math.random() * 100 - 50,
    Math.random() * 100 - 50,
    Math.random() * 100 - 50
  );
  instances.setMatrixAt(i, matrix);
}

scene.add(instances);

性能提升:1000个立方体,Draw Call从1000次降为1次


7. 常见问题解答

Q1:如何创建自定义形状?

  • 简单形状:组合基础几何体(Group)
  • 复杂形状:使用BufferGeometry手动设置顶点
  • 专业建模:Blender创建后导出GLTF

Q2:几何体分段数设置多少合适?

  • 静态物体:低分段(如Box用1x1x1)
  • 曲面物体:32-64分段(球体/圆柱)
  • 变形物体:≥64分段(波浪平面)
  • 性能临界点:单物体面数<10000

Q3:几何体显示为黑色怎么办?

  1. 检查材质是否需要光照(MeshBasicMaterial不受光)
  2. 确认场景中有灯光
  3. 验证法线方向是否正确(使用MeshNormalMaterial调试)

8. 总结

通过本文,你已掌握:

  1. 12种核心几何体的创建与参数配置
  2. 顶点(Vertex)与面(Face)的底层原理
  3. Vue3实现几何体参数实时调节器
  4. 几何体内存管理与性能优化技巧
  5. 高级操作:顶点修改、UV映射、法线计算

关键点:Three.js中所有几何体最终都转换为BufferGeometry,它使用TypedArray直接操作二进制数据,比传统Geometry性能提升3-5倍。


下一篇预告

第四篇:材质与纹理:让物体"真实"起来
你将学习:

  • 6种核心材质特性对比(Basic/Standard/Physical)
  • 纹理贴图技术:漫反射/法线/环境遮挡贴图
  • UV映射原理与自定义UV展开
  • PBR(物理渲染)材质工作流
  • Vue3实现材质实时编辑器

准备好为几何体注入灵魂了吗?让我们进入Three.js的视觉魔法世界!


网站公告

今日签到

点亮在社区的每一天
去签到