three-stdlib 2.8.4 → 2.8.5
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/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/package.json +2 -3
- 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.js +47 -50
- package/webxr/XRHandPrimitiveModel.cjs.js +1 -1
- package/webxr/XRHandPrimitiveModel.js +31 -41
- package/webxr/XRHandOculusMeshModel.cjs.js +0 -1
- package/webxr/XRHandOculusMeshModel.js +0 -89
@@ -0,0 +1,248 @@
|
|
1
|
+
import * as THREE from 'three';
|
2
|
+
|
3
|
+
const PINCH_MAX = 0.05;
|
4
|
+
const PINCH_THRESHOLD = 0.02;
|
5
|
+
const PINCH_MIN = 0.01;
|
6
|
+
const POINTER_ADVANCE_MAX = 0.02;
|
7
|
+
const POINTER_OPACITY_MAX = 1;
|
8
|
+
const POINTER_OPACITY_MIN = 0.4;
|
9
|
+
const POINTER_FRONT_RADIUS = 0.002;
|
10
|
+
const POINTER_REAR_RADIUS = 0.01;
|
11
|
+
const POINTER_REAR_RADIUS_MIN = 0.003;
|
12
|
+
const POINTER_LENGTH = 0.035;
|
13
|
+
const POINTER_SEGMENTS = 16;
|
14
|
+
const POINTER_RINGS = 12;
|
15
|
+
const POINTER_HEMISPHERE_ANGLE = 110;
|
16
|
+
const YAXIS = new THREE.Vector3(0, 1, 0);
|
17
|
+
const ZAXIS = new THREE.Vector3(0, 0, 1);
|
18
|
+
const CURSOR_RADIUS = 0.02;
|
19
|
+
const CURSOR_MAX_DISTANCE = 1.5;
|
20
|
+
|
21
|
+
class OculusHandPointerModel extends THREE.Object3D {
|
22
|
+
constructor(hand, controller) {
|
23
|
+
super();
|
24
|
+
this.hand = hand;
|
25
|
+
this.controller = controller;
|
26
|
+
this.motionController = null;
|
27
|
+
this.envMap = null;
|
28
|
+
this.mesh = null;
|
29
|
+
this.pointerGeometry = null;
|
30
|
+
this.pointerMesh = null;
|
31
|
+
this.pointerObject = null;
|
32
|
+
this.pinched = false;
|
33
|
+
this.attached = false;
|
34
|
+
this.cursorObject = null;
|
35
|
+
this.raycaster = null;
|
36
|
+
hand.addEventListener('connected', event => {
|
37
|
+
const xrInputSource = event.data;
|
38
|
+
|
39
|
+
if (xrInputSource.hand) {
|
40
|
+
this.visible = true;
|
41
|
+
this.xrInputSource = xrInputSource;
|
42
|
+
this.createPointer();
|
43
|
+
}
|
44
|
+
});
|
45
|
+
}
|
46
|
+
|
47
|
+
_drawVerticesRing(vertices, baseVector, ringIndex) {
|
48
|
+
const segmentVector = baseVector.clone();
|
49
|
+
|
50
|
+
for (var i = 0; i < POINTER_SEGMENTS; i++) {
|
51
|
+
segmentVector.applyAxisAngle(ZAXIS, Math.PI * 2 / POINTER_SEGMENTS);
|
52
|
+
const vid = ringIndex * POINTER_SEGMENTS + i;
|
53
|
+
vertices[3 * vid] = segmentVector.x;
|
54
|
+
vertices[3 * vid + 1] = segmentVector.y;
|
55
|
+
vertices[3 * vid + 2] = segmentVector.z;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
_updatePointerVertices(rearRadius) {
|
60
|
+
const vertices = this.pointerGeometry.attributes.position.array; // first ring for front face
|
61
|
+
|
62
|
+
const frontFaceBase = new THREE.Vector3(POINTER_FRONT_RADIUS, 0, -1 * (POINTER_LENGTH - rearRadius));
|
63
|
+
|
64
|
+
this._drawVerticesRing(vertices, frontFaceBase, 0); // rings for rear hemisphere
|
65
|
+
|
66
|
+
|
67
|
+
const rearBase = new THREE.Vector3(Math.sin(Math.PI * POINTER_HEMISPHERE_ANGLE / 180) * rearRadius, Math.cos(Math.PI * POINTER_HEMISPHERE_ANGLE / 180) * rearRadius, 0);
|
68
|
+
|
69
|
+
for (var i = 0; i < POINTER_RINGS; i++) {
|
70
|
+
this._drawVerticesRing(vertices, rearBase, i + 1);
|
71
|
+
|
72
|
+
rearBase.applyAxisAngle(YAXIS, Math.PI * POINTER_HEMISPHERE_ANGLE / 180 / (POINTER_RINGS * -2));
|
73
|
+
} // front and rear face center vertices
|
74
|
+
|
75
|
+
|
76
|
+
const frontCenterIndex = POINTER_SEGMENTS * (1 + POINTER_RINGS);
|
77
|
+
const rearCenterIndex = POINTER_SEGMENTS * (1 + POINTER_RINGS) + 1;
|
78
|
+
const frontCenter = new THREE.Vector3(0, 0, -1 * (POINTER_LENGTH - rearRadius));
|
79
|
+
vertices[frontCenterIndex * 3] = frontCenter.x;
|
80
|
+
vertices[frontCenterIndex * 3 + 1] = frontCenter.y;
|
81
|
+
vertices[frontCenterIndex * 3 + 2] = frontCenter.z;
|
82
|
+
const rearCenter = new THREE.Vector3(0, 0, rearRadius);
|
83
|
+
vertices[rearCenterIndex * 3] = rearCenter.x;
|
84
|
+
vertices[rearCenterIndex * 3 + 1] = rearCenter.y;
|
85
|
+
vertices[rearCenterIndex * 3 + 2] = rearCenter.z;
|
86
|
+
this.pointerGeometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3)); // verticesNeedUpdate = true;
|
87
|
+
}
|
88
|
+
|
89
|
+
createPointer() {
|
90
|
+
var i, j;
|
91
|
+
const vertices = new Array(((POINTER_RINGS + 1) * POINTER_SEGMENTS + 2) * 3).fill(0); // const vertices = [];
|
92
|
+
|
93
|
+
const indices = [];
|
94
|
+
this.pointerGeometry = new THREE.BufferGeometry();
|
95
|
+
this.pointerGeometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
|
96
|
+
|
97
|
+
this._updatePointerVertices(POINTER_REAR_RADIUS); // construct faces to connect rings
|
98
|
+
|
99
|
+
|
100
|
+
for (i = 0; i < POINTER_RINGS; i++) {
|
101
|
+
for (j = 0; j < POINTER_SEGMENTS - 1; j++) {
|
102
|
+
indices.push(i * POINTER_SEGMENTS + j, i * POINTER_SEGMENTS + j + 1, (i + 1) * POINTER_SEGMENTS + j);
|
103
|
+
indices.push(i * POINTER_SEGMENTS + j + 1, (i + 1) * POINTER_SEGMENTS + j + 1, (i + 1) * POINTER_SEGMENTS + j);
|
104
|
+
}
|
105
|
+
|
106
|
+
indices.push((i + 1) * POINTER_SEGMENTS - 1, i * POINTER_SEGMENTS, (i + 2) * POINTER_SEGMENTS - 1);
|
107
|
+
indices.push(i * POINTER_SEGMENTS, (i + 1) * POINTER_SEGMENTS, (i + 2) * POINTER_SEGMENTS - 1);
|
108
|
+
} // construct front and rear face
|
109
|
+
|
110
|
+
|
111
|
+
const frontCenterIndex = POINTER_SEGMENTS * (1 + POINTER_RINGS);
|
112
|
+
const rearCenterIndex = POINTER_SEGMENTS * (1 + POINTER_RINGS) + 1;
|
113
|
+
|
114
|
+
for (i = 0; i < POINTER_SEGMENTS - 1; i++) {
|
115
|
+
indices.push(frontCenterIndex, i + 1, i);
|
116
|
+
indices.push(rearCenterIndex, i + POINTER_SEGMENTS * POINTER_RINGS, i + POINTER_SEGMENTS * POINTER_RINGS + 1);
|
117
|
+
}
|
118
|
+
|
119
|
+
indices.push(frontCenterIndex, 0, POINTER_SEGMENTS - 1);
|
120
|
+
indices.push(rearCenterIndex, POINTER_SEGMENTS * (POINTER_RINGS + 1) - 1, POINTER_SEGMENTS * POINTER_RINGS);
|
121
|
+
const material = new THREE.MeshBasicMaterial();
|
122
|
+
material.transparent = true;
|
123
|
+
material.opacity = POINTER_OPACITY_MIN;
|
124
|
+
this.pointerGeometry.setIndex(indices);
|
125
|
+
this.pointerMesh = new THREE.Mesh(this.pointerGeometry, material);
|
126
|
+
this.pointerMesh.position.set(0, 0, -1 * POINTER_REAR_RADIUS);
|
127
|
+
this.pointerObject = new THREE.Object3D();
|
128
|
+
this.pointerObject.add(this.pointerMesh);
|
129
|
+
this.raycaster = new THREE.Raycaster(); // create cursor
|
130
|
+
|
131
|
+
const cursorGeometry = new THREE.SphereGeometry(CURSOR_RADIUS, 10, 10);
|
132
|
+
const cursorMaterial = new THREE.MeshBasicMaterial();
|
133
|
+
cursorMaterial.transparent = true;
|
134
|
+
cursorMaterial.opacity = POINTER_OPACITY_MIN;
|
135
|
+
this.cursorObject = new THREE.Mesh(cursorGeometry, cursorMaterial);
|
136
|
+
this.pointerObject.add(this.cursorObject);
|
137
|
+
this.add(this.pointerObject);
|
138
|
+
}
|
139
|
+
|
140
|
+
_updateRaycaster() {
|
141
|
+
if (this.raycaster) {
|
142
|
+
const pointerMatrix = this.pointerObject.matrixWorld;
|
143
|
+
const tempMatrix = new THREE.Matrix4();
|
144
|
+
tempMatrix.identity().extractRotation(pointerMatrix);
|
145
|
+
this.raycaster.ray.origin.setFromMatrixPosition(pointerMatrix);
|
146
|
+
this.raycaster.ray.direction.set(0, 0, -1).applyMatrix4(tempMatrix);
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
_updatePointer() {
|
151
|
+
this.pointerObject.visible = this.controller.visible;
|
152
|
+
const indexTip = this.hand.joints['index-finger-tip'];
|
153
|
+
const thumbTip = this.hand.joints['thumb-tip'];
|
154
|
+
const distance = indexTip.position.distanceTo(thumbTip.position);
|
155
|
+
const position = indexTip.position.clone().add(thumbTip.position).multiplyScalar(0.5);
|
156
|
+
this.pointerObject.position.copy(position);
|
157
|
+
this.pointerObject.quaternion.copy(this.controller.quaternion);
|
158
|
+
this.pinched = distance <= PINCH_THRESHOLD;
|
159
|
+
const pinchScale = (distance - PINCH_MIN) / (PINCH_MAX - PINCH_MIN);
|
160
|
+
const focusScale = (distance - PINCH_MIN) / (PINCH_THRESHOLD - PINCH_MIN);
|
161
|
+
|
162
|
+
if (pinchScale > 1) {
|
163
|
+
this._updatePointerVertices(POINTER_REAR_RADIUS);
|
164
|
+
|
165
|
+
this.pointerMesh.position.set(0, 0, -1 * POINTER_REAR_RADIUS);
|
166
|
+
this.pointerMesh.material.opacity = POINTER_OPACITY_MIN;
|
167
|
+
} else if (pinchScale > 0) {
|
168
|
+
const rearRadius = (POINTER_REAR_RADIUS - POINTER_REAR_RADIUS_MIN) * pinchScale + POINTER_REAR_RADIUS_MIN;
|
169
|
+
|
170
|
+
this._updatePointerVertices(rearRadius);
|
171
|
+
|
172
|
+
if (focusScale < 1) {
|
173
|
+
this.pointerMesh.position.set(0, 0, -1 * rearRadius - (1 - focusScale) * POINTER_ADVANCE_MAX);
|
174
|
+
this.pointerMesh.material.opacity = POINTER_OPACITY_MIN + (1 - focusScale) * (POINTER_OPACITY_MAX - POINTER_OPACITY_MIN);
|
175
|
+
} else {
|
176
|
+
this.pointerMesh.position.set(0, 0, -1 * rearRadius);
|
177
|
+
this.pointerMesh.material.opacity = POINTER_OPACITY_MIN;
|
178
|
+
}
|
179
|
+
} else {
|
180
|
+
this._updatePointerVertices(POINTER_REAR_RADIUS_MIN);
|
181
|
+
|
182
|
+
this.pointerMesh.position.set(0, 0, -1 * POINTER_REAR_RADIUS_MIN - POINTER_ADVANCE_MAX);
|
183
|
+
this.pointerMesh.material.opacity = POINTER_OPACITY_MAX;
|
184
|
+
}
|
185
|
+
|
186
|
+
this.cursorObject.material.opacity = this.pointerMesh.material.opacity;
|
187
|
+
}
|
188
|
+
|
189
|
+
updateMatrixWorld(force) {
|
190
|
+
super.updateMatrixWorld(force);
|
191
|
+
|
192
|
+
if (this.pointerGeometry) {
|
193
|
+
this._updatePointer();
|
194
|
+
|
195
|
+
this._updateRaycaster();
|
196
|
+
}
|
197
|
+
}
|
198
|
+
|
199
|
+
isPinched() {
|
200
|
+
return this.pinched;
|
201
|
+
}
|
202
|
+
|
203
|
+
setAttached(attached) {
|
204
|
+
this.attached = attached;
|
205
|
+
}
|
206
|
+
|
207
|
+
isAttached() {
|
208
|
+
return this.attached;
|
209
|
+
}
|
210
|
+
|
211
|
+
intersectObject(object, recursive = true) {
|
212
|
+
if (this.raycaster) {
|
213
|
+
return this.raycaster.intersectObject(object, recursive);
|
214
|
+
}
|
215
|
+
}
|
216
|
+
|
217
|
+
intersectObjects(objects, recursive = true) {
|
218
|
+
if (this.raycaster) {
|
219
|
+
return this.raycaster.intersectObjects(objects, recursive);
|
220
|
+
}
|
221
|
+
}
|
222
|
+
|
223
|
+
checkIntersections(objects, recursive = false) {
|
224
|
+
if (this.raycaster && !this.attached) {
|
225
|
+
const intersections = this.raycaster.intersectObjects(objects, recursive);
|
226
|
+
const direction = new THREE.Vector3(0, 0, -1);
|
227
|
+
|
228
|
+
if (intersections.length > 0) {
|
229
|
+
const intersection = intersections[0];
|
230
|
+
const distance = intersection.distance;
|
231
|
+
this.cursorObject.position.copy(direction.multiplyScalar(distance));
|
232
|
+
} else {
|
233
|
+
this.cursorObject.position.copy(direction.multiplyScalar(CURSOR_MAX_DISTANCE));
|
234
|
+
}
|
235
|
+
}
|
236
|
+
}
|
237
|
+
|
238
|
+
setCursor(distance) {
|
239
|
+
const direction = new THREE.Vector3(0, 0, -1);
|
240
|
+
|
241
|
+
if (this.raycaster && !this.attached) {
|
242
|
+
this.cursorObject.position.copy(direction.multiplyScalar(distance));
|
243
|
+
}
|
244
|
+
}
|
245
|
+
|
246
|
+
}
|
247
|
+
|
248
|
+
export { OculusHandPointerModel };
|
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";function e(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}Object.defineProperty(exports,"__esModule",{value:!0});var t=e(require("three"));exports.createText=function(e,r){const n=document.createElement("canvas"),l=n.getContext("2d");let o=null;const a=100;l.font="normal 100px Arial",o=l.measureText(e);const c=o.width;n.width=c,n.height=a,l.font="normal 100px Arial",l.textAlign="center",l.textBaseline="middle",l.fillStyle="#ffffff",l.fillText(e,c/2,50);const i=new t.Texture(n);i.needsUpdate=!0;const f=new t.MeshBasicMaterial({color:16777215,side:t.DoubleSide,map:i,transparent:!0}),s=new t.PlaneGeometry(r*c/a,r);return new t.Mesh(s,f)};
|
package/webxr/Text2D.js
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
import * as THREE from 'three';
|
2
|
+
|
3
|
+
function createText(message, height) {
|
4
|
+
const canvas = document.createElement('canvas');
|
5
|
+
const context = canvas.getContext('2d');
|
6
|
+
let metrics = null;
|
7
|
+
const textHeight = 100;
|
8
|
+
context.font = 'normal ' + textHeight + 'px Arial';
|
9
|
+
metrics = context.measureText(message);
|
10
|
+
const textWidth = metrics.width;
|
11
|
+
canvas.width = textWidth;
|
12
|
+
canvas.height = textHeight;
|
13
|
+
context.font = 'normal ' + textHeight + 'px Arial';
|
14
|
+
context.textAlign = 'center';
|
15
|
+
context.textBaseline = 'middle';
|
16
|
+
context.fillStyle = '#ffffff';
|
17
|
+
context.fillText(message, textWidth / 2, textHeight / 2);
|
18
|
+
const texture = new THREE.Texture(canvas);
|
19
|
+
texture.needsUpdate = true; //var spriteAlignment = new THREE.Vector2(0,0) ;
|
20
|
+
|
21
|
+
const material = new THREE.MeshBasicMaterial({
|
22
|
+
color: 0xffffff,
|
23
|
+
side: THREE.DoubleSide,
|
24
|
+
map: texture,
|
25
|
+
transparent: true
|
26
|
+
});
|
27
|
+
const geometry = new THREE.PlaneGeometry(height * textWidth / textHeight, height);
|
28
|
+
const plane = new THREE.Mesh(geometry, material);
|
29
|
+
return plane;
|
30
|
+
}
|
31
|
+
|
32
|
+
export { createText };
|
package/webxr/VRButton.cjs.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});
|
1
|
+
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}Object.defineProperty(exports,"__esModule",{value:!0});var t=e(require("@babel/runtime/helpers/defineProperty"));class n{static createButton(e,t){t&&console.error('THREE.VRButton: The "options" parameter has been removed. Please set the reference space type via renderer.xr.setReferenceSpaceType() instead.');const o=document.createElement("button");function s(){o.style.display="",o.style.cursor="auto",o.style.left="calc(50% - 75px)",o.style.width="150px",o.onmouseenter=null,o.onmouseleave=null,o.onclick=null,o.textContent="VR NOT SUPPORTED"}function r(e){e.style.position="absolute",e.style.bottom="20px",e.style.padding="12px 6px",e.style.border="1px solid #fff",e.style.borderRadius="4px",e.style.background="rgba(0,0,0,0.1)",e.style.color="#fff",e.style.font="normal 13px sans-serif",e.style.textAlign="center",e.style.opacity="0.5",e.style.outline="none",e.style.zIndex="999"}if("xr"in navigator)return o.id="VRButton",o.style.display="none",r(o),navigator.xr.isSessionSupported("immersive-vr").then((function(t){t?function(){let t=null;async function n(n){n.addEventListener("end",s),await e.xr.setSession(n),o.textContent="EXIT VR",t=n}function s(){t.removeEventListener("end",s),o.textContent="ENTER VR",t=null}o.style.display="",o.style.cursor="pointer",o.style.left="calc(50% - 50px)",o.style.width="100px",o.textContent="ENTER VR",o.onmouseenter=function(){o.style.opacity="1.0"},o.onmouseleave=function(){o.style.opacity="0.5"},o.onclick=function(){if(null===t){const e={optionalFeatures:["local-floor","bounded-floor","hand-tracking","layers"]};navigator.xr.requestSession("immersive-vr",e).then(n)}else t.end()}}():s(),t&&n.xrSessionIsGranted&&o.click()})),o;{const e=document.createElement("a");return!1===window.isSecureContext?(e.href=document.location.href.replace(/^http:/,"https:"),e.innerHTML="WEBXR NEEDS HTTPS"):(e.href="https://immersiveweb.dev/",e.innerHTML="WEBXR NOT AVAILABLE"),e.style.left="calc(50% - 90px)",e.style.width="180px",e.style.textDecoration="none",r(e),e}}static registerSessionGrantedListener(){"xr"in navigator&&navigator.xr.addEventListener("sessiongranted",(()=>{n.xrSessionIsGranted=!0}))}}t.default(n,"xrSessionIsGranted",!1),exports.VRButton=n;
|
package/webxr/VRButton.js
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
|
2
|
+
|
1
3
|
class VRButton {
|
2
4
|
static createButton(renderer, options) {
|
3
5
|
if (options) {
|
@@ -50,7 +52,7 @@ class VRButton {
|
|
50
52
|
// ('local' is always available for immersive sessions and doesn't need to
|
51
53
|
// be requested separately.)
|
52
54
|
const sessionInit = {
|
53
|
-
optionalFeatures: ['local-floor', 'bounded-floor', 'hand-tracking']
|
55
|
+
optionalFeatures: ['local-floor', 'bounded-floor', 'hand-tracking', 'layers']
|
54
56
|
};
|
55
57
|
navigator.xr.requestSession('immersive-vr', sessionInit).then(onSessionStarted);
|
56
58
|
} else {
|
@@ -95,6 +97,10 @@ class VRButton {
|
|
95
97
|
stylizeElement(button);
|
96
98
|
navigator.xr.isSessionSupported('immersive-vr').then(function (supported) {
|
97
99
|
supported ? showEnterVR() : showWebXRNotFound();
|
100
|
+
|
101
|
+
if (supported && VRButton.xrSessionIsGranted) {
|
102
|
+
button.click();
|
103
|
+
}
|
98
104
|
});
|
99
105
|
return button;
|
100
106
|
} else {
|
@@ -116,6 +122,16 @@ class VRButton {
|
|
116
122
|
}
|
117
123
|
}
|
118
124
|
|
125
|
+
static registerSessionGrantedListener() {
|
126
|
+
if ('xr' in navigator) {
|
127
|
+
navigator.xr.addEventListener('sessiongranted', () => {
|
128
|
+
VRButton.xrSessionIsGranted = true;
|
129
|
+
});
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
119
133
|
}
|
120
134
|
|
135
|
+
_defineProperty(VRButton, "xrSessionIsGranted", false);
|
136
|
+
|
121
137
|
export { VRButton };
|
@@ -1 +1 @@
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("three"),
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("three"),o=require("../loaders/GLTFLoader.cjs.js"),t=require("../libs/MotionControllers.cjs.js");class n extends e.Object3D{constructor(){super(),this.motionController=null,this.envMap=null}setEnvironmentMap(e){return this.envMap==e||(this.envMap=e,this.traverse((e=>{e.isMesh&&(e.material.envMap=this.envMap,e.material.needsUpdate=!0)}))),this}updateMatrixWorld(e){super.updateMatrixWorld(e),this.motionController&&(this.motionController.updateFromGamepad(),Object.values(this.motionController.components).forEach((e=>{Object.values(e.visualResponses).forEach((e=>{const{valueNode:o,minNode:n,maxNode:r,value:s,valueNodeProperty:a}=e;o&&(a===t.MotionControllerConstants.VisualResponseProperty.VISIBILITY?o.visible=s:a===t.MotionControllerConstants.VisualResponseProperty.TRANSFORM&&(o.quaternion.slerpQuaternions(n.quaternion,r.quaternion,s),o.position.lerpVectors(n.position,r.position,s)))}))})))}}function r(o,n){!function(o,n){Object.values(o.components).forEach((o=>{const{type:r,touchPointNodeName:s,visualResponses:a}=o;if(r===t.MotionControllerConstants.ComponentType.TOUCHPAD)if(o.touchPointNode=n.getObjectByName(s),o.touchPointNode){const t=new e.SphereGeometry(.001),n=new e.MeshBasicMaterial({color:255}),r=new e.Mesh(t,n);o.touchPointNode.add(r)}else console.warn(`Could not find touch dot, ${o.touchPointNodeName}, in touchpad component ${o.id}`);Object.values(a).forEach((e=>{const{valueNodeName:o,minNodeName:r,maxNodeName:s,valueNodeProperty:a}=e;if(a===t.MotionControllerConstants.VisualResponseProperty.TRANSFORM){if(e.minNode=n.getObjectByName(r),e.maxNode=n.getObjectByName(s),!e.minNode)return void console.warn(`Could not find ${r} in the model`);if(!e.maxNode)return void console.warn(`Could not find ${s} in the model`)}e.valueNode=n.getObjectByName(o),e.valueNode||console.warn(`Could not find ${o} in the model`)}))}))}(o.motionController,n),o.envMap&&n.traverse((e=>{e.isMesh&&(e.material.envMap=o.envMap,e.material.needsUpdate=!0)})),o.add(n)}exports.XRControllerModelFactory=class{constructor(e=null){this.gltfLoader=e,this.path="https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles",this._assetCache={},this.gltfLoader||(this.gltfLoader=new o.GLTFLoader)}createControllerModel(e){const o=new n;let s=null;return e.addEventListener("connected",(e=>{const n=e.data;"tracked-pointer"===n.targetRayMode&&n.gamepad&&t.fetchProfile(n,this.path,"generic-trigger").then((({profile:e,assetPath:a})=>{o.motionController=new t.MotionController(n,e,a);const l=this._assetCache[o.motionController.assetUrl];if(l)s=l.scene.clone(),r(o,s);else{if(!this.gltfLoader)throw new Error("GLTFLoader not set.");this.gltfLoader.setPath(""),this.gltfLoader.load(o.motionController.assetUrl,(e=>{this._assetCache[o.motionController.assetUrl]=e,s=e.scene.clone(),r(o,s)}),null,(()=>{throw new Error(`Asset ${o.motionController.assetUrl} missing or malformed.`)}))}})).catch((e=>{console.warn(e)}))})),e.addEventListener("disconnected",(()=>{o.motionController=null,o.remove(s),s=null})),o}};
|
@@ -1,19 +1,18 @@
|
|
1
|
-
import { Object3D,
|
1
|
+
import { Object3D, SphereGeometry, MeshBasicMaterial, Mesh } from 'three';
|
2
2
|
import { GLTFLoader } from '../loaders/GLTFLoader.js';
|
3
|
-
import {
|
3
|
+
import { fetchProfile, MotionController, MotionControllerConstants } from '../libs/MotionControllers.js';
|
4
4
|
|
5
5
|
const DEFAULT_PROFILES_PATH = 'https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles';
|
6
6
|
const DEFAULT_PROFILE = 'generic-trigger';
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
class XRControllerModel extends Object3D {
|
9
|
+
constructor() {
|
10
|
+
super();
|
11
|
+
this.motionController = null;
|
12
|
+
this.envMap = null;
|
13
|
+
}
|
13
14
|
|
14
|
-
|
15
|
-
constructor: XRControllerModel,
|
16
|
-
setEnvironmentMap: function (envMap) {
|
15
|
+
setEnvironmentMap(envMap) {
|
17
16
|
if (this.envMap == envMap) {
|
18
17
|
return this;
|
19
18
|
}
|
@@ -26,14 +25,15 @@ XRControllerModel.prototype = Object.assign(Object.create(Object3D.prototype), {
|
|
26
25
|
}
|
27
26
|
});
|
28
27
|
return this;
|
29
|
-
}
|
30
|
-
|
28
|
+
}
|
31
29
|
/**
|
32
30
|
* Polls data from the XRInputSource and updates the model's components to match
|
33
31
|
* the real world data
|
34
32
|
*/
|
35
|
-
|
36
|
-
|
33
|
+
|
34
|
+
|
35
|
+
updateMatrixWorld(force) {
|
36
|
+
super.updateMatrixWorld(force);
|
37
37
|
if (!this.motionController) return; // Cause the MotionController to poll the Gamepad for data
|
38
38
|
|
39
39
|
this.motionController.updateFromGamepad(); // Update the 3D model to reflect the button, thumbstick, and touchpad state
|
@@ -52,22 +52,24 @@ XRControllerModel.prototype = Object.assign(Object.create(Object3D.prototype), {
|
|
52
52
|
|
53
53
|
if (!valueNode) return; // Calculate the new properties based on the weight supplied
|
54
54
|
|
55
|
-
if (valueNodeProperty ===
|
55
|
+
if (valueNodeProperty === MotionControllerConstants.VisualResponseProperty.VISIBILITY) {
|
56
56
|
valueNode.visible = value;
|
57
|
-
} else if (valueNodeProperty ===
|
58
|
-
|
57
|
+
} else if (valueNodeProperty === MotionControllerConstants.VisualResponseProperty.TRANSFORM) {
|
58
|
+
valueNode.quaternion.slerpQuaternions(minNode.quaternion, maxNode.quaternion, value);
|
59
59
|
valueNode.position.lerpVectors(minNode.position, maxNode.position, value);
|
60
60
|
}
|
61
61
|
});
|
62
62
|
});
|
63
63
|
}
|
64
|
-
|
64
|
+
|
65
|
+
}
|
65
66
|
/**
|
66
67
|
* Walks the model's tree to find the nodes needed to animate the components and
|
67
68
|
* saves them to the motionContoller components for use in the frame loop. When
|
68
69
|
* touchpads are found, attaches a touch dot to them.
|
69
70
|
*/
|
70
71
|
|
72
|
+
|
71
73
|
function findNodes(motionController, scene) {
|
72
74
|
// Loop through the components and find the nodes needed for each components' visual responses
|
73
75
|
Object.values(motionController.components).forEach(component => {
|
@@ -77,7 +79,7 @@ function findNodes(motionController, scene) {
|
|
77
79
|
visualResponses
|
78
80
|
} = component;
|
79
81
|
|
80
|
-
if (type ===
|
82
|
+
if (type === MotionControllerConstants.ComponentType.TOUCHPAD) {
|
81
83
|
component.touchPointNode = scene.getObjectByName(touchPointNodeName);
|
82
84
|
|
83
85
|
if (component.touchPointNode) {
|
@@ -102,7 +104,7 @@ function findNodes(motionController, scene) {
|
|
102
104
|
valueNodeProperty
|
103
105
|
} = visualResponse; // If animating a transform, find the two nodes to be interpolated between.
|
104
106
|
|
105
|
-
if (valueNodeProperty ===
|
107
|
+
if (valueNodeProperty === MotionControllerConstants.VisualResponseProperty.TRANSFORM) {
|
106
108
|
visualResponse.minNode = scene.getObjectByName(minNodeName);
|
107
109
|
visualResponse.maxNode = scene.getObjectByName(maxNodeName); // If the extents cannot be found, skip this animation
|
108
110
|
|
@@ -144,8 +146,8 @@ function addAssetSceneToControllerModel(controllerModel, scene) {
|
|
144
146
|
controllerModel.add(scene);
|
145
147
|
}
|
146
148
|
|
147
|
-
|
148
|
-
|
149
|
+
class XRControllerModelFactory {
|
150
|
+
constructor(gltfLoader = null) {
|
149
151
|
this.gltfLoader = gltfLoader;
|
150
152
|
this.path = DEFAULT_PROFILES_PATH;
|
151
153
|
this._assetCache = {}; // If a GLTFLoader wasn't supplied to the constructor create a new one.
|
@@ -155,51 +157,48 @@ var XRControllerModelFactory = function () {
|
|
155
157
|
}
|
156
158
|
}
|
157
159
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
if (!this.gltfLoader) {
|
178
|
-
throw new Error('GLTFLoader not set.');
|
179
|
-
}
|
180
|
-
|
181
|
-
this.gltfLoader.setPath('');
|
182
|
-
this.gltfLoader.load(controllerModel.motionController.assetUrl, asset => {
|
183
|
-
this._assetCache[controllerModel.motionController.assetUrl] = asset;
|
184
|
-
scene = asset.scene.clone();
|
185
|
-
addAssetSceneToControllerModel(controllerModel, scene);
|
186
|
-
}, null, () => {
|
187
|
-
throw new Error(`Asset ${controllerModel.motionController.assetUrl} missing or malformed.`);
|
188
|
-
});
|
160
|
+
createControllerModel(controller) {
|
161
|
+
const controllerModel = new XRControllerModel();
|
162
|
+
let scene = null;
|
163
|
+
controller.addEventListener('connected', event => {
|
164
|
+
const xrInputSource = event.data;
|
165
|
+
if (xrInputSource.targetRayMode !== 'tracked-pointer' || !xrInputSource.gamepad) return;
|
166
|
+
fetchProfile(xrInputSource, this.path, DEFAULT_PROFILE).then(({
|
167
|
+
profile,
|
168
|
+
assetPath
|
169
|
+
}) => {
|
170
|
+
controllerModel.motionController = new MotionController(xrInputSource, profile, assetPath);
|
171
|
+
const cachedAsset = this._assetCache[controllerModel.motionController.assetUrl];
|
172
|
+
|
173
|
+
if (cachedAsset) {
|
174
|
+
scene = cachedAsset.scene.clone();
|
175
|
+
addAssetSceneToControllerModel(controllerModel, scene);
|
176
|
+
} else {
|
177
|
+
if (!this.gltfLoader) {
|
178
|
+
throw new Error('GLTFLoader not set.');
|
189
179
|
}
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
180
|
+
|
181
|
+
this.gltfLoader.setPath('');
|
182
|
+
this.gltfLoader.load(controllerModel.motionController.assetUrl, asset => {
|
183
|
+
this._assetCache[controllerModel.motionController.assetUrl] = asset;
|
184
|
+
scene = asset.scene.clone();
|
185
|
+
addAssetSceneToControllerModel(controllerModel, scene);
|
186
|
+
}, null, () => {
|
187
|
+
throw new Error(`Asset ${controllerModel.motionController.assetUrl} missing or malformed.`);
|
188
|
+
});
|
189
|
+
}
|
190
|
+
}).catch(err => {
|
191
|
+
console.warn(err);
|
198
192
|
});
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
193
|
+
});
|
194
|
+
controller.addEventListener('disconnected', () => {
|
195
|
+
controllerModel.motionController = null;
|
196
|
+
controllerModel.remove(scene);
|
197
|
+
scene = null;
|
198
|
+
});
|
199
|
+
return controllerModel;
|
200
|
+
}
|
201
|
+
|
202
|
+
}
|
204
203
|
|
205
204
|
export { XRControllerModelFactory };
|
@@ -1 +1 @@
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("three");class i{constructor(i,e,n,s,r){this.xrLight=i,this.renderer=e,this.lightProbe=n,this.xrWebGLBinding=null,this.estimationStartCallback=r,this.frameCallback=this.onXRFrame.bind(this);const h=e.xr.getSession();if(s&&"XRWebGLBinding"in window){const n=new t.WebGLCubeRenderTarget(16);i.environment=n.texture;const s=e.getContext();switch(h.preferredReflectionFormat){case"srgba8":s.getExtension("EXT_sRGB");break;case"rgba16f":s.getExtension("OES_texture_half_float")}this.xrWebGLBinding=new XRWebGLBinding(h,s),this.lightProbe.addEventListener("reflectionchange",(()=>{this.updateReflection()}))}h.requestAnimationFrame(this.frameCallback)}updateReflection(){const t=this.renderer.properties.get(this.xrLight.environment);if(t){const i=this.xrWebGLBinding.getReflectionCubeMap(this.lightProbe);i&&(t.__webglTexture=i)}}onXRFrame(t,i){if(!this.xrLight)return;i.session.requestAnimationFrame(this.frameCallback);const e=i.getLightEstimate(this.lightProbe);if(e){this.xrLight.lightProbe.sh.fromArray(e.sphericalHarmonicsCoefficients),this.xrLight.lightProbe.intensity=1;const t=Math.max(1,Math.max(e.primaryLightIntensity.x,Math.max(e.primaryLightIntensity.y,e.primaryLightIntensity.z)));this.xrLight.directionalLight.color.setRGB(e.primaryLightIntensity.x/t,e.primaryLightIntensity.y/t,e.primaryLightIntensity.z/t),this.xrLight.directionalLight.intensity=t,this.xrLight.directionalLight.position.copy(e.primaryLightDirection),this.estimationStartCallback&&(this.estimationStartCallback(),this.estimationStartCallback=null)}}dispose(){this.xrLight=null,this.renderer=null,this.lightProbe=null,this.xrWebGLBinding=null}}class e extends t.Group{constructor(e,n=!0){super(),this.lightProbe=new t.LightProbe,this.lightProbe.intensity=0,this.add(this.lightProbe),this.directionalLight=new t.DirectionalLight,this.directionalLight.intensity=0,this.add(this.directionalLight),this.environment=null;let s=null,r=!1;e.xr.addEventListener("sessionstart",(()=>{const t=e.xr.getSession();"requestLightProbe"in t&&t.requestLightProbe({reflectionFormat:t.preferredReflectionFormat}).then((t=>{s=new i(this,e,t,n,(()=>{r=!0,this.dispatchEvent({type:"estimationstart"})}))}))})),e.xr.addEventListener("sessionend",(()=>{s&&(s.dispose(),s=null),r&&this.dispatchEvent({type:"estimationend"})})),this.dispose=()=>{s&&(s.dispose(),s=null),this.remove(this.lightProbe),this.lightProbe=null,this.remove(this.directionalLight),this.directionalLight=null,this.environment=null}}}exports.XREstimatedLight=e;
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("three");class i{constructor(i,e,n,s,r){this.xrLight=i,this.renderer=e,this.lightProbe=n,this.xrWebGLBinding=null,this.estimationStartCallback=r,this.frameCallback=this.onXRFrame.bind(this);const h=e.xr.getSession();if(s&&"XRWebGLBinding"in window){const n=new t.WebGLCubeRenderTarget(16);i.environment=n.texture;const s=e.getContext();switch(h.preferredReflectionFormat){case"srgba8":s.getExtension("EXT_sRGB");break;case"rgba16f":s.getExtension("OES_texture_half_float")}this.xrWebGLBinding=new XRWebGLBinding(h,s),this.lightProbe.addEventListener("reflectionchange",(()=>{this.updateReflection()}))}h.requestAnimationFrame(this.frameCallback)}updateReflection(){const t=this.renderer.properties.get(this.xrLight.environment);if(t){const i=this.xrWebGLBinding.getReflectionCubeMap(this.lightProbe);i&&(t.__webglTexture=i,this.xrLight.environment.needsPMREMUpdate=!0)}}onXRFrame(t,i){if(!this.xrLight)return;i.session.requestAnimationFrame(this.frameCallback);const e=i.getLightEstimate(this.lightProbe);if(e){this.xrLight.lightProbe.sh.fromArray(e.sphericalHarmonicsCoefficients),this.xrLight.lightProbe.intensity=1;const t=Math.max(1,Math.max(e.primaryLightIntensity.x,Math.max(e.primaryLightIntensity.y,e.primaryLightIntensity.z)));this.xrLight.directionalLight.color.setRGB(e.primaryLightIntensity.x/t,e.primaryLightIntensity.y/t,e.primaryLightIntensity.z/t),this.xrLight.directionalLight.intensity=t,this.xrLight.directionalLight.position.copy(e.primaryLightDirection),this.estimationStartCallback&&(this.estimationStartCallback(),this.estimationStartCallback=null)}}dispose(){this.xrLight=null,this.renderer=null,this.lightProbe=null,this.xrWebGLBinding=null}}class e extends t.Group{constructor(e,n=!0){super(),this.lightProbe=new t.LightProbe,this.lightProbe.intensity=0,this.add(this.lightProbe),this.directionalLight=new t.DirectionalLight,this.directionalLight.intensity=0,this.add(this.directionalLight),this.environment=null;let s=null,r=!1;e.xr.addEventListener("sessionstart",(()=>{const t=e.xr.getSession();"requestLightProbe"in t&&t.requestLightProbe({reflectionFormat:t.preferredReflectionFormat}).then((t=>{s=new i(this,e,t,n,(()=>{r=!0,this.dispatchEvent({type:"estimationstart"})}))}))})),e.xr.addEventListener("sessionend",(()=>{s&&(s.dispose(),s=null),r&&this.dispatchEvent({type:"estimationend"})})),this.dispose=()=>{s&&(s.dispose(),s=null),this.remove(this.lightProbe),this.lightProbe=null,this.remove(this.directionalLight),this.directionalLight=null,this.environment=null}}}exports.XREstimatedLight=e;
|
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../loaders/GLTFLoader.cjs.js");require("three");exports.XRHandMeshModel=class{constructor(i,n,a,t){this.controller=n,this.handModel=i,this.bones=[];const r=new e.GLTFLoader;r.setPath(a||"https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles/generic-hand/"),r.load(`${t}.glb`,(e=>{const i=e.scene.children[0];this.handModel.add(i);const n=i.getObjectByProperty("type","SkinnedMesh");n.frustumCulled=!1,n.castShadow=!0,n.receiveShadow=!0;["wrist","thumb-metacarpal","thumb-phalanx-proximal","thumb-phalanx-distal","thumb-tip","index-finger-metacarpal","index-finger-phalanx-proximal","index-finger-phalanx-intermediate","index-finger-phalanx-distal","index-finger-tip","middle-finger-metacarpal","middle-finger-phalanx-proximal","middle-finger-phalanx-intermediate","middle-finger-phalanx-distal","middle-finger-tip","ring-finger-metacarpal","ring-finger-phalanx-proximal","ring-finger-phalanx-intermediate","ring-finger-phalanx-distal","ring-finger-tip","pinky-finger-metacarpal","pinky-finger-phalanx-proximal","pinky-finger-phalanx-intermediate","pinky-finger-phalanx-distal","pinky-finger-tip"].forEach((e=>{const n=i.getObjectByName(e);void 0!==n?n.jointName=e:console.warn(`Couldn't find ${e} in ${t} hand mesh`),this.bones.push(n)}))}))}updateMesh(){const e=this.controller.joints;for(let i=0;i<this.bones.length;i++){const n=this.bones[i];if(n){const i=e[n.jointName];if(i.visible){const e=i.position;n.position.copy(e),n.quaternion.copy(i.quaternion)}}}}};
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { Object3D } from 'three';
|
2
|
+
|
3
|
+
export class XRHandMeshModel {
|
4
|
+
controller: Object3D;
|
5
|
+
handModel: Object3D;
|
6
|
+
bones: Object3D[];
|
7
|
+
|
8
|
+
constructor(handModel: Object3D, controller: Object3D, path: string, handedness: string);
|
9
|
+
|
10
|
+
updateMesh(): void;
|
11
|
+
}
|