@preference-sl/pref-viewer 2.10.0-beta.1 → 2.10.0-beta.3
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/package.json +1 -1
- package/src/index.js +70 -8
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
* </pref-viewer>
|
|
40
40
|
* ```
|
|
41
41
|
*/
|
|
42
|
-
import { Engine, Scene, ArcRotateCamera, Vector3, Color4, HemisphericLight, DirectionalLight, PointLight, ShadowGenerator, LoadAssetContainerAsync, Tools } from "@babylonjs/core";
|
|
42
|
+
import { Engine, Scene, ArcRotateCamera, Vector3, Color4, HemisphericLight, DirectionalLight, PointLight, ShadowGenerator, LoadAssetContainerAsync, Tools, WebXRSessionManager, WebXRDefaultExperience, MeshBuilder, WebXRFeatureName } from "@babylonjs/core";
|
|
43
43
|
import "@babylonjs/loaders";
|
|
44
44
|
import { USDZExportAsync, GLTF2Export } from "@babylonjs/serializers";
|
|
45
45
|
import "@babylonjs/loaders/glTF/2.0/Extensions/KHR_draco_mesh_compression";
|
|
@@ -63,6 +63,8 @@ class PrefViewer extends HTMLElement {
|
|
|
63
63
|
visible: false,
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
+
// DOM elements
|
|
67
|
+
#wrapper = null;
|
|
66
68
|
#canvas = null;
|
|
67
69
|
|
|
68
70
|
// Babylon.js core objects
|
|
@@ -73,6 +75,7 @@ class PrefViewer extends HTMLElement {
|
|
|
73
75
|
#dirLight = null;
|
|
74
76
|
#cameraLight = null;
|
|
75
77
|
#shadowGen = null;
|
|
78
|
+
#XRExperience = null;
|
|
76
79
|
|
|
77
80
|
constructor() {
|
|
78
81
|
super();
|
|
@@ -162,19 +165,18 @@ class PrefViewer extends HTMLElement {
|
|
|
162
165
|
}
|
|
163
166
|
|
|
164
167
|
#wrapCanvas() {
|
|
165
|
-
|
|
166
|
-
Object.assign(wrapper.style, {
|
|
168
|
+
this.#wrapper = document.createElement("div");
|
|
169
|
+
Object.assign(this.#wrapper.style, {
|
|
167
170
|
width: "100%",
|
|
168
171
|
height: "100%",
|
|
169
172
|
position: "relative",
|
|
170
173
|
});
|
|
171
|
-
wrapper.appendChild(this.#canvas);
|
|
172
|
-
this.shadowRoot.append(wrapper);
|
|
174
|
+
this.#wrapper.appendChild(this.#canvas);
|
|
175
|
+
this.shadowRoot.append(this.#wrapper);
|
|
173
176
|
}
|
|
174
|
-
|
|
175
177
|
|
|
176
178
|
// Bbylon.js
|
|
177
|
-
#initializeBabylon() {
|
|
179
|
+
async #initializeBabylon() {
|
|
178
180
|
this.#engine = new Engine(this.#canvas, true, { alpha: true });
|
|
179
181
|
this.#scene = new Scene(this.#engine);
|
|
180
182
|
this.#scene.clearColor = new Color4(1, 1, 1, 1);
|
|
@@ -184,6 +186,66 @@ class PrefViewer extends HTMLElement {
|
|
|
184
186
|
|
|
185
187
|
this.#engine.runRenderLoop(() => this.#scene && this.#scene.render());
|
|
186
188
|
this.#canvasResizeObserver.observe(this.#canvas);
|
|
189
|
+
|
|
190
|
+
await this.#createXRExperience();
|
|
191
|
+
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
addStylesToARButton(){
|
|
195
|
+
const css = '.babylonVRicon { color: #868686; border-color: #868686; border-style: solid; margin-left: 10px; height: 50px; width: 80px; background-color: rgba(51,51,51,0.7); background-image: url(data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%222048%22%20height%3D%221152%22%20viewBox%3D%220%200%202048%201152%22%20version%3D%221.1%22%3E%3Cpath%20transform%3D%22rotate%28180%201024%2C576.0000000000001%29%22%20d%3D%22m1109%2C896q17%2C0%2030%2C-12t13%2C-30t-12.5%2C-30.5t-30.5%2C-12.5l-170%2C0q-18%2C0%20-30.5%2C12.5t-12.5%2C30.5t13%2C30t30%2C12l170%2C0zm-85%2C256q59%2C0%20132.5%2C-1.5t154.5%2C-5.5t164.5%2C-11.5t163%2C-20t150%2C-30t124.5%2C-41.5q23%2C-11%2042%2C-24t38%2C-30q27%2C-25%2041%2C-61.5t14%2C-72.5l0%2C-257q0%2C-123%20-47%2C-232t-128%2C-190t-190%2C-128t-232%2C-47l-81%2C0q-37%2C0%20-68.5%2C14t-60.5%2C34.5t-55.5%2C45t-53%2C45t-53%2C34.5t-55.5%2C14t-55.5%2C-14t-53%2C-34.5t-53%2C-45t-55.5%2C-45t-60.5%2C-34.5t-68.5%2C-14l-81%2C0q-123%2C0%20-232%2C47t-190%2C128t-128%2C190t-47%2C232l0%2C257q0%2C68%2038%2C115t97%2C73q54%2C24%20124.5%2C41.5t150%2C30t163%2C20t164.5%2C11.5t154.5%2C5.5t132.5%2C1.5zm939%2C-298q0%2C39%20-24.5%2C67t-58.5%2C42q-54%2C23%20-122%2C39.5t-143.5%2C28t-155.5%2C19t-157%2C11t-148.5%2C5t-129.5%2C1.5q-59%2C0%20-130%2C-1.5t-148%2C-5t-157%2C-11t-155.5%2C-19t-143.5%2C-28t-122%2C-39.5q-34%2C-14%20-58.5%2C-42t-24.5%2C-67l0%2C-257q0%2C-106%2040.5%2C-199t110%2C-162.5t162.5%2C-109.5t199%2C-40l81%2C0q27%2C0%2052%2C14t50%2C34.5t51%2C44.5t55.5%2C44.5t63.5%2C34.5t74%2C14t74%2C-14t63.5%2C-34.5t55.5%2C-44.5t51%2C-44.5t50%2C-34.5t52%2C-14l14%2C0q37%2C0%2070%2C0.5t64.5%2C4.5t63.5%2C12t68%2C23q71%2C30%20128.5%2C78.5t98.5%2C110t63.5%2C133.5t22.5%2C149l0%2C257z%22%20fill%3D%22white%22%20/%3E%3C/svg%3E%0A); background-size: 80%; background-repeat:no-repeat; background-position: center; border: none; outline: none; transition: transform 0.125s ease-out } .babylonVRicon:hover { transform: scale(1.05) } .babylonVRicon:active {background-color: rgba(51,51,51,1) } .babylonVRicon:focus {background-color: rgba(51,51,51,1) }.babylonVRicon.vrdisplaypresenting { background-image: none;} .vrdisplaypresenting::after { content: "EXIT"} .xr-error::after { content: "ERROR"}';
|
|
196
|
+
const style = document.createElement("style");
|
|
197
|
+
style.appendChild(document.createTextNode(css));
|
|
198
|
+
this.#wrapper.appendChild(style);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async #createXRExperience() {
|
|
202
|
+
if (this.#XRExperience) {
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const sessionMode = "immersive-ar";
|
|
207
|
+
const sessionSupported = await WebXRSessionManager.IsSessionSupportedAsync(sessionMode);
|
|
208
|
+
if (!sessionSupported) {
|
|
209
|
+
console.info("PrefViewer: WebXR in mode AR is not supported");
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
const ground = MeshBuilder.CreateGround("ground", { width: 1000, height: 1000 }, this.#scene);
|
|
215
|
+
ground.isVisible = false;
|
|
216
|
+
|
|
217
|
+
const options = {
|
|
218
|
+
floorMeshes: [ground],
|
|
219
|
+
uiOptions: {
|
|
220
|
+
sessionMode: sessionMode,
|
|
221
|
+
renderTarget: "xrLayer",
|
|
222
|
+
referenceSpaceType: "local",
|
|
223
|
+
},
|
|
224
|
+
optionalFeatures: true,
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
this.#XRExperience = await WebXRDefaultExperience.CreateAsync(this.#scene, options);
|
|
228
|
+
|
|
229
|
+
const featuresManager = this.#XRExperience.baseExperience.featuresManager;
|
|
230
|
+
featuresManager.enableFeature(WebXRFeatureName.TELEPORTATION, "stable", {
|
|
231
|
+
xrInput: this.#XRExperience.input,
|
|
232
|
+
floorMeshes: [ground],
|
|
233
|
+
timeToTeleport: 1500,
|
|
234
|
+
useMainComponentOnly: true,
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
this.#XRExperience.baseExperience.sessionManager.onXRReady.add(() => {
|
|
238
|
+
// Set the initial position of xrCamera: use nonVRCamera, which contains a copy of the original this.#scene.activeCamera before entering XR
|
|
239
|
+
this.#XRExperience.baseExperience.camera.setTransformationFromNonVRCamera(this.#XRExperience.baseExperience._nonVRCamera);
|
|
240
|
+
this.#XRExperience.baseExperience.camera.setTarget(Vector3.Zero());
|
|
241
|
+
this.#XRExperience.baseExperience.onInitialXRPoseSetObservable.notifyObservers(this.#XRExperience.baseExperience.camera);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
this.addStylesToARButton();
|
|
245
|
+
} catch (error) {
|
|
246
|
+
console.warn("PrefViewer: failed to create WebXR experience", error);
|
|
247
|
+
this.#XRExperience = null;
|
|
248
|
+
}
|
|
187
249
|
}
|
|
188
250
|
|
|
189
251
|
#canvasResizeObserver = new ResizeObserver(() => this.#engine && this.#engine.resize());
|
|
@@ -371,7 +433,7 @@ class PrefViewer extends HTMLElement {
|
|
|
371
433
|
}
|
|
372
434
|
|
|
373
435
|
this.#setVisibilityOfWallAndFloorInModel();
|
|
374
|
-
|
|
436
|
+
|
|
375
437
|
this.dispatchEvent(
|
|
376
438
|
new CustomEvent("model-loaded", {
|
|
377
439
|
detail: { success: "" },
|