Skip to content

原生几何体

Box(立方体)

js
const box = BABYLON.MeshBuilder.CreateBox("box", { size: 2, faceColors: [
    BABYLON.Color3.Blue(),
    BABYLON.Color3.Red(),
    BABYLON.Color3.Green(),
    BABYLON.Color3.Yellow(),
    BABYLON.Color3.Purple(),
    BABYLON.Color3.Orange()
] }, scene);

Sphere(球体)

js
const sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 2, segments: 32 }, scene);

Cylinder(圆柱体)

js
const cylinder = BABYLON.MeshBuilder.CreateCylinder("cylinder", { height: 3, diameterTop: 1, diameterBottom: 1, tessellation: 24, enclose: true }, scene);

Plane(平面)

js
const plane = BABYLON.MeshBuilder.CreatePlane("plane", { size: 5, sideOrientation: BABYLON.Mesh.DOUBLESIDE }, scene);

Torus(圆环体)

js
const torus = BABYLON.MeshBuilder.CreateTorus("torus", { radius: 2, tube: 0.5, tessellation: 32 }, scene);

MeshBuilder

支持链式调用,可以在一个语句中设置多个属性

js
const box = BABYLON.MeshBuilder.CreateBox("box", {
    size: 2,
    faceColors: [
        BABYLON.Color3.Blue(),
        BABYLON.Color3.Red(),
        BABYLON.Color3.Green(),
        BABYLON.Color3.Yellow(),
        BABYLON.Color3.Purple(),
        BABYLON.Color3.Orange()
    ],
    position: new BABYLON.Vector3(0, 1, 0)
}, scene);

参数化创建 创建一个带有不同尺寸的圆柱体

js
const cylinder = BABYLON.MeshBuilder.CreateCylinder("cylinder", { height: 5, diameterTop: 1, diameterBottom: 2, tessellation: 36 }, scene);

动态修改

js
box.scaling.x = 3; // 放大 x 轴方向
box.rotation.y = Math.PI / 4; // 绕 y 轴旋转 45 度
box.position.z = 3; // 移动到 z 轴方向 3 的位置

高级功能 使用 MeshBuilder 创建网格实例,从而提高渲染性能

js
const boxTemplate = BABYLON.MeshBuilder.CreateBox("boxTemplate", { size: 1 }, scene);
const boxInstance = new BABYLON.Mesh("boxInstance", scene);
boxInstance.setParent(boxTemplate);

合并几何体 Mesh.MergeMeshes 方法将多个网格合并成一个网格,减少绘制调用次数

js
const mergedMesh = BABYLON.Mesh.MergeMeshes([mesh1, mesh2, mesh3], true, true);

高级几何体生成与顶点缓冲区设计

使用参数化函数创建几何体

创建螺旋体

js
const createSpiral = (turns: number, radius: number, height: number, scene: BABYLON.Scene) => {
    const spiral = new BABYLON.Mesh("spiral", scene);
    const positions: number[] = [];
    const indices: number[] = [];
 
    const segments = 100;
    const angleStep = (2 * Math.PI) / segments;
    const heightStep = height / (turns * segments);
 
    for (let t = 0; t <= turns; t++) {
        for (let i = 0; i <= segments; i++) {
            const angle = i * angleStep;
            const x = radius * Math.cos(angle);
            const y = heightStep * t * segments + heightStep * i;
            const z = radius * Math.sin(angle);
            positions.push(x, y, z);
        }
    }
 
    for (let t = 0; t < turns; t++) {
        for (let i = 0; i < segments; i++) {
            const a = t * (segments + 1) + i;
            const b = a + segments + 1;
            indices.push(a, b, a + 1);
            indices.push(b, b + 1, a + 1);
        }
    }
 
    spiral.setVerticesData(BABYLON.VertexBuffer.PositionKind, positions, false);
    spiral.setIndices(indices);
    spiral.computeNormals();
    return spiral;
};
 
const spiral = createSpiral(5, 1, 5, scene);
  • 参数: 螺旋的圈数、半径、高度和所属场景。
  • positions: 存储顶点位置数据。
  • indices: 存储索引数据,用于定义三角面。
  • setVerticesData: 设置顶点数据。
  • setIndices: 设置索引数据。
  • computeNormals: 计算法线向量。

使用自定义顶点数据创建几何体

