目录
一、合并网格方法
轻松地将多个网格合并到单个网格,请使用类的MergeMeshes
静态Mesh
var newMesh = BABYLON.Mesh.MergeMeshes(options)
options的参数:
属性 | 描述 |
---|---|
arrayOfMeshes | 一组网格。它们都应该是相同的材料。 |
disposeSource(可选) | 当为 true(默认)时,源网格将在完成后被处理。 |
allow32BitsIndices(可选) | 当顶点的总和 > 64k 时,必须将其设置为 true。 |
meshSubclass 可选) | 设置后,顶点插入此网格。然后可以将网格合并到一个网格子类中。 |
subdivideWithSubMeshes(可选) | 当为真(默认为假)时,将网格细分为具有网格源的子网格数组。 |
multiMultiMaterials(可选) | 当为 true(默认为 false)时,细分网格并接受多个多材质,忽略 subdivideWithSubMeshes。 |
由于multiMultiMaterials
默认为 false,因此生成的合并网格将仅应用一个材质(取自第一个网格)
注意:当你合并克隆的网格时,你需要在调用函数之前用 computeWorldMatrix 更新网格的世界矩阵。
二、详细内容
注意:本文介绍了内部合并过程。您还可以使用BABYLON.VertexData
object 及其merge()
函数来获得更简单的解决方案。
var mergeMeshes = function (meshName, arrayObj, scene) {
var arrayPos = [];
var arrayNormal = [];
var arrayUv = [];
var arrayUv2 = [];
var arrayColor = [];
var arrayMatricesIndices = [];
var arrayMatricesWeights = [];
var arrayIndice = [];
var savedPosition = [];
var savedNormal = [];
var newMesh = new BABYLON.Mesh(meshName, scene);
var UVKind = true;
var UV2Kind = true;
var ColorKind = true;
var MatricesIndicesKind = true;
var MatricesWeightsKind = true;
for (var i = 0; i != arrayObj.length; i++) {
if (!arrayObj[i].isVerticesDataPresent([BABYLON.VertexBuffer.UVKind])) UVKind = false;
if (!arrayObj[i].isVerticesDataPresent([BABYLON.VertexBuffer.UV2Kind])) UV2Kind = false;
if (!arrayObj[i].isVerticesDataPresent([BABYLON.VertexBuffer.ColorKind])) ColorKind = false;
if (!arrayObj[i].isVerticesDataPresent([BABYLON.VertexBuffer.MatricesIndicesKind])) MatricesIndicesKind = false;
if (!arrayObj[i].isVerticesDataPresent([BABYLON.VertexBuffer.MatricesWeightsKind])) MatricesWeightsKind = false;
}
for (i = 0; i != arrayObj.length; i++) {
var ite = 0;
var iter = 0;
arrayPos[i] = arrayObj[i].getVerticesData(BABYLON.VertexBuffer.PositionKind);
arrayNormal[i] = arrayObj[i].getVerticesData(BABYLON.VertexBuffer.NormalKind);
if (UVKind) arrayUv = arrayUv.concat(arrayObj[i].getVerticesData(BABYLON.VertexBuffer.UVKind));
if (UV2Kind) arrayUv2 = arrayUv2.concat(arrayObj[i].getVerticesData(BABYLON.VertexBuffer.UV2Kind));
if (ColorKind) arrayColor = arrayColor.concat(arrayObj[i].getVerticesData(BABYLON.VertexBuffer.ColorKind));
if (MatricesIndicesKind) arrayMatricesIndices = arrayMatricesIndices.concat(arrayObj[i].getVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind));
if (MatricesWeightsKind) arrayMatricesWeights = arrayMatricesWeights.concat(arrayObj[i].getVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind));
var maxValue = savedPosition.length / 3;
arrayObj[i].computeWorldMatrix(true);
var worldMatrix = arrayObj[i].getWorldMatrix();
for (var ite = 0; ite != arrayPos[i].length; ite += 3) {
var vertex = BABYLON.Vector3.TransformCoordinates(new BABYLON.Vector3(arrayPos[i][ite], arrayPos[i][ite + 1], arrayPos[i][ite + 2]), worldMatrix);
savedPosition.push(vertex.x);
savedPosition.push(vertex.y);
savedPosition.push(vertex.z);
}
for (var iter = 0; iter != arrayNormal[i].length; iter += 3) {
var vertex = BABYLON.Vector3.TransformNormal(new BABYLON.Vector3(arrayNormal[i][iter], arrayNormal[i][iter + 1], arrayNormal[i][iter + 2]), worldMatrix);
savedNormal.push(vertex.x);
savedNormal.push(vertex.y);
savedNormal.push(vertex.z);
}
var tmp = arrayObj[i].getIndices();
for (it = 0; it != tmp.length; it++) {
arrayIndice.push(tmp[it] + maxValue);
}
arrayIndice = arrayIndice.concat(tmp);
arrayObj[i].dispose(false);
}
newMesh.setVerticesData(BABYLON.VertexBuffer.PositionKind, savedPosition, false);
newMesh.setVerticesData(BABYLON.VertexBuffer.NormalKind, savedNormal, false);
if (arrayUv.length > 0) newMesh.setVerticesData(BABYLON.VertexBuffer.UVKind, arrayUv, false);
if (arrayUv2.length > 0) newMesh.setVerticesData(BABYLON.VertexBuffer.UV2Kind, arrayUv, false);
if (arrayColor.length > 0) newMesh.setVerticesData(BABYLON.VertexBuffer.ColorKind, arrayUv, false);
if (arrayMatricesIndices.length > 0) newMesh.setVerticesData(BABYLON.VertexBuffer.MatricesIndicesKind, arrayUv, false);
if (arrayMatricesWeights.length > 0) newMesh.setVerticesData(BABYLON.VertexBuffer.MatricesWeightsKind, arrayUv, false);
newMesh.setIndices(arrayIndice);
return newMesh;
};
还可以使用CSG类的subtract
、inverse
、union
和intersect
方法构造复杂的网格。
假设要创建一个具有内径和外径的“管道”形状(即,不仅仅是一个“管”网格,它是一个没有“厚度”的曲面)。这可以通过首先创建一个“圆柱”网格,然后从它的内部减去一个“管”网格来构建。
function createPipe(diamInner: number, diamOuter: number, length: number, scene: BABYLON.Scene): BABYLON.Mesh {
// Create the outer wall using a Cylinder mesh
const mOuter = BABYLON.MeshBuilder.CreateCylinder(
"mOuter",
{
diameter: diamOuter,
height: length,
},
scene,
);
// Create the inner wall using a Tube mesh
const mInner = BABYLON.MeshBuilder.CreateTube(
"mInner",
{
path: [new BABYLON.Vector3(0, -length / 2, 0), new BABYLON.Vector3(0, length / 2, 0)],
radius: diamInner / 2,
sideOrientation: BABYLON.Mesh.DOUBLESIDE,
},
scene,
);
// Create CSG objects from each mesh
const outerCSG = BABYLON.CSG.FromMesh(mOuter);
const innerCSG = BABYLON.CSG.FromMesh(mInner);
// Create a new CSG object by subtracting the inner tube from the outer cylinder
const pipeCSG = outerCSG.subtract(innerCSG);
// Create the resulting mesh from the new CSG object
const mPipe = pipeCSG.toMesh("mPipe", null, scene);
// Dispose of the meshes, no longer needed
mInner.dispose();
mOuter.dispose();
scene.removeMesh(mInner);
scene.removeMesh(mOuter);
// Return the result
return mPipe;
}