Mr.doob пре 2 година
родитељ
комит
574f70895b

+ 46 - 1
examples/js/exporters/USDZExporter.js

@@ -2,7 +2,16 @@
 
 	class USDZExporter {
 
-		async parse( scene ) {
+		async parse( scene, options = {
+			ar: {
+				anchoring: {
+					type: 'plane'
+				},
+				planeAnchoring: {
+					alignment: 'vertical'
+				}
+			}
+		} ) {
 
 			const files = {};
 			const modelFileName = 'model.usda';
@@ -10,6 +19,7 @@
 			// model file should be first in USDZ archive so we init it here
 			files[ modelFileName ] = null;
 			let output = buildHeader();
+			output += buildSceneStart( options );
 			const materials = {};
 			const textures = {};
 			scene.traverseVisible( object => {
@@ -49,6 +59,7 @@
 				}
 
 			} );
+			output += buildSceneEnd();
 			output += buildMaterials( materials, textures );
 			files[ modelFileName ] = fflate.strToU8( output );
 			output = null;
@@ -146,6 +157,40 @@
     upAxis = "Y"
 )
 
+`;
+
+	}
+
+	function buildSceneStart( options ) {
+
+		return `def Xform "Root"
+{
+    def Scope "Scenes" (
+        kind = "sceneLibrary"
+    )
+    {
+        def Xform "Scene" (
+            customData = {
+                bool preliminary_collidesWithEnvironment = 0
+                string sceneName = "Scene"
+            }
+            sceneName = "Scene"
+        )
+        {
+        token preliminary:anchoring:type = "${options.ar.anchoring.type}"
+        token preliminary:planeAnchoring:alignment = "${options.ar.planeAnchoring.alignment}"
+
+`;
+
+	}
+
+	function buildSceneEnd() {
+
+		return `
+        }
+    }
+}
+
 `;
 
 	}

+ 1 - 1
examples/js/loaders/3DMLoader.js

@@ -502,7 +502,7 @@
 							light.position.set( geometry.location[ 0 ] - height / 2, geometry.location[ 1 ], geometry.location[ 2 ] - width / 2 );
 							light.height = height;
 							light.width = width;
-							light.lookAt( new THREE.Vector3( geometry.direction[ 0 ], geometry.direction[ 1 ], geometry.direction[ 2 ] ) );
+							light.lookAt( geometry.direction[ 0 ], geometry.direction[ 1 ], geometry.direction[ 2 ] );
 							break;
 						case 'LightStyle_WorldDirectional':
 							light = new THREE.DirectionalLight();

+ 24 - 5
examples/js/loaders/GLTFLoader.js

@@ -444,12 +444,19 @@
 			// here, because node-level parsing will only override position if explicitly specified.
 			lightNode.position.set( 0, 0, 0 );
 			lightNode.decay = 2;
+			assignExtrasToUserData( lightNode, lightDef );
 			if ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity;
 			lightNode.name = parser.createUniqueName( lightDef.name || 'light_' + lightIndex );
 			dependency = Promise.resolve( lightNode );
 			parser.cache.add( cacheKey, dependency );
 			return dependency;
 
+		}
+		getDependency( type, index ) {
+
+			if ( type !== 'light' ) return;
+			return this._loadLight( index );
+
 		}
 		createNodeAttachment( nodeIndex ) {
 
@@ -2478,7 +2485,18 @@
 						dependency = this.loadCamera( index );
 						break;
 					default:
-						throw new Error( 'Unknown type: ' + type );
+						dependency = this._invokeOne( function ( ext ) {
+
+							return ext != this && ext.getDependency && ext.getDependency( type, index );
+
+						} );
+						if ( ! dependency ) {
+
+							throw new Error( 'Unknown type: ' + type );
+
+						}
+
+						break;
 
 				}
 
@@ -2580,10 +2598,11 @@
 			const accessorDef = this.json.accessors[ accessorIndex ];
 			if ( accessorDef.bufferView === undefined && accessorDef.sparse === undefined ) {
 
-				// Ignore empty accessors, which may be used to declare runtime
-				// information about attributes coming from another source (e.g. Draco
-				// compression extension).
-				return Promise.resolve( null );
+				const itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];
+				const TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];
+				const normalized = accessorDef.normalized === true;
+				const array = new TypedArray( accessorDef.count * itemSize );
+				return Promise.resolve( new THREE.BufferAttribute( array, itemSize, normalized ) );
 
 			}
 

+ 102 - 0
examples/js/utils/BufferGeometryUtils.js

@@ -1040,6 +1040,107 @@
 
 	}
 
+	// Creates a new, non-indexed geometry with smooth normals everywhere except faces that meet at
+	// an angle greater than the crease angle.
+	function toCreasedNormals( geometry, creaseAngle = Math.PI / 3 /* 60 degrees */ ) {
+
+		const creaseDot = Math.cos( creaseAngle );
+		const hashMultiplier = ( 1 + 1e-10 ) * 1e2;
+
+		// reusable vertors
+		const verts = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
+		const tempVec1 = new THREE.Vector3();
+		const tempVec2 = new THREE.Vector3();
+		const tempNorm = new THREE.Vector3();
+		const tempNorm2 = new THREE.Vector3();
+
+		// hashes a vector
+		function hashVertex( v ) {
+
+			const x = ~ ~ ( v.x * hashMultiplier );
+			const y = ~ ~ ( v.y * hashMultiplier );
+			const z = ~ ~ ( v.z * hashMultiplier );
+			return `${x},${y},${z}`;
+
+		}
+
+		const resultGeometry = geometry.toNonIndexed();
+		const posAttr = resultGeometry.attributes.position;
+		const vertexMap = {};
+
+		// find all the normals shared by commonly located vertices
+		for ( let i = 0, l = posAttr.count / 3; i < l; i ++ ) {
+
+			const i3 = 3 * i;
+			const a = verts[ 0 ].fromBufferAttribute( posAttr, i3 + 0 );
+			const b = verts[ 1 ].fromBufferAttribute( posAttr, i3 + 1 );
+			const c = verts[ 2 ].fromBufferAttribute( posAttr, i3 + 2 );
+			tempVec1.subVectors( c, b );
+			tempVec2.subVectors( a, b );
+
+			// add the normal to the map for all vertices
+			const normal = new THREE.Vector3().crossVectors( tempVec1, tempVec2 ).normalize();
+			for ( let n = 0; n < 3; n ++ ) {
+
+				const vert = verts[ n ];
+				const hash = hashVertex( vert );
+				if ( ! ( hash in vertexMap ) ) {
+
+					vertexMap[ hash ] = [];
+
+				}
+
+				vertexMap[ hash ].push( normal );
+
+			}
+
+		}
+
+		// average normals from all vertices that share a common location if they are within the
+		// provided crease threshold
+		const normalArray = new Float32Array( posAttr.count * 3 );
+		const normAttr = new THREE.BufferAttribute( normalArray, 3, false );
+		for ( let i = 0, l = posAttr.count / 3; i < l; i ++ ) {
+
+			// get the face normal for this vertex
+			const i3 = 3 * i;
+			const a = verts[ 0 ].fromBufferAttribute( posAttr, i3 + 0 );
+			const b = verts[ 1 ].fromBufferAttribute( posAttr, i3 + 1 );
+			const c = verts[ 2 ].fromBufferAttribute( posAttr, i3 + 2 );
+			tempVec1.subVectors( c, b );
+			tempVec2.subVectors( a, b );
+			tempNorm.crossVectors( tempVec1, tempVec2 ).normalize();
+
+			// average all normals that meet the threshold and set the normal value
+			for ( let n = 0; n < 3; n ++ ) {
+
+				const vert = verts[ n ];
+				const hash = hashVertex( vert );
+				const otherNormals = vertexMap[ hash ];
+				tempNorm2.set( 0, 0, 0 );
+				for ( let k = 0, lk = otherNormals.length; k < lk; k ++ ) {
+
+					const otherNorm = otherNormals[ k ];
+					if ( tempNorm.dot( otherNorm ) > creaseDot ) {
+
+						tempNorm2.add( otherNorm );
+
+					}
+
+				}
+
+				tempNorm2.normalize();
+				normAttr.setXYZ( i3 + n, tempNorm2.x, tempNorm2.y, tempNorm2.z );
+
+			}
+
+		}
+
+		resultGeometry.setAttribute( 'normal', normAttr );
+		return resultGeometry;
+
+	}
+
 	THREE.BufferGeometryUtils = {};
 	THREE.BufferGeometryUtils.computeMikkTSpaceTangents = computeMikkTSpaceTangents;
 	THREE.BufferGeometryUtils.computeMorphedAttributes = computeMorphedAttributes;
@@ -1053,6 +1154,7 @@
 	THREE.BufferGeometryUtils.mergeBufferGeometries = mergeBufferGeometries;
 	THREE.BufferGeometryUtils.mergeGroups = mergeGroups;
 	THREE.BufferGeometryUtils.mergeVertices = mergeVertices;
+	THREE.BufferGeometryUtils.toCreasedNormals = toCreasedNormals;
 	THREE.BufferGeometryUtils.toTrianglesDrawMode = toTrianglesDrawMode;
 
 } )();