Преглед на файлове

Updated examples builds.

Mr.doob преди 3 години
родител
ревизия
83c8f1d7a9

+ 28 - 16
examples/js/exporters/GLTFExporter.js

@@ -300,27 +300,15 @@
 
 
 	}
 	}
 
 
-	let cachedCanvas = null;
-
 	function getCanvas() {
 	function getCanvas() {
 
 
-		if ( cachedCanvas ) {
-
-			return cachedCanvas;
-
-		}
-
 		if ( typeof document === 'undefined' && typeof OffscreenCanvas !== 'undefined' ) {
 		if ( typeof document === 'undefined' && typeof OffscreenCanvas !== 'undefined' ) {
 
 
-			cachedCanvas = new OffscreenCanvas( 1, 1 );
-
-		} else {
-
-			cachedCanvas = document.createElement( 'canvas' );
+			return new OffscreenCanvas( 1, 1 );
 
 
 		}
 		}
 
 
-		return cachedCanvas;
+		return document.createElement( 'canvas' );
 
 
 	}
 	}
 
 
@@ -676,6 +664,27 @@
 		buildMetalRoughTexture( metalnessMap, roughnessMap ) {
 		buildMetalRoughTexture( metalnessMap, roughnessMap ) {
 
 
 			if ( metalnessMap === roughnessMap ) return metalnessMap;
 			if ( metalnessMap === roughnessMap ) return metalnessMap;
+
+			function getEncodingConversion( map ) {
+
+				if ( map.encoding === THREE.sRGBEncoding ) {
+
+					return function SRGBToLinear( c ) {
+
+						return c < 0.04045 ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
+
+					};
+
+				}
+
+				return function LinearToLinear( c ) {
+
+					return c;
+
+				};
+
+			}
+
 			console.warn( 'THREE.GLTFExporter: Merged metalnessMap and roughnessMap textures.' );
 			console.warn( 'THREE.GLTFExporter: Merged metalnessMap and roughnessMap textures.' );
 			const metalness = metalnessMap?.image;
 			const metalness = metalnessMap?.image;
 			const roughness = roughnessMap?.image;
 			const roughness = roughnessMap?.image;
@@ -692,11 +701,12 @@
 			if ( metalness ) {
 			if ( metalness ) {
 
 
 				context.drawImage( metalness, 0, 0, width, height );
 				context.drawImage( metalness, 0, 0, width, height );
+				const convert = getEncodingConversion( metalnessMap );
 				const data = context.getImageData( 0, 0, width, height ).data;
 				const data = context.getImageData( 0, 0, width, height ).data;
 
 
 				for ( let i = 2; i < data.length; i += 4 ) {
 				for ( let i = 2; i < data.length; i += 4 ) {
 
 
-					composite.data[ i ] = data[ i ];
+					composite.data[ i ] = convert( data[ i ] / 256 ) * 256;
 
 
 				}
 				}
 
 
@@ -705,11 +715,12 @@
 			if ( roughness ) {
 			if ( roughness ) {
 
 
 				context.drawImage( roughness, 0, 0, width, height );
 				context.drawImage( roughness, 0, 0, width, height );
+				const convert = getEncodingConversion( roughnessMap );
 				const data = context.getImageData( 0, 0, width, height ).data;
 				const data = context.getImageData( 0, 0, width, height ).data;
 
 
 				for ( let i = 1; i < data.length; i += 4 ) {
 				for ( let i = 1; i < data.length; i += 4 ) {
 
 
-					composite.data[ i ] = data[ i ];
+					composite.data[ i ] = convert( data[ i ] / 256 ) * 256;
 
 
 				}
 				}
 
 
@@ -720,6 +731,7 @@
 			const reference = metalnessMap || roughnessMap;
 			const reference = metalnessMap || roughnessMap;
 			const texture = reference.clone();
 			const texture = reference.clone();
 			texture.source = new THREE.Source( canvas );
 			texture.source = new THREE.Source( canvas );
+			texture.encoding = THREE.LinearEncoding;
 			return texture;
 			return texture;
 
 
 		}
 		}

+ 6 - 0
examples/js/exporters/USDZExporter.js

@@ -380,6 +380,12 @@ ${array.join( '' )}
 
 
 		}
 		}
 
 
+		if ( material.side === THREE.DoubleSide ) {
+
+			console.warn( 'THREE.USDZExporter: USDZ does not support double sided materials', material );
+
+		}
+
 		if ( material.map !== null ) {
 		if ( material.map !== null ) {
 
 
 			inputs.push( `${pad}color3f inputs:diffuseColor.connect = </Materials/Material_${material.id}/Texture_${material.map.id}_diffuse.outputs:rgb>` );
 			inputs.push( `${pad}color3f inputs:diffuseColor.connect = </Materials/Material_${material.id}/Texture_${material.map.id}_diffuse.outputs:rgb>` );

+ 2 - 13
examples/js/loaders/EXRLoader.js

@@ -1610,20 +1610,9 @@
 
 
 			const parseInt64 = function ( dataView, offset ) {
 			const parseInt64 = function ( dataView, offset ) {
 
 
-				let int;
-
-				if ( 'getBigInt64' in DataView.prototype ) {
-
-					int = Number( dataView.getBigInt64( offset.value, true ) );
-
-				} else {
-
-					int = dataView.getUint32( offset.value + 4, true ) + Number( dataView.getUint32( offset.value, true ) << 32 );
-
-				}
-
+				const Int64 = Number( dataView.getBigInt64( offset.value, true ) );
 				offset.value += ULONG_SIZE;
 				offset.value += ULONG_SIZE;
-				return int;
+				return Int64;
 
 
 			};
 			};
 
 

+ 1 - 1
examples/js/loaders/FontLoader.js

@@ -63,7 +63,7 @@
 
 
 			for ( let p = 0, pl = paths.length; p < pl; p ++ ) {
 			for ( let p = 0, pl = paths.length; p < pl; p ++ ) {
 
 
-				Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
+				shapes.push( ...paths[ p ].toShapes() );
 
 
 			}
 			}
 
 

+ 27 - 27
examples/js/loaders/GLTFLoader.js

@@ -1733,44 +1733,44 @@
 
 
 		}
 		}
 
 
-	}
+		interpolate_( i1, t0, t, t1 ) {
 
 
-	GLTFCubicSplineInterpolant.prototype.interpolate_ = function ( i1, t0, t, t1 ) {
+			const result = this.resultBuffer;
+			const values = this.sampleValues;
+			const stride = this.valueSize;
+			const stride2 = stride * 2;
+			const stride3 = stride * 3;
+			const td = t1 - t0;
+			const p = ( t - t0 ) / td;
+			const pp = p * p;
+			const ppp = pp * p;
+			const offset1 = i1 * stride3;
+			const offset0 = offset1 - stride3;
+			const s2 = - 2 * ppp + 3 * pp;
+			const s3 = ppp - pp;
+			const s0 = 1 - s2;
+			const s1 = s3 - pp + p; // Layout of keyframe output values for CUBICSPLINE animations:
+			//   [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ]
 
 
-		const result = this.resultBuffer;
-		const values = this.sampleValues;
-		const stride = this.valueSize;
-		const stride2 = stride * 2;
-		const stride3 = stride * 3;
-		const td = t1 - t0;
-		const p = ( t - t0 ) / td;
-		const pp = p * p;
-		const ppp = pp * p;
-		const offset1 = i1 * stride3;
-		const offset0 = offset1 - stride3;
-		const s2 = - 2 * ppp + 3 * pp;
-		const s3 = ppp - pp;
-		const s0 = 1 - s2;
-		const s1 = s3 - pp + p; // Layout of keyframe output values for CUBICSPLINE animations:
-		//   [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ]
+			for ( let i = 0; i !== stride; i ++ ) {
 
 
-		for ( let i = 0; i !== stride; i ++ ) {
+				const p0 = values[ offset0 + i + stride ]; // splineVertex_k
 
 
-			const p0 = values[ offset0 + i + stride ]; // splineVertex_k
+				const m0 = values[ offset0 + i + stride2 ] * td; // outTangent_k * (t_k+1 - t_k)
 
 
-			const m0 = values[ offset0 + i + stride2 ] * td; // outTangent_k * (t_k+1 - t_k)
+				const p1 = values[ offset1 + i + stride ]; // splineVertex_k+1
 
 
-			const p1 = values[ offset1 + i + stride ]; // splineVertex_k+1
+				const m1 = values[ offset1 + i ] * td; // inTangent_k+1 * (t_k+1 - t_k)
 
 
-			const m1 = values[ offset1 + i ] * td; // inTangent_k+1 * (t_k+1 - t_k)
+				result[ i ] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1;
 
 
-			result[ i ] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1;
+			}
 
 
-		}
+			return result;
 
 
-		return result;
+		}
 
 
-	};
+	}
 
 
 	const _q = new THREE.Quaternion();
 	const _q = new THREE.Quaternion();
 
 

