three-stdlib 2.8.4 → 2.8.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|