three-stdlib
Version:
stand-alone library of threejs examples
176 lines (175 loc) • 7.15 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const GLTFLoader = require("../loaders/GLTFLoader.cjs");
const MotionControllers = require("../libs/MotionControllers.cjs");
const DEFAULT_PROFILES_PATH = "https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles";
const DEFAULT_PROFILE = "generic-trigger";
const applyEnvironmentMap = (envMap, obj) => {
obj.traverse((child) => {
if (child instanceof THREE.Mesh && "envMap" in child.material) {
child.material.envMap = envMap;
child.material.needsUpdate = true;
}
});
};
class XRControllerModel extends THREE.Object3D {
constructor() {
super();
__publicField(this, "envMap");
__publicField(this, "motionController");
this.motionController = null;
this.envMap = null;
}
setEnvironmentMap(envMap) {
if (this.envMap == envMap) {
return this;
}
this.envMap = envMap;
applyEnvironmentMap(this.envMap, this);
return this;
}
/**
* Polls data from the XRInputSource and updates the model's components to match
* the real world data
*/
updateMatrixWorld(force) {
super.updateMatrixWorld(force);
if (!this.motionController)
return;
this.motionController.updateFromGamepad();
Object.values(this.motionController.components).forEach((component) => {
Object.values(component.visualResponses).forEach((visualResponse) => {
const { valueNode, minNode, maxNode, value, valueNodeProperty } = visualResponse;
if (!valueNode)
return;
if (valueNodeProperty === MotionControllers.MotionControllerConstants.VisualResponseProperty.VISIBILITY && typeof value === "boolean") {
valueNode.visible = value;
} else if (valueNodeProperty === MotionControllers.MotionControllerConstants.VisualResponseProperty.TRANSFORM && minNode && maxNode && typeof value === "number") {
valueNode.quaternion.slerpQuaternions(minNode.quaternion, maxNode.quaternion, value);
valueNode.position.lerpVectors(minNode.position, maxNode.position, value);
}
});
});
}
}
function findNodes(motionController, scene) {
Object.values(motionController.components).forEach((component) => {
const { type, touchPointNodeName, visualResponses } = component;
if (type === MotionControllers.MotionControllerConstants.ComponentType.TOUCHPAD && touchPointNodeName) {
component.touchPointNode = scene.getObjectByName(touchPointNodeName);
if (component.touchPointNode) {
const sphereGeometry = new THREE.SphereGeometry(1e-3);
const material = new THREE.MeshBasicMaterial({ color: 255 });
const sphere = new THREE.Mesh(sphereGeometry, material);
component.touchPointNode.add(sphere);
} else {
console.warn(`Could not find touch dot, ${component.touchPointNodeName}, in touchpad component ${component.id}`);
}
}
Object.values(visualResponses).forEach((visualResponse) => {
const { valueNodeName, minNodeName, maxNodeName, valueNodeProperty } = visualResponse;
if (valueNodeProperty === MotionControllers.MotionControllerConstants.VisualResponseProperty.TRANSFORM && minNodeName && maxNodeName) {
visualResponse.minNode = scene.getObjectByName(minNodeName);
visualResponse.maxNode = scene.getObjectByName(maxNodeName);
if (!visualResponse.minNode) {
console.warn(`Could not find ${minNodeName} in the model`);
return;
}
if (!visualResponse.maxNode) {
console.warn(`Could not find ${maxNodeName} in the model`);
return;
}
}
visualResponse.valueNode = scene.getObjectByName(valueNodeName);
if (!visualResponse.valueNode) {
console.warn(`Could not find ${valueNodeName} in the model`);
}
});
});
}
function addAssetSceneToControllerModel(controllerModel, scene) {
findNodes(controllerModel.motionController, scene);
if (controllerModel.envMap) {
applyEnvironmentMap(controllerModel.envMap, scene);
}
controllerModel.add(scene);
}
class XRControllerModelFactory {
constructor(gltfLoader = null) {
__publicField(this, "gltfLoader");
__publicField(this, "path");
__publicField(this, "_assetCache");
this.gltfLoader = gltfLoader;
this.path = DEFAULT_PROFILES_PATH;
this._assetCache = {};
if (!this.gltfLoader) {
this.gltfLoader = new GLTFLoader.GLTFLoader();
}
}
createControllerModel(controller) {
const controllerModel = new XRControllerModel();
let scene = null;
const onConnected = (event) => {
const xrInputSource = event.data;
if (xrInputSource.targetRayMode !== "tracked-pointer" || !xrInputSource.gamepad)
return;
MotionControllers.fetchProfile(xrInputSource, this.path, DEFAULT_PROFILE).then(({ profile, assetPath }) => {
if (!assetPath) {
throw new Error("no asset path");
}
controllerModel.motionController = new MotionControllers.MotionController(xrInputSource, profile, assetPath);
const assetUrl = controllerModel.motionController.assetUrl;
const cachedAsset = this._assetCache[assetUrl];
if (cachedAsset) {
scene = cachedAsset.scene.clone();
addAssetSceneToControllerModel(controllerModel, scene);
} else {
if (!this.gltfLoader) {
throw new Error("GLTFLoader not set.");
}
this.gltfLoader.setPath("");
this.gltfLoader.load(
controllerModel.motionController.assetUrl,
(asset) => {
if (!controllerModel.motionController) {
console.warn("motionController gone while gltf load, bailing...");
return;
}
this._assetCache[assetUrl] = asset;
scene = asset.scene.clone();
addAssetSceneToControllerModel(controllerModel, scene);
},
() => {
},
() => {
throw new Error(`Asset ${assetUrl} missing or malformed.`);
}
);
}
}).catch((err) => {
console.warn(err);
});
};
controller.addEventListener("connected", onConnected);
const onDisconnected = () => {
controller.removeEventListener("connected", onConnected);
controller.removeEventListener("disconnected", onDisconnected);
controllerModel.motionController = null;
if (scene) {
controllerModel.remove(scene);
}
scene = null;
};
controller.addEventListener("disconnected", onDisconnected);
return controllerModel;
}
}
exports.XRControllerModelFactory = XRControllerModelFactory;
//# sourceMappingURL=XRControllerModelFactory.cjs.map
;