+ 99 - 18
examples/js/loaders/KTX2Loader.js

@@ -5,8 +5,8 @@
  *
  *
  * KTX 2.0 is a container format for various GPU texture formats. The loader
  * KTX 2.0 is a container format for various GPU texture formats. The loader
  * supports Basis Universal GPU textures, which can be quickly transcoded to
  * supports Basis Universal GPU textures, which can be quickly transcoded to
- * a wide variety of GPU texture compression formats. While KTX 2.0 also allows
- * other hardware-specific formats, this loader does not yet parse them.
+ * a wide variety of GPU texture compression formats, as well as some
+ * uncompressed THREE.DataTexture and THREE.Data3DTexture formats.
  *
  *
  * References:
  * References:
  * - KTX: http://github.khronos.org/KTX-Specification/
  * - KTX: http://github.khronos.org/KTX-Specification/
@@ -137,7 +137,6 @@
 			const loader = new THREE.FileLoader( this.manager );
 			const loader = new THREE.FileLoader( this.manager );
 			loader.setResponseType( 'arraybuffer' );
 			loader.setResponseType( 'arraybuffer' );
 			loader.setWithCredentials( this.withCredentials );
 			loader.setWithCredentials( this.withCredentials );
-			const texture = new THREE.CompressedTexture();
 			loader.load( url, buffer => {
 			loader.load( url, buffer => {
 
 
 				// Check for an existing task using this buffer. A transferred buffer cannot be transferred
 				// Check for an existing task using this buffer. A transferred buffer cannot be transferred
@@ -150,16 +149,9 @@
 
 
 				}
 				}
 
 
-				this._createTexture( [ buffer ] ).then( function ( _texture ) {
-
-					texture.copy( _texture );
-					texture.needsUpdate = true;
-					if ( onLoad ) onLoad( texture );
-
-				} ).catch( onError );
+				this._createTexture( buffer ).then( texture => onLoad ? onLoad( texture ) : null ).catch( onError );
 
 
 			}, onProgress, onError );
 			}, onProgress, onError );
-			return texture;
 
 
 		}
 		}
 
 
@@ -187,26 +179,35 @@
 
 
 		}
 		}
 		/**
 		/**
-   * @param {ArrayBuffer[]} buffers
+   * @param {ArrayBuffer} buffer
    * @param {object?} config
    * @param {object?} config
-   * @return {Promise<CompressedTexture>}
+   * @return {Promise<CompressedTexture|DataTexture|Data3DTexture>}
    */
    */
 
 
 
 
-		_createTexture( buffers, config = {} ) {
+		_createTexture( buffer, config = {} ) {
+
+			const container = read( new Uint8Array( buffer ) );
+
+			if ( container.vkFormat !== VK_FORMAT_UNDEFINED ) {
+
+				return createDataTexture( container );
+
+			} //
+
 
 
 			const taskConfig = config;
 			const taskConfig = config;
 			const texturePending = this.init().then( () => {
 			const texturePending = this.init().then( () => {
 
 
 				return this.workerPool.postMessage( {
 				return this.workerPool.postMessage( {
 					type: 'transcode',
 					type: 'transcode',
-					buffers,
+					buffer,
 					taskConfig: taskConfig
 					taskConfig: taskConfig
-				}, buffers );
+				}, [ buffer ] );
 
 
 			} ).then( e => this._createTextureFrom( e.data ) ); // Cache the task result.
 			} ).then( e => this._createTextureFrom( e.data ) ); // Cache the task result.
 
 
-			_taskCache.set( buffers[ 0 ], {
+			_taskCache.set( buffer, {
 				promise: texturePending
 				promise: texturePending
 			} );
 			} );
 
 
@@ -299,7 +300,7 @@
 								format,
 								format,
 								dfdTransferFn,
 								dfdTransferFn,
 								dfdFlags
 								dfdFlags
-							} = transcode( message.buffers[ 0 ] );
+							} = transcode( message.buffer );
 							const buffers = [];
 							const buffers = [];
 
 
 							for ( let i = 0; i < mipmaps.length; ++ i ) {
 							for ( let i = 0; i < mipmaps.length; ++ i ) {
@@ -551,7 +552,87 @@
 
 
 		}
 		}
 
 