js
const createCustomPlane = (width: number, height: number, segments: number, scene: BABYLON.Scene) => {
    const plane = new BABYLON.Mesh("customPlane", scene);
    const positions: number[] = [];
    const normals: number[] = [];
    const uvs: number[] = [];
    const indices: number[] = [];
 
    const widthStep = width / segments;
    const heightStep = height / segments;
 
    for (let i = 0; i <= segments; i++) {
        for (let j = 0; j <= segments; j++) {
            const x = -width / 2 + i * widthStep;
            const y = 0;
            const z = -height / 2 + j * heightStep;
            positions.push(x, y, z);
            normals.push(0, 1, 0);
            uvs.push(i / segments, j / segments);
        }
    }
 
    for (let i = 0; i < segments; i++) {
        for (let j = 0; j < segments; j++) {
            const a = i * (segments + 1) + j;
            const b = a + segments + 1;
            indices.push(a, b, a + 1);
            indices.push(b, b + 1, a + 1);
        }
    }
 
    plane.setVerticesData(BABYLON.VertexBuffer.PositionKind, positions, false);
    plane.setVerticesData(BABYLON.VertexBuffer.NormalKind, normals, false);
    plane.setVerticesData(BABYLON.VertexBuffer.UVKind, uvs, false);
    plane.setIndices(indices);
    return plane;
};
 
const customPlane = createCustomPlane(5, 5, 100, scene);
  • 参数: 平面的宽度、高度、细分段数和所属场景。
  • positions: 存储顶点位置数据。
  • normals: 存储法线向量数据。
  • uvs: 存储纹理坐标数据。
  • indices: 存储索引数据,用于定义三角面。
  • setVerticesData: 设置不同类型的顶点数据。

使用顶点缓冲区 (Vertex Buffer) 创建几何体

js
const createWavePlane = (width: number, height: number, segments: number, scene: BABYLON.Scene) => {
    const plane = new BABYLON.Mesh("wavePlane", scene);
    const positions = new Float32Array((segments + 1) * (segments + 1) * 3);
    const normals = new Float32Array((segments + 1) * (segments + 1) * 3);
    const uvs = new Float32Array((segments + 1) * (segments + 1) * 2);
    const indices = new Uint32Array(segments * segments * 6);
 
    const widthStep = width / segments;
    const heightStep = height / segments;
 
    for (let i = 0; i <= segments; i++) {
        for (let j = 0; j <= segments; j++) {
            const x = -width / 2 + i * widthStep;
            const y = Math.sin(Math.sqrt(x * x + (i * heightStep) * (i * heightStep))) * 0.5;
            const z = -height / 2 + j * heightStep;
            const index = i * (segments + 1) + j;
            positions[index * 3] = x;
            positions[index * 3 + 1] = y;
            positions[index * 3 + 2] = z;
            normals[index * 3] = 0;
            normals[index * 3 + 1] = 1;
            normals[index * 3 + 2] = 0;
            uvs[index * 2] = i / segments;
            uvs[index * 2 + 1] = j / segments;
        }
    }
 
    for (let i = 0; i < segments; i++) {
        for (let j = 0; j < segments; j++) {
            const a = i * (segments + 1) + j;
            const b = a + segments + 1;
            indices[i * segments * 6 + j * 6] = a;
            indices[i * segments * 6 + j * 6 + 1] = b;
            indices[i * segments * 6 + j * 6 + 2] = a + 1;
            indices[i * segments * 6 + j * 6 + 3] = b;
            indices[i * segments * 6 + j * 6 + 4] = b + 1;
            indices[i * segments * 6 + j * 6 + 5] = a + 1;
        }
    }
 
    plane.setVerticesData(BABYLON.VertexBuffer.PositionKind, positions, false);
    plane.setVerticesData(BABYLON.VertexBuffer.NormalKind, normals, false);
    plane.setVerticesData(BABYLON.VertexBuffer.UVKind, uvs, false);
    plane.setIndices(indices);
    return plane;
};
 
const wavePlane = createWavePlane(10, 10, 100, scene);
  • 波浪形平面: 通过对 y 坐标应用正弦函数,生成波浪形状。
  • 顶点缓冲区: 使用 Float32Array 和 Uint32Array 来存储顶点数据。
  • setVerticesData: 设置顶点数据,包括位置、法线和纹理坐标。
  • setIndices: 设置索引数据。

性能优化

优先使用索引网格

js
const box = BABYLON.MeshBuilder.CreateBox("box", { size: 2 }, scene);
// 转换为非索引网格(不推荐)
box.setIndices(null);

顶点缓存优化

js
const boxTemplate = BABYLON.MeshBuilder.CreateBox("boxTemplate", { size: 1 }, scene);
const boxInstance1 = new BABYLON.Mesh("boxInstance1", scene);
boxInstance1.setParent(boxTemplate);
const boxInstance2 = new BABYLON.Mesh("boxInstance2", scene);
boxInstance2.setParent(boxTemplate);

Mesh.MergeMeshes 方法将多个网格合并成一个网格,减少绘制调用次数

js
const mergedMesh = BABYLON.Mesh.MergeMeshes([mesh1, mesh2, mesh3], true, true);