Andrew V Butt Sr 5 vuotta sitten
vanhempi
commit
019e27d0ba
4 muutettua tiedostoa jossa 241 lisäystä ja 210 poistoa
  1. 205 166
      src/Meshes/Builders/capsuleBuilder.ts
  2. 11 0
      src/Meshes/mesh.ts
  3. 12 16
      src/Meshes/mesh.vertexData.ts
  4. 13 28
      src/Meshes/meshBuilder.ts

+ 205 - 166
src/Meshes/Builders/capsuleBuilder.ts

@@ -1,53 +1,51 @@
 import { VertexData } from "../mesh.vertexData";
 import { Vector2, Vector3 } from "../../Maths/math.vector";
 import { Mesh, _CreationDataStorage } from "../mesh";
-
-VertexData.CreateCapsule = function(options: {
-        orientation: Vector3, 
-        subdivisions: number, 
-        tessellation: number, 
-        height: number, 
-        radius:number, 
-        capSubdivisions: number, 
-        radiusTop:number, 
-        radiusBottom: number, 
-        thetaStart:number, 
-        thetaLength:number,
-        topCapSubdivisions:number,
-        bottomCapSubdivisions:number
+    /** based off of https://github.com/maximeq/three-js-capsule-geometry/blob/master/src/CapsuleBufferGeometry.js
+     * @param options the constructors options used to shape the mesh.
+     * @returns the capsule VertexData
+     * @see https://doc.babylonjs.com/how_to/capsule_shape
+     */
+VertexData.CreateCapsule = function(
+    options: ICreateCapsuleOptions = {
+        orientation : Vector3.Up(),
+        subdivisions: 2,
+        tessellation: 16,
+        height: 1,
+        radius: 0.25,
+        capSubdivisions: 6
     }): VertexData {
     //let path = options.orientation || Vector3.Up()
-    let subdivisions = Math.max(options.subdivisions?options.subdivisions:2, 1)
-    let tessellation = Math.max(options.tessellation?options.tessellation:16, 3)
-    let height = Math.max(options.height?options.height:2, 0.)
-    let radius = Math.max(options.radius?options.radius:1, 0.)
-    let capDetail = Math.max(options.capSubdivisions?options.capSubdivisions:6, 1)
+    let subdivisions = Math.max(options.subdivisions ? options.subdivisions : 2, 1);
+    let tessellation = Math.max(options.tessellation ? options.tessellation : 16, 3);
+    let height = Math.max(options.height ? options.height : 2, 0.);
+    let radius = Math.max(options.radius ? options.radius : 1, 0.);
+    let capDetail = Math.max(options.capSubdivisions ? options.capSubdivisions : 6, 1);
 
     let  radialSegments = tessellation;
-	let  heightSegments = subdivisions;
+    let  heightSegments = subdivisions;
 
-    let radiusTop = Math.max(options.radiusTop?options.radiusTop:radius, 0.)
-    let radiusBottom = Math.max(options.radiusBottom?options.radiusBottom:radius, 0.)
+    let radiusTop = Math.max(options.radiusTop ? options.radiusTop : radius, 0.);
+    let radiusBottom = Math.max(options.radiusBottom ? options.radiusBottom : radius, 0.);
 
-    let thetaStart = options.thetaStart || 0.0
-    let thetaLength = options.thetaLength || (2.0 * Math.PI)
+    let thetaStart = 0.0;
+    let thetaLength = (2.0 * Math.PI);
 
-    let capsTopSegments = Math.max(options.topCapSubdivisions?options.topCapSubdivisions:capDetail, 1)
-    let capsBottomSegments = Math.max(options.bottomCapSubdivisions?options.bottomCapSubdivisions:capDetail, 1)
+    let capsTopSegments = Math.max(options.topCapSubdivisions ? options.topCapSubdivisions : capDetail, 1);
+    let capsBottomSegments = Math.max(options.bottomCapSubdivisions ? options.bottomCapSubdivisions : capDetail, 1);
 
-    var alpha = Math.acos((radiusBottom-radiusTop)/height)
-    //var eqRadii = (radiusTop-radiusBottom === 0)
+    var alpha = Math.acos((radiusBottom - radiusTop) / height);
+
+    var indices = [];
+    var vertices = [];
+    var normals = [];
+    var uvs = [];
 
-    var indices = []
-	var vertices = []
-	var normals = []
-	var uvs = []
-    
     var index = 0,
-	    //indexOffset = 0,
-	    indexArray = [],
-	    halfHeight = height / 2;
-    
+        //indexOffset = 0,
+        indexArray = [],
+        halfHeight = height / 2;
+
     var x, y;
     var normal = Vector3.Zero();
     var vertex = Vector3.Zero();
@@ -57,208 +55,249 @@ VertexData.CreateCapsule = function(options: {
 
         var cone_length =
             new Vector2(
-                radiusTop*sinAlpha,
-                halfHeight+radiusTop*cosAlpha
+                radiusTop * sinAlpha,
+                halfHeight + radiusTop * cosAlpha
                 ).subtract(new Vector2(
-                    radiusBottom*sinAlpha,
-                    -halfHeight+radiusBottom*cosAlpha
+                    radiusBottom * sinAlpha,
+                    -halfHeight + radiusBottom * cosAlpha
                 )
             ).length();
 
         // Total length for v texture coord
-        var vl = radiusTop*alpha
+        var vl = radiusTop * alpha
                  + cone_length
-                 + radiusBottom*(Math.PI/2-alpha);
+                 + radiusBottom * (Math.PI / 2 - alpha);
 
-		//var groupCount = 0;
+        //var groupCount = 0;
 
-		// generate vertices, normals and uvs
+        // generate vertices, normals and uvs
 
         var v = 0;
-        for( y = 0; y <= capsTopSegments; y++ ) {
+        for (y = 0; y <= capsTopSegments; y++) {
 
             var indexRow = [];
 
-            var a = Math.PI/2 - alpha*(y / capsTopSegments);
+            var a = Math.PI / 2 - alpha * (y / capsTopSegments);
 
-            v += radiusTop*alpha/capsTopSegments;
+            v += radiusTop * alpha / capsTopSegments;
 
             var cosA = Math.cos(a);
             var sinA = Math.sin(a);
 
             // calculate the radius of the current row
-			var _radius = cosA*radiusTop;
+            var _radius = cosA * radiusTop;
 
-            for ( x = 0; x <= radialSegments; x ++ ) {
+            for (x = 0; x <= radialSegments; x ++) {
 
-				var u = x / radialSegments;
+                var u = x / radialSegments;
 
-				var theta = u * thetaLength + thetaStart;
+                var theta = u * thetaLength + thetaStart;
 
-				var sinTheta = Math.sin( theta );
-				var cosTheta = Math.cos( theta );
+                var sinTheta = Math.sin(theta);
+                var cosTheta = Math.cos(theta);
 
-				// vertex
-				vertex.x = _radius * sinTheta;
-				vertex.y = halfHeight + sinA*radiusTop;
-				vertex.z = _radius * cosTheta;
-				vertices.push( vertex.x, vertex.y, vertex.z );
+                // vertex
+                vertex.x = _radius * sinTheta;
+                vertex.y = halfHeight + sinA * radiusTop;
+                vertex.z = _radius * cosTheta;
+                vertices.push(vertex.x, vertex.y, vertex.z);
 
-				// normal
-				normal.set( cosA*sinTheta, sinA, cosA*cosTheta );
-				normals.push( normal.x, normal.y, normal.z );
-				// uv
-				uvs.push( u, 1 - v/vl );
-				// save index of vertex in respective row
-				indexRow.push( index );
-				// increase index
-				index ++;
-			}
+                // normal
+                normal.set(cosA * sinTheta, sinA, cosA * cosTheta);
+                normals.push(normal.x, normal.y, normal.z);
+                // uv
+                uvs.push(u, 1 - v / vl);
+                // save index of vertex in respective row
+                indexRow.push(index);
+                // increase index
+                index ++;
+            }
 
             // now save vertices of the row in our index array
-			indexArray.push( indexRow );
+            indexArray.push(indexRow);
 
         }
 
-        var cone_height = height + cosAlpha*radiusTop - cosAlpha*radiusBottom;
-        var slope = sinAlpha * ( radiusBottom - radiusTop ) / cone_height;
-		for ( y = 1; y <= heightSegments; y++ ) {
+        var cone_height = height + cosAlpha * radiusTop - cosAlpha * radiusBottom;
+        var slope = sinAlpha * (radiusBottom - radiusTop) / cone_height;
+        for (y = 1; y <= heightSegments; y++) {
 
-			var indexRow = [];
+            var indexRow = [];
 
-			v += cone_length/heightSegments;
+            v += cone_length / heightSegments;
 
-			// calculate the radius of the current row
-			var _radius = sinAlpha * ( y * ( radiusBottom - radiusTop ) / heightSegments + radiusTop);
+            // calculate the radius of the current row
+            var _radius = sinAlpha * (y * (radiusBottom - radiusTop) / heightSegments + radiusTop);
 
-			for ( x = 0; x <= radialSegments; x ++ ) {
+            for (x = 0; x <= radialSegments; x ++) {
 
-				var u = x / radialSegments;
+                var u = x / radialSegments;
 
-				var theta = u * thetaLength + thetaStart;
+                var theta = u * thetaLength + thetaStart;
 
-				var sinTheta = Math.sin( theta );
-				var cosTheta = Math.cos( theta );
+                var sinTheta = Math.sin(theta);
+                var cosTheta = Math.cos(theta);
 
-				// vertex
-				vertex.x = _radius * sinTheta;
-				vertex.y = halfHeight + cosAlpha*radiusTop - y * cone_height / heightSegments;
-				vertex.z = _radius * cosTheta;
-				vertices.push( vertex.x, vertex.y, vertex.z );
+                // vertex
+                vertex.x = _radius * sinTheta;
+                vertex.y = halfHeight + cosAlpha * radiusTop - y * cone_height / heightSegments;
+                vertex.z = _radius * cosTheta;
+                vertices.push(vertex.x, vertex.y, vertex.z);
 
-				// normal
-				normal.set( sinTheta, slope, cosTheta ).normalize();
-				normals.push( normal.x, normal.y, normal.z );
+                // normal
+                normal.set(sinTheta, slope, cosTheta).normalize();
+                normals.push(normal.x, normal.y, normal.z);
 
-				// uv
-				uvs.push( u, 1 - v/vl );
+                // uv
+                uvs.push(u, 1 - v / vl);
 
-				// save index of vertex in respective row
-				indexRow.push( index );
+                // save index of vertex in respective row
+                indexRow.push(index);
 
-				// increase index
-				index ++;
+                // increase index
+                index ++;
 
-			}
+            }
 
-			// now save vertices of the row in our index array
-			indexArray.push( indexRow );
+            // now save vertices of the row in our index array
+            indexArray.push(indexRow);
 
-		}
+        }
 
-        for( y = 1; y <= capsBottomSegments; y++ ) {
+        for (y = 1; y <= capsBottomSegments; y++) {
 
             var indexRow = [];
 
-            var a = (Math.PI/2 - alpha) - (Math.PI - alpha)*( y / capsBottomSegments);
+            var a = (Math.PI / 2 - alpha) - (Math.PI - alpha) * (y / capsBottomSegments);
 
-            v += radiusBottom*alpha/capsBottomSegments;
+            v += radiusBottom * alpha / capsBottomSegments;
 
             var cosA = Math.cos(a);
             var sinA = Math.sin(a);
 
             // calculate the radius of the current row
-			var _radius = cosA*radiusBottom;
+            var _radius = cosA * radiusBottom;
 
-            for ( x = 0; x <= radialSegments; x ++ ) {
+            for (x = 0; x <= radialSegments; x ++) {
 
-				var u = x / radialSegments;
+                var u = x / radialSegments;
 
-				var theta = u * thetaLength + thetaStart;
+                var theta = u * thetaLength + thetaStart;
 
-				var sinTheta = Math.sin( theta );
-				var cosTheta = Math.cos( theta );
+                var sinTheta = Math.sin(theta);
+                var cosTheta = Math.cos(theta);
 
-				// vertex
-				vertex.x = _radius * sinTheta;
-				vertex.y = -halfHeight + sinA*radiusBottom;;
-				vertex.z = _radius * cosTheta;
-				vertices.push( vertex.x, vertex.y, vertex.z );
+                // vertex
+                vertex.x = _radius * sinTheta;
+                vertex.y = -halfHeight + sinA * radiusBottom;
+                vertex.z = _radius * cosTheta;
+                vertices.push(vertex.x, vertex.y, vertex.z);
 
-				// normal
-				normal.set( cosA*sinTheta, sinA, cosA*cosTheta );
-				normals.push( normal.x, normal.y, normal.z );
+                // normal
+                normal.set(cosA * sinTheta, sinA, cosA * cosTheta);
+                normals.push(normal.x, normal.y, normal.z);
 
-				// uv
-				uvs.push( u, 1 - v/vl );
+                // uv
+                uvs.push(u, 1 - v / vl);
 
-				// save index of vertex in respective row
-				indexRow.push( index );
-				// increase index
-				index ++;
-			}
+                // save index of vertex in respective row
+                indexRow.push(index);
+                // increase index
+                index ++;
+            }
             // now save vertices of the row in our index array
-			indexArray.push( indexRow );
+            indexArray.push(indexRow);
+        }
+        // generate indices
+        for (x = 0; x < radialSegments; x ++) {
+            for (y = 0; y < capsTopSegments + heightSegments + capsBottomSegments; y ++) {
+                // we use the index array to access the correct indices
+                var i1 = indexArray[ y ][ x ];
+                var i2 = indexArray[ y + 1 ][ x ];
+                var i3 = indexArray[ y + 1 ][ x + 1 ];
+                var i4 = indexArray[ y ][ x + 1 ];
+                // face one
+                indices.push(i1);
+                indices.push(i2);
+                indices.push(i4);
+                // face two
+                indices.push(i2);
+                indices.push(i3);
+                indices.push(i4);
+            }
         }
-		// generate indices
-		for ( x = 0; x < radialSegments; x ++ ) {
-			for ( y = 0; y < capsTopSegments + heightSegments + capsBottomSegments; y ++ ) {
-				// we use the index array to access the correct indices
-				var i1 = indexArray[ y ][ x ];
-				var i2 = indexArray[ y + 1 ][ x ];
-				var i3 = indexArray[ y + 1 ][ x + 1 ];
-				var i4 = indexArray[ y ][ x + 1 ];
-				// face one
-				indices.push( i1 ); 
-				indices.push( i2 );
-				indices.push( i4 );
-				// face two
-				indices.push( i2 ); 
-				indices.push( i3 );
-				indices.push( i4 );
-			}
-		}
-        indices = indices.reverse()
-
-       let vDat = new VertexData()
-       vDat.positions = vertices
-       vDat.normals = normals
-       vDat.uvs = uvs
-       vDat.indices = indices
-
-       return vDat
+        indices = indices.reverse();
+
+       let vDat = new VertexData();
+       vDat.positions = vertices;
+       vDat.normals = normals;
+       vDat.uvs = uvs;
+       vDat.indices = indices;
+
+       return vDat;
+};
+
+/**
+ * The options Interface for creating a Capsule Mesh
+ */
+export interface ICreateCapsuleOptions{
+    /** The Orientation of the capsule.  Default : Vector3.Up() */
+    orientation: Vector3;
+
+    /** Number of sub segments on the tube section of the capsule running parallel to orientation. */
+    subdivisions: number;
+
+    /** Number of cylindrical segments on the capsule. */
+    tessellation: number;
+
+    /** Height or Length of the capsule. */
+    height: number;
+
+    /** Radius of the capsule. */
+    radius: number;
+
+    /** Height or Length of the capsule. */
+    capSubdivisions: number;
+
+    /** Overwrite for the top radius. */
+    radiusTop?: number;
+
+    /** Overwrite for the bottom radius. */
+    radiusBottom?: number;
+
+    /** Overwrite for the top capSubdivisions. */
+    topCapSubdivisions?: number;
+
+    /** Overwrite for the bottom capSubdivisions. */
+    bottomCapSubdivisions?: number;
 }
 
 /**
+ * @param name defines the name of the mesh.
+ * @param options the constructors options used to shape the mesh.
+ * @param scene defines the scene the mesh is scoped to.
+ * @returns the capsule mesh
+ * @see https://doc.babylonjs.com/how_to/capsule_shape
+ */
+Mesh.CreateCapsule = (name: string, options: ICreateCapsuleOptions, scene): Mesh => {
+    return CapsuleBuilder.CreateCapsule(name, options, scene);
+};
+/**
  * Class containing static functions to help procedurally build meshes
  */
 export class CapsuleBuilder {
     /**
-     * Creates a capsule or a pill mesh  
+     * Creates a capsule or a pill mesh
+     * @param name defines the name of the mesh
+     * @param options The constructors options.
      */
-    public static CreateCapsule(name: string, options:{ 
-            orientation: Vector3, 
-            subdivisions: number, 
-            tessellation: number, 
-            height: number, 
-            radius:number, 
-            capSubdivisions: number, 
-            radiusTop:number, 
-            radiusBottom: number, 
-            thetaStart:number, 
-            thetaLength:number,
-            topCapSubdivisions:number,
-            bottomCapSubdivisions:number
+    public static CreateCapsule(name: string, options: ICreateCapsuleOptions = {
+            orientation : Vector3.Up(),
+            subdivisions: 2,
+            tessellation: 16,
+            height: 1,
+            radius: 0.25,
+            capSubdivisions: 6
         }, scene: any): Mesh {
 
         var capsule = new Mesh(name, scene);

+ 11 - 0
src/Meshes/mesh.ts

@@ -35,6 +35,7 @@ import { Path3D } from '../Maths/math.path';
 import { Plane } from '../Maths/math.plane';
 import { TransformNode } from './transformNode';
 import { CanvasGenerator } from '../Misc/canvasGenerator';
+import { ICreateCapsuleOptions } from './Builders/capsuleBuilder';
 
 declare type LinesMesh = import("./linesMesh").LinesMesh;
 declare type InstancedMesh = import("./instancedMesh").InstancedMesh;
@@ -4019,6 +4020,16 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
         throw _DevTools.WarnImport("MeshBuilder");
     }
 
+    /** Creates a Capsule Mesh
+     * @param name defines the name of the mesh.
+     * @param options the constructors options used to shape the mesh.
+     * @param scene defines the scene the mesh is scoped to.
+     * @returns the capsule mesh
+     * @see https://doc.babylonjs.com/how_to/capsule_shape
+     */
+    public static CreateCapsule(name: string, options: ICreateCapsuleOptions, scene: Scene): Mesh {
+        throw _DevTools.WarnImport("MeshBuilder");
+    }
     // Skeletons
 
     /**

+ 12 - 16
src/Meshes/mesh.vertexData.ts

@@ -8,6 +8,8 @@ import { Logger } from '../Misc/logger';
 declare type Geometry = import("../Meshes/geometry").Geometry;
 declare type Mesh = import("../Meshes/mesh").Mesh;
 
+import { ICreateCapsuleOptions } from "./Builders/capsuleBuilder";
+
 /**
  * Define an interface for all classes that will get and set the data on vertices
  */
@@ -1041,27 +1043,21 @@ export class VertexData {
         throw _DevTools.WarnImport("polyhedronBuilder");
     }
 
-    // 
+    //
     /**
      * Creates the VertexData for a Capsule, inspired from https://github.com/maximeq/three-js-capsule-geometry/blob/master/src/CapsuleBufferGeometry.js
      * @param options an object used to set the following optional parameters for the capsule, required but can be empty
-     * type provided types are:    
+     * type provided types are:
      * @returns the VertexData of the Capsule
      */
-    public static CreateCapsule(options: {
-            orientation: Vector3,
-            subdivisions: number,
-            tessellation: number,
-            height: number,
-            radius: number,
-            capSubdivisions: number,
-            radiusTop:number,
-            radiusBottom: number,
-            thetaStart:number,
-            thetaLength:number,
-            topCapSubdivisions:number,
-            bottomCapSubdivisions:number
-        }): VertexData {
+    public static CreateCapsule(options: ICreateCapsuleOptions = {
+        orientation : Vector3.Up(),
+        subdivisions: 2,
+        tessellation: 16,
+        height: 1,
+        radius: 0.25,
+        capSubdivisions: 6
+    }): VertexData {
         throw _DevTools.WarnImport("capsuleBuilder");
     }
 

+ 13 - 28
src/Meshes/meshBuilder.ts

@@ -17,8 +17,7 @@ import { TubeBuilder } from "./Builders/tubeBuilder";
 import { PolyhedronBuilder } from "./Builders/polyhedronBuilder";
 import { IcoSphereBuilder } from "./Builders/icoSphereBuilder";
 import { DecalBuilder } from "./Builders/decalBuilder";
-import { CapsuleBuilder } from "./Builders/capsuleBuilder";
-
+import { CapsuleBuilder, ICreateCapsuleOptions } from "./Builders/capsuleBuilder";
 import { Vector4, Vector3, Vector2 } from "../Maths/math.vector";
 import { Nullable } from "../types";
 import { Scene } from "../scene";
@@ -548,34 +547,20 @@ export class MeshBuilder {
         return DecalBuilder.CreateDecal(name, sourceMesh, options);
     }
 
-
     /**
-     * Creates a decal mesh.
-     * A decal is a mesh usually applied as a model onto the surface of another mesh. So don't forget the parameter `sourceMesh` depicting the decal
-     * * The parameter `position` (Vector3, default `(0, 0, 0)`) sets the position of the decal in World coordinates
-     * * The parameter `normal` (Vector3, default `Vector3.Up`) sets the normal of the mesh where the decal is applied onto in World coordinates
-     * * The parameter `size` (Vector3, default `(1, 1, 1)`) sets the decal scaling
-     * * The parameter `angle` (float in radian, default 0) sets the angle to rotate the decal
-     * @param name defines the name of the mesh
-     * @param sourceMesh defines the mesh where the decal must be applied
-     * @param options defines the options used to create the mesh
-     * @param scene defines the hosting scene
-     * @returns the decal mesh
-     * @see https://doc.babylonjs.com/how_to/decals
+     * @param name defines the name of the mesh.
+     * @param options the constructors options used to shape the mesh.
+     * @param scene defines the scene the mesh is scoped to.
+     * @returns the capsule mesh
+     * @see https://doc.babylonjs.com/how_to/capsule_shape
      */
-    public static CreateCapsule(name: string, options: {
-        orientation: Vector3,
-        subdivisions: number,
-        tessellation: number,
-        height: number,
-        radius: number,
-        capSubdivisions: number,
-        radiusTop:number,
-        radiusBottom: number,
-        thetaStart:number,
-        thetaLength:number,
-        topCapSubdivisions:number,
-        bottomCapSubdivisions:number
+    public static CreateCapsule(name: string, options: ICreateCapsuleOptions = {
+        orientation : Vector3.Up(),
+        subdivisions: 2,
+        tessellation: 16,
+        height: 1,
+        radius: 0.25,
+        capSubdivisions: 6
     }, scene: Nullable<Scene> = null): Mesh {
         return CapsuleBuilder.CreateCapsule(name, options, scene);
     }