Explorar el Código

Allow the factory to cache controllers

Noticed that there was a significant delay in controllers reappearing after jumping into and out of a system menu, which was primarily caused by re-parsing the glTF assets. This change makes it much smoother.

Also includes a few bug fixes.
Brandon Jones hace 5 años
padre
commit
23054b4e69
Se han modificado 1 ficheros con 50 adiciones y 30 borrados
  1. 50 30
      examples/jsm/webxr/XRControllerModelFactory.js

+ 50 - 30
examples/jsm/webxr/XRControllerModelFactory.js

@@ -11,15 +11,15 @@ import {
 	SphereGeometry,
 } from "../../../build/three.module.js";
 
-import { GLTFLoader } from '../loaders/GLTFLoader.js'
+import { GLTFLoader } from '../loaders/GLTFLoader.js';
 
 import {
 	Constants as MotionControllerConstants,
 	fetchProfile,
 	MotionController
-} from '../libs/motion-controllers.module.js'
+} from '../libs/motion-controllers.module.js';
 
-const DEFAULT_PROFILES_PATH = 'https://cdn.jsdelivr.net/npm/@webxr-input-profiles/[email protected]/dist/profiles'
+const DEFAULT_PROFILES_PATH = 'https://cdn.jsdelivr.net/npm/@webxr-input-profiles/[email protected]/dist/profiles';
 
 function XRControllerModel( ) {
 
@@ -182,12 +182,37 @@ function findNodes( motionController, scene ) {
 	});
 }
 
+function addAssetSceneToControllerModel( controllerModel, scene ) {
+	// Find the nodes needed for animation and cache them on the motionController.
+	findNodes( controllerModel.motionController, scene );
+
+	// Apply any environment map that the mesh already has set.
+	if ( controllerModel.envMap ) {
+
+		scene.traverse(( child ) => {
+
+			if ( child.isMesh ) {
+
+				child.material.envMap = controllerModel.envMap;
+				child.material.needsUpdate = true;
+
+			}
+
+		});
+
+	}
+
+	// Add the glTF scene to the controllerModel.
+	controllerModel.add( scene );
+}
+
 var XRControllerModelFactory = ( function () {
 
 	function XRControllerModelFactory( gltfLoader = null ) {
 
 		this.gltfLoader = gltfLoader;
 		this.path = DEFAULT_PROFILES_PATH;
+		this._assetCache = {};
 
 		// If a GLTFLoader wasn't supplied to the constructor create a new one.
 		if ( !this.gltfLoader ) {
@@ -204,12 +229,6 @@ var XRControllerModelFactory = ( function () {
 
 		createControllerModel: function ( controller ) {
 
-			if ( !this.gltfLoader ) {
-
-				throw new Error(`GLTFLoader not set.`);
-
-			}
-
 			const controllerModel = new XRControllerModel();
 			let scene = null;
 
@@ -217,6 +236,8 @@ var XRControllerModelFactory = ( function () {
 
 				const xrInputSource = event.data;
 
+				if (xrInputSource.targetRayMode !== 'tracked-pointer' ) return;
+
 				fetchProfile(xrInputSource, this.path).then(({ profile, assetPath }) => {
 
 					controllerModel.motionController = new MotionController(
@@ -225,40 +246,39 @@ var XRControllerModelFactory = ( function () {
 						assetPath
 					);
 
-					this.gltfLoader.setPath('');
-					this.gltfLoader.load( controllerModel.motionController.assetUrl, ( asset ) => {
+					let cachedAsset = this._assetCache[controllerModel.motionController.assetUrl];
+					if (cachedAsset) {
 
-						scene = asset.scene;
+						scene = cachedAsset.scene.clone();
 
-						// Find the nodes needed for animation and cache them on the motionController.
-						findNodes( controllerModel.motionController, scene );
+						addAssetSceneToControllerModel(controllerModel, scene);
 
-						// Apply any environment map that the mesh already has set.
-						if ( controllerModel.envMap ) {
+					} else {
 
-							scene.traverse(( child ) => {
+						if ( !this.gltfLoader ) {
 
-								if ( child.isMesh ) {
+							throw new Error(`GLTFLoader not set.`);
 
-									child.material.envMap = controllerModel.envMap;
-									child.material.needsUpdate = true;
+						}
 
-								}
+						this.gltfLoader.setPath('');
+						this.gltfLoader.load( controllerModel.motionController.assetUrl, ( asset ) => {
 
-							});
+							this._assetCache[controllerModel.motionController.assetUrl] = asset;
 
-						}
+							scene = asset.scene.clone();
+
+							addAssetSceneToControllerModel(controllerModel, scene);
 
-						// Add the glTF scene to the controllerModel.
-						controllerModel.add( scene );
+						},
+						null,
+						() => {
 
-					},
-					null,
-					() => {
+							throw new Error(`Asset ${motionController.assetUrl} missing or malformed.`);
 
-						throw new Error(`Asset ${motionController.assetUrl} missing or malformed.`);
+						});
 
-					});
+					}
 
 				}).catch((err) => {