Michael Herzog 1 год назад
Родитель
Сommit
aec32f75f8

+ 18 - 0
examples/jsm/webxr/ARButton.js

@@ -1,5 +1,23 @@
+/**
+ * A utility class for creating a button that allows to initinate
+ * immersive AR sessions based on WebXR. The button can be created
+ * with a factory method and then appended ot the website's DOM.
+ *
+ * ```js
+ * document.body.appendChild( ARButton.createButton( renderer ) );
+ * ```
+ *
+ * @hideconstructor
+ */
 class ARButton {
 
+	/**
+	 * Constructs a new AR button.
+	 *
+	 * @param {WebGLRenderer|WebGPURenderer} renderer - The renderer.
+	 * @param {XRSessionInit} [sessionInit] - The a configuration object for the AR session.
+	 * @return {HTMLElement} The button or an error message if `immersive-ar` isn't supported.
+	 */
 	static createButton( renderer, sessionInit = {} ) {
 
 		const button = document.createElement( 'button' );

+ 82 - 0
examples/jsm/webxr/OculusHandModel.js

@@ -4,19 +4,77 @@ import { XRHandMeshModel } from './XRHandMeshModel.js';
 const TOUCH_RADIUS = 0.01;
 const POINTING_JOINT = 'index-finger-tip';
 
+/**
+ * Represents an Oculus hand model.
+ *
+ * @augments Object3D
+ */
 class OculusHandModel extends Object3D {
 
+	/**
+	 * Constructs a new Oculus hand model.
+	 *
+	 * @param {Group} controller - The hand controller.
+	 * @param {?Loader} [loader=null] - A loader that is used to load hand models.
+	 * @param {?Function} [onLoad=null] - A callback that is executed when a hand model has been loaded.
+	 */
 	constructor( controller, loader = null, onLoad = null ) {
 
 		super();
 
+		/**
+		 * The hand controller.
+		 *
+		 * @type {Group}
+		 */
 		this.controller = controller;
+
+		/**
+		 * The motion controller.
+		 *
+		 * @type {?MotionController}
+		 * @default null
+		 */
 		this.motionController = null;
+
+		/**
+		 * The model's environment map.
+		 *
+		 * @type {?Texture}
+		 * @default null
+		 */
 		this.envMap = null;
+
+		/**
+		 * A loader that is used to load hand models.
+		 *
+		 * @type {?Loader}
+		 * @default null
+		 */
 		this.loader = loader;
+
+		/**
+		 * A callback that is executed when a hand model has been loaded.
+		 *
+		 * @type {?Function}
+		 * @default null
+		 */
 		this.onLoad = onLoad;
+
+		/**
+		 * The path to the model repository.
+		 *
+		 * @type {?string}
+		 * @default null
+		 */
 		this.path = null;
 
+		/**
+		 * The model mesh.
+		 *
+		 * @type {Mesh}
+		 * @default null
+		 */
 		this.mesh = null;
 
 		controller.addEventListener( 'connected', ( event ) => {
@@ -42,6 +100,12 @@ class OculusHandModel extends Object3D {
 
 	}
 
+	/**
+	 * Overwritten with a custom implementation. Makes sure the motion controller updates the mesh.
+	 *
+	 * @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even
+	 * when {@link Object3D#matrixWorldAutoUpdate} is set to `false`.
+	 */
 	updateMatrixWorld( force ) {
 
 		super.updateMatrixWorld( force );
@@ -54,6 +118,11 @@ class OculusHandModel extends Object3D {
 
 	}
 
+	/**
+	 * Returns the pointer posiiton which is the position of the index finger tip.
+	 *
+	 * @return {Vector3|null} The pointer position. Returns `null` if not index finger tip joint was found.
+	 */
 	getPointerPosition() {
 
 		const indexFingerTip = this.controller.joints[ POINTING_JOINT ];
@@ -69,6 +138,13 @@ class OculusHandModel extends Object3D {
 
 	}
 
+	/**
+	 * Returns `true` if the current pointer position (the index finger tip) intersections
+	 * with the given box object.
+	 *
+	 *  @param {Mesh} boxObject - The box object.
+	 * @return {boolean} Whether an intersection was found or not.
+	 */
 	intersectBoxObject( boxObject ) {
 
 		const pointerPosition = this.getPointerPosition();
@@ -86,6 +162,12 @@ class OculusHandModel extends Object3D {
 
 	}
 
+	/**
+	 * Executed actions depending on the interaction state with
+	 * the given button.
+	 *
+	 *  @param {Object} button - The button.
+	 */
 	checkButton( button ) {
 
 		if ( this.intersectBoxObject( button ) ) {

+ 125 - 0
examples/jsm/webxr/OculusHandPointerModel.js

@@ -19,13 +19,35 @@ const ZAXIS = /* @__PURE__ */ new Vector3( 0, 0, 1 );
 const CURSOR_RADIUS = 0.02;
 const CURSOR_MAX_DISTANCE = 1.5;
 
+/**
+ * Represents an Oculus hand pointer model.
+ *
+ * @augments Object3D
+ */
 class OculusHandPointerModel extends Object3D {
 
+	/**
+	 * Constructs a new Oculus hand model.
+	 *
+	 * @param {Group} hand - The hand controller.
+	 * @param {Group} controller - The WebXR controller in target ray space.
+	 */
 	constructor( hand, controller ) {
 
 		super();
 
+		/**
+		 * The hand controller.
+		 *
+		 * @type {Group}
+		 */
 		this.hand = hand;
+
+		/**
+		 * The WebXR controller in target ray space.
+		 *
+		 * @type {Group}
+		 */
 		this.controller = controller;
 
 		// Unused
@@ -33,15 +55,61 @@ class OculusHandPointerModel extends Object3D {
 		this.envMap = null;
 		this.mesh = null;
 
+		/**
+		 * The pointer geometry.
+		 *
+		 * @type {?BufferGeometry}
+		 * @default null
+		 */
 		this.pointerGeometry = null;
+
+		/**
+		 * The pointer mesh.
+		 *
+		 * @type {?Mesh}
+		 * @default null
+		 */
 		this.pointerMesh = null;
+
+		/**
+		 * The pointer object that holds the pointer mesh.
+		 *
+		 * @type {?Object3D}
+		 * @default null
+		 */
 		this.pointerObject = null;
 
+		/**
+		 * Whether the model is pinched or not.
+		 *
+		 * @type {?boolean}
+		 * @default false
+		 */
 		this.pinched = false;
+
+		/**
+		 * Whether the model is attached or not.
+		 *
+		 * @type {?boolean}
+		 * @default false
+		 */
 		this.attached = false;
 
+		/**
+		 * The cursor object.
+		 *
+		 * @type {?Mesh}
+		 * @default null
+		 */
 		this.cursorObject = null;
 
+		/**
+		 * The internal raycaster used for detecting
+		 * intersections.
+		 *
+		 * @type {?Raycaster}
+		 * @default null
+		 */
 		this.raycaster = null;
 
 		this._onConnected = this._onConnected.bind( this );
@@ -143,6 +211,9 @@ class OculusHandPointerModel extends Object3D {
 
 	}
 
+	/**
+	 * Creates a pointer mesh and adds it to this model.
+	 */
 	createPointer() {
 
 		let i, j;
@@ -317,6 +388,12 @@ class OculusHandPointerModel extends Object3D {
 
 	}
 
+	/**
+	 * Overwritten with a custom implementation. Makes sure the internal pointer and raycaster are updated.
+	 *
+	 * @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even
+	 * when {@link Object3D#matrixWorldAutoUpdate} is set to `false`.
+	 */
 	updateMatrixWorld( force ) {
 
 		super.updateMatrixWorld( force );
@@ -329,24 +406,47 @@ class OculusHandPointerModel extends Object3D {
 
 	}
 
+	/**
+	 * Returns `true` is the model is pinched.
+	 *
+	 * @return {boolean} Whether the model is pinched or not.
+	 */
 	isPinched() {
 
 		return this.pinched;
 
 	}
 
+	/**
+	 * Sets the attached state.
+	 *
+	 * @param {boolean} attached - Whether the model is attached or not.
+	 */
 	setAttached( attached ) {
 
 		this.attached = attached;
 
 	}
 
+	/**
+	 * Returns `true` is the model is attached.
+	 *
+	 * @return {boolean} Whether the model is attached or not.
+	 */
 	isAttached() {
 
 		return this.attached;
 
 	}
 
+	/**
+	 * Perfoms an intersection test with the model's raycaster and the given object.
+	 *
+	 * @param {Object3D} object - The 3D object to check for intersection with the ray.
+	 * @param {boolean} [recursive=true] - If set to `true`, it also checks all descendants.
+	 * Otherwise it only checks intersection with the object.
+	 * @return {Array<Raycaster~Intersection>} An array holding the intersection points.
+	 */
 	intersectObject( object, recursive = true ) {
 
 		if ( this.raycaster ) {
@@ -357,6 +457,14 @@ class OculusHandPointerModel extends Object3D {
 
 	}
 
+	/**
+	 * Perfoms an intersection test with the model's raycaster and the given objects.
+	 *
+	 * @param {Array<Object3D>} objects - The 3D objects to check for intersection with the ray.
+	 * @param {boolean} [recursive=true] - If set to `true`, it also checks all descendants.
+	 * Otherwise it only checks intersection with the object.
+	 * @return {Array<Raycaster~Intersection>} An array holding the intersection points.
+	 */
 	intersectObjects( objects, recursive = true ) {
 
 		if ( this.raycaster ) {
@@ -367,6 +475,14 @@ class OculusHandPointerModel extends Object3D {
 
 	}
 
+	/**
+	 * Checks for intersections between the model's raycaster and the given objects. The method
+	 * updates the cursor object to the intersection point.
+	 *
+	 * @param {Array<Object3D>} objects - The 3D objects to check for intersection with the ray.
+	 * @param {boolean} [recursive=false] - If set to `true`, it also checks all descendants.
+	 * Otherwise it only checks intersection with the object.
+	 */
 	checkIntersections( objects, recursive = false ) {
 
 		if ( this.raycaster && ! this.attached ) {
@@ -389,6 +505,11 @@ class OculusHandPointerModel extends Object3D {
 
 	}
 
+	/**
+	 * Sets the cursor to the given distance.
+	 *
+	 * @param {number} distance - The distance to set the cursor to.
+	 */
 	setCursor( distance ) {
 
 		const direction = new Vector3( 0, 0, - 1 );
@@ -400,6 +521,10 @@ class OculusHandPointerModel extends Object3D {
 
 	}
 
+	/**
+	 * Frees the GPU-related resources allocated by this instance. Call this
+	 * method whenever this instance is no longer used in your app.
+	 */
 	dispose() {
 
 		this._onDisconnected();

+ 11 - 0
examples/jsm/webxr/Text2D.js

@@ -1,5 +1,16 @@
 import { DoubleSide, Mesh, MeshBasicMaterial, PlaneGeometry, Texture } from 'three';
 
+/** @module Text2D */
+
+/**
+ * A helper function for creating a simple plane mesh
+ * that can be used as a text label. The mesh's material
+ * holds a canvas texture that displays the given message.
+ *
+ * @param {string} message - The message to display.
+ * @param {number} height - The labels height.
+ * @return {Mesh} The plane mesh representing a text label.
+ */
 function createText( message, height ) {
 
 	const canvas = document.createElement( 'canvas' );

+ 30 - 0
examples/jsm/webxr/VRButton.js

@@ -1,5 +1,23 @@
+/**
+ * A utility class for creating a button that allows to initinate
+ * immersive VR sessions based on WebXR. The button can be created
+ * with a factory method and then appended ot the website's DOM.
+ *
+ * ```js
+ * document.body.appendChild( VRButton.createButton( renderer ) );
+ * ```
+ *
+ * @hideconstructor
+ */
 class VRButton {
 
+	/**
+	 * Constructs a new VR button.
+	 *
+	 * @param {WebGLRenderer|WebGPURenderer} renderer - The renderer.
+	 * @param {XRSessionInit} [sessionInit] - The a configuration object for the AR session.
+	 * @return {HTMLElement} The button or an error message if `immersive-ar` isn't supported.
+	 */
 	static createButton( renderer, sessionInit = {} ) {
 
 		const button = document.createElement( 'button' );
@@ -207,6 +225,11 @@ class VRButton {
 
 	}
 
+	/**
+	 * Registers a `sessiongranted` event listener. When a session is granted, the {@link VRButton#xrSessionIsGranted}
+	 * flag will evaluate to `true`. This method is automtically called by the module itself so there
+	 * should be no need to use it on app level.
+	 */
 	static registerSessionGrantedListener() {
 
 		if ( typeof navigator !== 'undefined' && 'xr' in navigator ) {
@@ -227,6 +250,13 @@ class VRButton {
 
 }
 
+/**
+ * Whether a XR session has been granted or not.
+ *
+ * @static
+ * @type {boolean}
+ * @default false
+ */
 VRButton.xrSessionIsGranted = false;
 VRButton.registerSessionGrantedListener();
 

+ 22 - 0
examples/jsm/webxr/XRButton.js

@@ -1,5 +1,27 @@
+/**
+ * A utility class for creating a button that allows to initinate
+ * immersive XR sessions based on WebXR. The button can be created
+ * with a factory method and then appended ot the website's DOM.
+ *
+ * ```js
+ * document.body.appendChild( XRButton.createButton( renderer ) );
+ * ```
+ *
+ * Compared to {@link ARButton} and {@link VRButton}, this class will
+ * try to offer an immersive AR session first. If the device does not
+ * support this type of session, it uses an immersive VR session.
+ *
+ * @hideconstructor
+ */
 class XRButton {
 
+	/**
+	 * Constructs a new XR button.
+	 *
+	 * @param {WebGLRenderer|WebGPURenderer} renderer - The renderer.
+	 * @param {XRSessionInit} [sessionInit] - The a configuration object for the AR session.
+	 * @return {HTMLElement} The button or an error message if WebXR isn't supported.
+	 */
 	static createButton( renderer, sessionInit = {} ) {
 
 		const button = document.createElement( 'button' );

+ 87 - 3
examples/jsm/webxr/XRControllerModelFactory.js

@@ -16,17 +16,44 @@ import {
 const DEFAULT_PROFILES_PATH = 'https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles';
 const DEFAULT_PROFILE = 'generic-trigger';
 
+/**
+ * Represents a XR controller model.
+ *
+ * @augments Object3D
+ */
 class XRControllerModel extends Object3D {
 
+	/**
+	 * Constructs a new XR controller model.
+	 */
 	constructor() {
 
 		super();
 
+		/**
+		 * The motion controller.
+		 *
+		 * @type {?MotionController}
+		 * @default null
+		 */
 		this.motionController = null;
+
+		/**
+		 * The controller's environment map.
+		 *
+		 * @type {?Texture}
+		 * @default null
+		 */
 		this.envMap = null;
 
 	}
 
+	/**
+	 * Sets an environment map that is applied to the controller model.
+	 *
+	 * @param {?Texture} envMap - The environment map to apply.
+	 * @return {XRControllerModel} A reference to this instance.
+	 */
 	setEnvironmentMap( envMap ) {
 
 		if ( this.envMap == envMap ) {
@@ -52,10 +79,11 @@ class XRControllerModel extends Object3D {
 	}
 
 	/**
-	 * Polls data from the XRInputSource and updates the model's components to match
-	 * the real world data
+	 * Overwritten with a custom implementation. Polls data from the XRInputSource and updates the
+	 * model's components to match the real world data.
 	 *
-	 * @param {boolean} force
+	 * @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even
+	 * when {@link Object3D#matrixWorldAutoUpdate} is set to `false`.
 	 */
 	updateMatrixWorld( force ) {
 
@@ -112,6 +140,7 @@ class XRControllerModel extends Object3D {
  * saves them to the motionController components for use in the frame loop. When
  * touchpads are found, attaches a touch dot to them.
  *
+ * @private
  * @param {MotionController} motionController
  * @param {Object3D} scene
  */
@@ -209,13 +238,56 @@ function addAssetSceneToControllerModel( controllerModel, scene ) {
 
 }
 
+/**
+ * Allows to create controller models for WebXR controllersthat can be added as a visual
+ * representation to your scene. `XRControllerModelFactory` will automatically fetch controller
+ * models that match what the user is holding as closely as possible. The models should be
+ * attached to the object returned from getControllerGrip in order to match the orientation of
+ * the held device.
+ *
+ * This module depends on the [motion-controllers]{@link https://github.com/immersive-web/webxr-input-profiles/blob/main/packages/motion-controllers/README.md}
+ * third-part library.
+ *
+ * ```js
+ * const controllerModelFactory = new XRControllerModelFactory();
+ *
+ * const controllerGrip = renderer.xr.getControllerGrip( 0 );
+ * controllerGrip.add( controllerModelFactory.createControllerModel( controllerGrip ) );
+ * scene.add( controllerGrip );
+ * ```
+ */
 class XRControllerModelFactory {
 
+	/**
+	 * Constructs a new XR controller model factory.
+	 *
+	 * @param {?GLTFLoader} [gltfLoader=null] - A glTF loader that is used to load controller models.
+	 * @param {?Function} [onLoad=null] - A callback that is executed when a controller model has been loaded.
+	 */
 	constructor( gltfLoader = null, onLoad = null ) {
 
+		/**
+		 * A glTF loader that is used to load controller models.
+		 *
+		 * @type {?GLTFLoader}
+		 * @default null
+		 */
 		this.gltfLoader = gltfLoader;
+
+		/**
+		 * The path to the model repository.
+		 *
+		 * @type {string}
+		 */
 		this.path = DEFAULT_PROFILES_PATH;
 		this._assetCache = {};
+
+		/**
+		 * A callback that is executed when a controller model has been loaded.
+		 *
+		 * @type {?Function}
+		 * @default null
+		 */
 		this.onLoad = onLoad;
 
 		// If a GLTFLoader wasn't supplied to the constructor create a new one.
@@ -227,6 +299,12 @@ class XRControllerModelFactory {
 
 	}
 
+	/**
+	 * Sets the path to the model repository.
+	 *
+	 * @param {string} path - The path to set.
+	 * @return {XRControllerModelFactory} A reference to this instance.
+	 */
 	setPath( path ) {
 
 		this.path = path;
@@ -235,6 +313,12 @@ class XRControllerModelFactory {
 
 	}
 
+	/**
+	 * Creates a controller model for the given WebXR controller.
+	 *
+	 * @param {Group} controller - The controller.
+	 * @return {XRControllerModel} The XR controller model.
+	 */
 	createControllerModel( controller ) {
 
 		const controllerModel = new XRControllerModel();

+ 33 - 3
examples/jsm/webxr/XREstimatedLight.js

@@ -133,22 +133,49 @@ class SessionLightProbe {
 
 }
 
+/**
+ * This class can be used to represent the environmental light of
+ * a XR session. It relies on the WebXR Lighting Estimation API.
+ *
+ * @augments Group
+ */
 export class XREstimatedLight extends Group {
 
+	/**
+	 * Constructs a new light.
+	 *
+	 * @param {WebGLRenderer} renderer - The renderer.
+	 * @param {boolean} [environmentEstimation=true] - Whether to use environment estimation or not.
+	 */
 	constructor( renderer, environmentEstimation = true ) {
 
 		super();
 
+		/**
+		 * The light probe that represents the estimated light.
+		 *
+		 * @type {LightProbe}
+		 */
 		this.lightProbe = new LightProbe();
 		this.lightProbe.intensity = 0;
 		this.add( this.lightProbe );
 
+		/**
+		 * Represents the primariy light from the XR environment.
+		 *
+		 * @type {DirectionalLight}
+		 */
 		this.directionalLight = new DirectionalLight();
 		this.directionalLight.intensity = 0;
 		this.add( this.directionalLight );
 
-		// Will be set to a cube map in the SessionLightProbe if environment estimation is
-		// available and requested.
+		/**
+		 * Will be set to a cube map in the SessionLightProbe if environment estimation is
+		 * available and requested.
+		 *
+		 * @type {?Texture}
+		 * @default null
+		 */
 		this.environment = null;
 
 		let sessionLightProbe = null;
@@ -198,7 +225,10 @@ export class XREstimatedLight extends Group {
 
 		} );
 
-		// Done inline to provide access to sessionLightProbe.
+		/**
+		 * Frees the GPU-related resources allocated by this instance. Call this
+		 * method whenever this instance is no longer used in your app.
+		 */
 		this.dispose = () => {
 
 			if ( sessionLightProbe ) {

+ 35 - 0
examples/jsm/webxr/XRHandMeshModel.js

@@ -2,13 +2,45 @@ import { GLTFLoader } from '../loaders/GLTFLoader.js';
 
 const DEFAULT_HAND_PROFILE_PATH = 'https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles/generic-hand/';
 
+/**
+ * Represents one of the hand model types {@link XRHandModelFactory} might produce
+ * depending on the selected profile. `XRHandMeshModel` represents a hand with a
+ * custom asset.
+ */
 class XRHandMeshModel {
 
+	/**
+	 * Constructs a new XR hand mesh model.
+	 *
+	 * @param {XRHandModel} handModel - The hand model.
+	 * @param {Group} controller - The WebXR controller.
+	 * @param {string} path - The model path.
+	 * @param {XRHandedness} handedness - The handedness of the XR input source.
+	 * @param {?Loader} [loader=null] - The loader. If not provided, an instance of `GLTFLoader` will be used to load models.
+	 * @param {?Function} [onLoad=null] - A callback that is executed when a controller model has been loaded.
+	 */
 	constructor( handModel, controller, path, handedness, loader = null, onLoad = null ) {
 
+		/**
+		 * The WebXR controller.
+		 *
+		 * @type {Group}
+		 */
 		this.controller = controller;
+
+		/**
+		 * The hand model.
+		 *
+		 * @type {XRHandModel}
+		 */
 		this.handModel = handModel;
 
+		/**
+		 * An array of bones representing the bones
+		 * of the hand skeleton.
+		 *
+		 * @type {Array<Bone>}
+		 */
 		this.bones = [];
 
 		if ( loader === null ) {
@@ -80,6 +112,9 @@ class XRHandMeshModel {
 
 	}
 
+	/**
+	 * Updates the mesh based on the tracked XR joints data.
+	 */
 	updateMesh() {
 
 		// XR Joints

+ 92 - 0
examples/jsm/webxr/XRHandModelFactory.js

@@ -10,20 +10,61 @@ import {
 	XRHandMeshModel
 } from './XRHandMeshModel.js';
 
+/**
+ * Represents a XR hand model.
+ *
+ * @augments Object3D
+ */
 class XRHandModel extends Object3D {
 
+	/**
+	 * Constructs a new XR hand model.
+	 *
+	 * @param {Group} controller - The hand controller.
+	 */
 	constructor( controller ) {
 
 		super();
 
+		/**
+		 * The hand controller.
+		 *
+		 * @type {Group}
+		 */
 		this.controller = controller;
+
+		/**
+		 * The motion controller.
+		 *
+		 * @type {?MotionController}
+		 * @default null
+		 */
 		this.motionController = null;
+
+		/**
+		 * The controller's environment map.
+		 *
+		 * @type {?Texture}
+		 * @default null
+		 */
 		this.envMap = null;
 
+		/**
+		 * The model mesh.
+		 *
+		 * @type {Mesh}
+		 * @default null
+		 */
 		this.mesh = null;
 
 	}
 
+	/**
+	 * Overwritten with a custom implementation. Makes sure the motion controller updates the mesh.
+	 *
+	 * @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even
+	 * when {@link Object3D#matrixWorldAutoUpdate} is set to `false`.
+	 */
 	updateMatrixWorld( force ) {
 
 		super.updateMatrixWorld( force );
@@ -38,16 +79,60 @@ class XRHandModel extends Object3D {
 
 }
 
+/**
+ * Similar to {@link XRControllerModelFactory}, this class allows to create hand models
+ * for WebXR controllers that can be added as a visual representation to your scene.
+ *
+ * ```js
+ * const handModelFactory = new XRHandModelFactory();
+ *
+ * const hand = renderer.xr.getHand( 0 );
+ * hand.add( handModelFactory.createHandModel( hand ) );
+ * scene.add( hand );
+ * ```
+ */
 class XRHandModelFactory {
 
+	/**
+	 * Constructs a new XR hand model factory.
+	 *
+	 * @param {?GLTFLoader} [gltfLoader=null] - A glTF loader that is used to load hand models.
+	 * @param {?Function} [onLoad=null] - A callback that is executed when a hand model has been loaded.
+	 */
 	constructor( gltfLoader = null, onLoad = null ) {
 
+		/**
+		 * A glTF loader that is used to load hand models.
+		 *
+		 * @type {?GLTFLoader}
+		 * @default null
+		 */
 		this.gltfLoader = gltfLoader;
+
+		/**
+		 * The path to the model repository.
+		 *
+		 * @type {?string}
+		 * @default null
+		 */
 		this.path = null;
+
+		/**
+		 * A callback that is executed when a hand model has been loaded.
+		 *
+		 * @type {?Function}
+		 * @default null
+		 */
 		this.onLoad = onLoad;
 
 	}
 
+	/**
+	 * Sets the path to the hand model repository.
+	 *
+	 * @param {string} path - The path to set.
+	 * @return {XRHandModelFactory} A reference to this instance.
+	 */
 	setPath( path ) {
 
 		this.path = path;
@@ -56,6 +141,13 @@ class XRHandModelFactory {
 
 	}
 
+	/**
+	 * Creates a controller model for the given WebXR hand controller.
+	 *
+	 * @param {Group} controller - The hand controller.
+	 * @param {('spheres'|'boxes'|'mesh')} [profile] - The model profile that defines the model type.
+	 * @return {XRHandModel} The XR hand model.
+	 */
 	createHandModel( controller, profile ) {
 
 		const handModel = new XRHandModel( controller );

+ 42 - 0
examples/jsm/webxr/XRHandPrimitiveModel.js

@@ -11,12 +11,44 @@ import {
 const _matrix = new Matrix4();
 const _vector = new Vector3();
 
+/**
+ * Represents one of the hand model types {@link XRHandModelFactory} might produce
+ * depending on the selected profile. `XRHandPrimitiveModel` represents a hand
+ * with sphere or box primitives according to the selected `primitive` option.
+ */
 class XRHandPrimitiveModel {
 
+	/**
+	 * Constructs a new XR hand primitive model.
+	 *
+	 * @param {XRHandModel} handModel - The hand model.
+	 * @param {Group} controller - The WebXR controller.
+	 * @param {string} path - The model path.
+	 * @param {XRHandedness} handedness - The handedness of the XR input source.
+	 * @param {XRHandPrimitiveModel~Options} options - The model options.
+	 */
 	constructor( handModel, controller, path, handedness, options ) {
 
+		/**
+		 * The WebXR controller.
+		 *
+		 * @type {Group}
+		 */
 		this.controller = controller;
+
+		/**
+		 * The hand model.
+		 *
+		 * @type {XRHandModel}
+		 */
 		this.handModel = handModel;
+
+		/**
+		 * The model's environment map.
+		 *
+		 * @type {?Texture}
+		 * @default null
+		 */
 		this.envMap = null;
 
 		let geometry;
@@ -70,6 +102,9 @@ class XRHandPrimitiveModel {
 
 	}
 
+	/**
+	 * Updates the mesh based on the tracked XR joints data.
+	 */
 	updateMesh() {
 
 		const defaultRadius = 0.008;
@@ -100,4 +135,11 @@ class XRHandPrimitiveModel {
 
 }
 
+/**
+ * Constructor options of `XRHandPrimitiveModel`.
+ *
+ * @typedef {Object} XRHandPrimitiveModel~Options
+ * @property {('box'|'sphere')} [primitive] - The primitive type.
+ **/
+
 export { XRHandPrimitiveModel };

+ 17 - 0
examples/jsm/webxr/XRPlanes.js

@@ -6,8 +6,25 @@ import {
 	Object3D
 } from 'three';
 
+/**
+ * A utility class for the WebXR Plane Detection Module. If planes
+ * are detected by WebXR, this class will automatically add them
+ * as thin box meshes to the scene when below code snippet is used.
+ *
+ * ```js
+ * const planes = new XRPlanes( renderer );
+ * scene.add( planes );
+ * ```
+ *
+ * @augments Object3D
+ */
 class XRPlanes extends Object3D {
 
+	/**
+	 * Constructs a new XR plane container.
+	 *
+	 * @param {WebGLRenderer|WebGPURenderer} renderer - The renderer.
+	 */
 	constructor( renderer ) {
 
 		super();

+ 1 - 0
utils/docs/jsdoc.config.json

@@ -33,6 +33,7 @@
             "examples/jsm/renderers",
             "examples/jsm/textures",
             "examples/jsm/tsl",
+            "examples/jsm/webxr",
             "src"
         ],
         "exclude": [

粤ICP备19079148号