@shopware-ag/dive 1.19.1-beta.0 → 1.19.1-beta.2
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/build/dive.cjs +362 -199
- package/build/dive.cjs.map +1 -1
- package/build/dive.js +330 -167
- package/build/dive.js.map +1 -1
- package/build/dive.mjs +10803 -8714
- package/build/dive.mjs.map +1 -1
- package/build/src/converter/Converter.d.ts +3 -12
- package/build/src/dive.d.ts +1 -0
- package/build/src/exporter/Exporter.d.ts +20 -2
- package/build/src/loader/Loader.d.ts +0 -4
- package/build/src/types/error/index.d.ts +12 -0
- package/build/src/types/file/FileTypes.d.ts +17 -0
- package/build/src/types/file/index.d.ts +1 -0
- package/build/src/types/index.d.ts +5 -8
- package/package.json +2 -3
- package/build/src/types/ExporterOptions.d.ts +0 -15
- package/build/src/types/FileTypes.d.ts +0 -27
- package/src/__test__/DIVE.test.ts +0 -274
- package/src/animation/AnimationSystem.ts +0 -34
- package/src/animation/__test__/AnimationSystem.test.ts +0 -40
- package/src/ar/AR.ts +0 -101
- package/src/ar/__test__/AR.test.ts +0 -276
- package/src/ar/arquicklook/ARQuickLook.ts +0 -53
- package/src/ar/arquicklook/__test__/ARQuickLook.test.ts +0 -144
- package/src/ar/sceneviewer/SceneViewer.ts +0 -119
- package/src/ar/sceneviewer/__test__/SceneViewer.test.ts +0 -190
- package/src/ar/webxr/WebXR.ts +0 -177
- package/src/ar/webxr/controller/WebXRController.ts +0 -340
- package/src/ar/webxr/crosshair/WebXRCrosshair.ts +0 -35
- package/src/ar/webxr/origin/WebXROrigin.ts +0 -192
- package/src/ar/webxr/overlay/Overlay.ts +0 -50
- package/src/ar/webxr/raycaster/WebXRRaycaster.ts +0 -131
- package/src/ar/webxr/raycaster/ar/WebXRRaycasterAR.ts +0 -102
- package/src/ar/webxr/raycaster/three/WebXRRaycasterTHREE.ts +0 -49
- package/src/ar/webxr/touchscreencontrols/WebXRTouchscreenControls.ts +0 -356
- package/src/axiscamera/AxisCamera.ts +0 -108
- package/src/axiscamera/__test__/AxisCamera.test.ts +0 -150
- package/src/camera/PerspectiveCamera.ts +0 -63
- package/src/camera/__test__/PerspectiveCamera.test.ts +0 -36
- package/src/com/Communication.ts +0 -806
- package/src/com/__test__/Communication.test.ts +0 -1030
- package/src/com/actions/camera/computeencompassingview.ts +0 -10
- package/src/com/actions/camera/getcameratransform.ts +0 -10
- package/src/com/actions/camera/movecamera.ts +0 -18
- package/src/com/actions/camera/resetcamera.ts +0 -5
- package/src/com/actions/camera/setcameralayer.ts +0 -5
- package/src/com/actions/camera/setcameratransform.ts +0 -10
- package/src/com/actions/camera/zoomcamera.ts +0 -5
- package/src/com/actions/index.ts +0 -61
- package/src/com/actions/media/generatemedia.ts +0 -18
- package/src/com/actions/object/addobject.ts +0 -7
- package/src/com/actions/object/deleteobject.ts +0 -7
- package/src/com/actions/object/deselectobject.ts +0 -7
- package/src/com/actions/object/getallobjects.ts +0 -7
- package/src/com/actions/object/getobjects.ts +0 -7
- package/src/com/actions/object/model/dropit.ts +0 -5
- package/src/com/actions/object/model/modelloaded.ts +0 -5
- package/src/com/actions/object/model/placeonfloor.ts +0 -5
- package/src/com/actions/object/selectobject.ts +0 -7
- package/src/com/actions/object/setparent.ts +0 -10
- package/src/com/actions/object/updateobject.ts +0 -7
- package/src/com/actions/renderer/startrender.ts +0 -5
- package/src/com/actions/scene/exportscene.ts +0 -7
- package/src/com/actions/scene/getallscenedata.ts +0 -7
- package/src/com/actions/scene/launchar.ts +0 -7
- package/src/com/actions/scene/setbackground.ts +0 -5
- package/src/com/actions/scene/updatescene.ts +0 -11
- package/src/com/actions/toolbox/select/setgizmomode.ts +0 -5
- package/src/com/actions/toolbox/transform/setgizmoscalelinked.ts +0 -5
- package/src/com/actions/toolbox/transform/setgizmovisible.ts +0 -5
- package/src/com/actions/toolbox/usetool.ts +0 -7
- package/src/com/types/COMBaseEntity.ts +0 -9
- package/src/com/types/COMEntity.ts +0 -7
- package/src/com/types/COMEntityType.ts +0 -1
- package/src/com/types/COMGeometry.ts +0 -8
- package/src/com/types/COMGeometryType.ts +0 -9
- package/src/com/types/COMGroup.ts +0 -9
- package/src/com/types/COMLight.ts +0 -11
- package/src/com/types/COMMaterial.ts +0 -12
- package/src/com/types/COMModel.ts +0 -12
- package/src/com/types/COMPov.ts +0 -8
- package/src/com/types/COMPrimitive.ts +0 -12
- package/src/com/types/index.ts +0 -23
- package/src/constant/AxisHelperColors.ts +0 -7
- package/src/constant/GridColors.ts +0 -2
- package/src/constant/VisibilityLayerMask.ts +0 -5
- package/src/controls/OrbitControls.ts +0 -211
- package/src/controls/__test__/OrbitControls.test.ts +0 -256
- package/src/converter/Converter.ts +0 -117
- package/src/dive.ts +0 -363
- package/src/events/EventExecutor.ts +0 -35
- package/src/exporter/Exporter.ts +0 -75
- package/src/gizmo/Gizmo.ts +0 -144
- package/src/gizmo/handles/AxisHandle.ts +0 -153
- package/src/gizmo/handles/RadialHandle.ts +0 -149
- package/src/gizmo/handles/ScaleHandle.ts +0 -195
- package/src/gizmo/plane/GizmoPlane.ts +0 -84
- package/src/gizmo/rotate/RotateGizmo.ts +0 -143
- package/src/gizmo/scale/ScaleGizmo.ts +0 -125
- package/src/gizmo/translate/TranslateGizmo.ts +0 -114
- package/src/grid/Grid.ts +0 -34
- package/src/grid/__test__/Grid.test.ts +0 -28
- package/src/group/Group.ts +0 -184
- package/src/group/__test__/Group.test.ts +0 -212
- package/src/helper/applyMixins/__test__/applyMixins.test.ts +0 -30
- package/src/helper/applyMixins/applyMixins.ts +0 -70
- package/src/helper/findInterface/__test__/findInterface.test.ts +0 -63
- package/src/helper/findInterface/findInterface.ts +0 -13
- package/src/helper/findSceneRecursive/__test__/findSceneRecursive.test.ts +0 -40
- package/src/helper/findSceneRecursive/findSceneRecursive.ts +0 -16
- package/src/helper/getObjectDelta/__test__/getObjectDelta.test.ts +0 -186
- package/src/helper/getObjectDelta/getObjectDelta.ts +0 -105
- package/src/helper/isInterface/__test__/implementsInterface.test.ts +0 -19
- package/src/helper/isInterface/implementsInterface.ts +0 -9
- package/src/info/Info.ts +0 -178
- package/src/info/__test__/Info.test.ts +0 -346
- package/src/interface/Draggable.ts +0 -14
- package/src/interface/Hoverable.ts +0 -14
- package/src/interface/Movable.ts +0 -12
- package/src/interface/Rotatable.ts +0 -10
- package/src/interface/Scalable.ts +0 -10
- package/src/interface/Selectable.ts +0 -11
- package/src/io/IO.ts +0 -62
- package/src/io/__test__/IO.test.ts +0 -116
- package/src/io/gltf/GLTFIO.ts +0 -56
- package/src/io/gltf/__test__/GLTFIO.test.ts +0 -108
- package/src/light/AmbientLight.ts +0 -39
- package/src/light/PointLight.ts +0 -115
- package/src/light/SceneLight.ts +0 -63
- package/src/light/__test__/AmbientLight.test.ts +0 -29
- package/src/light/__test__/PointLight.test.ts +0 -74
- package/src/light/__test__/SceneLight.test.ts +0 -47
- package/src/loader/Loader.ts +0 -48
- package/src/math/__test__/DIVEMath.test.ts +0 -12
- package/src/math/ceil/__test__/ceilExp.test.ts +0 -12
- package/src/math/ceil/ceilExp.ts +0 -6
- package/src/math/degToRad/__test__/degToRad.test.ts +0 -172
- package/src/math/degToRad/degToRad.ts +0 -5
- package/src/math/floor/__test__/floorExp.test.ts +0 -14
- package/src/math/floor/floorExp.ts +0 -6
- package/src/math/helper/__test__/shift.test.ts +0 -12
- package/src/math/helper/shift.ts +0 -4
- package/src/math/index.ts +0 -28
- package/src/math/radToDeg/__test__/radToDeg.test.ts +0 -155
- package/src/math/radToDeg/radToDeg.ts +0 -5
- package/src/math/round/__test__/roundExp.test.ts +0 -14
- package/src/math/round/roundExp.ts +0 -10
- package/src/math/signedAngleTo/__test__/signedAngleTo.test.ts +0 -20
- package/src/math/signedAngleTo/signedAngleTo.ts +0 -20
- package/src/math/toFixed/__test__/toFixedExp.test.ts +0 -14
- package/src/math/toFixed/toFixedExp.ts +0 -9
- package/src/math/truncate/__test__/truncateExp.test.ts +0 -14
- package/src/math/truncate/truncateExp.ts +0 -9
- package/src/mediacreator/MediaCreator.ts +0 -75
- package/src/mediacreator/__test__/MediaCreator.test.ts +0 -155
- package/src/model/Model.ts +0 -190
- package/src/model/__test__/Model.test.ts +0 -215
- package/src/module/Module.ts +0 -45
- package/src/module/__test__/Module.test.ts +0 -54
- package/src/node/Node.ts +0 -100
- package/src/node/__test__/Node.test.ts +0 -120
- package/src/primitive/Primitive.ts +0 -299
- package/src/primitive/__test__/Primitive.test.ts +0 -281
- package/src/primitive/floor/Floor.ts +0 -45
- package/src/primitive/floor/__test__/Floor.test.ts +0 -24
- package/src/renderer/Renderer.ts +0 -215
- package/src/renderer/__test__/Renderer.test.ts +0 -228
- package/src/scene/Scene.ts +0 -106
- package/src/scene/__test__/Scene.test.ts +0 -124
- package/src/scene/root/Root.ts +0 -426
- package/src/scene/root/__test__/Root.test.ts +0 -903
- package/src/scene/xrroot/XRRoot.ts +0 -56
- package/src/scene/xrroot/xrlightroot/XRLightRoot.ts +0 -80
- package/src/toolbox/BaseTool.ts +0 -319
- package/src/toolbox/Toolbox.ts +0 -129
- package/src/toolbox/__test__/BaseTool.test.ts +0 -627
- package/src/toolbox/__test__/Toolbox.test.ts +0 -143
- package/src/toolbox/select/SelectTool.ts +0 -92
- package/src/toolbox/select/__test__/SelectTool.test.ts +0 -237
- package/src/toolbox/transform/TransformTool.ts +0 -166
- package/src/toolbox/transform/__test__/TransformTool.test.ts +0 -147
- package/src/types/ExporterOptions.ts +0 -14
- package/src/types/FileTypes.ts +0 -37
- package/src/types/SceneData.ts +0 -26
- package/src/types/SceneObjects.ts +0 -14
- package/src/types/SceneType.ts +0 -14
- package/src/types/index.ts +0 -31
- package/src/types/info/index.ts +0 -76
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import { Box3, Color, Euler, Mesh, Object3D, Vector3 } from 'three';
|
|
2
|
-
import { DIVEScene } from '../../../scene/Scene';
|
|
3
|
-
import { ARSystemOptions } from '../../AR';
|
|
4
|
-
import { SceneViewer } from '../SceneViewer';
|
|
5
|
-
import { SystemInfo } from '../../../info/Info';
|
|
6
|
-
|
|
7
|
-
// Mock DIVEInfo
|
|
8
|
-
jest.mock('../../../info/Info', () => ({
|
|
9
|
-
DIVEInfo: {
|
|
10
|
-
GetSystem: jest.fn().mockReturnValue('Android'),
|
|
11
|
-
GetSupportsARQuickLook: jest.fn().mockReturnValue(false),
|
|
12
|
-
},
|
|
13
|
-
}));
|
|
14
|
-
|
|
15
|
-
jest.mock('../../../scene/Scene', () => {
|
|
16
|
-
return {
|
|
17
|
-
DIVEScene: jest.fn(function () {
|
|
18
|
-
this.add = jest.fn();
|
|
19
|
-
this.children = [];
|
|
20
|
-
this.Root = {
|
|
21
|
-
children: [],
|
|
22
|
-
};
|
|
23
|
-
this.traverse = jest.fn((callback) => {
|
|
24
|
-
this.Root.children.forEach((child: Object3D) => {
|
|
25
|
-
callback(child);
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
return this;
|
|
29
|
-
}),
|
|
30
|
-
};
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
// Mock URL and document APIs
|
|
34
|
-
const mockLocation = new URL('https://example.com');
|
|
35
|
-
const mockCreateElement = jest.fn();
|
|
36
|
-
const mockSetAttribute = jest.fn();
|
|
37
|
-
const mockClick = jest.fn();
|
|
38
|
-
|
|
39
|
-
Object.defineProperty(window, 'location', {
|
|
40
|
-
value: mockLocation,
|
|
41
|
-
writable: true,
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
document.createElement = mockCreateElement.mockReturnValue({
|
|
45
|
-
setAttribute: mockSetAttribute,
|
|
46
|
-
click: mockClick,
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
describe('DIVESceneViewer', () => {
|
|
50
|
-
const mockUri = 'https://example.com/model.glb';
|
|
51
|
-
let mockOptions: ARSystemOptions;
|
|
52
|
-
|
|
53
|
-
beforeEach(() => {
|
|
54
|
-
mockOptions = {
|
|
55
|
-
arPlacement: 'horizontal',
|
|
56
|
-
arScale: 'auto',
|
|
57
|
-
};
|
|
58
|
-
jest.clearAllMocks();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe('constructor', () => {
|
|
62
|
-
it('should create an instance', () => {
|
|
63
|
-
const sceneViewer = new SceneViewer();
|
|
64
|
-
expect(sceneViewer).toBeInstanceOf(SceneViewer);
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
describe('launch', () => {
|
|
69
|
-
it('should launch with default options', () => {
|
|
70
|
-
const sceneViewer = new SceneViewer();
|
|
71
|
-
sceneViewer.launch(mockUri);
|
|
72
|
-
|
|
73
|
-
expect(mockCreateElement).toHaveBeenCalledWith('a');
|
|
74
|
-
expect(mockSetAttribute).toHaveBeenCalledWith(
|
|
75
|
-
'href',
|
|
76
|
-
expect.stringContaining('mode=ar_preferred'),
|
|
77
|
-
);
|
|
78
|
-
expect(mockClick).toHaveBeenCalled();
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('should launch with custom options', () => {
|
|
82
|
-
const options: ARSystemOptions = {
|
|
83
|
-
arPlacement: 'vertical',
|
|
84
|
-
arScale: 'fixed',
|
|
85
|
-
};
|
|
86
|
-
const sceneViewer = new SceneViewer();
|
|
87
|
-
sceneViewer.launch(mockUri, options);
|
|
88
|
-
|
|
89
|
-
expect(mockCreateElement).toHaveBeenCalledWith('a');
|
|
90
|
-
expect(mockSetAttribute).toHaveBeenCalledWith(
|
|
91
|
-
'href',
|
|
92
|
-
expect.stringContaining('enable_vertical_placement=true'),
|
|
93
|
-
);
|
|
94
|
-
expect(mockSetAttribute).toHaveBeenCalledWith(
|
|
95
|
-
'href',
|
|
96
|
-
expect.stringContaining('resizable=false'),
|
|
97
|
-
);
|
|
98
|
-
expect(mockClick).toHaveBeenCalled();
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('should handle sound parameter in URL', () => {
|
|
102
|
-
const sceneViewer = new SceneViewer();
|
|
103
|
-
const params = new URLSearchParams();
|
|
104
|
-
params.set('sound', 'sound.mp3');
|
|
105
|
-
|
|
106
|
-
// Access private method for testing
|
|
107
|
-
const applySoundOption = (sceneViewer as any)._applySoundOption;
|
|
108
|
-
applySoundOption(params, mockLocation.toString());
|
|
109
|
-
|
|
110
|
-
expect(params.get('sound')).toBe('https://example.com/sound.mp3');
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('should handle link parameter in URL', () => {
|
|
114
|
-
const sceneViewer = new SceneViewer();
|
|
115
|
-
const params = new URLSearchParams();
|
|
116
|
-
params.set('link', 'details.html');
|
|
117
|
-
|
|
118
|
-
// Access private method for testing
|
|
119
|
-
const applyLinkOption = (sceneViewer as any)._applyLinkOption;
|
|
120
|
-
applyLinkOption(params, mockLocation.toString());
|
|
121
|
-
|
|
122
|
-
expect(params.get('link')).toBe('https://example.com/details.html');
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('should create intent URL with correct parameters', () => {
|
|
126
|
-
const sceneViewer = new SceneViewer();
|
|
127
|
-
const params = new URLSearchParams();
|
|
128
|
-
params.set('mode', 'ar_preferred');
|
|
129
|
-
|
|
130
|
-
// Access private method for testing and bind it to the instance
|
|
131
|
-
const createIntent = (sceneViewer as any)._createIntent.bind(
|
|
132
|
-
sceneViewer,
|
|
133
|
-
);
|
|
134
|
-
const intentUrl = createIntent(
|
|
135
|
-
mockLocation.toString(),
|
|
136
|
-
mockUri,
|
|
137
|
-
params,
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
expect(intentUrl).toContain(
|
|
141
|
-
'intent://arvr.google.com/scene-viewer/1.2',
|
|
142
|
-
);
|
|
143
|
-
expect(intentUrl).toContain('mode=ar_preferred');
|
|
144
|
-
expect(intentUrl).toContain('file=' + mockUri);
|
|
145
|
-
expect(intentUrl).toContain('scheme=https');
|
|
146
|
-
expect(intentUrl).toContain(
|
|
147
|
-
'package=com.google.android.googlequicksearchbox',
|
|
148
|
-
);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
it('should handle relative model URLs', () => {
|
|
152
|
-
const relativeUri = '/models/model.glb';
|
|
153
|
-
const sceneViewer = new SceneViewer();
|
|
154
|
-
sceneViewer.launch(relativeUri);
|
|
155
|
-
|
|
156
|
-
expect(mockSetAttribute).toHaveBeenCalledWith(
|
|
157
|
-
'href',
|
|
158
|
-
expect.stringContaining(
|
|
159
|
-
'file=https://example.com/models/model.glb',
|
|
160
|
-
),
|
|
161
|
-
);
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it('should handle absolute model URLs', () => {
|
|
165
|
-
const absoluteUri = 'https://cdn.example.com/model.glb';
|
|
166
|
-
const sceneViewer = new SceneViewer();
|
|
167
|
-
sceneViewer.launch(absoluteUri);
|
|
168
|
-
|
|
169
|
-
expect(mockSetAttribute).toHaveBeenCalledWith(
|
|
170
|
-
'href',
|
|
171
|
-
expect.stringContaining(
|
|
172
|
-
'file=https://cdn.example.com/model.glb',
|
|
173
|
-
),
|
|
174
|
-
);
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it('should handle special characters in model URL', () => {
|
|
178
|
-
const specialUri = 'https://example.com/model with spaces.glb';
|
|
179
|
-
const sceneViewer = new SceneViewer();
|
|
180
|
-
sceneViewer.launch(specialUri);
|
|
181
|
-
|
|
182
|
-
expect(mockSetAttribute).toHaveBeenCalledWith(
|
|
183
|
-
'href',
|
|
184
|
-
expect.stringContaining(
|
|
185
|
-
'file=https://example.com/model%20with%20spaces.glb',
|
|
186
|
-
),
|
|
187
|
-
);
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
});
|
package/src/ar/webxr/WebXR.ts
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import { Vector3 } from 'three';
|
|
2
|
-
import DIVEOrbitControls from '../../controls/OrbitControls';
|
|
3
|
-
import { type DIVERenderer } from '../../renderer/Renderer';
|
|
4
|
-
import { type DIVEScene } from '../../scene/Scene';
|
|
5
|
-
import { Overlay } from './overlay/Overlay';
|
|
6
|
-
import { DIVEWebXRController } from './controller/WebXRController';
|
|
7
|
-
|
|
8
|
-
export class DIVEWebXR {
|
|
9
|
-
// general members
|
|
10
|
-
private static _renderer: DIVERenderer;
|
|
11
|
-
private static _scene: DIVEScene;
|
|
12
|
-
private static _controller: DIVEOrbitControls;
|
|
13
|
-
|
|
14
|
-
// camera reset members
|
|
15
|
-
private static _cameraPosition: Vector3;
|
|
16
|
-
private static _cameraTarget: Vector3;
|
|
17
|
-
|
|
18
|
-
// render loop members
|
|
19
|
-
private static _renderCallbackId: string | null = null;
|
|
20
|
-
|
|
21
|
-
// setup members
|
|
22
|
-
private static _session: XRSession | null = null;
|
|
23
|
-
private static _referenceSpaceType: XRReferenceSpaceType = 'local';
|
|
24
|
-
private static _overlay: Overlay | null = null;
|
|
25
|
-
private static _options = {
|
|
26
|
-
requiredFeatures: [
|
|
27
|
-
'local',
|
|
28
|
-
'hit-test',
|
|
29
|
-
],
|
|
30
|
-
optionalFeatures: [
|
|
31
|
-
'light-estimation',
|
|
32
|
-
'local-floor',
|
|
33
|
-
'dom-overlay',
|
|
34
|
-
'depth-sensing',
|
|
35
|
-
],
|
|
36
|
-
depthSensing: {
|
|
37
|
-
usagePreference: ['gpu-optimized'],
|
|
38
|
-
dataFormatPreference: [],
|
|
39
|
-
},
|
|
40
|
-
domOverlay: { root: {} as HTMLElement },
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
private static _xrController: DIVEWebXRController | null = null;
|
|
44
|
-
|
|
45
|
-
public static async Launch(
|
|
46
|
-
renderer: DIVERenderer,
|
|
47
|
-
scene: DIVEScene,
|
|
48
|
-
controller: DIVEOrbitControls,
|
|
49
|
-
): Promise<void> {
|
|
50
|
-
this._renderer = renderer;
|
|
51
|
-
this._scene = scene;
|
|
52
|
-
this._controller = controller;
|
|
53
|
-
|
|
54
|
-
// setting camera reset values
|
|
55
|
-
this._cameraPosition = this._controller.object.position.clone();
|
|
56
|
-
this._cameraTarget = this._controller.target.clone();
|
|
57
|
-
|
|
58
|
-
if (!navigator.xr) {
|
|
59
|
-
console.error('WebXR not supported');
|
|
60
|
-
return Promise.reject();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// setup current instance
|
|
64
|
-
this._renderer.xr.enabled = true;
|
|
65
|
-
this._scene.InitXR(renderer);
|
|
66
|
-
|
|
67
|
-
// creating overlay
|
|
68
|
-
if (!DIVEWebXR._overlay) {
|
|
69
|
-
const overlay = new Overlay();
|
|
70
|
-
DIVEWebXR._overlay = overlay;
|
|
71
|
-
}
|
|
72
|
-
DIVEWebXR._options.domOverlay = { root: DIVEWebXR._overlay.Element };
|
|
73
|
-
|
|
74
|
-
// request session
|
|
75
|
-
const session = await navigator.xr
|
|
76
|
-
.requestSession('immersive-ar', this._options)
|
|
77
|
-
.catch((reason) => {
|
|
78
|
-
return Promise.reject(reason);
|
|
79
|
-
});
|
|
80
|
-
session.addEventListener('end', () => {
|
|
81
|
-
this._onSessionEnded();
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
// build up session
|
|
85
|
-
renderer.xr.setReferenceSpaceType(this._referenceSpaceType);
|
|
86
|
-
await renderer.xr.setSession(session);
|
|
87
|
-
DIVEWebXR._overlay.Element.style.display = '';
|
|
88
|
-
this._session = session;
|
|
89
|
-
|
|
90
|
-
// add end session event listener
|
|
91
|
-
DIVEWebXR._overlay.CloseButton.addEventListener('click', () =>
|
|
92
|
-
this.End(),
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
// start session
|
|
96
|
-
await this._onSessionStarted();
|
|
97
|
-
|
|
98
|
-
return Promise.resolve();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
public static Update(_time: DOMHighResTimeStamp, frame: XRFrame): void {
|
|
102
|
-
if (!this._session) return;
|
|
103
|
-
|
|
104
|
-
if (this._xrController) {
|
|
105
|
-
this._xrController.Update(frame);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
public static End(): void {
|
|
110
|
-
if (!this._session) return;
|
|
111
|
-
this._session.end();
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private static async _onSessionStarted(): Promise<void> {
|
|
115
|
-
if (!this._session) return;
|
|
116
|
-
|
|
117
|
-
// add update callback to render loop
|
|
118
|
-
this._renderCallbackId = this._renderer.AddPreRenderCallback(
|
|
119
|
-
(time: DOMHighResTimeStamp, frame: XRFrame) => {
|
|
120
|
-
this.Update(time, frame);
|
|
121
|
-
},
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
this._xrController = new DIVEWebXRController(
|
|
125
|
-
this._session,
|
|
126
|
-
this._renderer,
|
|
127
|
-
this._scene,
|
|
128
|
-
);
|
|
129
|
-
await this._xrController.Init().catch(() => {
|
|
130
|
-
this.End();
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
return Promise.resolve();
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
private static _onSessionEnded(): void {
|
|
137
|
-
if (!this._session) return;
|
|
138
|
-
|
|
139
|
-
if (this._xrController) {
|
|
140
|
-
this._xrController.Dispose();
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// remove Update() callback
|
|
144
|
-
if (this._renderCallbackId) {
|
|
145
|
-
this._renderer.RemovePreRenderCallback(this._renderCallbackId);
|
|
146
|
-
this._renderCallbackId = null;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// disable XR on renderer to restore canvas rendering
|
|
150
|
-
this._renderer.xr.enabled = false;
|
|
151
|
-
|
|
152
|
-
// resize renderer
|
|
153
|
-
const canvasWrapper = this._renderer.domElement.parentElement;
|
|
154
|
-
if (canvasWrapper) {
|
|
155
|
-
const { clientWidth, clientHeight } = canvasWrapper;
|
|
156
|
-
this._renderer.OnResize(clientWidth, clientHeight);
|
|
157
|
-
|
|
158
|
-
// resize camera
|
|
159
|
-
this._controller.object.OnResize(clientWidth, clientHeight);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// reset camera
|
|
163
|
-
this._controller.object.position.copy(this._cameraPosition);
|
|
164
|
-
this._controller.target.copy(this._cameraTarget);
|
|
165
|
-
|
|
166
|
-
// reset camera values
|
|
167
|
-
this._cameraPosition.set(0, 0, 0);
|
|
168
|
-
this._cameraTarget.set(0, 0, 0);
|
|
169
|
-
|
|
170
|
-
// dispose xr scene
|
|
171
|
-
this._scene.DisposeXR();
|
|
172
|
-
|
|
173
|
-
this._session.removeEventListener('end', this._onSessionEnded);
|
|
174
|
-
DIVEWebXR._overlay!.Element.style.display = 'none';
|
|
175
|
-
this._session = null;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
@@ -1,340 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Matrix4,
|
|
3
|
-
Mesh,
|
|
4
|
-
Object3D,
|
|
5
|
-
Quaternion,
|
|
6
|
-
Vector3,
|
|
7
|
-
WebXRArrayCamera,
|
|
8
|
-
} from 'three';
|
|
9
|
-
import { DIVERenderer } from '../../../renderer/Renderer';
|
|
10
|
-
import { DIVEScene } from '../../../scene/Scene';
|
|
11
|
-
import { DIVEWebXRCrosshair } from '../crosshair/WebXRCrosshair';
|
|
12
|
-
import { DIVEWebXRRaycaster } from '../raycaster/WebXRRaycaster';
|
|
13
|
-
import { DIVEWebXROrigin } from '../origin/WebXROrigin';
|
|
14
|
-
import {
|
|
15
|
-
DIVETouchscreenEvents,
|
|
16
|
-
DIVEWebXRTouchscreenControls,
|
|
17
|
-
} from '../touchscreencontrols/WebXRTouchscreenControls';
|
|
18
|
-
import { type DIVEMovable } from '../.././../interface/Movable';
|
|
19
|
-
import { findInterface } from '../../../helper/findInterface/findInterface';
|
|
20
|
-
|
|
21
|
-
export class DIVEWebXRController extends Object3D {
|
|
22
|
-
// general members
|
|
23
|
-
private _renderer: DIVERenderer;
|
|
24
|
-
private _scene: DIVEScene;
|
|
25
|
-
private _session: XRSession;
|
|
26
|
-
|
|
27
|
-
private _frameBuffer: XRFrame | null = null;
|
|
28
|
-
|
|
29
|
-
// raycaster members
|
|
30
|
-
private _xrRaycaster: DIVEWebXRRaycaster;
|
|
31
|
-
private _origin: DIVEWebXROrigin;
|
|
32
|
-
|
|
33
|
-
// crosshair
|
|
34
|
-
private _crosshair: DIVEWebXRCrosshair;
|
|
35
|
-
|
|
36
|
-
// controller members
|
|
37
|
-
private _touchscreenControls: DIVEWebXRTouchscreenControls;
|
|
38
|
-
private _handNodeInitialPosition = new Vector3();
|
|
39
|
-
private _xrCamera: WebXRArrayCamera;
|
|
40
|
-
private _placed: boolean = false;
|
|
41
|
-
|
|
42
|
-
// grabbing
|
|
43
|
-
private _grabbedObject: Object3D | null = null;
|
|
44
|
-
private _arHitPosition: Vector3 = new Vector3();
|
|
45
|
-
private _arHitQuaternion: Quaternion = new Quaternion();
|
|
46
|
-
private _arHitScale: Vector3 = new Vector3(1, 1, 1);
|
|
47
|
-
|
|
48
|
-
// grabbing position
|
|
49
|
-
private _initialObjectPosition: Vector3 | null = null;
|
|
50
|
-
private _initialRaycastHit: Vector3 | null = null;
|
|
51
|
-
private _deltaRaycastHit: Vector3 = new Vector3();
|
|
52
|
-
|
|
53
|
-
// grabbing rotation
|
|
54
|
-
private _touchQuaterion: Quaternion = new Quaternion();
|
|
55
|
-
|
|
56
|
-
// grabbing scale
|
|
57
|
-
private _touchScale: number = 1;
|
|
58
|
-
private _scaleThreshold: number = 0.1;
|
|
59
|
-
|
|
60
|
-
constructor(session: XRSession, renderer: DIVERenderer, scene: DIVEScene) {
|
|
61
|
-
super();
|
|
62
|
-
|
|
63
|
-
this._renderer = renderer;
|
|
64
|
-
this._scene = scene;
|
|
65
|
-
this._session = session;
|
|
66
|
-
|
|
67
|
-
this._xrRaycaster = new DIVEWebXRRaycaster(session, renderer, scene);
|
|
68
|
-
this._origin = new DIVEWebXROrigin(this._session, this._renderer, [
|
|
69
|
-
'plane',
|
|
70
|
-
]);
|
|
71
|
-
|
|
72
|
-
this._crosshair = new DIVEWebXRCrosshair();
|
|
73
|
-
this._crosshair.visible = false;
|
|
74
|
-
|
|
75
|
-
this._xrCamera = this._renderer.xr.getCamera();
|
|
76
|
-
|
|
77
|
-
this._scene.XRRoot.XRHandNode.position.set(0, -0.05, -0.25);
|
|
78
|
-
this._handNodeInitialPosition =
|
|
79
|
-
this._scene.XRRoot.XRHandNode.position.clone();
|
|
80
|
-
|
|
81
|
-
this._touchscreenControls = new DIVEWebXRTouchscreenControls(
|
|
82
|
-
this._session,
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
// translating
|
|
86
|
-
this._touchscreenControls.Subscribe('TOUCH_START', () =>
|
|
87
|
-
this.onTouchStart(),
|
|
88
|
-
);
|
|
89
|
-
this._touchscreenControls.Subscribe('TOUCH_MOVE', () =>
|
|
90
|
-
this.onTouchMove(),
|
|
91
|
-
);
|
|
92
|
-
this._touchscreenControls.Subscribe('TOUCH_END', (p) =>
|
|
93
|
-
this.onTouchEnd(p),
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
// rotating
|
|
97
|
-
this._touchscreenControls.Subscribe('ROTATE_START', () =>
|
|
98
|
-
this.onRotateStart(),
|
|
99
|
-
);
|
|
100
|
-
this._touchscreenControls.Subscribe('ROTATE_MOVE', (p) =>
|
|
101
|
-
this.onRotateMove(p),
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
// scaling
|
|
105
|
-
this._touchscreenControls.Subscribe('PINCH_START', () =>
|
|
106
|
-
this.onPinchStart(),
|
|
107
|
-
);
|
|
108
|
-
this._touchscreenControls.Subscribe('PINCH_MOVE', (p) =>
|
|
109
|
-
this.onPinchMove(p),
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
public async Init(): Promise<this> {
|
|
114
|
-
this.prepareScene();
|
|
115
|
-
|
|
116
|
-
await this.initOrigin();
|
|
117
|
-
await this.initRaycaster();
|
|
118
|
-
|
|
119
|
-
return Promise.resolve(this);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
public Dispose(): void {
|
|
123
|
-
this.restoreScene();
|
|
124
|
-
|
|
125
|
-
this._origin.Dispose();
|
|
126
|
-
this._xrRaycaster.Dispose();
|
|
127
|
-
|
|
128
|
-
// reset placement members
|
|
129
|
-
this._placed = false;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
public Update(frame: XRFrame): void {
|
|
133
|
-
this._frameBuffer = frame;
|
|
134
|
-
|
|
135
|
-
if (!this._placed) {
|
|
136
|
-
this.updateHandNode();
|
|
137
|
-
|
|
138
|
-
if (this._origin) {
|
|
139
|
-
this._origin.Update(frame);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
private updateHandNode(): void {
|
|
145
|
-
this._xrCamera.updateMatrixWorld();
|
|
146
|
-
this._scene.XRRoot.XRHandNode.position.copy(
|
|
147
|
-
this._handNodeInitialPosition
|
|
148
|
-
.clone()
|
|
149
|
-
.applyMatrix4(this._xrCamera.matrixWorld),
|
|
150
|
-
);
|
|
151
|
-
this._scene.XRRoot.XRHandNode.quaternion.setFromRotationMatrix(
|
|
152
|
-
this._xrCamera.matrixWorld,
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// placement
|
|
157
|
-
private async initOrigin(): Promise<void> {
|
|
158
|
-
// initialize origin
|
|
159
|
-
this._origin = await this._origin.Init();
|
|
160
|
-
|
|
161
|
-
// set resolve callback: place objects at origin when it is set
|
|
162
|
-
this._origin.originSet.then(() => {
|
|
163
|
-
this.placeObjects(this._origin.matrix);
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
private placeObjects(matrix: Matrix4): void {
|
|
168
|
-
this._scene.XRRoot.XRModelRoot.matrix.copy(matrix);
|
|
169
|
-
|
|
170
|
-
// we are copying children to a new array to keep the original array intact
|
|
171
|
-
[...this._scene.XRRoot.XRHandNode.children].forEach((child) => {
|
|
172
|
-
this._scene.XRRoot.XRModelRoot.add(child);
|
|
173
|
-
});
|
|
174
|
-
this._placed = true;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// grabbing
|
|
178
|
-
private updateObject(): void {
|
|
179
|
-
if (!this._grabbedObject) return;
|
|
180
|
-
|
|
181
|
-
this._grabbedObject.position.copy(this._arHitPosition);
|
|
182
|
-
this._grabbedObject.quaternion.copy(
|
|
183
|
-
this._arHitQuaternion.clone().multiply(this._touchQuaterion),
|
|
184
|
-
);
|
|
185
|
-
this._grabbedObject.scale.copy(
|
|
186
|
-
new Vector3(
|
|
187
|
-
this._touchScale,
|
|
188
|
-
this._touchScale,
|
|
189
|
-
this._touchScale,
|
|
190
|
-
).multiply(this._arHitScale),
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
private onTouchStart(): void {
|
|
195
|
-
const sceneHits = this._xrRaycaster.GetSceneIntersections();
|
|
196
|
-
console.log('sceneHits', sceneHits);
|
|
197
|
-
if (sceneHits.length === 0) return;
|
|
198
|
-
if (!sceneHits[0].object) return;
|
|
199
|
-
|
|
200
|
-
const moveable = findInterface<DIVEMovable>(
|
|
201
|
-
sceneHits[0].object,
|
|
202
|
-
'isMovable',
|
|
203
|
-
);
|
|
204
|
-
if (!moveable) return;
|
|
205
|
-
|
|
206
|
-
this._grabbedObject = moveable;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
private onTouchMove(): void {
|
|
210
|
-
// raycast ar
|
|
211
|
-
if (!this._frameBuffer) return;
|
|
212
|
-
if (!this._grabbedObject) return;
|
|
213
|
-
|
|
214
|
-
const intersections = this._xrRaycaster.GetARIntersections(
|
|
215
|
-
this._frameBuffer,
|
|
216
|
-
);
|
|
217
|
-
if (intersections.length === 0) {
|
|
218
|
-
this._crosshair.visible = false;
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const hit = intersections[0];
|
|
223
|
-
|
|
224
|
-
this._crosshair.visible = true;
|
|
225
|
-
this._crosshair.matrix.copy(hit.matrix);
|
|
226
|
-
|
|
227
|
-
if (!this._grabbedObject) return;
|
|
228
|
-
|
|
229
|
-
// if initial values have been reset by TOUCH_END event then set them again
|
|
230
|
-
if (!this._initialObjectPosition || !this._initialRaycastHit) {
|
|
231
|
-
this._initialObjectPosition = this._grabbedObject.position.clone();
|
|
232
|
-
this._initialRaycastHit = hit.point.clone();
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// decompose hit matrix to apply hit matrix to object
|
|
236
|
-
hit.matrix.decompose(
|
|
237
|
-
this._arHitPosition,
|
|
238
|
-
this._arHitQuaternion,
|
|
239
|
-
this._arHitScale,
|
|
240
|
-
);
|
|
241
|
-
|
|
242
|
-
// calculate raycast hit delta
|
|
243
|
-
this._deltaRaycastHit.copy(
|
|
244
|
-
hit.point.clone().sub(this._initialRaycastHit),
|
|
245
|
-
);
|
|
246
|
-
|
|
247
|
-
// apply moved raycast delta to actual object position
|
|
248
|
-
this._arHitPosition.copy(
|
|
249
|
-
this._initialObjectPosition.clone().add(this._deltaRaycastHit),
|
|
250
|
-
);
|
|
251
|
-
|
|
252
|
-
console.log('arHitPosition', this._arHitPosition);
|
|
253
|
-
|
|
254
|
-
this.updateObject();
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
private onTouchEnd(payload: DIVETouchscreenEvents['TOUCH_END']): void {
|
|
258
|
-
if (payload.touchCount === 0) {
|
|
259
|
-
this._crosshair.visible = false;
|
|
260
|
-
|
|
261
|
-
// reset grab
|
|
262
|
-
this._initialObjectPosition = null;
|
|
263
|
-
this._initialRaycastHit = null;
|
|
264
|
-
this._grabbedObject = null;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
private _startTouchQuaternion: Quaternion = new Quaternion();
|
|
269
|
-
private onRotateStart(): void {
|
|
270
|
-
this._startTouchQuaternion = this._touchQuaterion.clone();
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
private onRotateMove(payload: DIVETouchscreenEvents['ROTATE_MOVE']): void {
|
|
274
|
-
this._touchQuaterion.setFromAxisAngle(
|
|
275
|
-
new Vector3(0, -1, 0),
|
|
276
|
-
payload.delta * 3,
|
|
277
|
-
);
|
|
278
|
-
this._touchQuaterion.multiply(this._startTouchQuaternion);
|
|
279
|
-
this.updateObject();
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
private _startTouchScale: number = 1;
|
|
283
|
-
private onPinchStart(): void {
|
|
284
|
-
this._startTouchScale = this._touchScale;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
private onPinchMove(payload: DIVETouchscreenEvents['PINCH_MOVE']): void {
|
|
288
|
-
this._touchScale = this._startTouchScale * payload.current;
|
|
289
|
-
this.updateObject();
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// prepare & cleanup scene
|
|
293
|
-
private prepareScene(): void {
|
|
294
|
-
this._scene.XRRoot.XRModelRoot.matrixAutoUpdate = false;
|
|
295
|
-
|
|
296
|
-
// initialize crosshair
|
|
297
|
-
this._scene.add(this._crosshair);
|
|
298
|
-
|
|
299
|
-
// hang current scene children to hand node
|
|
300
|
-
const children: Object3D[] = [];
|
|
301
|
-
this._scene.Root.children.forEach((child) => {
|
|
302
|
-
const clone = child.clone();
|
|
303
|
-
clone.layers.enableAll();
|
|
304
|
-
clone.traverse((obj) => {
|
|
305
|
-
obj.layers.enableAll();
|
|
306
|
-
if (obj instanceof Mesh) {
|
|
307
|
-
obj.scale.set(0.1, 0.1, 0.1);
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
clone.position.set(0, 0, 0);
|
|
311
|
-
children.push(clone);
|
|
312
|
-
});
|
|
313
|
-
this._scene.XRRoot.XRHandNode.add(...children);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
private restoreScene(): void {
|
|
317
|
-
this._scene.remove(this._crosshair);
|
|
318
|
-
|
|
319
|
-
// clear hand node and remove attached models
|
|
320
|
-
this._scene.XRRoot.XRHandNode.clear();
|
|
321
|
-
this._scene.XRRoot.XRModelRoot.clear();
|
|
322
|
-
|
|
323
|
-
this._scene.XRRoot.XRModelRoot.matrixAutoUpdate = true;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// raycast
|
|
327
|
-
private async initRaycaster(): Promise<void> {
|
|
328
|
-
// initialize raycaster
|
|
329
|
-
await this._xrRaycaster.Init();
|
|
330
|
-
|
|
331
|
-
// check if successful
|
|
332
|
-
if (!this._xrRaycaster) {
|
|
333
|
-
console.error(
|
|
334
|
-
'Raycaster not initialized successfully. Aborting WebXR...',
|
|
335
|
-
);
|
|
336
|
-
this.Dispose();
|
|
337
|
-
return Promise.reject();
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|