Browse Source

GLTFLoader: Fix incorrect boundingBox for normalized attributes. (#21554)

Don McCurdy 4 years ago
parent
commit
71759eb24a
2 changed files with 90 additions and 50 deletions
  1. 45 25
      examples/js/loaders/GLTFLoader.js
  2. 45 25
      examples/jsm/loaders/GLTFLoader.js

+ 45 - 25
examples/js/loaders/GLTFLoader.js

@@ -1805,6 +1805,32 @@ THREE.GLTFLoader = ( function () {
 
 
 	}
 	}
 
 
+	function getNormalizedComponentScale( constructor ) {
+
+		// Reference:
+		// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization#encoding-quantized-data
+
+		switch ( constructor ) {
+
+			case Int8Array:
+				return 1 / 127;
+
+			case Uint8Array:
+				return 1 / 255;
+
+			case Int16Array:
+				return 1 / 32767;
+
+			case Uint16Array:
+				return 1 / 65535;
+
+			default:
+				throw new Error( 'THREE.GLTFLoader: Unsupported normalized accessor component type.' );
+
+		}
+
+	}
+
 	/* GLTF PARSER */
 	/* GLTF PARSER */
 
 
 	function GLTFParser( json, options ) {
 	function GLTFParser( json, options ) {
@@ -2870,7 +2896,16 @@ THREE.GLTFLoader = ( function () {
 
 
 				box.set(
 				box.set(
 					new THREE.Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ),
 					new THREE.Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ),
-					new THREE.Vector3( max[ 0 ], max[ 1 ], max[ 2 ] ) );
+					new THREE.Vector3( max[ 0 ], max[ 1 ], max[ 2 ] )
+				);
+
+				if ( accessor.normalized ) {
+
+					var boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] );
+					box.min.multiplyScalar( boxScale );
+					box.max.multiplyScalar( boxScale );
+
+				}
 
 
 			} else {
 			} else {
 
 
@@ -2912,6 +2947,14 @@ THREE.GLTFLoader = ( function () {
 						vector.setY( Math.max( Math.abs( min[ 1 ] ), Math.abs( max[ 1 ] ) ) );
 						vector.setY( Math.max( Math.abs( min[ 1 ] ), Math.abs( max[ 1 ] ) ) );
 						vector.setZ( Math.max( Math.abs( min[ 2 ] ), Math.abs( max[ 2 ] ) ) );
 						vector.setZ( Math.max( Math.abs( min[ 2 ] ), Math.abs( max[ 2 ] ) ) );
 
 
+
+						if ( accessor.normalized ) {
+
+							var boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] );
+							vector.multiplyScalar( boxScale );
+
+						}
+
 						// Note: this assumes that the sum of all weights is at most 1. This isn't quite correct - it's more conservative
 						// Note: this assumes that the sum of all weights is at most 1. This isn't quite correct - it's more conservative
 						// to assume that each target can have a max weight of 1. However, for some use cases - notably, when morph targets
 						// to assume that each target can have a max weight of 1. However, for some use cases - notably, when morph targets
 						// are used to implement key-frame animations and as such only two are active at a time - this results in very large
 						// are used to implement key-frame animations and as such only two are active at a time - this results in very large
@@ -3482,30 +3525,7 @@ THREE.GLTFLoader = ( function () {
 
 
 				if ( outputAccessor.normalized ) {
 				if ( outputAccessor.normalized ) {
 
 
-					var scale;
-
-					if ( outputArray.constructor === Int8Array ) {
-
-						scale = 1 / 127;
-
-					} else if ( outputArray.constructor === Uint8Array ) {
-
-						scale = 1 / 255;
-
-					} else if ( outputArray.constructor == Int16Array ) {
-
-						scale = 1 / 32767;
-
-					} else if ( outputArray.constructor === Uint16Array ) {
-
-						scale = 1 / 65535;
-
-					} else {
-
-						throw new Error( 'THREE.GLTFLoader: Unsupported output accessor component type.' );
-
-					}
-
+					var scale = getNormalizedComponentScale( outputArray.constructor );
 					var scaled = new Float32Array( outputArray.length );
 					var scaled = new Float32Array( outputArray.length );
 
 
 					for ( var j = 0, jl = outputArray.length; j < jl; j ++ ) {
 					for ( var j = 0, jl = outputArray.length; j < jl; j ++ ) {

+ 45 - 25
examples/jsm/loaders/GLTFLoader.js

@@ -1870,6 +1870,32 @@ var GLTFLoader = ( function () {
 
 
 	}
 	}
 
 
+	function getNormalizedComponentScale( constructor ) {
+
+		// Reference:
+		// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization#encoding-quantized-data
+
+		switch ( constructor ) {
+
+			case Int8Array:
+				return 1 / 127;
+
+			case Uint8Array:
+				return 1 / 255;
+
+			case Int16Array:
+				return 1 / 32767;
+
+			case Uint16Array:
+				return 1 / 65535;
+
+			default:
+				throw new Error( 'THREE.GLTFLoader: Unsupported normalized accessor component type.' );
+
+		}
+
+	}
+
 	/* GLTF PARSER */
 	/* GLTF PARSER */
 
 
 	function GLTFParser( json, options ) {
 	function GLTFParser( json, options ) {
@@ -2935,7 +2961,16 @@ var GLTFLoader = ( function () {
 
 
 				box.set(
 				box.set(
 					new Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ),
 					new Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ),
-					new Vector3( max[ 0 ], max[ 1 ], max[ 2 ] ) );
+					new Vector3( max[ 0 ], max[ 1 ], max[ 2 ] )
+				);
+
+				if ( accessor.normalized ) {
+
+					var boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] );
+					box.min.multiplyScalar( boxScale );
+					box.max.multiplyScalar( boxScale );
+
+				}
 
 
 			} else {
 			} else {
 
 
@@ -2977,6 +3012,14 @@ var GLTFLoader = ( function () {
 						vector.setY( Math.max( Math.abs( min[ 1 ] ), Math.abs( max[ 1 ] ) ) );
 						vector.setY( Math.max( Math.abs( min[ 1 ] ), Math.abs( max[ 1 ] ) ) );
 						vector.setZ( Math.max( Math.abs( min[ 2 ] ), Math.abs( max[ 2 ] ) ) );
 						vector.setZ( Math.max( Math.abs( min[ 2 ] ), Math.abs( max[ 2 ] ) ) );
 
 
+
+						if ( accessor.normalized ) {
+
+							var boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] );
+							vector.multiplyScalar( boxScale );
+
+						}
+
 						// Note: this assumes that the sum of all weights is at most 1. This isn't quite correct - it's more conservative
 						// Note: this assumes that the sum of all weights is at most 1. This isn't quite correct - it's more conservative
 						// to assume that each target can have a max weight of 1. However, for some use cases - notably, when morph targets
 						// to assume that each target can have a max weight of 1. However, for some use cases - notably, when morph targets
 						// are used to implement key-frame animations and as such only two are active at a time - this results in very large
 						// are used to implement key-frame animations and as such only two are active at a time - this results in very large
@@ -3547,30 +3590,7 @@ var GLTFLoader = ( function () {
 
 
 				if ( outputAccessor.normalized ) {
 				if ( outputAccessor.normalized ) {
 
 
-					var scale;
-
-					if ( outputArray.constructor === Int8Array ) {
-
-						scale = 1 / 127;
-
-					} else if ( outputArray.constructor === Uint8Array ) {
-
-						scale = 1 / 255;
-
-					} else if ( outputArray.constructor == Int16Array ) {
-
-						scale = 1 / 32767;
-
-					} else if ( outputArray.constructor === Uint16Array ) {
-
-						scale = 1 / 65535;
-
-					} else {
-
-						throw new Error( 'THREE.GLTFLoader: Unsupported output accessor component type.' );
-
-					}
-
+					var scale = getNormalizedComponentScale( outputArray.constructor );
 					var scaled = new Float32Array( outputArray.length );
 					var scaled = new Float32Array( outputArray.length );
 
 
 					for ( var j = 0, jl = outputArray.length; j < jl; j ++ ) {
 					for ( var j = 0, jl = outputArray.length; j < jl; j ++ ) {