@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
132 lines • 8.2 kB
JavaScript
import { Vector3, Matrix } from "../../Maths/math.vector.js";
import { Mesh } from "../mesh.js";
import { VertexData } from "../mesh.vertexData.js";
import { useOpenGLOrientationForUV } from "../../Compat/compatibilityOptions.js";
/**
* Creates the VertexData for an ellipsoid, defaults to a sphere
* @param options an object used to set the following optional parameters for the box, required but can be empty
* * segments sets the number of horizontal strips optional, default 32
* * diameter sets the axes dimensions, diameterX, diameterY and diameterZ to the value of diameter, optional default 1
* * diameterX sets the diameterX (x direction) of the ellipsoid, overwrites the diameterX set by diameter, optional, default diameter
* * diameterY sets the diameterY (y direction) of the ellipsoid, overwrites the diameterY set by diameter, optional, default diameter
* * diameterZ sets the diameterZ (z direction) of the ellipsoid, overwrites the diameterZ set by diameter, optional, default diameter
* * arc a number from 0 to 1, to create an unclosed ellipsoid based on the fraction of the circumference (latitude) given by the arc value, optional, default 1
* * slice a number from 0 to 1, to create an unclosed ellipsoid based on the fraction of the height (latitude) given by the arc value, optional, default 1
* * sideOrientation optional and takes the values : Mesh.FRONTSIDE (default), Mesh.BACKSIDE or Mesh.DOUBLESIDE
* * frontUvs only usable when you create a double-sided mesh, used to choose what parts of the texture image to crop and apply on the front side, optional, default vector4 (0, 0, 1, 1)
* * backUVs only usable when you create a double-sided mesh, used to choose what parts of the texture image to crop and apply on the back side, optional, default vector4 (0, 0, 1, 1)
* @returns the VertexData of the ellipsoid
*/
export function CreateSphereVertexData(options) {
const segments = (options.segments || 32) | 0;
const diameterX = options.diameterX || options.diameter || 1;
const diameterY = options.diameterY || options.diameter || 1;
const diameterZ = options.diameterZ || options.diameter || 1;
const arc = options.arc && (options.arc <= 0 || options.arc > 1) ? 1.0 : options.arc || 1.0;
const slice = options.slice && options.slice <= 0 ? 1.0 : options.slice || 1.0;
const sideOrientation = options.sideOrientation === 0 ? 0 : options.sideOrientation || VertexData.DEFAULTSIDE;
const dedupTopBottomIndices = !!options.dedupTopBottomIndices;
const radius = new Vector3(diameterX / 2, diameterY / 2, diameterZ / 2);
const totalZRotationSteps = 2 + segments;
const totalYRotationSteps = 2 * totalZRotationSteps;
const indices = [];
const positions = [];
const normals = [];
const uvs = [];
for (let zRotationStep = 0; zRotationStep <= totalZRotationSteps; zRotationStep++) {
const normalizedZ = zRotationStep / totalZRotationSteps;
const angleZ = normalizedZ * Math.PI * slice;
for (let yRotationStep = 0; yRotationStep <= totalYRotationSteps; yRotationStep++) {
const normalizedY = yRotationStep / totalYRotationSteps;
const angleY = normalizedY * Math.PI * 2 * arc;
const rotationZ = Matrix.RotationZ(-angleZ);
const rotationY = Matrix.RotationY(angleY);
const afterRotZ = Vector3.TransformCoordinates(Vector3.Up(), rotationZ);
const complete = Vector3.TransformCoordinates(afterRotZ, rotationY);
const vertex = complete.multiply(radius);
const normal = complete.divide(radius).normalize();
positions.push(vertex.x, vertex.y, vertex.z);
normals.push(normal.x, normal.y, normal.z);
uvs.push(normalizedY, useOpenGLOrientationForUV ? 1.0 - normalizedZ : normalizedZ);
}
if (zRotationStep > 0) {
const verticesCount = positions.length / 3;
for (let firstIndex = verticesCount - 2 * (totalYRotationSteps + 1); firstIndex + totalYRotationSteps + 2 < verticesCount; firstIndex++) {
if (dedupTopBottomIndices) {
if (zRotationStep > 1) {
indices.push(firstIndex);
indices.push(firstIndex + 1);
indices.push(firstIndex + totalYRotationSteps + 1);
}
if (zRotationStep < totalZRotationSteps || slice < 1.0) {
indices.push(firstIndex + totalYRotationSteps + 1);
indices.push(firstIndex + 1);
indices.push(firstIndex + totalYRotationSteps + 2);
}
}
else {
indices.push(firstIndex);
indices.push(firstIndex + 1);
indices.push(firstIndex + totalYRotationSteps + 1);
indices.push(firstIndex + totalYRotationSteps + 1);
indices.push(firstIndex + 1);
indices.push(firstIndex + totalYRotationSteps + 2);
}
}
}
}
// Sides
VertexData._ComputeSides(sideOrientation, positions, indices, normals, uvs, options.frontUVs, options.backUVs);
// Result
const vertexData = new VertexData();
vertexData.indices = indices;
vertexData.positions = positions;
vertexData.normals = normals;
vertexData.uvs = uvs;
return vertexData;
}
/**
* Creates a sphere mesh
* * The parameter `diameter` sets the diameter size (float) of the sphere (default 1)
* * You can set some different sphere dimensions, for instance to build an ellipsoid, by using the parameters `diameterX`, `diameterY` and `diameterZ` (all by default have the same value of `diameter`)
* * The parameter `segments` sets the sphere number of horizontal stripes (positive integer, default 32)
* * You can create an unclosed sphere with the parameter `arc` (positive float, default 1), valued between 0 and 1, what is the ratio of the circumference (latitude) : 2 x PI x ratio
* * You can create an unclosed sphere on its height with the parameter `slice` (positive float, default1), valued between 0 and 1, what is the height ratio (longitude)
* * You can also set the mesh side orientation with the values : BABYLON.Mesh.FRONTSIDE (default), BABYLON.Mesh.BACKSIDE or BABYLON.Mesh.DOUBLESIDE
* * If you create a double-sided mesh, you can choose what parts of the texture image to crop and stick respectively on the front and the back sides with the parameters `frontUVs` and `backUVs` (Vector4). Detail here : https://doc.babylonjs.com/features/featuresDeepDive/mesh/creation/set#side-orientation
* * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created
* @param name defines the name of the mesh
* @param options defines the options used to create the mesh
* @param scene defines the hosting scene
* @returns the sphere mesh
* @see https://doc.babylonjs.com/features/featuresDeepDive/mesh/creation/set#sphere
*/
export function CreateSphere(name, options = {}, scene = null) {
const sphere = new Mesh(name, scene);
options.sideOrientation = Mesh._GetDefaultSideOrientation(options.sideOrientation);
sphere._originalBuilderSideOrientation = options.sideOrientation;
const vertexData = CreateSphereVertexData(options);
vertexData.applyToMesh(sphere, options.updatable);
return sphere;
}
/**
* Class containing static functions to help procedurally build meshes
* @deprecated use CreateSphere directly
*/
export const SphereBuilder = {
// eslint-disable-next-line @typescript-eslint/naming-convention
CreateSphere,
};
VertexData.CreateSphere = CreateSphereVertexData;
Mesh.CreateSphere = (name, segments, diameter, scene, updatable, sideOrientation) => {
const options = {
segments: segments,
diameterX: diameter,
diameterY: diameter,
diameterZ: diameter,
sideOrientation: sideOrientation,
updatable: updatable,
};
return CreateSphere(name, options, scene);
};
//# sourceMappingURL=sphereBuilder.js.map