+	}; //
+	// THREE.DataTexture and THREE.Data3DTexture parsing.
+
+
+	const FORMAT_MAP = {
+		[ VK_FORMAT_R32G32B32A32_SFLOAT ]: THREE.RGBAFormat,
+		[ VK_FORMAT_R16G16B16A16_SFLOAT ]: THREE.RGBAFormat,
+		[ VK_FORMAT_R8G8B8A8_UNORM ]: THREE.RGBAFormat,
+		[ VK_FORMAT_R8G8B8A8_SRGB ]: THREE.RGBAFormat,
+		[ VK_FORMAT_R32G32_SFLOAT ]: THREE.RGFormat,
+		[ VK_FORMAT_R16G16_SFLOAT ]: THREE.RGFormat,
+		[ VK_FORMAT_R8G8_UNORM ]: THREE.RGFormat,
+		[ VK_FORMAT_R8G8_SRGB ]: THREE.RGFormat,
+		[ VK_FORMAT_R32_SFLOAT ]: THREE.RedFormat,
+		[ VK_FORMAT_R16_SFLOAT ]: THREE.RedFormat,
+		[ VK_FORMAT_R8_SRGB ]: THREE.RedFormat,
+		[ VK_FORMAT_R8_UNORM ]: THREE.RedFormat
 	};
 	};
+	const TYPE_MAP = {
+		[ VK_FORMAT_R32G32B32A32_SFLOAT ]: THREE.FloatType,
+		[ VK_FORMAT_R16G16B16A16_SFLOAT ]: THREE.HalfFloatType,
+		[ VK_FORMAT_R8G8B8A8_UNORM ]: THREE.UnsignedByteType,
+		[ VK_FORMAT_R8G8B8A8_SRGB ]: THREE.UnsignedByteType,
+		[ VK_FORMAT_R32G32_SFLOAT ]: THREE.FloatType,
+		[ VK_FORMAT_R16G16_SFLOAT ]: THREE.HalfFloatType,
+		[ VK_FORMAT_R8G8_UNORM ]: THREE.UnsignedByteType,
+		[ VK_FORMAT_R8G8_SRGB ]: THREE.UnsignedByteType,
+		[ VK_FORMAT_R32_SFLOAT ]: THREE.FloatType,
+		[ VK_FORMAT_R16_SFLOAT ]: THREE.HalfFloatType,
+		[ VK_FORMAT_R8_SRGB ]: THREE.UnsignedByteType,
+		[ VK_FORMAT_R8_UNORM ]: THREE.UnsignedByteType
+	};
+	const ENCODING_MAP = {
+		[ VK_FORMAT_R8G8B8A8_SRGB ]: THREE.sRGBEncoding,
+		[ VK_FORMAT_R8G8_SRGB ]: THREE.sRGBEncoding,
+		[ VK_FORMAT_R8_SRGB ]: THREE.sRGBEncoding
+	};
+
+	function createDataTexture( container ) {
+
+		const {
+			vkFormat,
+			pixelWidth,
+			pixelHeight,
+			pixelDepth
+		} = container;
+
+		if ( FORMAT_MAP[ vkFormat ] === undefined ) {
+
+			throw new Error( 'THREE.KTX2Loader: Unsupported vkFormat.' );
+
+		} //
+
+
+		let view;
+		const levelData = container.levels[ 0 ].levelData;
+
+		if ( TYPE_MAP[ vkFormat ] === THREE.FloatType ) {
+
+			view = new Float32Array( levelData.buffer, levelData.byteOffset, levelData.byteLength / Float32Array.BYTES_PER_ELEMENT );
+
+		} else if ( TYPE_MAP[ vkFormat ] === THREE.HalfFloatType ) {
+
+			view = new Uint16Array( levelData.buffer, levelData.byteOffset, levelData.byteLength / Uint16Array.BYTES_PER_ELEMENT );
+
+		} else {
+
+			view = levelData;
+
+		} //
+
+
+		const texture = pixelDepth === 0 ? new THREE.DataTexture( view, pixelWidth, pixelHeight ) : new THREE.Data3DTexture( view, pixelWidth, pixelHeight, pixelDepth );
+		texture.type = TYPE_MAP[ vkFormat ];
+		texture.format = FORMAT_MAP[ vkFormat ];
+		texture.encoding = ENCODING_MAP[ vkFormat ] || THREE.LinearEncoding;
+		texture.needsUpdate = true; //
+
+		return Promise.resolve( texture );
+
+	}
 
 
 	THREE.KTX2Loader = KTX2Loader;
 	THREE.KTX2Loader = KTX2Loader;
 
 

+ 33 - 24
examples/js/loaders/VRMLLoader.js

