Babylon.js学习之路《十、高级几何体:自定义模型与复杂形状生成》

发布于:2025-06-21 ⋅ 阅读:(16) ⋅ 点赞:(0)

在这里插入图片描述


1. 引言:高级几何体的应用场景

  • 核心价值

    • 突破基础几何体限制,创建复杂模型(如建筑结构、有机生物、工业零件)。
  • 案例对比

    • 基础几何体:仅能表现简单形状(立方体/球体),缺乏细节。
    • 高级几何体:通过参数化建模生成齿轮、地形、管道等专业模型。

2. 参数化建模:Babylon.MeshBuilder

2.1 扩展几何体类型

  • 内置复杂几何体

    // 创建十二面体
    const dodecahedron = BABYLON.MeshBuilder.CreatePolyhedron("dodeca", 
      { type: 2, size: 2 }, // type 2 对应十二面体
      scene
    );
    

    在这里插入图片描述

    // 创建圆环结(Torus Knot)
    const torusKnot = BABYLON.MeshBuilder.CreateTorusKnot(
      "knot", // 网格的名称
      0.5, // 设置圆环结的全局半径大小
      0.2, // 设置圆环管的直径大小
      128, // 设置每个管段上的边数
      64, // 设置要将结分解为的管的数量
      2: // X轴上的匝数
      3: // Y轴上的匝数
      scene
    );
    

    在这里插入图片描述

2.2 自定义多边形(ExtrudePolygon)

  • 生成2D形状拉伸的3D模型
    // Poteau Gauche
    const pts_pg = [
        new BABYLON.Vector3(0, 0, 0), 
        new BABYLON.Vector3(100, 0, 0),   
        new BABYLON.Vector3(100, 0, 100), 
        new BABYLON.Vector3(0, 0, 100), 
        
    ]
    const poteau_gauche = BABYLON.MeshBuilder.ExtrudePolygon(
        "poteau_gauche",
        {
            shape: pts_pg,
            depth: 1100
        }
    )
    
    在这里插入图片描述

3. 顶点级建模:自定义VertexData

3.1 手动定义顶点数据

  • 步骤
    定义顶点位置(positions)
    定义顶点索引(indices)
    可选:法线(normals)、UV坐标(uvs)
  • 代码示例:创建三角锥
    const customMesh = new BABYLON.Mesh("custom", scene);
    const vertexData = new BABYLON.VertexData();
    
    // 顶点坐标(4个点:底面3个,顶点1个)
    vertexData.positions = [
      0, 0, 0,   // 底面点1
      1, 0, 0,   // 底面点2
      0.5, 0, 1, // 底面点3
      0.5, 1, 0.5 // 顶点
    ];
    
    // 三角形面索引(4个面:底面+3个侧面)
    vertexData.indices = [
      0, 1, 2,   // 底面
      0, 1, 3,   // 侧面1
      1, 2, 3,   // 侧面2
      2, 0, 3    // 侧面3
    ];
    
    // 计算法线(否则光照异常)
    BABYLON.VertexData.ComputeNormals(vertexData.positions, vertexData.indices, vertexData.normals);
    
    vertexData.applyToMesh(customMesh);
    

3.2 动态生成地形(高度图)

  • 基于噪声函数生成起伏地形
    const size = 100;
    const subdivisions = 50;
    const terrain = BABYLON.MeshBuilder.CreateGround("terrain", 
      { width: size, height: size, subdivisions: subdivisions },
      scene
    );
    
    // 修改顶点Y坐标
    const positions = terrain.getVerticesData(BABYLON.VertexBuffer.PositionKind);
    for (let i = 0; i < positions.length; i += 3) {
      const x = positions[i];
      const z = positions[i + 2];
      positions[i + 1] = 5 * Math.sin(x * 0.2) * Math.cos(z * 0.2); // 噪声函数
    }
    terrain.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positions);
    

4. 几何体变形与动态更新

4.1 实时顶点动画(波浪效果)

  • 代码
    scene.registerBeforeRender(() => {
      const time = performance.now() / 1000;
      const positions = plane.getVerticesData(BABYLON.VertexBuffer.PositionKind);
      for (let i = 0; i < positions.length; i += 3) {
        const x = positions[i];
        const z = positions[i + 2];
        positions[i + 1] = Math.sin(x + time) * Math.cos(z + time);
      }
      plane.updateVerticesData(BABYLON.VertexBuffer.PositionKind, positions);
    });
    

4.2 几何体布尔运算(差集/并集)

  • 使用CSG(Constructive Solid Geometry)
    const box = BABYLON.MeshBuilder.CreateBox("box", { size: 2 }, scene);
    const sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 2 }, scene);
    sphere.position.x = 1;
    
    // 转换为CSG对象
    const boxCSG = BABYLON.CSG.FromMesh(box);
    const sphereCSG = BABYLON.CSG.FromMesh(sphere);
    
    // 布尔运算(差集:立方体减去球体)
    const resultCSG = boxCSG.subtract(sphereCSG);
    const resultMesh = resultCSG.toMesh("result", null, scene);
    box.dispose();
    sphere.dispose();
    

5. 实战任务

任务1:生成参数化齿轮

  • 目标
  • 代码要点
    function createGear(teeth: number, radius: number) {
      const points = [];
      for (let i = 0; i < teeth * 2; i++) {
        const angle = (i / (teeth * 2)) * Math.PI * 2;
        const r = i % 2 === 0 ? radius : radius * 0.8; // 交替半径生成齿槽
        points.push(new BABYLON.Vector3(r * Math.cos(angle), 0, r * Math.sin(angle)));
      }
      return BABYLON.MeshBuilder.ExtrudePolygon("gear", 
        { shape: points, depth: 0.5 },
        scene
      );
    }
    const gear = createGear(16, 3); // 16齿,半径3
    

任务2:动态生长的植物

  • 目标
  • 实现步骤
    1. 使用L-System算法生成分支结构。
    2. 通过顶点数据构建圆柱体分支。
    3. 添加生长动画(逐帧增加分支长度)。

6. 性能优化与调试

6.1 优化策略

  • 合并网格(MergeMeshes):减少Draw Call。
    const merged = BABYLON.Mesh.MergeMeshes([mesh1, mesh2], true); // 第二个参数启用材质合并
    
  • 简化复杂网格:使用simplify()方法降低面数。
    const simplified = BABYLON.SimplificationStrategy.QUADRATIC(mesh);
    mesh.simplify([{ distance: 100, quality: 0.8 }]); // 根据距离简化
    

6.2 调试工具

  • 显示顶点法线
    BABYLON.Debug.AxesViewer(scene, 1); // 显示坐标系
    const normalsViewer = new BABYLON.Debug.NormalsViewer(mesh, scene); // 显示法线
    

7. 总结与扩展

  • 核心技能:参数化建模、顶点操作、布尔运算、动态几何更新。
  • 扩展方向
    • GPU加速生成:通过Compute Shader实时生成几何体。
    • 程序化城市生成:结合噪声函数和规则系统。
    • 三维扫描重建:从点云数据生成网格。

通过本指南,开发者可掌握从基础扩展几何体到专业级程序化建模的全套技能,满足工业设计、游戏开发等领域的复杂需求。


网站公告

今日签到

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