@realsee/dnalogel 2.0.0-alpha.26-beta → 2.0.0-alpha.28-beta

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.
Files changed (139) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/CSS3DRenderPlugin/Plugin.d.ts +49 -0
  3. package/dist/CSS3DRenderPlugin/index.d.ts +3 -48
  4. package/dist/CameraMovementPlugin/CameraMovementPlugin.d.ts +7 -0
  5. package/dist/CameraMovementPlugin/index.d.ts +4 -6
  6. package/dist/CameraMovementPlugin/index.js +12 -12
  7. package/dist/ModelChassisCompassPlugin/Plugin.d.ts +19 -0
  8. package/dist/ModelChassisCompassPlugin/index.d.ts +3 -18
  9. package/dist/ModelEntryDoorGuidePlugin/Plugin.d.ts +26 -0
  10. package/dist/ModelEntryDoorGuidePlugin/index.d.ts +3 -25
  11. package/dist/ModelEntryDoorGuidePlugin/index.js +0 -5
  12. package/dist/ModelItemLabelPlugin/ModelItemLabelPlugin.d.ts +4 -0
  13. package/dist/ModelItemLabelPlugin/index.d.ts +8 -3
  14. package/dist/ModelItemLabelPlugin/index.js +14 -8
  15. package/dist/ModelRoomLabelPlugin/index.js +82 -46
  16. package/dist/ModelTVVideoPlugin/Plugin.d.ts +4 -0
  17. package/dist/ModelTVVideoPlugin/index.d.ts +4 -3
  18. package/dist/ModelTVVideoPlugin/index.js +3 -3
  19. package/dist/ModelViewPlugin/Plugin.d.ts +17 -0
  20. package/dist/ModelViewPlugin/index.d.ts +3 -16
  21. package/dist/PanoCompassPlugin/Plugin.d.ts +47 -0
  22. package/dist/PanoCompassPlugin/index.d.ts +4 -47
  23. package/dist/PanoCompassPlugin/index.js +5 -4
  24. package/dist/PanoMeasurePlugin/index.d.ts +1 -1
  25. package/dist/PanoMeasurePlugin/index.js +4 -1
  26. package/dist/PanoRulerPlugin/Plugin.d.ts +31 -0
  27. package/dist/PanoRulerPlugin/index.d.ts +4 -30
  28. package/dist/PanoRulerPlugin/index.js +0 -5
  29. package/dist/PanoSpatialTagPlugin/Plugin.d.ts +33 -0
  30. package/dist/PanoSpatialTagPlugin/index.d.ts +4 -32
  31. package/dist/PanoSpatialTagPlugin/index.js +23 -21
  32. package/dist/_index.d.ts +30 -0
  33. package/dist/index.d.ts +16 -29
  34. package/dist/index.es.js +122 -70
  35. package/dist/index.js +145 -90
  36. package/dist/index.umd.js +145 -90
  37. package/docs/assets/search.js +1 -1
  38. package/docs/classes/ModelRoomLabelController.html +6 -6
  39. package/docs/classes/PanoFloorplanRadarPluginController.html +3 -0
  40. package/docs/enums/CameraMovementEffect.html +3 -0
  41. package/docs/enums/DIRECTION.html +1 -0
  42. package/docs/enums/DISPLAY_STRATEGY_TYPE.html +1 -0
  43. package/docs/enums/FLOOR_PLAN_ATTACHED_TO.html +1 -1
  44. package/docs/enums/ModelFloorplanErrorType.html +1 -1
  45. package/docs/enums/Rotation.html +3 -0
  46. package/docs/index.html +1 -1
  47. package/docs/interfaces/CSS3DRenderPluginExportType.html +4 -0
  48. package/docs/interfaces/CameraMovementPluginExportType.html +17 -0
  49. package/docs/interfaces/LineJson.html +1 -1
  50. package/docs/interfaces/ModelChassisCompassPluginData.html +1 -1
  51. package/docs/interfaces/ModelChassisCompassPluginExportType.html +1 -1
  52. package/docs/interfaces/ModelChassisCompassPluginParameterType.html +1 -1
  53. package/docs/interfaces/ModelEntryDoorGuidePluginData.html +1 -1
  54. package/docs/interfaces/ModelEntryDoorGuidePluginExportType.html +1 -1
  55. package/docs/interfaces/ModelFloorplanParameterType.html +1 -1
  56. package/docs/interfaces/ModelFloorplanViewEvent.html +2 -2
  57. package/docs/interfaces/ModelItemLabelPluginData.html +1 -1
  58. package/docs/interfaces/ModelItemLabelPluginExportReturnsType.html +1 -1
  59. package/docs/interfaces/ModelItemLabelPluginParametersType.html +1 -1
  60. package/docs/interfaces/ModelRoomLabelPluginData.html +1 -1
  61. package/docs/interfaces/ModelTVVideoPluginData.html +1 -1
  62. package/docs/interfaces/ModelTVVideoPluginExportType.html +1 -1
  63. package/docs/interfaces/ModelTVVideoPluginParameterType.html +1 -1
  64. package/docs/interfaces/ModelViewPluginExportType.html +1 -0
  65. package/docs/interfaces/PanoCompassPluginData.html +1 -1
  66. package/docs/interfaces/PanoCompassPluginParameterType.html +1 -1
  67. package/docs/interfaces/PanoCursorRaycasterPluginExportType.html +6 -6
  68. package/docs/interfaces/PanoCursorRaycasterPluginParameterType.html +1 -0
  69. package/docs/interfaces/PanoFloorplanRadarPluginControllerParameter.html +1 -0
  70. package/docs/interfaces/PanoRulerPluginExportType.html +1 -1
  71. package/docs/interfaces/PanoRulerPluginOptions.html +1 -1
  72. package/docs/interfaces/PanoRulerPluginParameterType.html +1 -1
  73. package/docs/interfaces/PanoSpatialTagPluginContentEvent.html +1 -0
  74. package/docs/interfaces/PanoSpatialTagPluginContentReplacement.html +1 -0
  75. package/docs/interfaces/PanoSpatialTagPluginData.html +1 -1
  76. package/docs/interfaces/PanoSpatialTagPluginDataElement.html +1 -0
  77. package/docs/interfaces/PanoSpatialTagPluginExportType.html +1 -1
  78. package/docs/interfaces/PanoSpatialTagPluginOriginElement.html +1 -0
  79. package/docs/interfaces/PanoSpatialTagPluginParameterType.html +1 -1
  80. package/docs/interfaces/PanoSpatialTagPluginPointElement.html +1 -0
  81. package/docs/interfaces/PanoSpatialTagPluginTagElement.html +1 -0
  82. package/docs/interfaces/Point.html +1 -0
  83. package/docs/interfaces/PointJson.html +1 -1
  84. package/docs/interfaces/Room.html +1 -0
  85. package/docs/interfaces/RoomInfo.html +1 -0
  86. package/docs/interfaces/RoomLabel.html +7 -7
  87. package/docs/interfaces/RoomRules.html +1 -0
  88. package/docs/interfaces/Rooms.html +1 -0
  89. package/docs/interfaces/TopviewFloorplanPluginParameterType.html +8 -8
  90. package/docs/modules.html +20 -12
  91. package/libs/CSS3DRenderPlugin/Plugin.d.ts +49 -0
  92. package/libs/CSS3DRenderPlugin/Plugin.js +182 -0
  93. package/libs/CSS3DRenderPlugin/index.d.ts +3 -48
  94. package/libs/CSS3DRenderPlugin/index.js +2 -181
  95. package/libs/CameraMovementPlugin/CameraMovementPlugin.d.ts +7 -0
  96. package/libs/CameraMovementPlugin/CameraMovementPlugin.js +159 -0
  97. package/libs/CameraMovementPlugin/index.d.ts +4 -6
  98. package/libs/CameraMovementPlugin/index.js +3 -158
  99. package/libs/ModelChassisCompassPlugin/Plugin.d.ts +19 -0
  100. package/libs/ModelChassisCompassPlugin/Plugin.js +75 -0
  101. package/libs/ModelChassisCompassPlugin/index.d.ts +3 -18
  102. package/libs/ModelChassisCompassPlugin/index.js +2 -74
  103. package/libs/ModelEntryDoorGuidePlugin/Plugin.d.ts +26 -0
  104. package/libs/ModelEntryDoorGuidePlugin/Plugin.js +140 -0
  105. package/libs/ModelEntryDoorGuidePlugin/index.d.ts +3 -25
  106. package/libs/ModelEntryDoorGuidePlugin/index.js +2 -139
  107. package/libs/ModelItemLabelPlugin/ItemLabelComponent.js +1 -1
  108. package/libs/ModelItemLabelPlugin/ModelItemLabelPlugin.d.ts +4 -0
  109. package/libs/ModelItemLabelPlugin/ModelItemLabelPlugin.js +120 -0
  110. package/libs/ModelItemLabelPlugin/index.d.ts +8 -3
  111. package/libs/ModelItemLabelPlugin/index.js +7 -119
  112. package/libs/ModelRoomLabelPlugin/RoomLabelItems.js +83 -47
  113. package/libs/ModelTVVideoPlugin/Plugin.d.ts +4 -0
  114. package/libs/ModelTVVideoPlugin/Plugin.js +254 -0
  115. package/libs/ModelTVVideoPlugin/index.d.ts +4 -3
  116. package/libs/ModelTVVideoPlugin/index.js +3 -253
  117. package/libs/ModelViewPlugin/Plugin.d.ts +17 -0
  118. package/libs/ModelViewPlugin/Plugin.js +160 -0
  119. package/libs/ModelViewPlugin/index.d.ts +3 -16
  120. package/libs/ModelViewPlugin/index.js +2 -159
  121. package/libs/PanoCompassPlugin/Plugin.d.ts +47 -0
  122. package/libs/PanoCompassPlugin/Plugin.js +249 -0
  123. package/libs/PanoCompassPlugin/index.d.ts +4 -47
  124. package/libs/PanoCompassPlugin/index.js +3 -249
  125. package/libs/PanoMeasurePlugin/index.d.ts +1 -1
  126. package/libs/PanoMeasurePlugin/index.js +1 -1
  127. package/libs/PanoRulerPlugin/Plugin.d.ts +31 -0
  128. package/libs/PanoRulerPlugin/Plugin.js +402 -0
  129. package/libs/PanoRulerPlugin/index.d.ts +4 -30
  130. package/libs/PanoRulerPlugin/index.js +2 -401
  131. package/libs/PanoSpatialTagPlugin/Plugin.d.ts +33 -0
  132. package/libs/PanoSpatialTagPlugin/Plugin.js +415 -0
  133. package/libs/PanoSpatialTagPlugin/index.d.ts +4 -32
  134. package/libs/PanoSpatialTagPlugin/index.js +4 -412
  135. package/libs/_index.d.ts +30 -0
  136. package/libs/_index.js +18 -0
  137. package/libs/index.d.ts +16 -29
  138. package/libs/index.js +25 -16
  139. package/package.json +6 -5