@@ -212,16 +212,16 @@
 			function createVisitor( BaseVRMLVisitor ) {
 			function createVisitor( BaseVRMLVisitor ) {
 
 
 				// the visitor is created dynmaically based on the given base class
 				// the visitor is created dynmaically based on the given base class
-				function VRMLToASTVisitor() {
+				class VRMLToASTVisitor extends BaseVRMLVisitor {
 
 
-					BaseVRMLVisitor.call( this );
-					this.validateVisitor();
+					constructor() {
 
 
-				}
+						super();
+						this.validateVisitor();
+
+					}
 
 
-				VRMLToASTVisitor.prototype = Object.assign( Object.create( BaseVRMLVisitor.prototype ), {
-					constructor: VRMLToASTVisitor,
-					vrml: function ( ctx ) {
+					vrml( ctx ) {
 
 
 						const data = {
 						const data = {
 							version: this.visit( ctx.version ),
 							version: this.visit( ctx.version ),
@@ -249,13 +249,15 @@
 
 
 						return data;
 						return data;
 
 
-					},
-					version: function ( ctx ) {
+					}
+
+					version( ctx ) {
 
 
 						return ctx.Version[ 0 ].image;
 						return ctx.Version[ 0 ].image;
 
 
-					},
-					node: function ( ctx ) {
+					}
+
+					node( ctx ) {
 
 
 						const data = {
 						const data = {
 							name: ctx.NodeName[ 0 ].image,
 							name: ctx.NodeName[ 0 ].image,
@@ -282,8 +284,9 @@
 
 
 						return data;
 						return data;
 
 
-					},
-					field: function ( ctx ) {
+					}
+
+					field( ctx ) {
 
 
 						const data = {
 						const data = {
 							name: ctx.Identifier[ 0 ].image,
 							name: ctx.Identifier[ 0 ].image,
@@ -309,30 +312,35 @@
 						data.values = result.values;
 						data.values = result.values;
 						return data;
 						return data;
 
 
-					},
-					def: function ( ctx ) {
+					}
+
+					def( ctx ) {
 
 
 						return ( ctx.Identifier || ctx.NodeName )[ 0 ].image;
 						return ( ctx.Identifier || ctx.NodeName )[ 0 ].image;
 
 
-					},
-					use: function ( ctx ) {
+					}
+
+					use( ctx ) {
 
 
 						return {
 						return {
 							USE: ( ctx.Identifier || ctx.NodeName )[ 0 ].image
 							USE: ( ctx.Identifier || ctx.NodeName )[ 0 ].image
 						};
 						};
 
 
-					},
-					singleFieldValue: function ( ctx ) {
+					}
+
+					singleFieldValue( ctx ) {
 
 
 						return processField( this, ctx );
 						return processField( this, ctx );
 
 
-					},
-					multiFieldValue: function ( ctx ) {
+					}
+
+					multiFieldValue( ctx ) {
 
 
 						return processField( this, ctx );
 						return processField( this, ctx );
 
 
-					},
-					route: function ( ctx ) {
+					}
+
+					route( ctx ) {
 
 
 						const data = {
 						const data = {
 							FROM: ctx.RouteIdentifier[ 0 ].image,
 							FROM: ctx.RouteIdentifier[ 0 ].image,
@@ -341,7 +349,8 @@
 						return data;
 						return data;
 
 
 					}
 					}
-				} );
+
+				}
 
 
 				function processField( scope, ctx ) {
 				function processField( scope, ctx ) {
 
 

+ 1 - 1
examples/js/loaders/VTKLoader.js

@@ -855,7 +855,7 @@
 							// Depending on the number of DataArrays
 							// Depending on the number of DataArrays
 							let arr;
 							let arr;
 
 
-							if ( Object.prototype.toString.call( section.DataArray ) === '[object Array]' ) {
+							if ( Array.isArray( section.DataArray ) ) {
 
 
 								arr = section.DataArray;
 								arr = section.DataArray;
 
 

+ 8 - 7
examples/js/loaders/lwo/LWO2Parser.js

@@ -1,14 +1,14 @@
 ( function () {
 ( function () {
 
 
-	function LWO2Parser( IFFParser ) {
+	class LWO2Parser {
 
 
-		this.IFF = IFFParser;
+		constructor( IFFParser ) {
 
 
-	}
+			this.IFF = IFFParser;
+
+		}
 
 
-	LWO2Parser.prototype = {
-		constructor: LWO2Parser,
-		parseBlock: function () {
+		parseBlock() {
 
 
 			this.IFF.debugger.offset = this.IFF.reader.offset;
 			this.IFF.debugger.offset = this.IFF.reader.offset;
 			this.IFF.debugger.closeForms();
 			this.IFF.debugger.closeForms();
@@ -440,7 +440,8 @@
 			}
 			}
 
 
 		}
 		}
-	};
+
+	}
 
 
 	THREE.LWO2Parser = LWO2Parser;
 	THREE.LWO2Parser = LWO2Parser;
 
 

+ 8 - 7
examples/js/loaders/lwo/LWO3Parser.js

@@ -1,14 +1,14 @@
 ( function () {
 ( function () {
 
 
-	function LWO3Parser( IFFParser ) {
+	class LWO3Parser {
 
 
-		this.IFF = IFFParser;
+		constructor( IFFParser ) {
 
 
-	}
+			this.IFF = IFFParser;
+
+		}
 
 
-	LWO3Parser.prototype = {
-		constructor: LWO3Parser,
-		parseBlock: function () {
+		parseBlock() {
 
 
 			this.IFF.debugger.offset = this.IFF.reader.offset;
 			this.IFF.debugger.offset = this.IFF.reader.offset;
 			this.IFF.debugger.closeForms();
 			this.IFF.debugger.closeForms();
@@ -394,7 +394,8 @@
 			}
 			}
 
 
 		}
 		}
-	};
+
+	}
 
 
 	THREE.LWO3Parser = LWO3Parser;
 	THREE.LWO3Parser = LWO3Parser;
 
 

+ 198 - 190
examples/js/misc/Volume.js

@@ -13,205 +13,203 @@
  * @param   {ArrayBuffer}   arrayBuffer     The buffer with volume data
  * @param   {ArrayBuffer}   arrayBuffer     The buffer with volume data
  */
  */
 
 
-	function Volume( xLength, yLength, zLength, type, arrayBuffer ) {
+	class Volume {
+
+		constructor( xLength, yLength, zLength, type, arrayBuffer ) {
+
+			if ( xLength !== undefined ) {
+
+				/**
+       * @member {number} xLength Width of the volume in the IJK coordinate system
+       */
+				this.xLength = Number( xLength ) || 1;
+				/**
+       * @member {number} yLength Height of the volume in the IJK coordinate system
+       */
+
+				this.yLength = Number( yLength ) || 1;
+				/**
+       * @member {number} zLength Depth of the volume in the IJK coordinate system
+       */
+
+				this.zLength = Number( zLength ) || 1;
+				/**
+       * @member {Array<string>} The order of the Axis dictated by the NRRD header
+       */
+
+				this.axisOrder = [ 'x', 'y', 'z' ];
+				/**
+       * @member {TypedArray} data Data of the volume
+       */
+
+				switch ( type ) {
+
+					case 'Uint8':
+					case 'uint8':
+					case 'uchar':
+					case 'unsigned char':
+					case 'uint8_t':
+						this.data = new Uint8Array( arrayBuffer );
+						break;
+
+					case 'Int8':
+					case 'int8':
+					case 'signed char':
+					case 'int8_t':
+						this.data = new Int8Array( arrayBuffer );
+						break;
+
+					case 'Int16':
+					case 'int16':
+					case 'short':
+					case 'short int':
+					case 'signed short':
+					case 'signed short int':
+					case 'int16_t':
+						this.data = new Int16Array( arrayBuffer );
+						break;
+
+					case 'Uint16':
+					case 'uint16':
+					case 'ushort':
+					case 'unsigned short':
+					case 'unsigned short int':
+					case 'uint16_t':
+						this.data = new Uint16Array( arrayBuffer );
+						break;
+
+					case 'Int32':
+					case 'int32':
+					case 'int':
+					case 'signed int':
+					case 'int32_t':
+						this.data = new Int32Array( arrayBuffer );
+						break;
+
+					case 'Uint32':
+					case 'uint32':
+					case 'uint':
+					case 'unsigned int':
+					case 'uint32_t':
+						this.data = new Uint32Array( arrayBuffer );
+						break;
+
+					case 'longlong':
+					case 'long long':
+					case 'long long int':
+					case 'signed long long':
+					case 'signed long long int':
+					case 'int64':
+					case 'int64_t':
+					case 'ulonglong':
+					case 'unsigned long long':
+					case 'unsigned long long int':
+					case 'uint64':
+					case 'uint64_t':
+						throw new Error( 'Error in Volume constructor : this type is not supported in JavaScript' );
+						break;
+
+					case 'Float32':
+					case 'float32':
+					case 'float':
+						this.data = new Float32Array( arrayBuffer );
+						break;
+
+					case 'Float64':
+					case 'float64':
+					case 'double':
+						this.data = new Float64Array( arrayBuffer );
+						break;
+
+					default:
+						this.data = new Uint8Array( arrayBuffer );
 
 
-		if ( arguments.length > 0 ) {
+				}
+
+				if ( this.data.length !== this.xLength * this.yLength * this.zLength ) {
 
 
+					throw new Error( 'Error in Volume constructor, lengths are not matching arrayBuffer size' );
+
+				}
+
+			}
 			/**
 			/**
-     * @member {number} xLength Width of the volume in the IJK coordinate system
+     * @member {Array}  spacing Spacing to apply to the volume from IJK to RAS coordinate system
      */
      */
-			this.xLength = Number( xLength ) || 1;
+
+
+			this.spacing = [ 1, 1, 1 ];
 			/**
 			/**
-     * @member {number} yLength Height of the volume in the IJK coordinate system
+     * @member {Array}  offset Offset of the volume in the RAS coordinate system
      */
      */
 
 
-			this.yLength = Number( yLength ) || 1;
+			this.offset = [ 0, 0, 0 ];
 			/**
 			/**
-     * @member {number} zLength Depth of the volume in the IJK coordinate system
+     * @member {Martrix3} matrix The IJK to RAS matrix
      */
      */
 
 
-			this.zLength = Number( zLength ) || 1;
+			this.matrix = new THREE.Matrix3();
+			this.matrix.identity();
 			/**
 			/**
-     * @member {Array<string>} The order of the Axis dictated by the NRRD header
+     * @member {Martrix3} inverseMatrix The RAS to IJK matrix
      */
      */
 
 
-			this.axisOrder = [ 'x', 'y', 'z' ];
 			/**
 			/**
-     * @member {TypedArray} data Data of the volume
+     * @member {number} lowerThreshold The voxels with values under this threshold won't appear in the slices.
+     *                      If changed, geometryNeedsUpdate is automatically set to true on all the slices associated to this volume
      */
      */
 
 
-			switch ( type ) {
+			let lowerThreshold = - Infinity;
+			Object.defineProperty( this, 'lowerThreshold', {
+				get: function () {
 
 
-				case 'Uint8':
-				case 'uint8':
-				case 'uchar':
-				case 'unsigned char':
-				case 'uint8_t':
-					this.data = new Uint8Array( arrayBuffer );
-					break;
+					return lowerThreshold;
 
 
-				case 'Int8':
-				case 'int8':
-				case 'signed char':
-				case 'int8_t':
-					this.data = new Int8Array( arrayBuffer );
-					break;
+				},
+				set: function ( value ) {
 
 
-				case 'Int16':
-				case 'int16':
-				case 'short':
-				case 'short int':
-				case 'signed short':
-				case 'signed short int':
-				case 'int16_t':
-					this.data = new Int16Array( arrayBuffer );
-					break;
+					lowerThreshold = value;
+					this.sliceList.forEach( function ( slice ) {
 
 
-				case 'Uint16':
-				case 'uint16':
-				case 'ushort':
-				case 'unsigned short':
-				case 'unsigned short int':
-				case 'uint16_t':
-					this.data = new Uint16Array( arrayBuffer );
-					break;
+						slice.geometryNeedsUpdate = true;
 
 
-				case 'Int32':
-				case 'int32':
-				case 'int':
-				case 'signed int':
-				case 'int32_t':
-					this.data = new Int32Array( arrayBuffer );
-					break;
+					} );
 
 
-				case 'Uint32':
-				case 'uint32':
-				case 'uint':
-				case 'unsigned int':
-				case 'uint32_t':
-					this.data = new Uint32Array( arrayBuffer );
-					break;
+				}
+			} );
+			/**
+     * @member {number} upperThreshold The voxels with values over this threshold won't appear in the slices.
+     *                      If changed, geometryNeedsUpdate is automatically set to true on all the slices associated to this volume
+     */
 
 
-				case 'longlong':
-				case 'long long':
-				case 'long long int':
-				case 'signed long long':
-				case 'signed long long int':
-				case 'int64':
-				case 'int64_t':
-				case 'ulonglong':
-				case 'unsigned long long':
-				case 'unsigned long long int':
-				case 'uint64':
-				case 'uint64_t':
-					throw new Error( 'Error in Volume constructor : this type is not supported in JavaScript' );
-					break;
+			let upperThreshold = Infinity;
+			Object.defineProperty( this, 'upperThreshold', {
+				get: function () {
 
 
-				case 'Float32':
-				case 'float32':
-				case 'float':
-					this.data = new Float32Array( arrayBuffer );
-					break;
+					return upperThreshold;
 
 
-				case 'Float64':
-				case 'float64':
-				case 'double':
-					this.data = new Float64Array( arrayBuffer );
-					break;
+				},
+				set: function ( value ) {
 
 
-				default:
-					this.data = new Uint8Array( arrayBuffer );
+					upperThreshold = value;
+					this.sliceList.forEach( function ( slice ) {
 
 
-			}
+						slice.geometryNeedsUpdate = true;
 
 
-			if ( this.data.length !== this.xLength * this.yLength * this.zLength ) {
+					} );
 
 
-				throw new Error( 'Error in Volume constructor, lengths are not matching arrayBuffer size' );
+				}
+			} );
+			/**
+     * @member {Array} sliceList The list of all the slices associated to this volume
+     */
 
 
-			}
+			this.sliceList = [];
+			/**
+     * @member {Array} RASDimensions This array holds the dimensions of the volume in the RAS space
+     */
 
 
 		}
 		}
-		/**
-   * @member {Array}  spacing Spacing to apply to the volume from IJK to RAS coordinate system
-   */
-
-
-		this.spacing = [ 1, 1, 1 ];
-		/**
-   * @member {Array}  offset Offset of the volume in the RAS coordinate system
-   */
-
-		this.offset = [ 0, 0, 0 ];
-		/**
-   * @member {Martrix3} matrix The IJK to RAS matrix
-   */
-
-		this.matrix = new THREE.Matrix3();
-		this.matrix.identity();
-		/**
-   * @member {Martrix3} inverseMatrix The RAS to IJK matrix
-   */
-
-		/**
-   * @member {number} lowerThreshold The voxels with values under this threshold won't appear in the slices.
-   *                      If changed, geometryNeedsUpdate is automatically set to true on all the slices associated to this volume
-   */
-
-		let lowerThreshold = - Infinity;
-		Object.defineProperty( this, 'lowerThreshold', {
-			get: function () {
-
-				return lowerThreshold;
-
-			},
-			set: function ( value ) {
-
-				lowerThreshold = value;
-				this.sliceList.forEach( function ( slice ) {
-
-					slice.geometryNeedsUpdate = true;
-
-				} );
-
-			}
-		} );
-		/**
-   * @member {number} upperThreshold The voxels with values over this threshold won't appear in the slices.
-   *                      If changed, geometryNeedsUpdate is automatically set to true on all the slices associated to this volume
-   */
-
-		let upperThreshold = Infinity;
-		Object.defineProperty( this, 'upperThreshold', {
-			get: function () {
-
-				return upperThreshold;
-
-			},
-			set: function ( value ) {
-
-				upperThreshold = value;
-				this.sliceList.forEach( function ( slice ) {
-
-					slice.geometryNeedsUpdate = true;
-
-				} );
-
-			}
-		} );
-		/**
-   * @member {Array} sliceList The list of all the slices associated to this volume
-   */
-
-		this.sliceList = [];
-		/**
-   * @member {Array} RASDimensions This array holds the dimensions of the volume in the RAS space
-   */
-
-	}
-
-	Volume.prototype = {
-		constructor: Volume,
-
 		/**
 		/**
    * @member {Function} getData Shortcut for data[access(i,j,k)]
    * @member {Function} getData Shortcut for data[access(i,j,k)]
    * @memberof Volume
    * @memberof Volume
@@ -220,12 +218,13 @@
    * @param {number} k    Third coordinate
    * @param {number} k    Third coordinate
    * @returns {number}  value in the data array
    * @returns {number}  value in the data array
    */
    */
-		getData: function ( i, j, k ) {
 
 
-			return this.data[ k * this.xLength * this.yLength + j * this.xLength + i ];
 
 
-		},
+		getData( i, j, k ) {
+
+			return this.data[ k * this.xLength * this.yLength + j * this.xLength + i ];
 
 
+		}
 		/**
 		/**
    * @member {Function} access compute the index in the data array corresponding to the given coordinates in IJK system
    * @member {Function} access compute the index in the data array corresponding to the given coordinates in IJK system
    * @memberof Volume
    * @memberof Volume
@@ -234,27 +233,29 @@
    * @param {number} k    Third coordinate
    * @param {number} k    Third coordinate
    * @returns {number}  index
    * @returns {number}  index
    */
    */
-		access: function ( i, j, k ) {
 
 
-			return k * this.xLength * this.yLength + j * this.xLength + i;
 
 
-		},
+		access( i, j, k ) {
+
+			return k * this.xLength * this.yLength + j * this.xLength + i;
 
 
+		}
 		/**
 		/**
    * @member {Function} reverseAccess Retrieve the IJK coordinates of the voxel corresponding of the given index in the data
    * @member {Function} reverseAccess Retrieve the IJK coordinates of the voxel corresponding of the given index in the data
    * @memberof Volume
    * @memberof Volume
    * @param {number} index index of the voxel
    * @param {number} index index of the voxel
    * @returns {Array}  [x,y,z]
    * @returns {Array}  [x,y,z]
    */
    */
-		reverseAccess: function ( index ) {
+
+
+		reverseAccess( index ) {
 
 
 			const z = Math.floor( index / ( this.yLength * this.xLength ) );
 			const z = Math.floor( index / ( this.yLength * this.xLength ) );
 			const y = Math.floor( ( index - z * this.yLength * this.xLength ) / this.xLength );
 			const y = Math.floor( ( index - z * this.yLength * this.xLength ) / this.xLength );
 			const x = index - z * this.yLength * this.xLength - y * this.xLength;
 			const x = index - z * this.yLength * this.xLength - y * this.xLength;
 			return [ x, y, z ];
 			return [ x, y, z ];
 
 
-		},
-
+		}
 		/**
 		/**
    * @member {Function} map Apply a function to all the voxels, be careful, the value will be replaced
    * @member {Function} map Apply a function to all the voxels, be careful, the value will be replaced
    * @memberof Volume
    * @memberof Volume
@@ -265,7 +266,9 @@
    * @param {Object}   context    You can specify a context in which call the function, default if this Volume
    * @param {Object}   context    You can specify a context in which call the function, default if this Volume
    * @returns {Volume}   this
    * @returns {Volume}   this
    */
    */
-		map: function ( functionToMap, context ) {
+
+
+		map( functionToMap, context ) {
 
 
 			const length = this.data.length;
 			const length = this.data.length;
 			context = context || this;
 			context = context || this;
@@ -278,8 +281,7 @@
 
 
 			return this;
 			return this;
 
 
-		},
-
+		}
 		/**
 		/**
    * @member {Function} extractPerpendicularPlane Compute the orientation of the slice and returns all the information relative to the geometry such as sliceAccess, the plane matrix (orientation and position in RAS coordinate) and the dimensions of the plane in both coordinate system.
    * @member {Function} extractPerpendicularPlane Compute the orientation of the slice and returns all the information relative to the geometry such as sliceAccess, the plane matrix (orientation and position in RAS coordinate) and the dimensions of the plane in both coordinate system.
    * @memberof Volume
    * @memberof Volume
@@ -287,7 +289,9 @@
    * @param {number}            index the index of the slice
    * @param {number}            index the index of the slice
    * @returns {Object} an object containing all the usefull information on the geometry of the slice
    * @returns {Object} an object containing all the usefull information on the geometry of the slice
    */
    */
-		extractPerpendicularPlane: function ( axis, RASIndex ) {
+
+
+		extractPerpendicularPlane( axis, RASIndex ) {
 
 
 			let firstSpacing, secondSpacing, positionOffset, IJKIndex;
 			let firstSpacing, secondSpacing, positionOffset, IJKIndex;
 			const axisInIJK = new THREE.Vector3(),
 			const axisInIJK = new THREE.Vector3(),
@@ -386,8 +390,7 @@
 				planeHeight: planeHeight
 				planeHeight: planeHeight
 			};
 			};
 
 
-		},
-
+		}
 		/**
 		/**
    * @member {Function} extractSlice Returns a slice corresponding to the given axis and index
    * @member {Function} extractSlice Returns a slice corresponding to the given axis and index
    *                        The coordinate are given in the Right Anterior Superior coordinate format
    *                        The coordinate are given in the Right Anterior Superior coordinate format
@@ -396,21 +399,24 @@
    * @param {number}            index the index of the slice
    * @param {number}            index the index of the slice
    * @returns {VolumeSlice} the extracted slice
    * @returns {VolumeSlice} the extracted slice
    */
    */
-		extractSlice: function ( axis, index ) {
+
+
+		extractSlice( axis, index ) {
 
 
 			const slice = new THREE.VolumeSlice( this, index, axis );
 			const slice = new THREE.VolumeSlice( this, index, axis );
 			this.sliceList.push( slice );
 			this.sliceList.push( slice );
 			return slice;
 			return slice;
 
 
-		},
-
+		}
 		/**
 		/**
    * @member {Function} repaintAllSlices Call repaint on all the slices extracted from this volume
    * @member {Function} repaintAllSlices Call repaint on all the slices extracted from this volume
    * @see THREE.VolumeSlice.repaint
    * @see THREE.VolumeSlice.repaint
    * @memberof Volume
    * @memberof Volume
    * @returns {Volume} this
    * @returns {Volume} this
    */
    */
-		repaintAllSlices: function () {
+
+
+		repaintAllSlices() {
 
 
 			this.sliceList.forEach( function ( slice ) {
 			this.sliceList.forEach( function ( slice ) {
 
 
@@ -419,14 +425,15 @@
 			} );
 			} );
 			return this;
 			return this;
 
 
-		},
-
+		}
 		/**
 		/**
    * @member {Function} computeMinMax Compute the minimum and the maximum of the data in the volume
    * @member {Function} computeMinMax Compute the minimum and the maximum of the data in the volume
    * @memberof Volume
    * @memberof Volume
    * @returns {Array} [min,max]
    * @returns {Array} [min,max]
    */
    */
-		computeMinMax: function () {
+
+
+		computeMinMax() {
 
 
 			let min = Infinity;
 			let min = Infinity;
 			let max = - Infinity; // buffer the length
 			let max = - Infinity; // buffer the length
@@ -451,7 +458,8 @@
 			return [ min, max ];
 			return [ min, max ];
 
 
 		}
 		}
-	};
+
+	}
 
 
 	THREE.Volume = Volume;
 	THREE.Volume = Volume;
 
 

+ 90 - 88
examples/js/misc/VolumeSlice.js

@@ -9,103 +9,103 @@
  * @see Volume
  * @see Volume
  */
  */
 
 
-	function VolumeSlice( volume, index, axis ) {
+	class VolumeSlice {
 
 
-		const slice = this;
-		/**
-   * @member {Volume} volume The associated volume
-   */
-
-		this.volume = volume;
-		/**
-   * @member {Number} index The index of the slice, if changed, will automatically call updateGeometry at the next repaint
-   */
-
-		index = index || 0;
-		Object.defineProperty( this, 'index', {
-			get: function () {
+		constructor( volume, index, axis ) {
 
 
-				return index;
-
-			},
-			set: function ( value ) {
-
-				index = value;
-				slice.geometryNeedsUpdate = true;
-				return index;
-
-			}
-		} );
-		/**
-   * @member {String} axis The normal axis
-   */
+			const slice = this;
+			/**
+     * @member {Volume} volume The associated volume
+     */
 
 
-		this.axis = axis || 'z';
-		/**
-   * @member {HTMLCanvasElement} canvas The final canvas used for the texture
-   */
+			this.volume = volume;
+			/**
+     * @member {Number} index The index of the slice, if changed, will automatically call updateGeometry at the next repaint
+     */
 
 
-		/**
-   * @member {CanvasRenderingContext2D} ctx Context of the canvas
-   */
+			index = index || 0;
+			Object.defineProperty( this, 'index', {
+				get: function () {
 
 
-		this.canvas = document.createElement( 'canvas' );
-		/**
-   * @member {HTMLCanvasElement} canvasBuffer The intermediary canvas used to paint the data
-   */
+					return index;
 
 
-		/**
-   * @member {CanvasRenderingContext2D} ctxBuffer Context of the canvas buffer
-   */
+				},
+				set: function ( value ) {
 
 
-		this.canvasBuffer = document.createElement( 'canvas' );
-		this.updateGeometry();
-		const canvasMap = new THREE.Texture( this.canvas );
-		canvasMap.minFilter = THREE.LinearFilter;
-		canvasMap.wrapS = canvasMap.wrapT = THREE.ClampToEdgeWrapping;
-		const material = new THREE.MeshBasicMaterial( {
-			map: canvasMap,
-			side: THREE.DoubleSide,
-			transparent: true
-		} );
-		/**
-   * @member {Mesh} mesh The mesh ready to get used in the scene
-   */
+					index = value;
+					slice.geometryNeedsUpdate = true;
+					return index;
 
 
-		this.mesh = new THREE.Mesh( this.geometry, material );
-		this.mesh.matrixAutoUpdate = false;
-		/**
-   * @member {Boolean} geometryNeedsUpdate If set to true, updateGeometry will be triggered at the next repaint
-   */
-
-		this.geometryNeedsUpdate = true;
-		this.repaint();
-		/**
-   * @member {Number} iLength Width of slice in the original coordinate system, corresponds to the width of the buffer canvas
-   */
-
-		/**
-   * @member {Number} jLength Height of slice in the original coordinate system, corresponds to the height of the buffer canvas
-   */
-
-		/**
-   * @member {Function} sliceAccess Function that allow the slice to access right data
-   * @see Volume.extractPerpendicularPlane
-   * @param {Number} i The first coordinate
-   * @param {Number} j The second coordinate
-   * @returns {Number} the index corresponding to the voxel in volume.data of the given position in the slice
-   */
-
-	}
-
-	VolumeSlice.prototype = {
-		constructor: VolumeSlice,
+				}
+			} );
+			/**
+     * @member {String} axis The normal axis
+     */
+
+			this.axis = axis || 'z';
+			/**
+     * @member {HTMLCanvasElement} canvas The final canvas used for the texture
+     */
+
+			/**
+     * @member {CanvasRenderingContext2D} ctx Context of the canvas
+     */
+
+			this.canvas = document.createElement( 'canvas' );
+			/**
+     * @member {HTMLCanvasElement} canvasBuffer The intermediary canvas used to paint the data
+     */
+
+			/**
+     * @member {CanvasRenderingContext2D} ctxBuffer Context of the canvas buffer
+     */
+
+			this.canvasBuffer = document.createElement( 'canvas' );
+			this.updateGeometry();
+			const canvasMap = new THREE.Texture( this.canvas );
+			canvasMap.minFilter = THREE.LinearFilter;
+			canvasMap.wrapS = canvasMap.wrapT = THREE.ClampToEdgeWrapping;
+			const material = new THREE.MeshBasicMaterial( {
+				map: canvasMap,
+				side: THREE.DoubleSide,
+				transparent: true
+			} );
+			/**
+     * @member {Mesh} mesh The mesh ready to get used in the scene
+     */
+
+			this.mesh = new THREE.Mesh( this.geometry, material );
+			this.mesh.matrixAutoUpdate = false;
+			/**
+     * @member {Boolean} geometryNeedsUpdate If set to true, updateGeometry will be triggered at the next repaint
+     */
+
+			this.geometryNeedsUpdate = true;
+			this.repaint();
+			/**
+     * @member {Number} iLength Width of slice in the original coordinate system, corresponds to the width of the buffer canvas
+     */
+
+			/**
+     * @member {Number} jLength Height of slice in the original coordinate system, corresponds to the height of the buffer canvas
+     */
+
+			/**
+     * @member {Function} sliceAccess Function that allow the slice to access right data
+     * @see Volume.extractPerpendicularPlane
+     * @param {Number} i The first coordinate
+     * @param {Number} j The second coordinate
+     * @returns {Number} the index corresponding to the voxel in volume.data of the given position in the slice
+     */
 
 
+		}
 		/**
 		/**
    * @member {Function} repaint Refresh the texture and the geometry if geometryNeedsUpdate is set to true
    * @member {Function} repaint Refresh the texture and the geometry if geometryNeedsUpdate is set to true
    * @memberof VolumeSlice
    * @memberof VolumeSlice
    */
    */
-		repaint: function () {
+
+
+		repaint() {
 
 
 			if ( this.geometryNeedsUpdate ) {
 			if ( this.geometryNeedsUpdate ) {
 
 
@@ -179,14 +179,15 @@
 			this.ctx.drawImage( canvas, 0, 0, iLength, jLength, 0, 0, this.canvas.width, this.canvas.height );
 			this.ctx.drawImage( canvas, 0, 0, iLength, jLength, 0, 0, this.canvas.width, this.canvas.height );
 			this.mesh.material.map.needsUpdate = true;
 			this.mesh.material.map.needsUpdate = true;
 
 
-		},
-
+		}
 		/**
 		/**
    * @member {Function} Refresh the geometry according to axis and index
    * @member {Function} Refresh the geometry according to axis and index
    * @see Volume.extractPerpendicularPlane
    * @see Volume.extractPerpendicularPlane
    * @memberof VolumeSlice
    * @memberof VolumeSlice
    */
    */
-		updateGeometry: function () {
+
+
+		updateGeometry() {
 
 
 			const extracted = this.volume.extractPerpendicularPlane( this.axis, this.index );
 			const extracted = this.volume.extractPerpendicularPlane( this.axis, this.index );
 			this.sliceAccess = extracted.sliceAccess;
 			this.sliceAccess = extracted.sliceAccess;
@@ -215,7 +216,8 @@
 			this.geometryNeedsUpdate = false;
 			this.geometryNeedsUpdate = false;
 
 
 		}
 		}
-	};
+
+	}
 
 
 	THREE.VolumeSlice = VolumeSlice;
 	THREE.VolumeSlice = VolumeSlice;
 
 

+ 1 - 1
examples/js/modifiers/SimplifyModifier.js

@@ -306,7 +306,7 @@
 
 
 		for ( let i = u.faces.length - 1; i >= 0; i -- ) {
 		for ( let i = u.faces.length - 1; i >= 0; i -- ) {
 
 
-			if ( u.faces[ i ].hasVertex( v ) ) {
+			if ( u.faces[ i ] && u.faces[ i ].hasVertex( v ) ) {
 
 
 				removeFace( u.faces[ i ], faces );
 				removeFace( u.faces[ i ], faces );
 
 

+ 5 - 1
examples/js/objects/ShadowMesh.js

@@ -14,7 +14,11 @@
 				color: 0x000000,
 				color: 0x000000,
 				transparent: true,
 				transparent: true,
 				opacity: 0.6,
 				opacity: 0.6,
-				depthWrite: false
+				depthWrite: false,
+				stencilWrite: true,
+				stencilFunc: THREE.EqualStencilFunc,
+				stencilRef: 0,
+				stencilZPass: THREE.IncrementStencilOp
 			} );
 			} );
 			super( mesh.geometry, shadowMaterial );
 			super( mesh.geometry, shadowMaterial );
 			this.isShadowMesh = true;
 			this.isShadowMesh = true;

+ 1 - 1
examples/js/utils/BufferGeometryUtils.js

@@ -409,7 +409,7 @@
 
 
 		if ( attribute.isInstancedInterleavedBufferAttribute ) {
 		if ( attribute.isInstancedInterleavedBufferAttribute ) {
 
 
-			newAttribute = new InstancedBufferAttribute( array, itemSize, normalized, attribute.meshPerAttribute );
+			newAttribute = new THREE.InstancedBufferAttribute( array, itemSize, normalized, attribute.meshPerAttribute );
 
 
 		} else {
 		} else {
 
 

+ 2 - 18
examples/js/utils/GeometryUtils.js

@@ -23,13 +23,7 @@
 
 
 		if ( 0 <= -- iterations ) {
 		if ( 0 <= -- iterations ) {
 
 
-			const tmp = [];
-			Array.prototype.push.apply( tmp, hilbert2D( vec[ 0 ], half, iterations, v0, v3, v2, v1 ) );
-			Array.prototype.push.apply( tmp, hilbert2D( vec[ 1 ], half, iterations, v0, v1, v2, v3 ) );
-			Array.prototype.push.apply( tmp, hilbert2D( vec[ 2 ], half, iterations, v0, v1, v2, v3 ) );
-			Array.prototype.push.apply( tmp, hilbert2D( vec[ 3 ], half, iterations, v2, v1, v0, v3 ) ); // Return recursive call
-
-			return tmp;
+			return [ ...hilbert2D( vec[ 0 ], half, iterations, v0, v3, v2, v1 ), ...hilbert2D( vec[ 1 ], half, iterations, v0, v1, v2, v3 ), ...hilbert2D( vec[ 2 ], half, iterations, v0, v1, v2, v3 ), ...hilbert2D( vec[ 3 ], half, iterations, v2, v1, v0, v3 ) ];
 
 
 		} // Return complete Hilbert Curve.
 		} // Return complete Hilbert Curve.
 
 
@@ -66,17 +60,7 @@
 
 
 		if ( -- iterations >= 0 ) {
 		if ( -- iterations >= 0 ) {
 
 
-			const tmp = [];
-			Array.prototype.push.apply( tmp, hilbert3D( vec[ 0 ], half, iterations, v0, v3, v4, v7, v6, v5, v2, v1 ) );
-			Array.prototype.push.apply( tmp, hilbert3D( vec[ 1 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) );
-			Array.prototype.push.apply( tmp, hilbert3D( vec[ 2 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) );
-			Array.prototype.push.apply( tmp, hilbert3D( vec[ 3 ], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5 ) );
-			Array.prototype.push.apply( tmp, hilbert3D( vec[ 4 ], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5 ) );
-			Array.prototype.push.apply( tmp, hilbert3D( vec[ 5 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ) );
-			Array.prototype.push.apply( tmp, hilbert3D( vec[ 6 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ) );
-			Array.prototype.push.apply( tmp, hilbert3D( vec[ 7 ], half, iterations, v6, v5, v2, v1, v0, v3, v4, v7 ) ); // Return recursive call
-
-			return tmp;
+			return [ ...hilbert3D( vec[ 0 ], half, iterations, v0, v3, v4, v7, v6, v5, v2, v1 ), ...hilbert3D( vec[ 1 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ), ...hilbert3D( vec[ 2 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ), ...hilbert3D( vec[ 3 ], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5 ), ...hilbert3D( vec[ 4 ], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5 ), ...hilbert3D( vec[ 5 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ), ...hilbert3D( vec[ 6 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ), ...hilbert3D( vec[ 7 ], half, iterations, v6, v5, v2, v1, v0, v3, v4, v7 ) ];
 
 
 		} // Return complete Hilbert Curve.
 		} // Return complete Hilbert Curve.