123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- import { Vector3, Matrix } from "../../Maths/math.vector.js";
- import { Mesh } from "../mesh.js";
- import { VertexData } from "../mesh.vertexData.js";
- import { CompatibilityOptions } 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, CompatibilityOptions.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
|