@@ -0,0 +1,254 @@
1
+ import * as THREE from 'three';
2
+ import { parseModelTVVideoPoints } from "./utils/parseData";
3
+ export const ModelTVVideoPlugin = (five, { videoElement }) => {
4
+ const state = {
5
+ videoMeshes: [],
6
+ videoTextureEnabled: false,
7
+ videoSource: '',
8
+ rectPoints: [],
9
+ enabled: false,
10
+ videoElement: videoElement,
11
+ };
12
+ const setMuted = (muted) => {
13
+ if (state.videoTexture) {
14
+ state.videoTexture.image.muted = muted;
15
+ state.videoTexture.image.play();
16
+ }
17
+ };
18
+ const getMuted = () => {
19
+ if (state.videoTexture)
20
+ return state.videoTexture.image.muted;
21
+ else
22
+ return true;
23
+ };
24
+ const enable = () => {
25
+ if (state.enabled)
26
+ return;
27
+ if (!state.videoTexture)
28
+ return;
29
+ state.enabled = true;
30
+ state.videoMeshes = createPanoVideoMeshes();
31
+ console.log('state.videoMeshes', state.videoMeshes);
32
+ state.videoMeshes.forEach((mesh) => five.scene.add(mesh));
33
+ const play = () => {
34
+ console.log('play', state.videoTexture);
35
+ if (!state.videoTexture)
36
+ return;
37
+ const timeupdate = () => {
38
+ var _a;
39
+ if (!state.videoTexture)
40
+ return;
41
+ (_a = state.videoTexture) === null || _a === void 0 ? void 0 : _a.image.removeEventListener('timeupdate', timeupdate);
42
+ state.videoTextureEnabled = true;
43
+ state.videoMeshes.forEach((mesh) => {
44
+ if (mesh.material.map !== state.videoTexture)
45
+ mesh.material.map = state.videoTexture;
46
+ });
47
+ five.needsRender = true;
48
+ };
49
+ state.videoTexture.image.addEventListener('timeupdate', timeupdate);
50
+ if (state.videoTexture && state.videoMeshes.length) {
51
+ state.videoTexture.image.play();
52
+ }
53
+ };
54
+ if (five.model.loaded)
55
+ play();
56
+ else {
57
+ return five.once('modelLoaded', () => play());
58
+ }
59
+ };
60
+ const disable = () => {
61
+ if (!state.enabled)
62
+ return;
63
+ state.enabled = false;
64
+ state.videoMeshes.forEach((mesh) => {
65
+ mesh.geometry.dispose();
66
+ mesh.material.dispose();
67
+ five.scene.remove(mesh);
68
+ if (state.videoTexture)
69
+ state.videoTexture.image.pause();
70
+ });
71
+ state.videoMeshes = [];
72
+ five.needsRender = true;
73
+ };
74
+ const createPanoVideoMeshes = () => {
75
+ return state.rectPoints.map((points, index) => {
76
+ const geometry = new THREE.BufferGeometry();
77
+ const segments = 128;
78
+ const verticesArray = [];
79
+ verticesArray.push(points[0].x, points[0].y, points[0].z);
80
+ for (let i = 1; i < segments; i++) {
81
+ verticesArray.push(points[0].x + ((points[1].x - points[0].x) * i) / segments, points[0].y + ((points[1].y - points[0].y) * i) / segments, points[0].z + ((points[1].z - points[0].z) * i) / segments);
82
+ }
83
+ verticesArray.push(points[1].x, points[1].y, points[1].z);
84
+ verticesArray.push(points[2].x, points[2].y, points[2].z);
85
+ for (let i = 1; i < segments; i++) {
86
+ verticesArray.push(points[2].x + ((points[3].x - points[2].x) * i) / segments, points[2].y + ((points[3].y - points[2].y) * i) / segments, points[2].z + ((points[3].z - points[2].z) * i) / segments);
87
+ }
88
+ verticesArray.push(points[3].x, points[3].y, points[3].z);
89
+ const uvArray = [];
90
+ uvArray.push(0, 1);
91
+ for (let i = 1; i < segments; i++) {
92
+ uvArray.push(0, 1 - i / segments);
93
+ }
94
+ uvArray.push(0, 0);
95
+ uvArray.push(1, 0);
96
+ for (let i = 1; i < segments; i++) {
97
+ uvArray.push(1, i / segments);
98
+ }
99
+ uvArray.push(1, 1);
100
+ const indicesArray = [];
101
+ for (let i = 0; i < segments; i++) {
102
+ indicesArray.push(i, i + 1, segments * 2 - i, i, segments * 2 - i, segments * 2 + 1 - i);
103
+ }
104
+ geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(verticesArray), 3));
105
+ geometry.setAttribute('uv', new THREE.BufferAttribute(new Float32Array(uvArray), 2));
106
+ geometry.setIndex(new THREE.BufferAttribute(new Uint32Array(indicesArray), 1));
107
+ const material = new THREE.MeshBasicMaterial({
108
+ map: state.videoTextureEnabled ? state.videoTexture : state.imageTexture,
109
+ side: THREE.DoubleSide,
110
+ });
111
+ const mesh = new THREE.Mesh(geometry, material);
112
+ mesh.renderOrder = 1;
113
+ mesh.name = `ModelTVVideoPlugin-${index}-${performance.now()}`;
114
+ return mesh;
115
+ });
116
+ };
117
+ const getImageTexture = (source) => {
118
+ const texture = new THREE.TextureLoader().load(source);
119
+ texture.minFilter = THREE.LinearFilter;
120
+ texture.magFilter = THREE.LinearFilter;
121
+ texture.format = THREE.RGBFormat;
122
+ return texture;
123
+ };
124
+ const getVideoTexture = (source, video) => {
125
+ return new Promise((resolve, reject) => {
126
+ const xhr = new XMLHttpRequest();
127
+ xhr.onreadystatechange = () => {
128
+ if (xhr.readyState == 4) {
129
+ if (xhr.status == 200) {
130
+ const url = window.URL || window.webkitURL;
131
+ video = video || document.createElement('video');
132
+ video.crossOrigin = 'anonymous';
133
+ video.autoplay = true;
134
+ video.muted = true;
135
+ video.loop = true;
136
+ video.playsInline = true;
137
+ video.src = url.createObjectURL(xhr.response);
138
+ const texture = new THREE.VideoTexture(video);
139
+ texture.minFilter = THREE.LinearFilter;
140
+ texture.magFilter = THREE.LinearFilter;
141
+ texture.format = THREE.RGBFormat;
142
+ resolve(Object.assign(texture, { videoSource: source }));
143
+ }
144
+ else {
145
+ reject(new Error('Video download Error: ' + xhr.status));
146
+ }
147
+ }
148
+ };
149
+ xhr.onerror = (error) => reject(error);
150
+ xhr.open('GET', source);
151
+ xhr.responseType = 'blob';
152
+ xhr.send();
153
+ });
154
+ };
155
+ const load = async (data, videoElement) => {
156
+ const { video_src, video_poster_src, points } = data;
157
+ state.videoSource = video_src;
158
+ // TODO 存疑,先处理多一次遍历 o(2n)
159
+ state.rectPoints = parseModelTVVideoPoints(points)
160
+ .map((items) => items.map(({ x, y, z }) => new THREE.Vector3(x, y, z)));
161
+ state.imageTexture = getImageTexture(video_poster_src);
162
+ if (videoElement) {
163
+ state.videoElement = videoElement;
164
+ }
165
+ state.videoTexture = await getVideoTexture(state.videoSource, state.videoElement);
166
+ state.enabled = !!data.enable;
167
+ if (state.enabled)
168
+ enable();
169
+ };
170
+ const dispose = () => {
171
+ disable();
172
+ state.videoTexture = undefined;
173
+ five.off('modeChange', () => setMuted(true));
174
+ five.off('wantsTapGesture', (raycaster) => {
175
+ if (!state.enabled)
176
+ return;
177
+ const [intersect] = raycaster.intersectObjects(five.scene.children, true);
178
+ if (!!intersect && /^video/.test(intersect.object.name)) {
179
+ if (state.videoTexture)
180
+ setMuted(!state.videoTexture.image.muted);
181
+ return false;
182
+ }
183
+ });
184
+ five.off('panoArrived', () => {
185
+ if (!state.enabled)
186
+ return;
187
+ if (getMuted())
188
+ return;
189
+ const cameraPosition = five.camera.position;
190
+ const visible = state.rectPoints.find((points) => {
191
+ const centerVector = points.reduce((total, curr) => new THREE.Vector3(total.x + curr.x / points.length, total.y + curr.y / points.length, total.z + curr.z / points.length), new THREE.Vector3());
192
+ return (points.map((point) => new THREE.Vector3((point.x + centerVector.x) / 2, (point.y + centerVector.y) / 2, (point.z + centerVector.z) / 2)).filter((vector) => {
193
+ vector = vector.clone().sub(cameraPosition).normalize();
194
+ const raycaster = new THREE.Raycaster(cameraPosition, vector);
195
+ const [intersect] = raycaster.intersectObjects(five.scene.children, true);
196
+ return !!intersect && /^video/.test(intersect.object.name);
197
+ }).length >= 2);
198
+ });
199
+ if (!visible)
200
+ setMuted(true);
201
+ });
202
+ five.off('renderFrame', () => {
203
+ // console.log('renderFrame', state.videoMeshes)
204
+ state.videoMeshes.forEach((meshes) => {
205
+ if (meshes)
206
+ //@ts-ignore
207
+ meshes.needsRender = true;
208
+ });
209
+ });
210
+ };
211
+ five.on('modeChange', () => setMuted(true));
212
+ five.on('wantsTapGesture', (raycaster) => {
213
+ if (!state.enabled)
214
+ return;
215
+ const targetMesh = five.scene.children.find(item => /^ModelTVVideoPlugin/.test(item.name));
216
+ if (!targetMesh)
217
+ return;
218
+ const intersectObjects = raycaster.intersectObjects([targetMesh]);
219
+ if (intersectObjects.length === 0)
220
+ return;
221
+ if (state.videoTexture)
222
+ setMuted(!state.videoTexture.image.muted); // TODO toggle video play
223
+ return false;
224
+ });
225
+ five.on('panoArrived', () => {
226
+ if (!state.enabled)
227
+ return;
228
+ if (getMuted())
229
+ return;
230
+ const cameraPosition = five.camera.position;
231
+ const visible = state.rectPoints.find((points) => {
232
+ const centerVector = points.reduce((total, curr) => new THREE.Vector3(total.x + curr.x / points.length, total.y + curr.y / points.length, total.z + curr.z / points.length), new THREE.Vector3());
233
+ return (points.map((point) => new THREE.Vector3((point.x + centerVector.x) / 2, (point.y + centerVector.y) / 2, (point.z + centerVector.z) / 2)).filter((vector) => {
234
+ vector = vector.clone().sub(cameraPosition).normalize();
235
+ const raycaster = new THREE.Raycaster(cameraPosition, vector);
236
+ const [intersect] = raycaster.intersectObjects(five.scene.children, true);
237
+ return !!intersect && /^video/.test(intersect.object.name);
238
+ }).length >= 2);
239
+ });
240
+ if (!visible)
241
+ setMuted(true);
242
+ });
243
+ five.on('renderFrame', () => {
244
+ // console.log('renderFrame', state.videoMeshes)
245
+ state.videoMeshes.forEach((meshes) => {
246
+ if (meshes)
247
+ //@ts-ignore
248
+ meshes.needsRender = true;
249
+ });
250
+ });
251
+ Object.assign(window, { $state: state });
252
+ return { enable, disable, load, dispose };
253
+ };
254
+ export default ModelTVVideoPlugin;
@@ -1,4 +1,5 @@
1
- import type { FivePlugin } from '@realsee/five';
2
- import type { ModelTVVideoPluginExportType, ModelTVVideoPluginParameterType } from "./typings";
3
- export declare const ModelTVVideoPlugin: FivePlugin<ModelTVVideoPluginParameterType, ModelTVVideoPluginExportType>;
1
+ import ModelTVVideoPlugin from './Plugin';
2
+ export { ModelTVVideoPlugin };
4
3
  export default ModelTVVideoPlugin;
