three-stdlib 2.8.2 → 2.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{BufferGeometryUtils-582025b8.js → BufferGeometryUtils-1a7a235c.js} +2 -1
- package/{BufferGeometryUtils-9eb5c2e7.js → BufferGeometryUtils-971dfde3.js} +0 -0
- package/animation/MMDAnimationHelper.d.ts +17 -17
- package/animation/MMDPhysics.d.ts +3 -3
- package/csm/CSM.d.ts +47 -22
- package/csm/CSMHelper.d.ts +20 -7
- package/effects/OutlineEffect.d.ts +4 -4
- package/effects/OutlineEffect.js +8 -2
- package/exporters/GLTFExporter.js +5 -10
- package/geometries/ConvexGeometry.d.ts +1 -1
- package/geometries/ParametricGeometries.d.ts +4 -2
- package/helpers/RectAreaLightHelper.d.ts +3 -3
- package/index.cjs.js +1 -1
- package/index.d.ts +9 -4
- package/index.js +9 -4
- package/libs/MotionControllers.cjs.js +1 -0
- package/libs/MotionControllers.js +403 -0
- package/loaders/AssimpLoader.js +39 -10
- package/loaders/ColladaLoader.js +22 -5
- package/loaders/EXRLoader.js +5 -1
- package/loaders/FBXLoader.js +10 -2
- package/loaders/GLTFLoader.cjs.js +1 -1
- package/loaders/GLTFLoader.d.ts +44 -20
- package/loaders/GLTFLoader.js +0 -1
- package/loaders/LDrawLoader.d.ts +6 -0
- package/loaders/MTLLoader.d.ts +18 -18
- package/loaders/RGBMLoader.d.ts +10 -10
- package/loaders/RGBMLoader.js +253 -178
- package/loaders/SVGLoader.d.ts +5 -3
- package/loaders/SVGLoader.js +10 -5
- package/loaders/lwo/IFFParser.js +4 -1
- package/math/OBB.d.ts +1 -1
- package/misc/GPUComputationRenderer.d.ts +8 -6
- package/misc/MD2CharacterComplex.js +9 -2
- package/misc/Volume.d.ts +2 -0
- package/modifiers/CurveModifier.cjs.js +1 -1
- package/modifiers/CurveModifier.js +1 -1
- package/modifiers/EdgeSplitModifier.cjs.js +1 -1
- package/modifiers/SimplifyModifier.cjs.js +1 -1
- package/nodes/inputs/ColorNode.d.ts +2 -2
- package/nodes/inputs/TextureNode.d.ts +3 -2
- package/nodes/materials/StandardNodeMaterial.d.ts +1 -1
- package/nodes/materials/nodes/StandardNode.d.ts +1 -0
- package/nodes/utils/ColorSpaceNode.d.ts +1 -1
- package/nodes/utils/JoinNode.d.ts +1 -0
- package/objects/MarchingCubes.d.ts +12 -4
- package/objects/Reflector.d.ts +4 -2
- package/objects/ReflectorForSSRPass.d.ts +6 -6
- package/objects/Refractor.d.ts +4 -2
- package/objects/Water.d.ts +4 -3
- package/objects/Water2.d.ts +12 -3
- package/package.json +2 -3
- package/postprocessing/ClearPass.d.ts +3 -3
- package/postprocessing/SAOPass.d.ts +3 -2
- package/postprocessing/SSAARenderPass.d.ts +3 -3
- package/postprocessing/SSAOPass.d.ts +3 -2
- package/postprocessing/SSRPass.d.ts +14 -17
- package/postprocessing/TAARenderPass.d.ts +2 -2
- package/renderers/CSS2DRenderer.d.ts +5 -1
- package/renderers/CSS3DRenderer.d.ts +5 -1
- package/renderers/webgpu/WebGPUTextures.js +62 -41
- package/shaders/SSRShader.d.ts +1 -2
- package/utils/BufferGeometryUtils.cjs.js +1 -1
- package/utils/BufferGeometryUtils.js +2 -1
- package/utils/LDrawUtils.cjs.js +1 -1
- package/utils/LDrawUtils.d.ts +5 -0
- package/utils/LDrawUtils.js +1 -1
- package/utils/RoughnessMipmapper.js +5 -1
- package/utils/SceneUtils.d.ts +10 -12
- package/utils/ShadowMapViewer.js +4 -1
- package/webxr/OculusHandModel.cjs.js +1 -0
- package/webxr/OculusHandModel.d.ts +19 -0
- package/webxr/OculusHandModel.js +72 -0
- package/webxr/OculusHandPointerModel.cjs.js +1 -0
- package/webxr/OculusHandPointerModel.d.ts +63 -0
- package/webxr/OculusHandPointerModel.js +248 -0
- package/webxr/Text2D.cjs.js +1 -0
- package/webxr/Text2D.d.ts +3 -0
- package/webxr/Text2D.js +32 -0
- package/webxr/VRButton.cjs.js +1 -1
- package/webxr/VRButton.js +17 -1
- package/webxr/XRControllerModelFactory.cjs.js +1 -1
- package/webxr/XRControllerModelFactory.js +65 -66
- package/webxr/XREstimatedLight.cjs.js +1 -1
- package/webxr/XREstimatedLight.js +1 -0
- package/webxr/XRHandMeshModel.cjs.js +1 -0
- package/webxr/XRHandMeshModel.d.ts +11 -0
- package/webxr/XRHandMeshModel.js +55 -0
- package/webxr/XRHandModelFactory.cjs.js +1 -1
- package/webxr/XRHandModelFactory.d.ts +3 -3
- package/webxr/XRHandModelFactory.js +47 -50
- package/webxr/XRHandPrimitiveModel.cjs.js +1 -1
- package/webxr/XRHandPrimitiveModel.d.ts +1 -1
- package/webxr/XRHandPrimitiveModel.js +31 -41
- package/csm/Frustum.d.ts +0 -16
- package/csm/Shader.d.ts +0 -6
- package/loaders/XLoader.d.ts +0 -19
- package/shaders/FresnelShader.d.ts +0 -13
- package/shaders/ParallaxShader.d.ts +0 -20
- package/utils/RoughnessMipmapper.d.ts +0 -7
- package/webxr/XRHandOculusMeshModel.cjs.js +0 -1
- package/webxr/XRHandOculusMeshModel.d.ts +0 -23
- package/webxr/XRHandOculusMeshModel.js +0 -89
package/index.d.ts
CHANGED
|
@@ -233,12 +233,16 @@ export * from './postprocessing/ShaderPass';
|
|
|
233
233
|
export * from './postprocessing/SSAARenderPass';
|
|
234
234
|
export * from './postprocessing/RenderPass';
|
|
235
235
|
export * from './postprocessing/BloomPass';
|
|
236
|
-
export * from './webxr/
|
|
237
|
-
export * from './webxr/
|
|
238
|
-
export * from './webxr/
|
|
236
|
+
export * from './webxr/ARButton';
|
|
237
|
+
export * from './webxr/OculusHandModel';
|
|
238
|
+
export * from './webxr/OculusHandPointerModel';
|
|
239
|
+
export * from './webxr/Text2D';
|
|
239
240
|
export * from './webxr/VRButton';
|
|
241
|
+
export * from './webxr/XRControllerModelFactory';
|
|
242
|
+
export * from './webxr/XREstimatedLight';
|
|
243
|
+
export * from './webxr/XRHandMeshModel';
|
|
244
|
+
export * from './webxr/XRHandModelFactory';
|
|
240
245
|
export * from './webxr/XRHandPrimitiveModel';
|
|
241
|
-
export * from './webxr/ARButton';
|
|
242
246
|
export * from './geometries/ParametricGeometries';
|
|
243
247
|
export * from './geometries/ConvexGeometry';
|
|
244
248
|
export * from './geometries/LightningStrike';
|
|
@@ -384,3 +388,4 @@ export * from './curves/NURBSSurface';
|
|
|
384
388
|
export * from './curves/CurveExtras';
|
|
385
389
|
export * from './deprecated/Geometry';
|
|
386
390
|
export * from './libs/MeshoptDecoder';
|
|
391
|
+
export * from './libs/MotionControllers';
|
package/index.js
CHANGED
|
@@ -178,12 +178,16 @@ export { ShaderPass } from './postprocessing/ShaderPass.js';
|
|
|
178
178
|
export { SSAARenderPass } from './postprocessing/SSAARenderPass.js';
|
|
179
179
|
export { RenderPass } from './postprocessing/RenderPass.js';
|
|
180
180
|
export { BloomPass } from './postprocessing/BloomPass.js';
|
|
181
|
-
export {
|
|
182
|
-
export {
|
|
183
|
-
export {
|
|
181
|
+
export { ARButton } from './webxr/ARButton.js';
|
|
182
|
+
export { OculusHandModel } from './webxr/OculusHandModel.js';
|
|
183
|
+
export { OculusHandPointerModel } from './webxr/OculusHandPointerModel.js';
|
|
184
|
+
export { createText } from './webxr/Text2D.js';
|
|
184
185
|
export { VRButton } from './webxr/VRButton.js';
|
|
186
|
+
export { XRControllerModelFactory } from './webxr/XRControllerModelFactory.js';
|
|
187
|
+
export { XREstimatedLight } from './webxr/XREstimatedLight.js';
|
|
188
|
+
export { XRHandMeshModel } from './webxr/XRHandMeshModel.js';
|
|
189
|
+
export { XRHandModelFactory } from './webxr/XRHandModelFactory.js';
|
|
185
190
|
export { XRHandPrimitiveModel } from './webxr/XRHandPrimitiveModel.js';
|
|
186
|
-
export { ARButton } from './webxr/ARButton.js';
|
|
187
191
|
export { ParametricGeometries } from './geometries/ParametricGeometries.js';
|
|
188
192
|
export { ConvexGeometry } from './geometries/ConvexGeometry.js';
|
|
189
193
|
export { LightningStrike } from './geometries/LightningStrike.js';
|
|
@@ -327,3 +331,4 @@ export { NURBSSurface } from './curves/NURBSSurface.js';
|
|
|
327
331
|
export { CinquefoilKnot, DecoratedTorusKnot4a, DecoratedTorusKnot4b, DecoratedTorusKnot5a, DecoratedTorusKnot5c, FigureEightPolynomialKnot, GrannyKnot, HeartCurve, HelixCurve, KnotCurve, TorusKnot, TrefoilKnot, TrefoilPolynomialKnot, VivianiCurve, scaleTo } from './curves/CurveExtras.js';
|
|
328
332
|
export { Face3, Geometry } from './deprecated/Geometry.js';
|
|
329
333
|
export { MeshoptDecoder } from './libs/MeshoptDecoder.js';
|
|
334
|
+
export { MotionController, MotionControllerConstants, fetchProfile, fetchProfilesList } from './libs/MotionControllers.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const e={Handedness:Object.freeze({NONE:"none",LEFT:"left",RIGHT:"right"}),ComponentState:Object.freeze({DEFAULT:"default",TOUCHED:"touched",PRESSED:"pressed"}),ComponentProperty:Object.freeze({BUTTON:"button",X_AXIS:"xAxis",Y_AXIS:"yAxis",STATE:"state"}),ComponentType:Object.freeze({TRIGGER:"trigger",SQUEEZE:"squeeze",TOUCHPAD:"touchpad",THUMBSTICK:"thumbstick",BUTTON:"button"}),ButtonTouchThreshold:.05,AxisTouchThreshold:.1,VisualResponseProperty:Object.freeze({TRANSFORM:"transform",VISIBILITY:"visibility"})};async function t(e){const t=await fetch(e);if(t.ok)return t.json();throw new Error(t.statusText)}async function s(e){if(!e)throw new Error("No basePath supplied");return await t(`${e}/profilesList.json`)}const o={xAxis:0,yAxis:0,button:0,state:e.ComponentState.DEFAULT};class a{constructor(t){this.componentProperty=t.componentProperty,this.states=t.states,this.valueNodeName=t.valueNodeName,this.valueNodeProperty=t.valueNodeProperty,this.valueNodeProperty===e.VisualResponseProperty.TRANSFORM&&(this.minNodeName=t.minNodeName,this.maxNodeName=t.maxNodeName),this.value=0,this.updateFromComponent(o)}updateFromComponent({xAxis:t,yAxis:s,button:o,state:a}){const{normalizedXAxis:i,normalizedYAxis:n}=function(e=0,t=0){let s=e,o=t;if(Math.sqrt(e*e+t*t)>1){const a=Math.atan2(t,e);s=Math.cos(a),o=Math.sin(a)}return{normalizedXAxis:.5*s+.5,normalizedYAxis:.5*o+.5}}(t,s);switch(this.componentProperty){case e.ComponentProperty.X_AXIS:this.value=this.states.includes(a)?i:.5;break;case e.ComponentProperty.Y_AXIS:this.value=this.states.includes(a)?n:.5;break;case e.ComponentProperty.BUTTON:this.value=this.states.includes(a)?o:0;break;case e.ComponentProperty.STATE:this.valueNodeProperty===e.VisualResponseProperty.VISIBILITY?this.value=this.states.includes(a):this.value=this.states.includes(a)?1:0;break;default:throw new Error(`Unexpected visualResponse componentProperty ${this.componentProperty}`)}}}class i{constructor(t,s){if(!(t&&s&&s.visualResponses&&s.gamepadIndices&&0!==Object.keys(s.gamepadIndices).length))throw new Error("Invalid arguments supplied");this.id=t,this.type=s.type,this.rootNodeName=s.rootNodeName,this.touchPointNodeName=s.touchPointNodeName,this.visualResponses={},Object.keys(s.visualResponses).forEach((e=>{const t=new a(s.visualResponses[e]);this.visualResponses[e]=t})),this.gamepadIndices=Object.assign({},s.gamepadIndices),this.values={state:e.ComponentState.DEFAULT,button:void 0!==this.gamepadIndices.button?0:void 0,xAxis:void 0!==this.gamepadIndices.xAxis?0:void 0,yAxis:void 0!==this.gamepadIndices.yAxis?0:void 0}}get data(){return{id:this.id,...this.values}}updateFromGamepad(t){if(this.values.state=e.ComponentState.DEFAULT,void 0!==this.gamepadIndices.button&&t.buttons.length>this.gamepadIndices.button){const s=t.buttons[this.gamepadIndices.button];this.values.button=s.value,this.values.button=this.values.button<0?0:this.values.button,this.values.button=this.values.button>1?1:this.values.button,s.pressed||1===this.values.button?this.values.state=e.ComponentState.PRESSED:(s.touched||this.values.button>e.ButtonTouchThreshold)&&(this.values.state=e.ComponentState.TOUCHED)}void 0!==this.gamepadIndices.xAxis&&t.axes.length>this.gamepadIndices.xAxis&&(this.values.xAxis=t.axes[this.gamepadIndices.xAxis],this.values.xAxis=this.values.xAxis<-1?-1:this.values.xAxis,this.values.xAxis=this.values.xAxis>1?1:this.values.xAxis,this.values.state===e.ComponentState.DEFAULT&&Math.abs(this.values.xAxis)>e.AxisTouchThreshold&&(this.values.state=e.ComponentState.TOUCHED)),void 0!==this.gamepadIndices.yAxis&&t.axes.length>this.gamepadIndices.yAxis&&(this.values.yAxis=t.axes[this.gamepadIndices.yAxis],this.values.yAxis=this.values.yAxis<-1?-1:this.values.yAxis,this.values.yAxis=this.values.yAxis>1?1:this.values.yAxis,this.values.state===e.ComponentState.DEFAULT&&Math.abs(this.values.yAxis)>e.AxisTouchThreshold&&(this.values.state=e.ComponentState.TOUCHED)),Object.values(this.visualResponses).forEach((e=>{e.updateFromComponent(this.values)}))}}exports.MotionController=class{constructor(e,t,s){if(!e)throw new Error("No xrInputSource supplied");if(!t)throw new Error("No profile supplied");this.xrInputSource=e,this.assetUrl=s,this.id=t.profileId,this.layoutDescription=t.layouts[e.handedness],this.components={},Object.keys(this.layoutDescription.components).forEach((e=>{const t=this.layoutDescription.components[e];this.components[e]=new i(e,t)})),this.updateFromGamepad()}get gripSpace(){return this.xrInputSource.gripSpace}get targetRaySpace(){return this.xrInputSource.targetRaySpace}get data(){const e=[];return Object.values(this.components).forEach((t=>{e.push(t.data)})),e}updateFromGamepad(){Object.values(this.components).forEach((e=>{e.updateFromGamepad(this.xrInputSource.gamepad)}))}},exports.MotionControllerConstants=e,exports.fetchProfile=async function(e,o,a=null,i=!0){if(!e)throw new Error("No xrInputSource supplied");if(!o)throw new Error("No basePath supplied");const n=await s(o);let r;if(e.profiles.some((e=>{const t=n[e];return t&&(r={profileId:e,profilePath:`${o}/${t.path}`,deprecated:!!t.deprecated}),!!r})),!r){if(!a)throw new Error("No matching profile name found");const e=n[a];if(!e)throw new Error(`No matching profile name found and default profile "${a}" missing.`);r={profileId:a,profilePath:`${o}/${e.path}`,deprecated:!!e.deprecated}}const h=await t(r.profilePath);let u;if(i){let t;if(t="any"===e.handedness?h.layouts[Object.keys(h.layouts)[0]]:h.layouts[e.handedness],!t)throw new Error(`No matching handedness, ${e.handedness}, in profile ${r.profileId}`);t.assetPath&&(u=r.profilePath.replace("profile.json",t.assetPath))}return{profile:h,assetPath:u}},exports.fetchProfilesList=s;
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @webxr-input-profiles/motion-controllers 1.0.0 https://github.com/immersive-web/webxr-input-profiles
|
|
3
|
+
*/
|
|
4
|
+
const MotionControllerConstants = {
|
|
5
|
+
Handedness: Object.freeze({
|
|
6
|
+
NONE: 'none',
|
|
7
|
+
LEFT: 'left',
|
|
8
|
+
RIGHT: 'right'
|
|
9
|
+
}),
|
|
10
|
+
ComponentState: Object.freeze({
|
|
11
|
+
DEFAULT: 'default',
|
|
12
|
+
TOUCHED: 'touched',
|
|
13
|
+
PRESSED: 'pressed'
|
|
14
|
+
}),
|
|
15
|
+
ComponentProperty: Object.freeze({
|
|
16
|
+
BUTTON: 'button',
|
|
17
|
+
X_AXIS: 'xAxis',
|
|
18
|
+
Y_AXIS: 'yAxis',
|
|
19
|
+
STATE: 'state'
|
|
20
|
+
}),
|
|
21
|
+
ComponentType: Object.freeze({
|
|
22
|
+
TRIGGER: 'trigger',
|
|
23
|
+
SQUEEZE: 'squeeze',
|
|
24
|
+
TOUCHPAD: 'touchpad',
|
|
25
|
+
THUMBSTICK: 'thumbstick',
|
|
26
|
+
BUTTON: 'button'
|
|
27
|
+
}),
|
|
28
|
+
ButtonTouchThreshold: 0.05,
|
|
29
|
+
AxisTouchThreshold: 0.1,
|
|
30
|
+
VisualResponseProperty: Object.freeze({
|
|
31
|
+
TRANSFORM: 'transform',
|
|
32
|
+
VISIBILITY: 'visibility'
|
|
33
|
+
})
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* @description Static helper function to fetch a JSON file and turn it into a JS object
|
|
37
|
+
* @param {string} path - Path to JSON file to be fetched
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
async function fetchJsonFile(path) {
|
|
41
|
+
const response = await fetch(path);
|
|
42
|
+
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
throw new Error(response.statusText);
|
|
45
|
+
} else {
|
|
46
|
+
return response.json();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function fetchProfilesList(basePath) {
|
|
51
|
+
if (!basePath) {
|
|
52
|
+
throw new Error('No basePath supplied');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const profileListFileName = 'profilesList.json';
|
|
56
|
+
const profilesList = await fetchJsonFile(`${basePath}/${profileListFileName}`);
|
|
57
|
+
return profilesList;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function fetchProfile(xrInputSource, basePath, defaultProfile = null, getAssetPath = true) {
|
|
61
|
+
if (!xrInputSource) {
|
|
62
|
+
throw new Error('No xrInputSource supplied');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!basePath) {
|
|
66
|
+
throw new Error('No basePath supplied');
|
|
67
|
+
} // Get the list of profiles
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
const supportedProfilesList = await fetchProfilesList(basePath); // Find the relative path to the first requested profile that is recognized
|
|
71
|
+
|
|
72
|
+
let match;
|
|
73
|
+
xrInputSource.profiles.some(profileId => {
|
|
74
|
+
const supportedProfile = supportedProfilesList[profileId];
|
|
75
|
+
|
|
76
|
+
if (supportedProfile) {
|
|
77
|
+
match = {
|
|
78
|
+
profileId,
|
|
79
|
+
profilePath: `${basePath}/${supportedProfile.path}`,
|
|
80
|
+
deprecated: !!supportedProfile.deprecated
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return !!match;
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (!match) {
|
|
88
|
+
if (!defaultProfile) {
|
|
89
|
+
throw new Error('No matching profile name found');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const supportedProfile = supportedProfilesList[defaultProfile];
|
|
93
|
+
|
|
94
|
+
if (!supportedProfile) {
|
|
95
|
+
throw new Error(`No matching profile name found and default profile "${defaultProfile}" missing.`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
match = {
|
|
99
|
+
profileId: defaultProfile,
|
|
100
|
+
profilePath: `${basePath}/${supportedProfile.path}`,
|
|
101
|
+
deprecated: !!supportedProfile.deprecated
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const profile = await fetchJsonFile(match.profilePath);
|
|
106
|
+
let assetPath;
|
|
107
|
+
|
|
108
|
+
if (getAssetPath) {
|
|
109
|
+
let layout;
|
|
110
|
+
|
|
111
|
+
if (xrInputSource.handedness === 'any') {
|
|
112
|
+
layout = profile.layouts[Object.keys(profile.layouts)[0]];
|
|
113
|
+
} else {
|
|
114
|
+
layout = profile.layouts[xrInputSource.handedness];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (!layout) {
|
|
118
|
+
throw new Error(`No matching handedness, ${xrInputSource.handedness}, in profile ${match.profileId}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (layout.assetPath) {
|
|
122
|
+
assetPath = match.profilePath.replace('profile.json', layout.assetPath);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
profile,
|
|
128
|
+
assetPath
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/** @constant {Object} */
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
const defaultComponentValues = {
|
|
135
|
+
xAxis: 0,
|
|
136
|
+
yAxis: 0,
|
|
137
|
+
button: 0,
|
|
138
|
+
state: MotionControllerConstants.ComponentState.DEFAULT
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* @description Converts an X, Y coordinate from the range -1 to 1 (as reported by the Gamepad
|
|
142
|
+
* API) to the range 0 to 1 (for interpolation). Also caps the X, Y values to be bounded within
|
|
143
|
+
* a circle. This ensures that thumbsticks are not animated outside the bounds of their physical
|
|
144
|
+
* range of motion and touchpads do not report touch locations off their physical bounds.
|
|
145
|
+
* @param {number} x The original x coordinate in the range -1 to 1
|
|
146
|
+
* @param {number} y The original y coordinate in the range -1 to 1
|
|
147
|
+
*/
|
|
148
|
+
|
|
149
|
+
function normalizeAxes(x = 0, y = 0) {
|
|
150
|
+
let xAxis = x;
|
|
151
|
+
let yAxis = y; // Determine if the point is outside the bounds of the circle
|
|
152
|
+
// and, if so, place it on the edge of the circle
|
|
153
|
+
|
|
154
|
+
const hypotenuse = Math.sqrt(x * x + y * y);
|
|
155
|
+
|
|
156
|
+
if (hypotenuse > 1) {
|
|
157
|
+
const theta = Math.atan2(y, x);
|
|
158
|
+
xAxis = Math.cos(theta);
|
|
159
|
+
yAxis = Math.sin(theta);
|
|
160
|
+
} // Scale and move the circle so values are in the interpolation range. The circle's origin moves
|
|
161
|
+
// from (0, 0) to (0.5, 0.5). The circle's radius scales from 1 to be 0.5.
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
const result = {
|
|
165
|
+
normalizedXAxis: xAxis * 0.5 + 0.5,
|
|
166
|
+
normalizedYAxis: yAxis * 0.5 + 0.5
|
|
167
|
+
};
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Contains the description of how the 3D model should visually respond to a specific user input.
|
|
172
|
+
* This is accomplished by initializing the object with the name of a node in the 3D model and
|
|
173
|
+
* property that need to be modified in response to user input, the name of the nodes representing
|
|
174
|
+
* the allowable range of motion, and the name of the input which triggers the change. In response
|
|
175
|
+
* to the named input changing, this object computes the appropriate weighting to use for
|
|
176
|
+
* interpolating between the range of motion nodes.
|
|
177
|
+
*/
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class VisualResponse {
|
|
181
|
+
constructor(visualResponseDescription) {
|
|
182
|
+
this.componentProperty = visualResponseDescription.componentProperty;
|
|
183
|
+
this.states = visualResponseDescription.states;
|
|
184
|
+
this.valueNodeName = visualResponseDescription.valueNodeName;
|
|
185
|
+
this.valueNodeProperty = visualResponseDescription.valueNodeProperty;
|
|
186
|
+
|
|
187
|
+
if (this.valueNodeProperty === MotionControllerConstants.VisualResponseProperty.TRANSFORM) {
|
|
188
|
+
this.minNodeName = visualResponseDescription.minNodeName;
|
|
189
|
+
this.maxNodeName = visualResponseDescription.maxNodeName;
|
|
190
|
+
} // Initializes the response's current value based on default data
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
this.value = 0;
|
|
194
|
+
this.updateFromComponent(defaultComponentValues);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Computes the visual response's interpolation weight based on component state
|
|
198
|
+
* @param {Object} componentValues - The component from which to update
|
|
199
|
+
* @param {number} xAxis - The reported X axis value of the component
|
|
200
|
+
* @param {number} yAxis - The reported Y axis value of the component
|
|
201
|
+
* @param {number} button - The reported value of the component's button
|
|
202
|
+
* @param {string} state - The component's active state
|
|
203
|
+
*/
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
updateFromComponent({
|
|
207
|
+
xAxis,
|
|
208
|
+
yAxis,
|
|
209
|
+
button,
|
|
210
|
+
state
|
|
211
|
+
}) {
|
|
212
|
+
const {
|
|
213
|
+
normalizedXAxis,
|
|
214
|
+
normalizedYAxis
|
|
215
|
+
} = normalizeAxes(xAxis, yAxis);
|
|
216
|
+
|
|
217
|
+
switch (this.componentProperty) {
|
|
218
|
+
case MotionControllerConstants.ComponentProperty.X_AXIS:
|
|
219
|
+
this.value = this.states.includes(state) ? normalizedXAxis : 0.5;
|
|
220
|
+
break;
|
|
221
|
+
|
|
222
|
+
case MotionControllerConstants.ComponentProperty.Y_AXIS:
|
|
223
|
+
this.value = this.states.includes(state) ? normalizedYAxis : 0.5;
|
|
224
|
+
break;
|
|
225
|
+
|
|
226
|
+
case MotionControllerConstants.ComponentProperty.BUTTON:
|
|
227
|
+
this.value = this.states.includes(state) ? button : 0;
|
|
228
|
+
break;
|
|
229
|
+
|
|
230
|
+
case MotionControllerConstants.ComponentProperty.STATE:
|
|
231
|
+
if (this.valueNodeProperty === MotionControllerConstants.VisualResponseProperty.VISIBILITY) {
|
|
232
|
+
this.value = this.states.includes(state);
|
|
233
|
+
} else {
|
|
234
|
+
this.value = this.states.includes(state) ? 1.0 : 0.0;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
break;
|
|
238
|
+
|
|
239
|
+
default:
|
|
240
|
+
throw new Error(`Unexpected visualResponse componentProperty ${this.componentProperty}`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
class Component {
|
|
247
|
+
/**
|
|
248
|
+
* @param {Object} componentId - Id of the component
|
|
249
|
+
* @param {Object} componentDescription - Description of the component to be created
|
|
250
|
+
*/
|
|
251
|
+
constructor(componentId, componentDescription) {
|
|
252
|
+
if (!componentId || !componentDescription || !componentDescription.visualResponses || !componentDescription.gamepadIndices || Object.keys(componentDescription.gamepadIndices).length === 0) {
|
|
253
|
+
throw new Error('Invalid arguments supplied');
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
this.id = componentId;
|
|
257
|
+
this.type = componentDescription.type;
|
|
258
|
+
this.rootNodeName = componentDescription.rootNodeName;
|
|
259
|
+
this.touchPointNodeName = componentDescription.touchPointNodeName; // Build all the visual responses for this component
|
|
260
|
+
|
|
261
|
+
this.visualResponses = {};
|
|
262
|
+
Object.keys(componentDescription.visualResponses).forEach(responseName => {
|
|
263
|
+
const visualResponse = new VisualResponse(componentDescription.visualResponses[responseName]);
|
|
264
|
+
this.visualResponses[responseName] = visualResponse;
|
|
265
|
+
}); // Set default values
|
|
266
|
+
|
|
267
|
+
this.gamepadIndices = Object.assign({}, componentDescription.gamepadIndices);
|
|
268
|
+
this.values = {
|
|
269
|
+
state: MotionControllerConstants.ComponentState.DEFAULT,
|
|
270
|
+
button: this.gamepadIndices.button !== undefined ? 0 : undefined,
|
|
271
|
+
xAxis: this.gamepadIndices.xAxis !== undefined ? 0 : undefined,
|
|
272
|
+
yAxis: this.gamepadIndices.yAxis !== undefined ? 0 : undefined
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
get data() {
|
|
277
|
+
const data = {
|
|
278
|
+
id: this.id,
|
|
279
|
+
...this.values
|
|
280
|
+
};
|
|
281
|
+
return data;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* @description Poll for updated data based on current gamepad state
|
|
285
|
+
* @param {Object} gamepad - The gamepad object from which the component data should be polled
|
|
286
|
+
*/
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
updateFromGamepad(gamepad) {
|
|
290
|
+
// Set the state to default before processing other data sources
|
|
291
|
+
this.values.state = MotionControllerConstants.ComponentState.DEFAULT; // Get and normalize button
|
|
292
|
+
|
|
293
|
+
if (this.gamepadIndices.button !== undefined && gamepad.buttons.length > this.gamepadIndices.button) {
|
|
294
|
+
const gamepadButton = gamepad.buttons[this.gamepadIndices.button];
|
|
295
|
+
this.values.button = gamepadButton.value;
|
|
296
|
+
this.values.button = this.values.button < 0 ? 0 : this.values.button;
|
|
297
|
+
this.values.button = this.values.button > 1 ? 1 : this.values.button; // Set the state based on the button
|
|
298
|
+
|
|
299
|
+
if (gamepadButton.pressed || this.values.button === 1) {
|
|
300
|
+
this.values.state = MotionControllerConstants.ComponentState.PRESSED;
|
|
301
|
+
} else if (gamepadButton.touched || this.values.button > MotionControllerConstants.ButtonTouchThreshold) {
|
|
302
|
+
this.values.state = MotionControllerConstants.ComponentState.TOUCHED;
|
|
303
|
+
}
|
|
304
|
+
} // Get and normalize x axis value
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
if (this.gamepadIndices.xAxis !== undefined && gamepad.axes.length > this.gamepadIndices.xAxis) {
|
|
308
|
+
this.values.xAxis = gamepad.axes[this.gamepadIndices.xAxis];
|
|
309
|
+
this.values.xAxis = this.values.xAxis < -1 ? -1 : this.values.xAxis;
|
|
310
|
+
this.values.xAxis = this.values.xAxis > 1 ? 1 : this.values.xAxis; // If the state is still default, check if the xAxis makes it touched
|
|
311
|
+
|
|
312
|
+
if (this.values.state === MotionControllerConstants.ComponentState.DEFAULT && Math.abs(this.values.xAxis) > MotionControllerConstants.AxisTouchThreshold) {
|
|
313
|
+
this.values.state = MotionControllerConstants.ComponentState.TOUCHED;
|
|
314
|
+
}
|
|
315
|
+
} // Get and normalize Y axis value
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
if (this.gamepadIndices.yAxis !== undefined && gamepad.axes.length > this.gamepadIndices.yAxis) {
|
|
319
|
+
this.values.yAxis = gamepad.axes[this.gamepadIndices.yAxis];
|
|
320
|
+
this.values.yAxis = this.values.yAxis < -1 ? -1 : this.values.yAxis;
|
|
321
|
+
this.values.yAxis = this.values.yAxis > 1 ? 1 : this.values.yAxis; // If the state is still default, check if the yAxis makes it touched
|
|
322
|
+
|
|
323
|
+
if (this.values.state === MotionControllerConstants.ComponentState.DEFAULT && Math.abs(this.values.yAxis) > MotionControllerConstants.AxisTouchThreshold) {
|
|
324
|
+
this.values.state = MotionControllerConstants.ComponentState.TOUCHED;
|
|
325
|
+
}
|
|
326
|
+
} // Update the visual response weights based on the current component data
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
Object.values(this.visualResponses).forEach(visualResponse => {
|
|
330
|
+
visualResponse.updateFromComponent(this.values);
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* @description Builds a motion controller with components and visual responses based on the
|
|
337
|
+
* supplied profile description. Data is polled from the xrInputSource's gamepad.
|
|
338
|
+
* @author Nell Waliczek / https://github.com/NellWaliczek
|
|
339
|
+
*/
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
class MotionController {
|
|
343
|
+
/**
|
|
344
|
+
* @param {Object} xrInputSource - The XRInputSource to build the MotionController around
|
|
345
|
+
* @param {Object} profile - The best matched profile description for the supplied xrInputSource
|
|
346
|
+
* @param {Object} assetUrl
|
|
347
|
+
*/
|
|
348
|
+
constructor(xrInputSource, profile, assetUrl) {
|
|
349
|
+
if (!xrInputSource) {
|
|
350
|
+
throw new Error('No xrInputSource supplied');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (!profile) {
|
|
354
|
+
throw new Error('No profile supplied');
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
this.xrInputSource = xrInputSource;
|
|
358
|
+
this.assetUrl = assetUrl;
|
|
359
|
+
this.id = profile.profileId; // Build child components as described in the profile description
|
|
360
|
+
|
|
361
|
+
this.layoutDescription = profile.layouts[xrInputSource.handedness];
|
|
362
|
+
this.components = {};
|
|
363
|
+
Object.keys(this.layoutDescription.components).forEach(componentId => {
|
|
364
|
+
const componentDescription = this.layoutDescription.components[componentId];
|
|
365
|
+
this.components[componentId] = new Component(componentId, componentDescription);
|
|
366
|
+
}); // Initialize components based on current gamepad state
|
|
367
|
+
|
|
368
|
+
this.updateFromGamepad();
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
get gripSpace() {
|
|
372
|
+
return this.xrInputSource.gripSpace;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
get targetRaySpace() {
|
|
376
|
+
return this.xrInputSource.targetRaySpace;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* @description Returns a subset of component data for simplified debugging
|
|
380
|
+
*/
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
get data() {
|
|
384
|
+
const data = [];
|
|
385
|
+
Object.values(this.components).forEach(component => {
|
|
386
|
+
data.push(component.data);
|
|
387
|
+
});
|
|
388
|
+
return data;
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* @description Poll for updated data based on current gamepad state
|
|
392
|
+
*/
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
updateFromGamepad() {
|
|
396
|
+
Object.values(this.components).forEach(component => {
|
|
397
|
+
component.updateFromGamepad(this.xrInputSource.gamepad);
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
export { MotionController, MotionControllerConstants, fetchProfile, fetchProfilesList };
|
package/loaders/AssimpLoader.js
CHANGED
|
@@ -568,12 +568,30 @@ AssimpLoader.prototype = Object.assign(Object.create(Loader.prototype), {
|
|
|
568
568
|
if (scene.mMaterials[this.mMaterialIndex]) mat = scene.mMaterials[this.mMaterialIndex].toTHREE(scene);else mat = new MeshLambertMaterial();
|
|
569
569
|
geometry.setIndex(new BufferAttribute(new Uint32Array(this.mIndexArray), 1));
|
|
570
570
|
geometry.setAttribute('position', new BufferAttribute(this.mVertexBuffer, 3));
|
|
571
|
-
|
|
572
|
-
if (this.
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
if (this.
|
|
571
|
+
|
|
572
|
+
if (this.mNormalBuffer && this.mNormalBuffer.length > 0) {
|
|
573
|
+
geometry.setAttribute('normal', new BufferAttribute(this.mNormalBuffer, 3));
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
if (this.mColorBuffer && this.mColorBuffer.length > 0) {
|
|
577
|
+
geometry.setAttribute('color', new BufferAttribute(this.mColorBuffer, 4));
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
if (this.mTexCoordsBuffers[0] && this.mTexCoordsBuffers[0].length > 0) {
|
|
581
|
+
geometry.setAttribute('uv', new BufferAttribute(new Float32Array(this.mTexCoordsBuffers[0]), 2));
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
if (this.mTexCoordsBuffers[1] && this.mTexCoordsBuffers[1].length > 0) {
|
|
585
|
+
geometry.setAttribute('uv1', new BufferAttribute(new Float32Array(this.mTexCoordsBuffers[1]), 2));
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
if (this.mTangentBuffer && this.mTangentBuffer.length > 0) {
|
|
589
|
+
geometry.setAttribute('tangents', new BufferAttribute(this.mTangentBuffer, 3));
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
if (this.mBitangentBuffer && this.mBitangentBuffer.length > 0) {
|
|
593
|
+
geometry.setAttribute('bitangents', new BufferAttribute(this.mBitangentBuffer, 3));
|
|
594
|
+
}
|
|
577
595
|
|
|
578
596
|
if (this.mBones.length > 0) {
|
|
579
597
|
var weights = [];
|
|
@@ -824,10 +842,21 @@ AssimpLoader.prototype = Object.assign(Object.create(Loader.prototype), {
|
|
|
824
842
|
var mat = new MeshPhongMaterial();
|
|
825
843
|
|
|
826
844
|
for (let i = 0; i < this.mProperties.length; i++) {
|
|
827
|
-
if (nameTypeMapping[this.mProperties[i].mKey] == 'float')
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
845
|
+
if (nameTypeMapping[this.mProperties[i].mKey] == 'float') {
|
|
846
|
+
mat[namePropMapping[this.mProperties[i].mKey]] = this.mProperties[i].dataAsFloat();
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
if (nameTypeMapping[this.mProperties[i].mKey] == 'color') {
|
|
850
|
+
mat[namePropMapping[this.mProperties[i].mKey]] = this.mProperties[i].dataAsColor();
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
if (nameTypeMapping[this.mProperties[i].mKey] == 'bool') {
|
|
854
|
+
mat[namePropMapping[this.mProperties[i].mKey]] = this.mProperties[i].dataAsBool();
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
if (nameTypeMapping[this.mProperties[i].mKey] == 'string') {
|
|
858
|
+
mat[namePropMapping[this.mProperties[i].mKey]] = this.mProperties[i].dataAsString();
|
|
859
|
+
}
|
|
831
860
|
|
|
832
861
|
if (nameTypeMapping[this.mProperties[i].mKey] == 'map') {
|
|
833
862
|
var prop = this.mProperties[i];
|
package/loaders/ColladaLoader.js
CHANGED
|
@@ -370,7 +370,11 @@ class ColladaLoader extends Loader {
|
|
|
370
370
|
}
|
|
371
371
|
|
|
372
372
|
if (positionData.length > 0) tracks.push(new VectorKeyframeTrack(name + '.position', times, positionData));
|
|
373
|
-
|
|
373
|
+
|
|
374
|
+
if (quaternionData.length > 0) {
|
|
375
|
+
tracks.push(new QuaternionKeyframeTrack(name + '.quaternion', times, quaternionData));
|
|
376
|
+
}
|
|
377
|
+
|
|
374
378
|
if (scaleData.length > 0) tracks.push(new VectorKeyframeTrack(name + '.scale', times, scaleData));
|
|
375
379
|
return tracks;
|
|
376
380
|
}
|
|
@@ -1835,13 +1839,26 @@ class ColladaLoader extends Loader {
|
|
|
1835
1839
|
} // build geometry
|
|
1836
1840
|
|
|
1837
1841
|
|
|
1838
|
-
if (position.array.length > 0)
|
|
1839
|
-
|
|
1842
|
+
if (position.array.length > 0) {
|
|
1843
|
+
geometry.setAttribute('position', new Float32BufferAttribute(position.array, position.stride));
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
if (normal.array.length > 0) {
|
|
1847
|
+
geometry.setAttribute('normal', new Float32BufferAttribute(normal.array, normal.stride));
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1840
1850
|
if (color.array.length > 0) geometry.setAttribute('color', new Float32BufferAttribute(color.array, color.stride));
|
|
1841
1851
|
if (uv.array.length > 0) geometry.setAttribute('uv', new Float32BufferAttribute(uv.array, uv.stride));
|
|
1842
1852
|
if (uv2.array.length > 0) geometry.setAttribute('uv2', new Float32BufferAttribute(uv2.array, uv2.stride));
|
|
1843
|
-
|
|
1844
|
-
if (
|
|
1853
|
+
|
|
1854
|
+
if (skinIndex.array.length > 0) {
|
|
1855
|
+
geometry.setAttribute('skinIndex', new Float32BufferAttribute(skinIndex.array, skinIndex.stride));
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
if (skinWeight.array.length > 0) {
|
|
1859
|
+
geometry.setAttribute('skinWeight', new Float32BufferAttribute(skinWeight.array, skinWeight.stride));
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1845
1862
|
build.data = geometry;
|
|
1846
1863
|
build.type = primitives[0].type;
|
|
1847
1864
|
build.materialKeys = materialKeys;
|
package/loaders/EXRLoader.js
CHANGED
|
@@ -1067,7 +1067,11 @@ class EXRLoader extends DataTextureLoader {
|
|
|
1067
1067
|
totalDcUncompressedCount: parseInt64(inDataView, inOffset),
|
|
1068
1068
|
acCompression: parseInt64(inDataView, inOffset)
|
|
1069
1069
|
};
|
|
1070
|
-
|
|
1070
|
+
|
|
1071
|
+
if (dwaHeader.version < 2) {
|
|
1072
|
+
throw 'EXRLoader.parse: ' + EXRHeader.compression + ' version ' + dwaHeader.version + ' is unsupported';
|
|
1073
|
+
} // Read channel ruleset information
|
|
1074
|
+
|
|
1071
1075
|
|
|
1072
1076
|
var channelRules = new Array();
|
|
1073
1077
|
var ruleSize = parseUint16(inDataView, inOffset) - INT16_SIZE;
|
package/loaders/FBXLoader.js
CHANGED
|
@@ -514,7 +514,11 @@ class FBXTreeParser {
|
|
|
514
514
|
if (deformerNode.attrType === 'Skin') {
|
|
515
515
|
const skeleton = this.parseSkeleton(relationships, DeformerNodes);
|
|
516
516
|
skeleton.ID = nodeID;
|
|
517
|
-
|
|
517
|
+
|
|
518
|
+
if (relationships.parents.length > 1) {
|
|
519
|
+
console.warn('THREE.FBXLoader: skeleton attached to more than one geometry is not supported.');
|
|
520
|
+
}
|
|
521
|
+
|
|
518
522
|
skeleton.geometryID = relationships.parents[0].ID;
|
|
519
523
|
skeletons[nodeID] = skeleton;
|
|
520
524
|
} else if (deformerNode.attrType === 'BlendShape') {
|
|
@@ -523,7 +527,11 @@ class FBXTreeParser {
|
|
|
523
527
|
};
|
|
524
528
|
morphTarget.rawTargets = this.parseMorphTargets(relationships, DeformerNodes);
|
|
525
529
|
morphTarget.id = nodeID;
|
|
526
|
-
|
|
530
|
+
|
|
531
|
+
if (relationships.parents.length > 1) {
|
|
532
|
+
console.warn('THREE.FBXLoader: morph target attached to more than one geometry is not supported.');
|
|
533
|
+
}
|
|
534
|
+
|
|
527
535
|
morphTargets[nodeID] = morphTarget;
|
|
528
536
|
}
|
|
529
537
|
}
|