瀏覽代碼

GLTFLoader: Pre-compute geometry bounds using attribute min/max

Instead of relying on three.js to compute bounding box/sphere, we now
compute them from attribute min/max specified in glTF file. These are
mandatory as per glTF spec.

This allows us to save time after loading the object - bounding sphere
is used for culling unconditionally.

Note that since glTF data doesn't directly specify bounding sphere data,
the bounding sphere is slightly larger because it's computed from min/max
values.
Arseny Kapoulkine 5 年之前
父節點
當前提交
02a8d5c238
共有 1 個文件被更改,包括 68 次插入0 次删除
  1. 68 0
      examples/js/loaders/GLTFLoader.js

+ 68 - 0
examples/js/loaders/GLTFLoader.js

@@ -2362,6 +2362,72 @@ THREE.GLTFLoader = ( function () {
 
 	};
 
+	/**
+	 * @param {THREE.BufferGeometry} geometry
+	 * @param {GLTF.Primitive} primitiveDef
+	 * @param {GLTFParser} parser
+	 */
+	function computeBounds( geometry, primitiveDef, parser ) {
+
+		var attributes = primitiveDef.attributes;
+
+		var box = new THREE.Box3();
+
+		if ( attributes.POSITION !== undefined ) {
+
+			var accessor = parser.json.accessors[ attributes.POSITION ];
+			var min = accessor.min;
+			var max = accessor.max;
+
+			box.set(
+				new THREE.Vector3( min[0], min[1], min[2] ),
+				new THREE.Vector3( max[0], max[1], max[2] ) );
+
+		} else {
+
+			return;
+		}
+
+		var targets = primitiveDef.targets;
+
+		if ( targets !== undefined ) {
+
+			var vector = new THREE.Vector3();
+
+			for ( var i = 0, il = targets.length; i < il; i ++ ) {
+
+				var target = targets[ i ];
+
+				if ( target.POSITION !== undefined ) {
+
+					var accessor = parser.json.accessors[ target.POSITION ];
+					var min = accessor.min;
+					var max = accessor.max;
+
+					// we need to get max of absolute components because target weight is [-1,1]
+					vector.setX( Math.max( Math.abs( min[0] ), Math.abs( max[0] ) ) );
+					vector.setY( Math.max( Math.abs( min[1] ), Math.abs( max[1] ) ) );
+					vector.setZ( Math.max( Math.abs( min[2] ), Math.abs( max[2] ) ) );
+
+					box.expandByVector( vector );
+
+				}
+
+			}
+
+		}
+
+		geometry.boundingBox = box;
+
+		var sphere = new THREE.Sphere();
+
+		box.getCenter( sphere.center );
+		sphere.radius = box.min.distanceTo( box.max ) / 2;
+
+		geometry.boundingSphere = sphere;
+
+	}
+
 	/**
 	 * @param {THREE.BufferGeometry} geometry
 	 * @param {GLTF.Primitive} primitiveDef
@@ -2410,6 +2476,8 @@ THREE.GLTFLoader = ( function () {
 
 		assignExtrasToUserData( geometry, primitiveDef );
 
+		computeBounds( geometry, primitiveDef, parser );
+
 		return Promise.all( pending ).then( function () {
 
 			return primitiveDef.targets !== undefined