4
+ export type { ModelTVVideoPluginParameterType, ModelTVVideoPluginData, Point, ModelTVVideoPluginExportType } from './typings';
5
+ export { DIRECTION } from './typings';
@@ -1,254 +1,4 @@
1
- import * as THREE from 'three';
2
- import { parseModelTVVideoPoints } from "./utils/parseData";
3
- export const ModelTVVideoPlugin = (five, { videoElement }) => {
4
- const state = {
5
- videoMeshes: [],
6
- videoTextureEnabled: false,
7
- videoSource: '',
8
- rectPoints: [],
9
- enabled: false,
10
- videoElement: videoElement,
11
- };
12
- const setMuted = (muted) => {
13
- if (state.videoTexture) {
14
- state.videoTexture.image.muted = muted;
15
- state.videoTexture.image.play();
16
- }
17
- };
18
- const getMuted = () => {
19
- if (state.videoTexture)
20
- return state.videoTexture.image.muted;
21
- else
22
- return true;
23
- };
24
- const enable = () => {
25
- if (state.enabled)
26
- return;
27
- if (!state.videoTexture)
28
- return;
29
- state.enabled = true;
30
- state.videoMeshes = createPanoVideoMeshes();
31
- console.log('state.videoMeshes', state.videoMeshes);
32
- state.videoMeshes.forEach((mesh) => five.scene.add(mesh));
33
- const play = () => {
34
- console.log('play', state.videoTexture);
35
- if (!state.videoTexture)
36
- return;
37
- const timeupdate = () => {
38
- var _a;
39
- if (!state.videoTexture)
40
- return;
41
- (_a = state.videoTexture) === null || _a === void 0 ? void 0 : _a.image.removeEventListener('timeupdate', timeupdate);
42
- state.videoTextureEnabled = true;
43
- state.videoMeshes.forEach((mesh) => {
44
- if (mesh.material.map !== state.videoTexture)
45
- mesh.material.map = state.videoTexture;
46
- });
47
- five.needsRender = true;
48
- };
49
- state.videoTexture.image.addEventListener('timeupdate', timeupdate);
50
- if (state.videoTexture && state.videoMeshes.length) {
51
- state.videoTexture.image.play();
52
- }
53
- };
54
- if (five.model.loaded)
55
- play();
56
- else {
57
- return five.once('modelLoaded', () => play());
58
- }
59
- };
60
- const disable = () => {
61
- if (!state.enabled)
62
- return;
63
- state.enabled = false;
64
- state.videoMeshes.forEach((mesh) => {
65
- mesh.geometry.dispose();
66
- mesh.material.dispose();
67
- five.scene.remove(mesh);
68
- if (state.videoTexture)
69
- state.videoTexture.image.pause();
70
- });
71
- state.videoMeshes = [];
72
- five.needsRender = true;
73
- };
74
- const createPanoVideoMeshes = () => {
75
- return state.rectPoints.map((points, index) => {
76
- const geometry = new THREE.BufferGeometry();
77
- const segments = 128;
78
- const verticesArray = [];
79
- verticesArray.push(points[0].x, points[0].y, points[0].z);
80
- for (let i = 1; i < segments; i++) {
81
- verticesArray.push(points[0].x + ((points[1].x - points[0].x) * i) / segments, points[0].y + ((points[1].y - points[0].y) * i) / segments, points[0].z + ((points[1].z - points[0].z) * i) / segments);
82
- }
83
- verticesArray.push(points[1].x, points[1].y, points[1].z);
84
- verticesArray.push(points[2].x, points[2].y, points[2].z);
85
- for (let i = 1; i < segments; i++) {
86
- verticesArray.push(points[2].x + ((points[3].x - points[2].x) * i) / segments, points[2].y + ((points[3].y - points[2].y) * i) / segments, points[2].z + ((points[3].z - points[2].z) * i) / segments);
87
- }
88
- verticesArray.push(points[3].x, points[3].y, points[3].z);
89
- const uvArray = [];
90
- uvArray.push(0, 1);
91
- for (let i = 1; i < segments; i++) {
92
- uvArray.push(0, 1 - i / segments);
93
- }
94
- uvArray.push(0, 0);
95
- uvArray.push(1, 0);
96
- for (let i = 1; i < segments; i++) {
97
- uvArray.push(1, i / segments);
98
- }
99
- uvArray.push(1, 1);
100
- const indicesArray = [];
101
- for (let i = 0; i < segments; i++) {
102
- indicesArray.push(i, i + 1, segments * 2 - i, i, segments * 2 - i, segments * 2 + 1 - i);
103
- }
104
- geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(verticesArray), 3));
105
- geometry.setAttribute('uv', new THREE.BufferAttribute(new Float32Array(uvArray), 2));
106
- geometry.setIndex(new THREE.BufferAttribute(new Uint32Array(indicesArray), 1));
107
- const material = new THREE.MeshBasicMaterial({
108
- map: state.videoTextureEnabled ? state.videoTexture : state.imageTexture,
109
- side: THREE.DoubleSide,
110
- });
111
- const mesh = new THREE.Mesh(geometry, material);
112
- mesh.renderOrder = 1;
113
- mesh.name = `ModelTVVideoPlugin-${index}-${performance.now()}`;
114
- return mesh;
115
- });
116
- };
117
- const getImageTexture = (source) => {
118
- const texture = new THREE.TextureLoader().load(source);
119
- texture.minFilter = THREE.LinearFilter;
120
- texture.magFilter = THREE.LinearFilter;
121
- texture.format = THREE.RGBFormat;
122
- return texture;
123
- };
124
- const getVideoTexture = (source, video) => {
125
- return new Promise((resolve, reject) => {
126
- const xhr = new XMLHttpRequest();
127
- xhr.onreadystatechange = () => {
128
- if (xhr.readyState == 4) {
129
- if (xhr.status == 200) {
130
- const url = window.URL || window.webkitURL;
131
- video = video || document.createElement('video');
132
- video.crossOrigin = 'anonymous';
133
- video.autoplay = true;
134
- video.muted = true;
135
- video.loop = true;
136
- video.playsInline = true;
137
- video.src = url.createObjectURL(xhr.response);
138
- const texture = new THREE.VideoTexture(video);
139
- texture.minFilter = THREE.LinearFilter;
140
- texture.magFilter = THREE.LinearFilter;
141
- texture.format = THREE.RGBFormat;
142
- resolve(Object.assign(texture, { videoSource: source }));
143
- }
144
- else {
145
- reject(new Error('Video download Error: ' + xhr.status));
146
- }
147
- }
148
- };
149
- xhr.onerror = (error) => reject(error);
150
- xhr.open('GET', source);
151
- xhr.responseType = 'blob';
152
- xhr.send();
153
- });
154
- };
155
- const load = async (data, videoElement) => {
156
- const { video_src, video_poster_src, points } = data;
157
- state.videoSource = video_src;
158
- // TODO 存疑,先处理多一次遍历 o(2n)
159
- state.rectPoints = parseModelTVVideoPoints(points)
160
- .map((items) => items.map(({ x, y, z }) => new THREE.Vector3(x, y, z)));
161
- state.imageTexture = getImageTexture(video_poster_src);
162
- if (videoElement) {
163
- state.videoElement = videoElement;
164
- }
165
- state.videoTexture = await getVideoTexture(state.videoSource, state.videoElement);
166
- state.enabled = !!data.enable;
167
- if (state.enabled)
168
- enable();
169
- };
170
- const dispose = () => {
171
- disable();
172
- state.videoTexture = undefined;
173
- five.off('modeChange', () => setMuted(true));
174
- five.off('wantsTapGesture', (raycaster) => {
175
- if (!state.enabled)
176
- return;
177
- const [intersect] = raycaster.intersectObjects(five.scene.children, true);
178
- if (!!intersect && /^video/.test(intersect.object.name)) {
179
- if (state.videoTexture)
180
- setMuted(!state.videoTexture.image.muted);
181
- return false;
182
- }
183
- });
184
- five.off('panoArrived', () => {
185
- if (!state.enabled)
186
- return;
187
- if (getMuted())
188
- return;
189
- const cameraPosition = five.camera.position;
190
- const visible = state.rectPoints.find((points) => {
191
- const centerVector = points.reduce((total, curr) => new THREE.Vector3(total.x + curr.x / points.length, total.y + curr.y / points.length, total.z + curr.z / points.length), new THREE.Vector3());
192
- return (points.map((point) => new THREE.Vector3((point.x + centerVector.x) / 2, (point.y + centerVector.y) / 2, (point.z + centerVector.z) / 2)).filter((vector) => {
193
- vector = vector.clone().sub(cameraPosition).normalize();
194
- const raycaster = new THREE.Raycaster(cameraPosition, vector);
195
- const [intersect] = raycaster.intersectObjects(five.scene.children, true);
196
- return !!intersect && /^video/.test(intersect.object.name);
197
- }).length >= 2);
198
- });
199
- if (!visible)
200
- setMuted(true);
201
- });
202
- five.off('renderFrame', () => {
203
- // console.log('renderFrame', state.videoMeshes)
204
- state.videoMeshes.forEach((meshes) => {
205
- if (meshes)
206
- //@ts-ignore
207
- meshes.needsRender = true;
208
- });
209
- });
210
- };
211
- five.on('modeChange', () => setMuted(true));
212
- five.on('wantsTapGesture', (raycaster) => {
213
- if (!state.enabled)
214
- return;
215
- const targetMesh = five.scene.children.find(item => /^ModelTVVideoPlugin/.test(item.name));
216
- if (!targetMesh)
217
- return;
218
- const intersectObjects = raycaster.intersectObjects([targetMesh]);
219
- if (intersectObjects.length === 0)
220
- return;
221
- if (state.videoTexture)
222
- setMuted(!state.videoTexture.image.muted); // TODO toggle video play
223
- return false;
224
- });
225
- five.on('panoArrived', () => {
226
- if (!state.enabled)
227
- return;
228
- if (getMuted())
229
- return;
230
- const cameraPosition = five.camera.position;
231
- const visible = state.rectPoints.find((points) => {
232
- const centerVector = points.reduce((total, curr) => new THREE.Vector3(total.x + curr.x / points.length, total.y + curr.y / points.length, total.z + curr.z / points.length), new THREE.Vector3());
233
- return (points.map((point) => new THREE.Vector3((point.x + centerVector.x) / 2, (point.y + centerVector.y) / 2, (point.z + centerVector.z) / 2)).filter((vector) => {
234
- vector = vector.clone().sub(cameraPosition).normalize();
235
- const raycaster = new THREE.Raycaster(cameraPosition, vector);
236
- const [intersect] = raycaster.intersectObjects(five.scene.children, true);
237
- return !!intersect && /^video/.test(intersect.object.name);
238
- }).length >= 2);
239
- });
240
- if (!visible)
241
- setMuted(true);
242
- });
243
- five.on('renderFrame', () => {
244
- // console.log('renderFrame', state.videoMeshes)
245
- state.videoMeshes.forEach((meshes) => {
246
- if (meshes)
247
- //@ts-ignore
248
- meshes.needsRender = true;
249
- });
250
- });
251
- Object.assign(window, { $state: state });
252
- return { enable, disable, load, dispose };
253
- };
1
+ import ModelTVVideoPlugin from './Plugin';
2
+ export { ModelTVVideoPlugin };
254
3
  export default ModelTVVideoPlugin;
4
+ export { DIRECTION } from './typings';
@@ -0,0 +1,17 @@
1
+ import type { FivePlugin } from '@realsee/five';
2
+ export interface ModelViewPluginExportType {
3
+ appendTo(element: HTMLElement, size?: {
4
+ width?: number;
5
+ height?: number;
6
+ }): void;
7
+ refresh(size?: {
8
+ width?: number;
9
+ height?: number;
10
+ }): void;
11
+ }
12
+ /**
13
+ * Five 模型插件
14
+ * @template ExportType 导出方法
15
+ */
16
+ export declare const ModelViewPlugin: FivePlugin<void, ModelViewPluginExportType>;
17
+ export default ModelViewPlugin;