@realsee/dnalogel 2.0.0-alpha.26 → 2.0.0-alpha.28
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/CHANGELOG.md +6 -0
- package/dist/CSS3DRenderPlugin/Plugin.d.ts +49 -0
- package/dist/CSS3DRenderPlugin/index.d.ts +3 -48
- package/dist/CameraMovementPlugin/CameraMovementPlugin.d.ts +7 -0
- package/dist/CameraMovementPlugin/index.d.ts +4 -6
- package/dist/CameraMovementPlugin/index.js +12 -12
- package/dist/ModelChassisCompassPlugin/Plugin.d.ts +19 -0
- package/dist/ModelChassisCompassPlugin/index.d.ts +3 -18
- package/dist/ModelEntryDoorGuidePlugin/Plugin.d.ts +26 -0
- package/dist/ModelEntryDoorGuidePlugin/index.d.ts +3 -25
- package/dist/ModelEntryDoorGuidePlugin/index.js +0 -5
- package/dist/ModelItemLabelPlugin/ModelItemLabelPlugin.d.ts +4 -0
- package/dist/ModelItemLabelPlugin/index.d.ts +8 -3
- package/dist/ModelItemLabelPlugin/index.js +13 -7
- package/dist/ModelTVVideoPlugin/Plugin.d.ts +4 -0
- package/dist/ModelTVVideoPlugin/index.d.ts +4 -3
- package/dist/ModelTVVideoPlugin/index.js +3 -3
- package/dist/ModelViewPlugin/Plugin.d.ts +17 -0
- package/dist/ModelViewPlugin/index.d.ts +3 -16
- package/dist/PanoCompassPlugin/Plugin.d.ts +47 -0
- package/dist/PanoCompassPlugin/index.d.ts +4 -47
- package/dist/PanoCompassPlugin/index.js +5 -4
- package/dist/PanoMeasurePlugin/index.d.ts +1 -1
- package/dist/PanoMeasurePlugin/index.js +4 -1
- package/dist/PanoRulerPlugin/Plugin.d.ts +31 -0
- package/dist/PanoRulerPlugin/index.d.ts +4 -30
- package/dist/PanoRulerPlugin/index.js +0 -5
- package/dist/PanoSpatialTagPlugin/Plugin.d.ts +33 -0
- package/dist/PanoSpatialTagPlugin/index.d.ts +4 -32
- package/dist/PanoSpatialTagPlugin/index.js +23 -21
- package/dist/_index.d.ts +30 -0
- package/dist/floorplan/index.d.ts +6 -0
- package/dist/index.d.ts +15 -30
- package/dist/index.es.js +149 -22
- package/dist/index.js +177 -43
- package/dist/index.umd.js +180 -47
- package/docs/assets/search.js +1 -1
- package/docs/classes/ModelRoomLabelController.html +5 -8
- package/docs/classes/PanoFloorplanRadarPluginController.html +3 -0
- package/docs/enums/CameraMovementEffect.html +3 -0
- package/docs/enums/DIRECTION.html +1 -0
- package/docs/enums/DISPLAY_STRATEGY_TYPE.html +1 -0
- package/docs/enums/FLOOR_PLAN_ATTACHED_TO.html +1 -1
- package/docs/enums/ModelFloorplanErrorType.html +1 -1
- package/docs/enums/Rotation.html +3 -0
- package/docs/index.html +2 -2
- package/docs/interfaces/CSS3DRenderPluginExportType.html +4 -0
- package/docs/interfaces/CameraMovementPluginExportType.html +17 -0
- package/docs/interfaces/FloorplanBounding.html +10 -0
- package/docs/interfaces/FloorplanData.html +3 -0
- package/docs/interfaces/FloorplanEntrance.html +15 -0
- package/docs/interfaces/FloorplanExtraObject.html +7 -0
- package/docs/interfaces/FloorplanExtraObject3D.html +3 -0
- package/docs/interfaces/FloorplanFloorData.html +3 -0
- package/docs/interfaces/FloorplanImagePosition.html +3 -0
- package/docs/interfaces/FloorplanObserver.html +5 -0
- package/docs/interfaces/FloorplanOutlineItem.html +3 -0
- package/docs/interfaces/FloorplanPosition.html +3 -0
- package/docs/interfaces/FloorplanRoomItem.html +17 -0
- package/docs/interfaces/FloorplanRoomLabelItem.html +7 -0
- package/docs/interfaces/FloorplanServerBounding.html +10 -0
- package/docs/interfaces/FloorplanServerComputedData.html +1 -0
- package/docs/interfaces/FloorplanServerData.html +3 -0
- package/docs/interfaces/FloorplanServerEntrance.html +15 -0
- package/docs/interfaces/FloorplanServerFloorData.html +3 -0
- package/docs/interfaces/FloorplanServerImagePosition.html +3 -0
- package/docs/interfaces/FloorplanServerObserver.html +5 -0
- package/docs/interfaces/FloorplanServerOutlineItem.html +3 -0
- package/docs/interfaces/FloorplanServerPosition.html +3 -0
- package/docs/interfaces/FloorplanServerRoomItem.html +20 -0
- package/docs/interfaces/FloorplanServerRoomLabelItem.html +7 -0
- package/docs/interfaces/LineJson.html +1 -1
- package/docs/interfaces/ModelChassisCompassPluginData.html +1 -1
- package/docs/interfaces/ModelChassisCompassPluginExportType.html +1 -1
- package/docs/interfaces/ModelChassisCompassPluginParameterType.html +1 -1
- package/docs/interfaces/ModelEntryDoorGuidePluginData.html +1 -1
- package/docs/interfaces/ModelEntryDoorGuidePluginExportType.html +1 -1
- package/docs/interfaces/ModelFloorplanParameterType.html +1 -1
- package/docs/interfaces/ModelFloorplanViewEvent.html +3 -3
- package/docs/interfaces/ModelItemLabelPluginData.html +1 -1
- package/docs/interfaces/ModelItemLabelPluginExportReturnsType.html +1 -1
- package/docs/interfaces/ModelItemLabelPluginParametersType.html +1 -1
- package/docs/interfaces/ModelRoomLabelPluginData.html +1 -1
- package/docs/interfaces/ModelTVVideoPluginData.html +1 -1
- package/docs/interfaces/ModelTVVideoPluginExportType.html +1 -1
- package/docs/interfaces/ModelTVVideoPluginParameterType.html +1 -1
- package/docs/interfaces/ModelViewPluginExportType.html +1 -0
- package/docs/interfaces/PanoCompassPluginData.html +1 -1
- package/docs/interfaces/PanoCompassPluginParameterType.html +1 -1
- package/docs/interfaces/PanoCursorRaycasterPluginExportType.html +6 -6
- package/docs/interfaces/PanoCursorRaycasterPluginParameterType.html +1 -0
- package/docs/interfaces/PanoFloorplanRadarPluginControllerParameter.html +1 -0
- package/docs/interfaces/PanoRulerPluginExportType.html +1 -1
- package/docs/interfaces/PanoRulerPluginOptions.html +1 -1
- package/docs/interfaces/PanoRulerPluginParameterType.html +1 -1
- package/docs/interfaces/PanoSpatialTagPluginContentEvent.html +1 -0
- package/docs/interfaces/PanoSpatialTagPluginContentReplacement.html +1 -0
- package/docs/interfaces/PanoSpatialTagPluginData.html +1 -1
- package/docs/interfaces/PanoSpatialTagPluginDataElement.html +1 -0
- package/docs/interfaces/PanoSpatialTagPluginExportType.html +1 -1
- package/docs/interfaces/PanoSpatialTagPluginOriginElement.html +1 -0
- package/docs/interfaces/PanoSpatialTagPluginParameterType.html +1 -1
- package/docs/interfaces/PanoSpatialTagPluginPointElement.html +1 -0
- package/docs/interfaces/PanoSpatialTagPluginTagElement.html +1 -0
- package/docs/interfaces/Point.html +1 -0
- package/docs/interfaces/PointJson.html +1 -1
- package/docs/interfaces/Room.html +1 -0
- package/docs/interfaces/RoomInfo.html +1 -0
- package/docs/interfaces/RoomLabel.html +7 -7
- package/docs/interfaces/RoomRules.html +1 -0
- package/docs/interfaces/Rooms.html +1 -0
- package/docs/interfaces/TopviewFloorplanPluginParameterType.html +10 -10
- package/docs/modules.html +28 -12
- package/libs/CSS3DRenderPlugin/Plugin.d.ts +49 -0
- package/libs/CSS3DRenderPlugin/Plugin.js +182 -0
- package/libs/CSS3DRenderPlugin/index.d.ts +3 -48
- package/libs/CSS3DRenderPlugin/index.js +2 -181
- package/libs/CameraMovementPlugin/CameraMovementPlugin.d.ts +7 -0
- package/libs/CameraMovementPlugin/CameraMovementPlugin.js +159 -0
- package/libs/CameraMovementPlugin/index.d.ts +4 -6
- package/libs/CameraMovementPlugin/index.js +3 -158
- package/libs/ModelChassisCompassPlugin/Plugin.d.ts +19 -0
- package/libs/ModelChassisCompassPlugin/Plugin.js +75 -0
- package/libs/ModelChassisCompassPlugin/index.d.ts +3 -18
- package/libs/ModelChassisCompassPlugin/index.js +2 -74
- package/libs/ModelEntryDoorGuidePlugin/Plugin.d.ts +26 -0
- package/libs/ModelEntryDoorGuidePlugin/Plugin.js +140 -0
- package/libs/ModelEntryDoorGuidePlugin/index.d.ts +3 -25
- package/libs/ModelEntryDoorGuidePlugin/index.js +2 -139
- package/libs/ModelItemLabelPlugin/ModelItemLabelPlugin.d.ts +4 -0
- package/libs/ModelItemLabelPlugin/ModelItemLabelPlugin.js +120 -0
- package/libs/ModelItemLabelPlugin/index.d.ts +8 -3
- package/libs/ModelItemLabelPlugin/index.js +7 -119
- package/libs/ModelTVVideoPlugin/Plugin.d.ts +4 -0
- package/libs/ModelTVVideoPlugin/Plugin.js +254 -0
- package/libs/ModelTVVideoPlugin/index.d.ts +4 -3
- package/libs/ModelTVVideoPlugin/index.js +3 -253
- package/libs/ModelViewPlugin/Plugin.d.ts +17 -0
- package/libs/ModelViewPlugin/Plugin.js +160 -0
- package/libs/ModelViewPlugin/index.d.ts +3 -16
- package/libs/ModelViewPlugin/index.js +2 -159
- package/libs/PanoCompassPlugin/Plugin.d.ts +47 -0
- package/libs/PanoCompassPlugin/Plugin.js +249 -0
- package/libs/PanoCompassPlugin/index.d.ts +4 -47
- package/libs/PanoCompassPlugin/index.js +3 -249
- package/libs/PanoMeasurePlugin/index.d.ts +1 -1
- package/libs/PanoMeasurePlugin/index.js +1 -1
- package/libs/PanoRulerPlugin/Plugin.d.ts +31 -0
- package/libs/PanoRulerPlugin/Plugin.js +402 -0
- package/libs/PanoRulerPlugin/index.d.ts +4 -30
- package/libs/PanoRulerPlugin/index.js +2 -401
- package/libs/PanoSpatialTagPlugin/Plugin.d.ts +33 -0
- package/libs/PanoSpatialTagPlugin/Plugin.js +415 -0
- package/libs/PanoSpatialTagPlugin/index.d.ts +4 -32
- package/libs/PanoSpatialTagPlugin/index.js +4 -412
- package/libs/_index.d.ts +30 -0
- package/libs/_index.js +18 -0
- package/libs/floorplan/index.d.ts +6 -0
- package/libs/floorplan/index.js +7 -0
- package/libs/index.d.ts +15 -30
- package/libs/index.js +25 -17
- package/package.json +5 -4
|
@@ -1,254 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
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;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
/**
|
|
3
|
+
* Five 模型插件
|
|
4
|
+
* @template ExportType 导出方法
|
|
5
|
+
*/
|
|
6
|
+
export const ModelViewPlugin = (five) => {
|
|
7
|
+
let needsRender = true;
|
|
8
|
+
let renderer = null;
|
|
9
|
+
const scene = new THREE.Scene();
|
|
10
|
+
const camera = new THREE.PerspectiveCamera(60, 1, 0.1, 1000);
|
|
11
|
+
let model = new THREE.Object3D();
|
|
12
|
+
{
|
|
13
|
+
const light = new THREE.DirectionalLight(0xffffff, 0.5);
|
|
14
|
+
light.position.copy(new THREE.Vector3(1, 1, 1));
|
|
15
|
+
scene.add(light);
|
|
16
|
+
}
|
|
17
|
+
{
|
|
18
|
+
const light = new THREE.DirectionalLight(0xffffff, 0.3);
|
|
19
|
+
scene.add(light);
|
|
20
|
+
}
|
|
21
|
+
{
|
|
22
|
+
const light = new THREE.AmbientLight(0xffffff, 0.3);
|
|
23
|
+
scene.add(light);
|
|
24
|
+
}
|
|
25
|
+
scene.add(model);
|
|
26
|
+
const initRendererIfNeeds = () => {
|
|
27
|
+
if (!five.renderer)
|
|
28
|
+
return;
|
|
29
|
+
if (!renderer) {
|
|
30
|
+
renderer = new THREE.WebGLRenderer({ antialias: false, alpha: true });
|
|
31
|
+
renderer.setPixelRatio(five.renderer.getPixelRatio());
|
|
32
|
+
renderer.outputEncoding = THREE.sRGBEncoding;
|
|
33
|
+
renderer.setClearColor(0x181a1c, 0);
|
|
34
|
+
renderer.autoClear = true;
|
|
35
|
+
}
|
|
36
|
+
return renderer;
|
|
37
|
+
};
|
|
38
|
+
const handleModelWillLoad = () => {
|
|
39
|
+
model.traverse((object) => {
|
|
40
|
+
if (object instanceof THREE.Mesh) {
|
|
41
|
+
const materials = [].concat(object.material);
|
|
42
|
+
materials.forEach((material) => material.dispose());
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
scene.remove(model);
|
|
46
|
+
model = new THREE.Object3D();
|
|
47
|
+
scene.add(model);
|
|
48
|
+
update();
|
|
49
|
+
};
|
|
50
|
+
const handleModelLoaded = () => {
|
|
51
|
+
function cloneMaterial(material) {
|
|
52
|
+
material = material.clone();
|
|
53
|
+
material.uniforms.modelAlpha.value = 1;
|
|
54
|
+
if (material.uniforms.map.value) {
|
|
55
|
+
material.uniforms.map.value.needsUpdate = true;
|
|
56
|
+
}
|
|
57
|
+
return material;
|
|
58
|
+
}
|
|
59
|
+
function cloneModel(model) {
|
|
60
|
+
if (model instanceof THREE.Mesh) {
|
|
61
|
+
const geometry = model.geometry;
|
|
62
|
+
const material = Array.isArray(model.material)
|
|
63
|
+
? model.material.map(cloneMaterial)
|
|
64
|
+
: cloneMaterial(model.material);
|
|
65
|
+
return new THREE.Mesh(geometry, material);
|
|
66
|
+
}
|
|
67
|
+
else if (model instanceof THREE.Group) {
|
|
68
|
+
const group = new THREE.Group();
|
|
69
|
+
model.children.forEach((object) => group.add(cloneModel(object)));
|
|
70
|
+
return group;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
const object3D = new THREE.Object3D();
|
|
74
|
+
model.children.forEach((object) => object3D.add(cloneModel(object)));
|
|
75
|
+
return object3D;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
scene.remove(model);
|
|
79
|
+
model = cloneModel(five.model);
|
|
80
|
+
scene.add(model);
|
|
81
|
+
update();
|
|
82
|
+
};
|
|
83
|
+
const appendTo = (element, size = {}) => {
|
|
84
|
+
const renderer = initRendererIfNeeds();
|
|
85
|
+
if (!renderer)
|
|
86
|
+
return;
|
|
87
|
+
element.appendChild(renderer.domElement);
|
|
88
|
+
refresh(size);
|
|
89
|
+
const positionType = window.getComputedStyle(element).position;
|
|
90
|
+
if (positionType !== 'relative' &&
|
|
91
|
+
positionType !== 'absolute' &&
|
|
92
|
+
positionType !== 'fixed' &&
|
|
93
|
+
positionType !== 'sticky')
|
|
94
|
+
element.style.position = 'relative';
|
|
95
|
+
};
|
|
96
|
+
const refresh = (size = {}) => {
|
|
97
|
+
if (!renderer)
|
|
98
|
+
return;
|
|
99
|
+
const element = renderer.domElement;
|
|
100
|
+
const container = element.parentNode;
|
|
101
|
+
if (container && container.nodeName) {
|
|
102
|
+
const { width = container.offsetWidth, height = container.offsetHeight } = size;
|
|
103
|
+
renderer.setSize(width, height);
|
|
104
|
+
// 修改摄像机 aspect 比值
|
|
105
|
+
camera.aspect = width / height;
|
|
106
|
+
camera.updateProjectionMatrix();
|
|
107
|
+
}
|
|
108
|
+
update();
|
|
109
|
+
};
|
|
110
|
+
const cameraDistance = () => {
|
|
111
|
+
const bounding = five.model.bounding;
|
|
112
|
+
const { fov, aspect } = camera;
|
|
113
|
+
const radius = Math.sqrt(Math.pow(bounding.max.x - bounding.min.x + 2, 2) +
|
|
114
|
+
Math.pow(bounding.max.y - bounding.min.y + 2, 2) +
|
|
115
|
+
Math.pow(bounding.max.z - bounding.min.z + 2, 2));
|
|
116
|
+
// fit screen
|
|
117
|
+
let distance = radius / 2 / Math.tan((Math.PI * fov) / 360);
|
|
118
|
+
if (aspect < 1)
|
|
119
|
+
distance = distance / aspect;
|
|
120
|
+
return isNaN(distance) ? radius : distance;
|
|
121
|
+
};
|
|
122
|
+
const update = () => {
|
|
123
|
+
const { longitude, latitude } = five.getPose();
|
|
124
|
+
const distance = cameraDistance();
|
|
125
|
+
const lookAt = five.model.bounding.getCenter(new THREE.Vector3());
|
|
126
|
+
const longitudeDistance = distance * Math.cos(latitude);
|
|
127
|
+
const cameraPosition = new THREE.Vector3();
|
|
128
|
+
cameraPosition.x = Math.sin(longitude) * longitudeDistance + lookAt.x;
|
|
129
|
+
cameraPosition.z = Math.cos(longitude) * longitudeDistance + lookAt.z;
|
|
130
|
+
cameraPosition.y = Math.sin(latitude) * distance + lookAt.y;
|
|
131
|
+
camera.position.copy(cameraPosition);
|
|
132
|
+
camera.lookAt(lookAt);
|
|
133
|
+
needsRender = true;
|
|
134
|
+
};
|
|
135
|
+
const render = () => {
|
|
136
|
+
if (needsRender !== true)
|
|
137
|
+
return;
|
|
138
|
+
if (!renderer)
|
|
139
|
+
return;
|
|
140
|
+
if (!renderer.domElement.parentNode)
|
|
141
|
+
return;
|
|
142
|
+
const parentNode = renderer.domElement.parentNode;
|
|
143
|
+
if (parentNode.offsetWidth === 0)
|
|
144
|
+
return;
|
|
145
|
+
renderer.render(scene, camera);
|
|
146
|
+
needsRender = false;
|
|
147
|
+
};
|
|
148
|
+
const dispose = () => {
|
|
149
|
+
if (renderer)
|
|
150
|
+
renderer.dispose();
|
|
151
|
+
renderer = null;
|
|
152
|
+
};
|
|
153
|
+
five.on('modelLoaded', handleModelLoaded);
|
|
154
|
+
five.on('modelWillLoad', handleModelWillLoad);
|
|
155
|
+
five.on('cameraDirectionUpdate', update);
|
|
156
|
+
five.on('dispose', dispose);
|
|
157
|
+
five.on('renderFrame', render);
|
|
158
|
+
return { appendTo, refresh };
|
|
159
|
+
};
|
|
160
|
+
export default ModelViewPlugin;
|
|
@@ -1,17 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
export
|
|
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>;
|
|
1
|
+
import ModelViewPlugin from './Plugin';
|
|
2
|
+
export { ModelViewPlugin };
|
|
17
3
|
export default ModelViewPlugin;
|
|
4
|
+
export type { ModelViewPluginExportType } from './Plugin';
|
|
@@ -1,160 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
* Five 模型插件
|
|
4
|
-
* @template ExportType 导出方法
|
|
5
|
-
*/
|
|
6
|
-
export const ModelViewPlugin = (five) => {
|
|
7
|
-
let needsRender = true;
|
|
8
|
-
let renderer = null;
|
|
9
|
-
const scene = new THREE.Scene();
|
|
10
|
-
const camera = new THREE.PerspectiveCamera(60, 1, 0.1, 1000);
|
|
11
|
-
let model = new THREE.Object3D();
|
|
12
|
-
{
|
|
13
|
-
const light = new THREE.DirectionalLight(0xffffff, 0.5);
|
|
14
|
-
light.position.copy(new THREE.Vector3(1, 1, 1));
|
|
15
|
-
scene.add(light);
|
|
16
|
-
}
|
|
17
|
-
{
|
|
18
|
-
const light = new THREE.DirectionalLight(0xffffff, 0.3);
|
|
19
|
-
scene.add(light);
|
|
20
|
-
}
|
|
21
|
-
{
|
|
22
|
-
const light = new THREE.AmbientLight(0xffffff, 0.3);
|
|
23
|
-
scene.add(light);
|
|
24
|
-
}
|
|
25
|
-
scene.add(model);
|
|
26
|
-
const initRendererIfNeeds = () => {
|
|
27
|
-
if (!five.renderer)
|
|
28
|
-
return;
|
|
29
|
-
if (!renderer) {
|
|
30
|
-
renderer = new THREE.WebGLRenderer({ antialias: false, alpha: true });
|
|
31
|
-
renderer.setPixelRatio(five.renderer.getPixelRatio());
|
|
32
|
-
renderer.outputEncoding = THREE.sRGBEncoding;
|
|
33
|
-
renderer.setClearColor(0x181a1c, 0);
|
|
34
|
-
renderer.autoClear = true;
|
|
35
|
-
}
|
|
36
|
-
return renderer;
|
|
37
|
-
};
|
|
38
|
-
const handleModelWillLoad = () => {
|
|
39
|
-
model.traverse((object) => {
|
|
40
|
-
if (object instanceof THREE.Mesh) {
|
|
41
|
-
const materials = [].concat(object.material);
|
|
42
|
-
materials.forEach((material) => material.dispose());
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
scene.remove(model);
|
|
46
|
-
model = new THREE.Object3D();
|
|
47
|
-
scene.add(model);
|
|
48
|
-
update();
|
|
49
|
-
};
|
|
50
|
-
const handleModelLoaded = () => {
|
|
51
|
-
function cloneMaterial(material) {
|
|
52
|
-
material = material.clone();
|
|
53
|
-
material.uniforms.modelAlpha.value = 1;
|
|
54
|
-
if (material.uniforms.map.value) {
|
|
55
|
-
material.uniforms.map.value.needsUpdate = true;
|
|
56
|
-
}
|
|
57
|
-
return material;
|
|
58
|
-
}
|
|
59
|
-
function cloneModel(model) {
|
|
60
|
-
if (model instanceof THREE.Mesh) {
|
|
61
|
-
const geometry = model.geometry;
|
|
62
|
-
const material = Array.isArray(model.material)
|
|
63
|
-
? model.material.map(cloneMaterial)
|
|
64
|
-
: cloneMaterial(model.material);
|
|
65
|
-
return new THREE.Mesh(geometry, material);
|
|
66
|
-
}
|
|
67
|
-
else if (model instanceof THREE.Group) {
|
|
68
|
-
const group = new THREE.Group();
|
|
69
|
-
model.children.forEach((object) => group.add(cloneModel(object)));
|
|
70
|
-
return group;
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
const object3D = new THREE.Object3D();
|
|
74
|
-
model.children.forEach((object) => object3D.add(cloneModel(object)));
|
|
75
|
-
return object3D;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
scene.remove(model);
|
|
79
|
-
model = cloneModel(five.model);
|
|
80
|
-
scene.add(model);
|
|
81
|
-
update();
|
|
82
|
-
};
|
|
83
|
-
const appendTo = (element, size = {}) => {
|
|
84
|
-
const renderer = initRendererIfNeeds();
|
|
85
|
-
if (!renderer)
|
|
86
|
-
return;
|
|
87
|
-
element.appendChild(renderer.domElement);
|
|
88
|
-
refresh(size);
|
|
89
|
-
const positionType = window.getComputedStyle(element).position;
|
|
90
|
-
if (positionType !== 'relative' &&
|
|
91
|
-
positionType !== 'absolute' &&
|
|
92
|
-
positionType !== 'fixed' &&
|
|
93
|
-
positionType !== 'sticky')
|
|
94
|
-
element.style.position = 'relative';
|
|
95
|
-
};
|
|
96
|
-
const refresh = (size = {}) => {
|
|
97
|
-
if (!renderer)
|
|
98
|
-
return;
|
|
99
|
-
const element = renderer.domElement;
|
|
100
|
-
const container = element.parentNode;
|
|
101
|
-
if (container && container.nodeName) {
|
|
102
|
-
const { width = container.offsetWidth, height = container.offsetHeight } = size;
|
|
103
|
-
renderer.setSize(width, height);
|
|
104
|
-
// 修改摄像机 aspect 比值
|
|
105
|
-
camera.aspect = width / height;
|
|
106
|
-
camera.updateProjectionMatrix();
|
|
107
|
-
}
|
|
108
|
-
update();
|
|
109
|
-
};
|
|
110
|
-
const cameraDistance = () => {
|
|
111
|
-
const bounding = five.model.bounding;
|
|
112
|
-
const { fov, aspect } = camera;
|
|
113
|
-
const radius = Math.sqrt(Math.pow(bounding.max.x - bounding.min.x + 2, 2) +
|
|
114
|
-
Math.pow(bounding.max.y - bounding.min.y + 2, 2) +
|
|
115
|
-
Math.pow(bounding.max.z - bounding.min.z + 2, 2));
|
|
116
|
-
// fit screen
|
|
117
|
-
let distance = radius / 2 / Math.tan((Math.PI * fov) / 360);
|
|
118
|
-
if (aspect < 1)
|
|
119
|
-
distance = distance / aspect;
|
|
120
|
-
return isNaN(distance) ? radius : distance;
|
|
121
|
-
};
|
|
122
|
-
const update = () => {
|
|
123
|
-
const { longitude, latitude } = five.getPose();
|
|
124
|
-
const distance = cameraDistance();
|
|
125
|
-
const lookAt = five.model.bounding.getCenter(new THREE.Vector3());
|
|
126
|
-
const longitudeDistance = distance * Math.cos(latitude);
|
|
127
|
-
const cameraPosition = new THREE.Vector3();
|
|
128
|
-
cameraPosition.x = Math.sin(longitude) * longitudeDistance + lookAt.x;
|
|
129
|
-
cameraPosition.z = Math.cos(longitude) * longitudeDistance + lookAt.z;
|
|
130
|
-
cameraPosition.y = Math.sin(latitude) * distance + lookAt.y;
|
|
131
|
-
camera.position.copy(cameraPosition);
|
|
132
|
-
camera.lookAt(lookAt);
|
|
133
|
-
needsRender = true;
|
|
134
|
-
};
|
|
135
|
-
const render = () => {
|
|
136
|
-
if (needsRender !== true)
|
|
137
|
-
return;
|
|
138
|
-
if (!renderer)
|
|
139
|
-
return;
|
|
140
|
-
if (!renderer.domElement.parentNode)
|
|
141
|
-
return;
|
|
142
|
-
const parentNode = renderer.domElement.parentNode;
|
|
143
|
-
if (parentNode.offsetWidth === 0)
|
|
144
|
-
return;
|
|
145
|
-
renderer.render(scene, camera);
|
|
146
|
-
needsRender = false;
|
|
147
|
-
};
|
|
148
|
-
const dispose = () => {
|
|
149
|
-
if (renderer)
|
|
150
|
-
renderer.dispose();
|
|
151
|
-
renderer = null;
|
|
152
|
-
};
|
|
153
|
-
five.on('modelLoaded', handleModelLoaded);
|
|
154
|
-
five.on('modelWillLoad', handleModelWillLoad);
|
|
155
|
-
five.on('cameraDirectionUpdate', update);
|
|
156
|
-
five.on('dispose', dispose);
|
|
157
|
-
five.on('renderFrame', render);
|
|
158
|
-
return { appendTo, refresh };
|
|
159
|
-
};
|
|
1
|
+
import ModelViewPlugin from './Plugin';
|
|
2
|
+
export { ModelViewPlugin };
|
|
160
3
|
export default ModelViewPlugin;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Five, FivePlugin } from '@realsee/five';
|
|
2
|
+
import type { FloorplanServerRoomItem } from '../floorplan/typings/floorplanServerData';
|
|
3
|
+
export interface PanoCompassPluginParameterType {
|
|
4
|
+
compassImageUrl?: string;
|
|
5
|
+
entryDoorImageUrl?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface PanoCompassPluginData {
|
|
8
|
+
north_rad: null | number;
|
|
9
|
+
entrance: null | undefined | {
|
|
10
|
+
position: {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
z: number;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
room_observers: undefined | {
|
|
17
|
+
index: number;
|
|
18
|
+
floor_index: number;
|
|
19
|
+
room: FloorplanServerRoomItem;
|
|
20
|
+
}[];
|
|
21
|
+
}
|
|
22
|
+
export declare type PanoCompassPluginExportType = PanoCompassController;
|
|
23
|
+
export declare const PanoCompassPlugin: FivePlugin<PanoCompassPluginParameterType | undefined, PanoCompassController>;
|
|
24
|
+
export default PanoCompassPlugin;
|
|
25
|
+
declare class PanoCompassController {
|
|
26
|
+
five: Five;
|
|
27
|
+
data?: PanoCompassPluginData;
|
|
28
|
+
config?: PanoCompassPluginParameterType;
|
|
29
|
+
private group;
|
|
30
|
+
private modelLoaded;
|
|
31
|
+
private roomInfoInstance?;
|
|
32
|
+
private roomInfoWrapperInstance?;
|
|
33
|
+
private compassMeshTween?;
|
|
34
|
+
private compassMesh?;
|
|
35
|
+
private entryDoorMesh?;
|
|
36
|
+
constructor(five: Five, config?: PanoCompassPluginParameterType);
|
|
37
|
+
load(data: PanoCompassPluginData): void;
|
|
38
|
+
dispose: () => void;
|
|
39
|
+
private onFiveFistPanoLoaded;
|
|
40
|
+
private init;
|
|
41
|
+
private loadCompassMesh;
|
|
42
|
+
private loadEntryDoorMesh;
|
|
43
|
+
private loadRoomInfo;
|
|
44
|
+
private onFivePanoWillArrive;
|
|
45
|
+
private onFivePanoArrived;
|
|
46
|
+
private onFiveCameraDirectionUpdate;
|
|
47
|
+
}
|