@realsee/dnalogel 2.0.0-alpha.34 → 2.0.0-alpha.35
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/dist/PanoSpatialTagPlugin/Plugin.d.ts +2 -0
- package/dist/PanoSpatialTagPlugin/index.js +57 -48
- package/dist/index.es.js +57 -48
- package/dist/index.js +57 -48
- package/dist/index.umd.js +57 -48
- package/docs/assets/search.js +1 -1
- package/docs/classes/Magnifier.html +4 -4
- package/docs/classes/ModelRoomLabelController.html +4 -4
- package/docs/classes/PanoFloorplanRadarPluginController.html +2 -2
- package/docs/enums/CameraMovementEffect.html +2 -2
- package/docs/enums/DIRECTION.html +1 -1
- package/docs/enums/DISPLAY_STRATEGY_TYPE.html +1 -1
- package/docs/enums/FLOOR_PLAN_ATTACHED_TO.html +1 -1
- package/docs/enums/ITEM_LABEL_PLUGIN_DISPLAY_STRATEGY_TYPE.html +1 -1
- package/docs/enums/ModelFloorplanErrorType.html +1 -1
- package/docs/enums/Rotation.html +2 -2
- package/docs/index.html +1 -1
- package/docs/interfaces/CSS3DRenderPluginExportType.html +2 -2
- package/docs/interfaces/CameraMovementPluginExportType.html +2 -2
- package/docs/interfaces/FloorplanBounding.html +4 -4
- package/docs/interfaces/FloorplanData.html +2 -2
- package/docs/interfaces/FloorplanEntrance.html +7 -7
- package/docs/interfaces/FloorplanExtraObject.html +3 -3
- package/docs/interfaces/FloorplanExtraObject3D.html +2 -2
- package/docs/interfaces/FloorplanFloorData.html +2 -2
- package/docs/interfaces/FloorplanImagePosition.html +2 -2
- package/docs/interfaces/FloorplanObserver.html +2 -2
- package/docs/interfaces/FloorplanOutlineItem.html +2 -2
- package/docs/interfaces/FloorplanPosition.html +2 -2
- package/docs/interfaces/FloorplanRoomItem.html +6 -6
- package/docs/interfaces/FloorplanRoomLabelItem.html +3 -3
- package/docs/interfaces/FloorplanServerBounding.html +4 -4
- package/docs/interfaces/FloorplanServerComputedData.html +1 -1
- package/docs/interfaces/FloorplanServerData.html +2 -2
- package/docs/interfaces/FloorplanServerEntrance.html +7 -7
- package/docs/interfaces/FloorplanServerFloorData.html +2 -2
- package/docs/interfaces/FloorplanServerImagePosition.html +2 -2
- package/docs/interfaces/FloorplanServerObserver.html +2 -2
- package/docs/interfaces/FloorplanServerOutlineItem.html +2 -2
- package/docs/interfaces/FloorplanServerPosition.html +2 -2
- package/docs/interfaces/FloorplanServerRoomItem.html +7 -7
- package/docs/interfaces/FloorplanServerRoomLabelItem.html +3 -3
- package/docs/interfaces/ItemLabelPluginData.html +1 -1
- package/docs/interfaces/ItemLabelPluginExportReturnsType.html +1 -1
- package/docs/interfaces/ItemLabelPluginParametersType.html +1 -1
- 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 +2 -2
- 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 -1
- package/docs/interfaces/OpenParameter.html +2 -2
- 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 -1
- package/docs/interfaces/PanoFloorplanRadarPluginControllerParameter.html +1 -1
- package/docs/interfaces/PanoMeasureParameterType.html +1 -1
- 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 -1
- package/docs/interfaces/PanoSpatialTagPluginContentReplacement.html +1 -1
- package/docs/interfaces/PanoSpatialTagPluginData.html +1 -1
- package/docs/interfaces/PanoSpatialTagPluginDataElement.html +1 -1
- package/docs/interfaces/PanoSpatialTagPluginExportType.html +1 -1
- package/docs/interfaces/PanoSpatialTagPluginOriginElement.html +1 -1
- package/docs/interfaces/PanoSpatialTagPluginParameterType.html +1 -1
- package/docs/interfaces/PanoSpatialTagPluginPointElement.html +1 -1
- package/docs/interfaces/PanoSpatialTagPluginTagElement.html +1 -1
- package/docs/interfaces/Point.html +1 -1
- package/docs/interfaces/PointJson.html +1 -1
- package/docs/interfaces/Room.html +1 -1
- package/docs/interfaces/RoomInfo.html +1 -1
- package/docs/interfaces/RoomLabel.html +7 -7
- package/docs/interfaces/RoomRules.html +1 -1
- package/docs/interfaces/Rooms.html +1 -1
- package/docs/interfaces/TopviewFloorplanPluginParameterType.html +9 -9
- package/docs/modules.html +20 -20
- package/libs/ModelSimulationPlugin/index.d.ts +33 -0
- package/libs/ModelSimulationPlugin/index.js +166 -0
- package/libs/ModelSimulationPlugin/shaders/fragment.d.ts +2 -0
- package/libs/ModelSimulationPlugin/shaders/fragment.js +96 -0
- package/libs/ModelSimulationPlugin/shaders/vertex.d.ts +2 -0
- package/libs/ModelSimulationPlugin/shaders/vertex.js +23 -0
- package/libs/PanoSpatialTagPlugin/Components/tag.js +2 -2
- package/libs/PanoSpatialTagPlugin/Plugin.d.ts +2 -0
- package/libs/PanoSpatialTagPlugin/Plugin.js +55 -46
- package/libs/floorplan/ModelFloorplanPlugin/Assets/compass.d.ts +1 -0
- package/libs/floorplan/ModelFloorplanPlugin/Assets/compass.js +1 -0
- package/libs/floorplan/ModelFloorplanPlugin/Components/Camera.js +120 -0
- package/libs/floorplan/ModelFloorplanPlugin/Components/Compass.js +106 -0
- package/libs/floorplan/ModelFloorplanPlugin/Components/CurrentFloor/CurrentFloor.js +463 -0
- package/libs/floorplan/ModelFloorplanPlugin/Components/Main.js +375 -0
- package/libs/floorplan/ModelFloorplanPlugin/Components/RoomLabels/RoomLabel.js +171 -0
- package/libs/floorplan/ModelFloorplanPlugin/Components/RoomLabels/RoomLabels.js +265 -0
- package/libs/floorplan/ModelFloorplanPlugin/Components/RuleLabels/RuleItem.js +301 -0
- package/libs/floorplan/ModelFloorplanPlugin/Components/RuleLabels/RuleLabels.js +219 -0
- package/libs/shared-utils/five/useFivePlugin.d.ts +1 -0
- package/libs/shared-utils/five/useFivePlugin.js +8 -0
- package/libs/shared-utils/useDebounce.d.ts +8 -0
- package/libs/shared-utils/useDebounce.js +22 -0
- package/libs/shared-utils/useThrottle.d.ts +8 -0
- package/libs/shared-utils/useThrottle.js +25 -0
- package/package.json +1 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { FivePlugin } from '@realsee/five';
|
|
2
|
+
export interface ModelSimulationPluginExportType {
|
|
3
|
+
enable: () => void;
|
|
4
|
+
disable: () => void;
|
|
5
|
+
play: () => void;
|
|
6
|
+
dispose: () => void;
|
|
7
|
+
init: () => void;
|
|
8
|
+
}
|
|
9
|
+
export interface ModelSimulationPluginParameterType {
|
|
10
|
+
simulationWorkData: ModelSimulationPluginWorkDataType;
|
|
11
|
+
simulationOptions: ModelSimulationPluginOptionsType;
|
|
12
|
+
}
|
|
13
|
+
export interface ModelSimulationPluginWorkDataType {
|
|
14
|
+
resourceUrl: string;
|
|
15
|
+
colorMapPath: string;
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
depth: number;
|
|
19
|
+
origin: number[];
|
|
20
|
+
step: number;
|
|
21
|
+
maxT: number;
|
|
22
|
+
minT: number;
|
|
23
|
+
maxKeyframes: number;
|
|
24
|
+
houseHeight: number;
|
|
25
|
+
}
|
|
26
|
+
export interface ModelSimulationPluginOptionsType {
|
|
27
|
+
globalOpacity: number;
|
|
28
|
+
boundingOpacity: number;
|
|
29
|
+
boundingOffset?: number;
|
|
30
|
+
keyFrameRate?: number;
|
|
31
|
+
}
|
|
32
|
+
declare const ModelSimulationPlugin: FivePlugin<ModelSimulationPluginParameterType, ModelSimulationPluginExportType>;
|
|
33
|
+
export default ModelSimulationPlugin;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import vertexShader from './shaders/vertex';
|
|
3
|
+
import fragmentShader from './shaders/fragment';
|
|
4
|
+
import tap from '../shared-utils/tap';
|
|
5
|
+
const houseOutLinePath = [
|
|
6
|
+
[-3.089, -4.219], [-4.834, -4.219],
|
|
7
|
+
[-8.197, -4.219], [-10.31, -4.219],
|
|
8
|
+
[-10.31, -1.002], [-10.31, 0.835],
|
|
9
|
+
[-10.31, 3.927], [-11.237, 3.927],
|
|
10
|
+
[-11.237, 5.45], [-8.104, 5.45],
|
|
11
|
+
[-8.104, 4.557], [-6.914, 4.557],
|
|
12
|
+
[-6.244, 4.557], [-6.244, 5.436],
|
|
13
|
+
[-3.78, 5.436], [-0.356, 5.436],
|
|
14
|
+
[0.286, 5.436], [0.286, 4.073],
|
|
15
|
+
[0.286, 0.395], [2.31, 0.395],
|
|
16
|
+
[2.31, -1.323], [2.31, -4.199],
|
|
17
|
+
[0.468, -4.199], [0.468, -3.547],
|
|
18
|
+
[-2.969, -3.547], [-3.089, -3.547]
|
|
19
|
+
];
|
|
20
|
+
const defaultKeyframes = 50;
|
|
21
|
+
const defaultBoundingOffset = 0.2;
|
|
22
|
+
let isTexutreReady = false;
|
|
23
|
+
const ModelSimulationPlugin = (five, options) => {
|
|
24
|
+
let heatTexutres = [];
|
|
25
|
+
let geometryTexture = null;
|
|
26
|
+
let simulationMaterial = null;
|
|
27
|
+
let boundingMaterial = null;
|
|
28
|
+
let boundingMesh = null;
|
|
29
|
+
let originMaterial = null;
|
|
30
|
+
const enable = () => {
|
|
31
|
+
};
|
|
32
|
+
const disable = () => {
|
|
33
|
+
five.model.setMaterial(originMaterial);
|
|
34
|
+
};
|
|
35
|
+
const createBounding = (path, material) => {
|
|
36
|
+
const shape = tap(new THREE.Shape(), shape => {
|
|
37
|
+
shape.moveTo(path[path.length - 1][0], path[path.length - 1][1]);
|
|
38
|
+
path.forEach(xz => shape.lineTo(xz[0], xz[1]));
|
|
39
|
+
});
|
|
40
|
+
const settings = {
|
|
41
|
+
depth: options.simulationWorkData.houseHeight + 2 * options.simulationOptions.boundingOffset ?? defaultBoundingOffset,
|
|
42
|
+
bevelEnabled: false,
|
|
43
|
+
};
|
|
44
|
+
const geometry = new THREE.ExtrudeGeometry(shape, settings);
|
|
45
|
+
boundingMesh = new THREE.Mesh(geometry, material);
|
|
46
|
+
boundingMesh.rotateX(Math.PI / 2);
|
|
47
|
+
boundingMesh.translateZ(-options.simulationWorkData.houseHeight - options.simulationOptions.boundingOffset);
|
|
48
|
+
boundingMesh.updateMatrix();
|
|
49
|
+
boundingMesh.updateMatrixWorld();
|
|
50
|
+
return boundingMesh;
|
|
51
|
+
};
|
|
52
|
+
const createSimulationMaterial = (isBounding) => {
|
|
53
|
+
const simulationMaterial = new THREE.RawShaderMaterial({
|
|
54
|
+
uniforms: {
|
|
55
|
+
heatMap: { value: new THREE.Texture() },
|
|
56
|
+
geometryMap: { value: new THREE.Texture() },
|
|
57
|
+
colorMap: { value: new THREE.TextureLoader().load(options.simulationWorkData.colorMapPath) },
|
|
58
|
+
bboxMin: { value: new THREE.Vector3().fromArray(options.simulationWorkData.origin) },
|
|
59
|
+
bboxMax: { value: new THREE.Vector3().fromArray(options.simulationWorkData.origin).add(new THREE.Vector3(options.simulationWorkData.width, options.simulationWorkData.height, options.simulationWorkData.depth).multiplyScalar(options.simulationWorkData.step)) },
|
|
60
|
+
step: { value: options.simulationWorkData.step },
|
|
61
|
+
maxT: { value: options.simulationWorkData.maxT },
|
|
62
|
+
minT: { value: options.simulationWorkData.minT },
|
|
63
|
+
opacity: { value: isBounding ? options.simulationOptions.boundingOpacity : options.simulationOptions.globalOpacity }
|
|
64
|
+
},
|
|
65
|
+
vertexShader,
|
|
66
|
+
fragmentShader,
|
|
67
|
+
});
|
|
68
|
+
if (isBounding)
|
|
69
|
+
simulationMaterial.transparent = true;
|
|
70
|
+
return simulationMaterial;
|
|
71
|
+
};
|
|
72
|
+
const create3DTextureTask = (url) => {
|
|
73
|
+
return fetch(url)
|
|
74
|
+
.then(res => {
|
|
75
|
+
return res.arrayBuffer();
|
|
76
|
+
})
|
|
77
|
+
.then(res => {
|
|
78
|
+
const texture = new THREE.DataTexture3D(new Float32Array(res), options.simulationWorkData.width, options.simulationWorkData.height, options.simulationWorkData.depth);
|
|
79
|
+
texture.type = THREE.FloatType;
|
|
80
|
+
texture.format = THREE.RedFormat;
|
|
81
|
+
texture.minFilter = THREE.LinearMipmapLinearFilter;
|
|
82
|
+
texture.magFilter = THREE.LinearFilter;
|
|
83
|
+
texture.generateMipmaps = true;
|
|
84
|
+
texture.unpackAlignment = 1;
|
|
85
|
+
return texture;
|
|
86
|
+
})
|
|
87
|
+
.catch(err => console.error("拉取三维纹理数据时发生错误"));
|
|
88
|
+
};
|
|
89
|
+
const init = () => {
|
|
90
|
+
simulationMaterial = createSimulationMaterial(false);
|
|
91
|
+
boundingMaterial = createSimulationMaterial(true);
|
|
92
|
+
//加载外bounding
|
|
93
|
+
five.scene.add(createBounding(houseOutLinePath, boundingMaterial));
|
|
94
|
+
//缓存原来的材质
|
|
95
|
+
originMaterial = five.model.getMaterial();
|
|
96
|
+
five.model.traverse(obj => {
|
|
97
|
+
if (!(obj instanceof THREE.Mesh))
|
|
98
|
+
return;
|
|
99
|
+
if (Array.isArray(obj.material)) {
|
|
100
|
+
obj.material = obj.material.map(_mtl => simulationMaterial);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
obj.material = simulationMaterial;
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
//温度数据
|
|
107
|
+
// const geometryTaskUrl = options.resourceUrl + 'geometry.vti'
|
|
108
|
+
const heatTextureTasks = [];
|
|
109
|
+
for (let i = 0; i < options.simulationWorkData.maxKeyframes; i++) {
|
|
110
|
+
const fileUrl = options.simulationWorkData.resourceUrl + i + '.vti';
|
|
111
|
+
heatTextureTasks.push(create3DTextureTask(fileUrl));
|
|
112
|
+
}
|
|
113
|
+
// //有效值数据
|
|
114
|
+
// create3DTextureTask(geometryTaskUrl)
|
|
115
|
+
// .then(texture => {
|
|
116
|
+
// simulationMaterial.uniforms.geometryMap.value = texture
|
|
117
|
+
// boundingMaterial.uniforms.geometryMap.value = texture
|
|
118
|
+
// })
|
|
119
|
+
// .catch(err => console.error("geometry texture loading failed"))
|
|
120
|
+
//加载首帧进行初始化
|
|
121
|
+
create3DTextureTask(options.simulationWorkData.resourceUrl + '0.vti')
|
|
122
|
+
.then(texture => {
|
|
123
|
+
simulationMaterial.uniforms.heatMap.value = texture;
|
|
124
|
+
boundingMaterial.uniforms.heatMap.value = texture;
|
|
125
|
+
five.needsRender = true;
|
|
126
|
+
})
|
|
127
|
+
.catch(err => console.error("loading textures failed"));
|
|
128
|
+
//加载全部
|
|
129
|
+
Promise.all(heatTextureTasks)
|
|
130
|
+
.then(textures => {
|
|
131
|
+
//缓存结果
|
|
132
|
+
isTexutreReady = true;
|
|
133
|
+
console.log("ready");
|
|
134
|
+
heatTexutres = textures;
|
|
135
|
+
})
|
|
136
|
+
.catch(err => console.error("loading textures failed"));
|
|
137
|
+
};
|
|
138
|
+
const play = () => {
|
|
139
|
+
if (!isTexutreReady)
|
|
140
|
+
throw new Error("textures are not ready yet,plz try again later");
|
|
141
|
+
let timeCount = 0;
|
|
142
|
+
const stop = setInterval(() => {
|
|
143
|
+
if (timeCount < options.simulationWorkData.maxKeyframes) {
|
|
144
|
+
simulationMaterial.uniforms.heatMap.value = heatTexutres[timeCount];
|
|
145
|
+
boundingMaterial.uniforms.heatMap.value = heatTexutres[timeCount];
|
|
146
|
+
timeCount++;
|
|
147
|
+
five.needsRender = true;
|
|
148
|
+
}
|
|
149
|
+
}, 1000 / options.simulationOptions.keyFrameRate ?? defaultKeyframes);
|
|
150
|
+
};
|
|
151
|
+
const dispose = () => {
|
|
152
|
+
simulationMaterial.dispose();
|
|
153
|
+
boundingMaterial.dispose();
|
|
154
|
+
boundingMesh.geometry.dispose();
|
|
155
|
+
geometryTexture.dispose();
|
|
156
|
+
heatTexutres.forEach(texture => texture.dispose());
|
|
157
|
+
};
|
|
158
|
+
return {
|
|
159
|
+
enable,
|
|
160
|
+
disable,
|
|
161
|
+
play,
|
|
162
|
+
init,
|
|
163
|
+
dispose
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
export default ModelSimulationPlugin;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare var _default: "#version 300 es\n#define MAX_STEPS 50\nprecision highp float;\nprecision highp sampler3D;\n\nuniform sampler3D heatMap;\nuniform sampler3D geometryMap;\nuniform sampler2D colorMap;\n\nuniform vec3 bboxMin;\nuniform vec3 bboxMax;\nuniform float step;\nuniform float minT;\nuniform float maxT;\nuniform float opacity;\n\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 linearToOutputTexel( vec4 value ) { return LinearTosRGB( value ); }\n\n\nfloat getHeatByLegalPos(vec3 pos){\n\tfloat geometryFactor = texture(geometryMap,pos).r;\n\tfloat legalFactor = clamp(geometryFactor,0.0,1.0);\n\treturn texture(heatMap,pos).r * legalFactor;\n}\n\nfloat sampleOc(vec3 pos){\n\t//平滑滤波步长\n\t//todo:可以作为define传入的外部常量还是直接传\n\tfloat step_x = step / (bboxMax.x - bboxMin.x) * 0.5;\n\tfloat step_y = step / (bboxMax.y - bboxMin.y) * 0.5;\n\tfloat step_z = step / (bboxMax.z - bboxMin.z) * 0.5;\n\tvec3 p1 = pos + vec3(step_x,step_y,step_z);\n\tvec3 p2 = pos + vec3(step_x,-step_y,step_z);\n\tvec3 p3 = pos + vec3(step_x,step_y,-step_z);\n\tvec3 p4 = pos + vec3(step_x,-step_y,-step_z);\n\tvec3 p5 = pos + vec3(-step_x,step_y,step_z);\n\tvec3 p6 = pos + vec3(-step_x,-step_y,step_z);\n\tvec3 p7 = pos + vec3(-step_x,step_y,-step_z);\n\tvec3 p8 = pos + vec3(-step_x,-step_y,-step_z);\n\n\treturn (getHeatByLegalPos(p1) + getHeatByLegalPos(p2) + getHeatByLegalPos(p3) + getHeatByLegalPos(p4) + getHeatByLegalPos(p5) + getHeatByLegalPos(p6) + getHeatByLegalPos(p7) + getHeatByLegalPos(p8)) * 0.125;\n\n}\n\n//考虑到有效仿真值连通域在三维空间中是封闭流形,这里直接按照normal方向搜索,牺牲一定精度,以保证展示效果\nfloat sampleByNormal(vec3 normal, vec3 pos){\n\tfloat searchStep = step ;\n\tvec3 currentPos = pos;\n\tfor (int iter=0; iter < MAX_STEPS; iter++) {\n\t\tif(iter >= MAX_STEPS){\n\t\t\treturn texture(heatMap,currentPos).r;\n\t\t}\n\t\tif(texture(geometryMap,currentPos).r < 0.5){\n\t\t\tcurrentPos += normal * searchStep;\n\t\t}else{\n\t\t\treturn texture(heatMap,currentPos).r;\n\t\t}\n\t}\n}\n\nfloat sample1(vec3 normal, vec3 pos){\n\treturn texture(heatMap,pos).r;\n}\n\nin vec2 vUv;\nin vec3 vPosition;\nin vec3 vNormal;\nout highp vec4 pc_fragColor;\n\n\nfloat normalizeHeat(float t){\n\tfloat _t = clamp(t,minT,maxT);\n\treturn (_t - minT)/(maxT - minT);\n}\n\nvec3 posToTexCood(vec3 pos){\n\tfloat x = (pos.x - bboxMin.x) / (bboxMax.x - bboxMin.x);\n\tfloat y = (pos.y - bboxMin.y) / (bboxMax.y - bboxMin.y);\n\tfloat z = (pos.z - bboxMin.z) / (bboxMax.z - bboxMin.z);\n\treturn vec3(x,y,z);\n}\n\n\nvoid main() {\n\tvec3 texCood = posToTexCood(vPosition);\n\t// float color = sampleByNormal(vNormal,texCood);\n\tfloat color = sample1(vNormal,texCood);\n\tfloat normalColor= normalizeHeat(color);\n\tvec4 colorMapColor = texture(colorMap,vec2(normalColor,0.2));\n\tpc_fragColor = vec4(colorMapColor.xyz,opacity);\n\t// pc_fragColor = linearToOutputTexel(vec4(colorMapColor.xyz,opacity));\n\t}\n";
|
|
2
|
+
export default _default;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export default `#version 300 es
|
|
2
|
+
#define MAX_STEPS 50
|
|
3
|
+
precision highp float;
|
|
4
|
+
precision highp sampler3D;
|
|
5
|
+
|
|
6
|
+
uniform sampler3D heatMap;
|
|
7
|
+
uniform sampler3D geometryMap;
|
|
8
|
+
uniform sampler2D colorMap;
|
|
9
|
+
|
|
10
|
+
uniform vec3 bboxMin;
|
|
11
|
+
uniform vec3 bboxMax;
|
|
12
|
+
uniform float step;
|
|
13
|
+
uniform float minT;
|
|
14
|
+
uniform float maxT;
|
|
15
|
+
uniform float opacity;
|
|
16
|
+
|
|
17
|
+
vec4 LinearTosRGB( in vec4 value ) {
|
|
18
|
+
return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );
|
|
19
|
+
}
|
|
20
|
+
vec4 linearToOutputTexel( vec4 value ) { return LinearTosRGB( value ); }
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
float getHeatByLegalPos(vec3 pos){
|
|
24
|
+
float geometryFactor = texture(geometryMap,pos).r;
|
|
25
|
+
float legalFactor = clamp(geometryFactor,0.0,1.0);
|
|
26
|
+
return texture(heatMap,pos).r * legalFactor;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
float sampleOc(vec3 pos){
|
|
30
|
+
//平滑滤波步长
|
|
31
|
+
//todo:可以作为define传入的外部常量还是直接传
|
|
32
|
+
float step_x = step / (bboxMax.x - bboxMin.x) * 0.5;
|
|
33
|
+
float step_y = step / (bboxMax.y - bboxMin.y) * 0.5;
|
|
34
|
+
float step_z = step / (bboxMax.z - bboxMin.z) * 0.5;
|
|
35
|
+
vec3 p1 = pos + vec3(step_x,step_y,step_z);
|
|
36
|
+
vec3 p2 = pos + vec3(step_x,-step_y,step_z);
|
|
37
|
+
vec3 p3 = pos + vec3(step_x,step_y,-step_z);
|
|
38
|
+
vec3 p4 = pos + vec3(step_x,-step_y,-step_z);
|
|
39
|
+
vec3 p5 = pos + vec3(-step_x,step_y,step_z);
|
|
40
|
+
vec3 p6 = pos + vec3(-step_x,-step_y,step_z);
|
|
41
|
+
vec3 p7 = pos + vec3(-step_x,step_y,-step_z);
|
|
42
|
+
vec3 p8 = pos + vec3(-step_x,-step_y,-step_z);
|
|
43
|
+
|
|
44
|
+
return (getHeatByLegalPos(p1) + getHeatByLegalPos(p2) + getHeatByLegalPos(p3) + getHeatByLegalPos(p4) + getHeatByLegalPos(p5) + getHeatByLegalPos(p6) + getHeatByLegalPos(p7) + getHeatByLegalPos(p8)) * 0.125;
|
|
45
|
+
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
//考虑到有效仿真值连通域在三维空间中是封闭流形,这里直接按照normal方向搜索,牺牲一定精度,以保证展示效果
|
|
49
|
+
float sampleByNormal(vec3 normal, vec3 pos){
|
|
50
|
+
float searchStep = step ;
|
|
51
|
+
vec3 currentPos = pos;
|
|
52
|
+
for (int iter=0; iter < MAX_STEPS; iter++) {
|
|
53
|
+
if(iter >= MAX_STEPS){
|
|
54
|
+
return texture(heatMap,currentPos).r;
|
|
55
|
+
}
|
|
56
|
+
if(texture(geometryMap,currentPos).r < 0.5){
|
|
57
|
+
currentPos += normal * searchStep;
|
|
58
|
+
}else{
|
|
59
|
+
return texture(heatMap,currentPos).r;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
float sample1(vec3 normal, vec3 pos){
|
|
65
|
+
return texture(heatMap,pos).r;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
in vec2 vUv;
|
|
69
|
+
in vec3 vPosition;
|
|
70
|
+
in vec3 vNormal;
|
|
71
|
+
out highp vec4 pc_fragColor;
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
float normalizeHeat(float t){
|
|
75
|
+
float _t = clamp(t,minT,maxT);
|
|
76
|
+
return (_t - minT)/(maxT - minT);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
vec3 posToTexCood(vec3 pos){
|
|
80
|
+
float x = (pos.x - bboxMin.x) / (bboxMax.x - bboxMin.x);
|
|
81
|
+
float y = (pos.y - bboxMin.y) / (bboxMax.y - bboxMin.y);
|
|
82
|
+
float z = (pos.z - bboxMin.z) / (bboxMax.z - bboxMin.z);
|
|
83
|
+
return vec3(x,y,z);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
void main() {
|
|
88
|
+
vec3 texCood = posToTexCood(vPosition);
|
|
89
|
+
// float color = sampleByNormal(vNormal,texCood);
|
|
90
|
+
float color = sample1(vNormal,texCood);
|
|
91
|
+
float normalColor= normalizeHeat(color);
|
|
92
|
+
vec4 colorMapColor = texture(colorMap,vec2(normalColor,0.2));
|
|
93
|
+
pc_fragColor = vec4(colorMapColor.xyz,opacity);
|
|
94
|
+
// pc_fragColor = linearToOutputTexel(vec4(colorMapColor.xyz,opacity));
|
|
95
|
+
}
|
|
96
|
+
`;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare var _default: "#version 300 es\n\tin vec3 position;\n\tin vec3 normal;\n\tout vec3 vPosition;\n\tout vec3 vNormal;\n\n\tuniform mat4 modelViewMatrix;\n\tuniform mat4 projectionMatrix;\n\tuniform vec3 cameraPos;\n\t// uniform vec3 normalMatrix;\n\tuniform mat4 modelMatrix;\n\n\tvoid main() {\n\n\t\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\t\tvec4 worldPosition = modelMatrix * vec4(position.xyz,1.0);\n\t\tvPosition = worldPosition.xyz;\n\t\t// vec3 transformedNormal = normalMatrix * normal;\n\t\tvNormal = normalize(normal);\n\n\t\tgl_Position = projectionMatrix * mvPosition;\n\t}\n";
|
|
2
|
+
export default _default;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export default `#version 300 es
|
|
2
|
+
in vec3 position;
|
|
3
|
+
in vec3 normal;
|
|
4
|
+
out vec3 vPosition;
|
|
5
|
+
out vec3 vNormal;
|
|
6
|
+
|
|
7
|
+
uniform mat4 modelViewMatrix;
|
|
8
|
+
uniform mat4 projectionMatrix;
|
|
9
|
+
uniform vec3 cameraPos;
|
|
10
|
+
// uniform vec3 normalMatrix;
|
|
11
|
+
uniform mat4 modelMatrix;
|
|
12
|
+
|
|
13
|
+
void main() {
|
|
14
|
+
|
|
15
|
+
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
|
|
16
|
+
vec4 worldPosition = modelMatrix * vec4(position.xyz,1.0);
|
|
17
|
+
vPosition = worldPosition.xyz;
|
|
18
|
+
// vec3 transformedNormal = normalMatrix * normal;
|
|
19
|
+
vNormal = normalize(normal);
|
|
20
|
+
|
|
21
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
22
|
+
}
|
|
23
|
+
`;
|
|
@@ -57,7 +57,7 @@ function create_fragment(ctx) {
|
|
|
57
57
|
div3 = element("div");
|
|
58
58
|
div2 = element("div");
|
|
59
59
|
attr(div0, "class", "PanoSpatialTagPlugin__tag-shadow svelte-8ki8yx");
|
|
60
|
-
set_style(div0, "transform", "translate(" + /*contentWidth*/ ctx[7] / 2 * /*contentZoom*/ ctx[3] * 3 + "px, " + /*contentHeight*/ ctx[8] / 2 * (/*upsideDown*/ ctx[1] ? -1 : 1) * /*contentZoom*/ ctx[3] * 3 + "px)");
|
|
60
|
+
set_style(div0, "transform", "translate(" + /*contentWidth*/ ctx[7] / 2 * /*contentZoom*/ ctx[3] * 3 + "px, " + /*contentHeight*/ ctx[8] / 2 * (/*upsideDown*/ ctx[1] ? -1 : 1) * /*contentZoom*/ ctx[3] * 3 + "px) scale(" + 1 / /*contentZoom*/ ctx[3] + ")");
|
|
61
61
|
attr(i0, "class", "PanoSpatialTagPlugin__tag-flagpole svelte-8ki8yx");
|
|
62
62
|
set_style(i0, "width", /*lineWidthZoom*/ ctx[4] + "rem");
|
|
63
63
|
attr(i1, "class", "PanoSpatialTagPlugin__tag-line1 svelte-8ki8yx");
|
|
@@ -97,7 +97,7 @@ function create_fragment(ctx) {
|
|
|
97
97
|
},
|
|
98
98
|
p(ctx, [dirty]) {
|
|
99
99
|
if (dirty & /*contentWidth, contentZoom, contentHeight, upsideDown*/ 394) {
|
|
100
|
-
set_style(div0, "transform", "translate(" + /*contentWidth*/ ctx[7] / 2 * /*contentZoom*/ ctx[3] * 3 + "px, " + /*contentHeight*/ ctx[8] / 2 * (/*upsideDown*/ ctx[1] ? -1 : 1) * /*contentZoom*/ ctx[3] * 3 + "px)");
|
|
100
|
+
set_style(div0, "transform", "translate(" + /*contentWidth*/ ctx[7] / 2 * /*contentZoom*/ ctx[3] * 3 + "px, " + /*contentHeight*/ ctx[8] / 2 * (/*upsideDown*/ ctx[1] ? -1 : 1) * /*contentZoom*/ ctx[3] * 3 + "px) scale(" + 1 / /*contentZoom*/ ctx[3] + ")");
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
if (dirty & /*lineWidthZoom*/ 16) {
|
|
@@ -15,6 +15,8 @@ export interface PanoSpatialTagPluginParameterType {
|
|
|
15
15
|
minRad?: number;
|
|
16
16
|
nearTolerance?: number;
|
|
17
17
|
upsideHeight?: number;
|
|
18
|
+
minDistance?: number;
|
|
19
|
+
maxDistance?: number;
|
|
18
20
|
}
|
|
19
21
|
export interface PanoSpatialTagPluginExportType {
|
|
20
22
|
load: (data: PanoSpatialTagPluginData) => void;
|
|
@@ -6,22 +6,22 @@ import Tag from './Components/tag';
|
|
|
6
6
|
import { pluginStyle } from './style';
|
|
7
7
|
import render from '../shared-utils/tinyEJSrender';
|
|
8
8
|
const MESH_SIZE = 0.001;
|
|
9
|
-
const RAY_ORIGIN_Y = 1.4;
|
|
10
9
|
const RAY_TOLERANT_DISTANCE = 0.01;
|
|
11
10
|
const BLUR_IMAGE_URL = 'https://vrlab-image4.ljcdn.com/release/web/PanoSpatialTagPlugin__blur.png';
|
|
12
|
-
const MIN_DISTANCE = 1.2;
|
|
13
|
-
const MAX_DISTANCE = 3.5;
|
|
14
11
|
/**
|
|
15
12
|
* 空间游走标签插件
|
|
16
13
|
*/
|
|
17
14
|
export const PanoSpatialTagPlugin = (five, params) => {
|
|
18
|
-
var _a, _b, _c, _d, _e, _f;
|
|
15
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
19
16
|
let wrapper = params === null || params === void 0 ? void 0 : params.container;
|
|
17
|
+
let centerY = 1.4;
|
|
20
18
|
const wait = (_a = params === null || params === void 0 ? void 0 : params.wait) !== null && _a !== void 0 ? _a : 200;
|
|
21
19
|
const maxNumberOnScreen = (_b = params === null || params === void 0 ? void 0 : params.maxNumberOnScreen) !== null && _b !== void 0 ? _b : 3;
|
|
22
20
|
const minRad = (_c = params === null || params === void 0 ? void 0 : params.minRad) !== null && _c !== void 0 ? _c : Math.PI / 4;
|
|
23
21
|
const nearTolerance = (_d = params === null || params === void 0 ? void 0 : params.nearTolerance) !== null && _d !== void 0 ? _d : 100;
|
|
24
22
|
const upsideHeight = (_e = params === null || params === void 0 ? void 0 : params.upsideHeight) !== null && _e !== void 0 ? _e : 1.6;
|
|
23
|
+
const minDistance = (_f = params === null || params === void 0 ? void 0 : params.minDistance) !== null && _f !== void 0 ? _f : 1.2;
|
|
24
|
+
const maxDistance = (_g = params === null || params === void 0 ? void 0 : params.maxDistance) !== null && _g !== void 0 ? _g : 3.5;
|
|
25
25
|
// const foldPercent = params?.foldPercent ?? 20
|
|
26
26
|
const css3DRender = CSS3DRenderPlugin(five);
|
|
27
27
|
const container = document.createElement('div');
|
|
@@ -75,8 +75,8 @@ export const PanoSpatialTagPlugin = (five, params) => {
|
|
|
75
75
|
projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
|
|
76
76
|
frustum.setFromProjectionMatrix(projScreenMatrix);
|
|
77
77
|
state.tags.forEach(tag => {
|
|
78
|
-
const distance = camera.position.clone().setY(
|
|
79
|
-
if (distance <
|
|
78
|
+
const distance = camera.position.clone().setY(centerY).distanceTo(tag.position);
|
|
79
|
+
if (distance < minDistance || distance > maxDistance)
|
|
80
80
|
return tag.destroying = true;
|
|
81
81
|
if (!frustum.containsPoint(tag.position))
|
|
82
82
|
return tag.destroying = true;
|
|
@@ -88,16 +88,16 @@ export const PanoSpatialTagPlugin = (five, params) => {
|
|
|
88
88
|
state.tags.forEach(tag => {
|
|
89
89
|
if (tag.destroying) {
|
|
90
90
|
tag.app.$set({
|
|
91
|
-
contentZoom: 0.1 + camera.position.distanceTo(tag.position) /
|
|
92
|
-
lineWidthZoom: 0.38 * (0.01 + camera.position.distanceTo(tag.position) /
|
|
91
|
+
contentZoom: 0.1 + camera.position.distanceTo(tag.position) / maxDistance,
|
|
92
|
+
lineWidthZoom: 0.38 * (0.01 + camera.position.distanceTo(tag.position) / maxDistance),
|
|
93
93
|
destroying: tag.destroying,
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
96
|
else {
|
|
97
97
|
tag.app.$set({
|
|
98
|
-
lineWidthZoom: 0.38 * (0.01 + camera.position.distanceTo(tag.position) /
|
|
99
|
-
lineHeightZoom: 0.4 + (camera.position.distanceTo(tag.position) -
|
|
100
|
-
contentZoom: 0.1 + camera.position.distanceTo(tag.position) /
|
|
98
|
+
lineWidthZoom: 0.38 * (0.01 + camera.position.distanceTo(tag.position) / maxDistance),
|
|
99
|
+
lineHeightZoom: 0.4 + (camera.position.distanceTo(tag.position) - minDistance) / maxDistance * 0.6,
|
|
100
|
+
contentZoom: 0.1 + camera.position.distanceTo(tag.position) / maxDistance,
|
|
101
101
|
});
|
|
102
102
|
}
|
|
103
103
|
});
|
|
@@ -170,8 +170,8 @@ export const PanoSpatialTagPlugin = (five, params) => {
|
|
|
170
170
|
const points = state.points.reduce((result, point) => {
|
|
171
171
|
if (state.tags.find(tag => point.id === tag.id && !tag.destroying))
|
|
172
172
|
return result;
|
|
173
|
-
const distance = camera.position.clone().setY(
|
|
174
|
-
if (distance <
|
|
173
|
+
const distance = camera.position.clone().setY(centerY).distanceTo(point.position);
|
|
174
|
+
if (distance < minDistance || distance > maxDistance)
|
|
175
175
|
return result;
|
|
176
176
|
if (!frustum.containsPoint(point.position))
|
|
177
177
|
return result;
|
|
@@ -231,10 +231,12 @@ export const PanoSpatialTagPlugin = (five, params) => {
|
|
|
231
231
|
Math.pow((mouse.y - _mouse.y) / 2 * clientHeight, 2)) > nearTolerance;
|
|
232
232
|
}))
|
|
233
233
|
continue;
|
|
234
|
-
const raycaster = new THREE.Raycaster(camera.position.clone().setY(
|
|
235
|
-
const [intersect] =
|
|
236
|
-
|
|
237
|
-
|
|
234
|
+
const raycaster = new THREE.Raycaster(camera.position.clone().setY(centerY), point.position.clone().sub(camera.position.clone().setY(centerY)).normalize(), 0, point.distance + RAY_TOLERANT_DISTANCE);
|
|
235
|
+
const [intersect] = state.intersectObjects ?
|
|
236
|
+
raycaster.intersectObjects(state.intersectObjects, true) :
|
|
237
|
+
(five.model.bvhs.loaded ?
|
|
238
|
+
five.model.intersectRaycaster(raycaster) :
|
|
239
|
+
raycaster.intersectObjects(five.model.children, true));
|
|
238
240
|
if (!intersect)
|
|
239
241
|
continue;
|
|
240
242
|
if (point.distance - intersect.distance < RAY_TOLERANT_DISTANCE) {
|
|
@@ -254,9 +256,9 @@ export const PanoSpatialTagPlugin = (five, params) => {
|
|
|
254
256
|
props: {
|
|
255
257
|
id,
|
|
256
258
|
content: state.render(state.template, replacement),
|
|
257
|
-
lineWidthZoom: 0.38 * (0.01 + camera.position.distanceTo(position) /
|
|
258
|
-
lineHeightZoom: 0.4 + (camera.position.distanceTo(position) -
|
|
259
|
-
contentZoom: 0.1 + camera.position.distanceTo(position) /
|
|
259
|
+
lineWidthZoom: 0.38 * (0.01 + camera.position.distanceTo(position) / maxDistance),
|
|
260
|
+
lineHeightZoom: 0.4 + (camera.position.distanceTo(position) - minDistance) / maxDistance * 0.6,
|
|
261
|
+
contentZoom: 0.1 + camera.position.distanceTo(position) / maxDistance,
|
|
260
262
|
upsideDown: position.y > upsideHeight,
|
|
261
263
|
folded: state.folded,
|
|
262
264
|
events: state.events,
|
|
@@ -301,6 +303,13 @@ export const PanoSpatialTagPlugin = (five, params) => {
|
|
|
301
303
|
if (data.folded === true)
|
|
302
304
|
state.folded = data.folded;
|
|
303
305
|
};
|
|
306
|
+
/** 设置射线碰撞检测objects
|
|
307
|
+
*
|
|
308
|
+
*/
|
|
309
|
+
const setIntersectObjects = (objects) => {
|
|
310
|
+
state.intersectObjects = objects;
|
|
311
|
+
updateTags();
|
|
312
|
+
};
|
|
304
313
|
/** 标签启用
|
|
305
314
|
* 启用插件并重新计算展示标签
|
|
306
315
|
*/
|
|
@@ -360,6 +369,22 @@ export const PanoSpatialTagPlugin = (five, params) => {
|
|
|
360
369
|
tag.app.$set({ folded: true });
|
|
361
370
|
});
|
|
362
371
|
};
|
|
372
|
+
const onResize = () => {
|
|
373
|
+
five.once('renderFrame', updateOrigins);
|
|
374
|
+
};
|
|
375
|
+
const onModelLoaded = () => {
|
|
376
|
+
if (!wrapper)
|
|
377
|
+
wrapper = five.getElement().parentElement;
|
|
378
|
+
if (wrapper)
|
|
379
|
+
wrapper.appendChild(container);
|
|
380
|
+
state.forbidden = false;
|
|
381
|
+
centerY = five.model.bounding.getCenter(new THREE.Vector3()).y;
|
|
382
|
+
updateTags();
|
|
383
|
+
five.on('panoWillArrive', onPanoWillArrive);
|
|
384
|
+
five.on('panoArrived', onPanoArrived);
|
|
385
|
+
five.on('modeChange', onModeChange);
|
|
386
|
+
five.on('cameraUpdate', onCameraUpdate);
|
|
387
|
+
};
|
|
363
388
|
const dispose = () => {
|
|
364
389
|
blurImage = null;
|
|
365
390
|
css3DRender.disposeAll();
|
|
@@ -370,40 +395,24 @@ export const PanoSpatialTagPlugin = (five, params) => {
|
|
|
370
395
|
});
|
|
371
396
|
state.origins = [];
|
|
372
397
|
state.tags = [];
|
|
398
|
+
five.off('modelLoaded', onModelLoaded);
|
|
399
|
+
five.off('renderFrame', updateOrigins);
|
|
373
400
|
five.off('panoWillArrive', onPanoWillArrive);
|
|
374
401
|
five.off('panoArrived', onPanoArrived);
|
|
375
402
|
five.off('modeChange', onModeChange);
|
|
376
403
|
five.off('cameraUpdate', onCameraUpdate);
|
|
404
|
+
five.off('dispose', dispose);
|
|
405
|
+
window.removeEventListener('resize', onResize, false);
|
|
377
406
|
};
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
state.forbidden = false;
|
|
384
|
-
updateTags();
|
|
385
|
-
five.on('panoWillArrive', onPanoWillArrive);
|
|
386
|
-
five.on('panoArrived', onPanoArrived);
|
|
387
|
-
five.on('modeChange', onModeChange);
|
|
388
|
-
five.on('cameraUpdate', onCameraUpdate);
|
|
389
|
-
}
|
|
390
|
-
else {
|
|
391
|
-
five.once('modelLoaded', () => {
|
|
392
|
-
if (!wrapper)
|
|
393
|
-
wrapper = five.getElement().parentElement;
|
|
394
|
-
if (wrapper)
|
|
395
|
-
wrapper.appendChild(container);
|
|
396
|
-
state.forbidden = false;
|
|
397
|
-
updateTags();
|
|
398
|
-
five.on('panoWillArrive', onPanoWillArrive);
|
|
399
|
-
five.on('panoArrived', onPanoArrived);
|
|
400
|
-
five.on('modeChange', onModeChange);
|
|
401
|
-
five.on('cameraUpdate', onCameraUpdate);
|
|
402
|
-
});
|
|
403
|
-
}
|
|
407
|
+
window.addEventListener('resize', onResize, false);
|
|
408
|
+
if ((_h = five === null || five === void 0 ? void 0 : five.model) === null || _h === void 0 ? void 0 : _h.loaded)
|
|
409
|
+
onModelLoaded();
|
|
410
|
+
else
|
|
411
|
+
five.once('modelLoaded', onModelLoaded);
|
|
404
412
|
five.on('dispose', dispose);
|
|
405
413
|
return {
|
|
406
414
|
load,
|
|
415
|
+
setIntersectObjects,
|
|
407
416
|
unfoldAll,
|
|
408
417
|
foldAll,
|
|
409
418
|
unfold,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const COMPASS_IMAGE = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAArUAAAB7CAMAAABdA4ieAAAC91BMVEUAAACOpP/H0P+yxP/a4/+asv/W3/+/z/+cs//S3f+mu//Q2//5+v/H1P/d5f/l6//y9f++zf/i6f+ww/+ovP/7/P/u8v/N2f+Mp//q7/+4yf+uwf+Wr/+7y/+1xv+Ho//x9P+9zP+2x/+swP+gt/+Oqf/Y4v/r8P/l7P/b4//F0/+juf+Zsv+XsP+Trf/p7v97mv9wj/+kuv+ftf/x9P92lf/3+f/I1f+5yv+Eof98m//8/f/4+f90lf+9zf/j6f/T3f/L1/+Bnv/6+/+SrP/m7P/f5v/O2v/L2P/E0v/Az//+///s8P/e5v+rv/+pvv+Anv+qvv+Pqv+Kpv+CoP93l/9xlP/z9v/p7v90lf9uj//P2//v8//o7f/k6v/K1v+6yv9rjv98nv/E0v/9/v/09//h6P/X4f9pjP/9/f/N2f/K1v/C0f+Ho/99nP/1+P9sj//6+//u8/+iuP/u8//g6P/U3v+3x/+0xv+etf+Vrv9pjf/B0P9ukf+ht/+Vr/94mP/G0/+8zP+2x//+/v/09v/W4f9ojv/c5P+xxP/d5v+xw/+vwv+Jo//g6P+nvP+SrP/R3P/1+f/W3//U3//C0P+Jp/9nh/+Kpv+Fov/Y4f/J1/+Pqf+rv/+Oqv+Oqv+muv+twP/f5//t8P97mf/h5/+twP+kuf/L2P+juP+Ipf+huP+Pqf/d5v+zxf+cs/+Zsf+wwv/V3v+8zP+Go/+zxP+GpP/T3f/r8P/u8v/o7f/d5P/m7P/H1P/w9P/D0f+uwf/Z4v/F0v/09//D0v/v8//s8v/d5P/Y4f/s8P+etv/X4f+gt/+ovf+bsv+xw/+Vr//j6v+1x//J1v+4yf/r8P+yxf/T3f/B0f+Fo//09//W4P/h6P/L1v/i6f/x9f/t8v/G0/+uwf/z9f/7/P/n7f/z9v/T3f+4yf/J1v/z9f/w8//q7v/O2v/8/f/5+v/y9f/w8//g6P/z9v+/zv+5yf+9zf/5+v/Q3P/B0P/u8f/R2//////LSJnaAAAA/HRSTlMAAwGMx2jAn2u7ebn0q8zX7J3TiHz45bRS35SFYZmPSembkYNwVMXh2cmodWVjXN43DHZu6gfyrJZGOvrzLAbVvbBB91raz7aypqH+4s6Bfj9/Vk9EMint3C8gt+fc1q+XGAml/O/SxBz7s66kSz3wI/bjc+fQvpOObV8VoyZyXjSpmgv97sMPyorNiYZN0XpYuvHCv6JNEhEWw61YgCUdGBIP5CIgHypaUEU6NS9JQy8lGlY6NCuMfVtPSzspJoRxcExBNTMUyn9zaWRfVkk9Oad9emtkY0RBMLGsnJaQj4ZmXVHhsaKbeW9owb466dnVy7mYj45wyaGV3bdGzuNnAAASkklEQVR42uyaS0iUURiGTUQZ1MaMURSEbOFt4ybGQClFHO9rBS8F3nAURHG0hZvyQrgQRsfNuKmRCTcGGaEzThNqMyouwswKNTVMLe/a/bLo+845/5z/dzIiumj971I3gz6+Puc9x0POT6bRaXfYrJa18YHFhYXXKzMz6+/fb2+/ePFia8uvWlXelFkcr6pO2NqCr2xv77xfn5lZWXm9sDgwvmZZGnHYzaZjHnLk/PaYzL0jS9Pji6+XN3Z3gvJPnTkTEJCT01xSUtWuVick+PlVJ6tUqvj44uLipkxIU3F5fLxKlZxc7efnl6BWt1eVlDTn5AQEnDl16lR+be2n3fWZlYWBNcugze485yFHzq/Kub7eEcv44tzyekpsbEhIZGRWVk1NUFBtPqU2gFGbANRWVycnI7XlCO0XQm25mFp1VRWjFrDNz68NCqqpyYqMDAmJjc3NzQ3cmJwfmLba7CZPDzlyfg5Wh3V6YG559HyhUhkVlZJSUJDLqK3pDkJqoS8ZtVWEWiCTUltejl37BaCVdG2Cul1MLUIb1M2pLShIiYpSKpWF58+37U3Oj1ue2E0ecuT8EK1mm3VoYG4vW6MrLQ0MDDwvUIvQ8q6tBWqZIeRQQ+DU8q51NwQxtbVAbRajNrZARG1gaWBpm0anyY6enB+bGOyV6ZVzIK6bPUPzs17Rx48fb80GaHVtpQRaF7XYtZFIbTcRBAFb7rWc2uJM1rVoCCqgFquWdy0TBDCEbqSWlm2KQC38rZSW6nS67OxW+CxXr0Z7ec/J8MqRxtQ7ONQ/2xIREeHlFR191UVtqRu1wBep2hpqCNxrpYYg6dp4Ude2Y9cG8K5FQ8hyNwSglnZtNoE22svLKyKirKxFsTo28cQsH9v+81Bevb29O1qMZQAtUhs9SqnVsK5199osRi3fENwNgXitcBqrrmZly7r2DKUWq7Zb8FrBEAoptW1tGg3rWk5tC3xSQ53ig8zuf5pzd4df9c8qFIrEOgOhtgyphdCubaVdC9iyrkVo+Wnsm12bID6NZYqWLxX32qpm0fKVD9ii10bSrkVDiJJ2bWuriFqjsaUDPmpdXWIifG7f1bGezT55bfhfYrrfM7Wamufrq9cjtIkGA+1aZgiArdRrlUBtirRr2YbAvBZGBLV71/INAcuWbwjcEERey7tWKe7abGnXdiC1DFq9r29eampF/3O5dv/1ODd7pj5og4ODU13UQtdyQ+Beq9FovnMaE20IAdwQJHut2BCE05jaffkSDAGwxbJl1CK27DQ2iqcxCFKLXWsgXatX+BJqg4O1aWlJz14N35XR/RfTeP/2VOeFpKS0tDQCLVDrq9AjtXVIrdFYVsaoHWWGQKgN3EdtCNVa91sGtdQQmvhpjFUtX74QWjoioNdm0a5lGwL3Wp1GI/HaCCP1WkMddi1Cm5cH1BJsky5UxGHrysLw7wQd9pl/XFfFBaRWq9UCtalIrZ56rcG7A7u2jHktMQQN91qllFq2fImoba468G5M6rVq4rV8Q0CvZdTGgtcitrxrNUgtli1QCyFe6+0yBL3eF6Cl1CYBtYBtnL9/0b2ezWseco56QGLvpV++7O8fF1dRAdhC16Ih0K4lhpBoQBaMLS6vZacxTdu+DSFXsiHkU689YENgd2MSQ0iQ7rXiG90Qvnxh2eJhTOfqWihb7rXUEIBalyFotaRru+IQ28uXY9LBF27JD3OObPqePn9TlJ4eExNDqO0CapOQWsCWdq2CUmtgGwKnli9f6LWFrg0hhFEr7doS1rXSu7HM8nK3DaHd7W6shnutyxACqdficYxSyzYEgVqEVsENQYtdi9j6U2rTi4oqfaZu32n0kHO04nlr+N3HjIaGoqIipNafUNsF1KIicK9VUK8FQ8Cu5YbAqQVslfv2Wuq1+TU7uxszK/DycG1t2mJZWrKOjIzYHA673Wx2Ok3nPImbNJqcfWa7vdfhsMG3rUtLFss0PG3Eh43ruzvC8sW7lhkCgxYMQXzLYCReyzYESGoePY0JXesPiYlBbCsbOjMyMu713L/uIedo5NiNm+8++vhkALSVlaRrqSEAtNKu1VNqWddKN4Rs3f6uLdxYnsTXsdNLg7Ze8y95WOhp6rM7RqyW6fGB+bnJ5Q0lNQRyo+u+fOGGIMFWOI2Rqq2ghgDUYtcSbH18fE4AuXLnHvr0PX30JvzEiRM+gG0nYFsE2IIgQARD0LINIY9vCNLla1R8ozu6PLc4brE6zH/iEcAxp90GD83mJ/dAqjU64TTGvNYodC0uX2SvJV1LNwSkFg3B1bWEWvhBhIdfeSjbwiHO9QeP34aFXQkPp9AitWgIgtfGYdcecBrrMJYJy1c0gLIHb62GrE96+/7aCmoyOwYnhvrnJo3otXz5Yl6roNCmptLTGHYtei1imy50rQ+lFrANC7v48ra86B6+HLs1/PDs2YsA7RWAlmLb0MkNgXStdENwv2WIUKzi2yrnoZo98ekkPpYQ7saQWtq1dPlCr+WGIO1axJZSe/Hs2bePHsiae4jSeOfxpdBQhJZULe/aSmIISG0cNwTetQoIMQTDbP9Qj818mP+Pejp7ByfGVmeF5WufIVw4wGuxahm1oaGh9S9vyqPYYYgnnL1O19cDtEAt7VrqtXCIdnWtsCEkYdfyWwaF4jMp174j9JtsvGvrGer/oMcNQXzL0CVZvhoaMii1iG2YQG19/enTp08+li33K/tm7JNGGIbxqiEht5m7iasMcBuwwOJk0tEFcn9BG7s1bizQGBycCCbXpUkTo9VFJVpRSeNkuBqnq6BRoiwOMtldm3Tr+37fJ9+dtFEUbNX3+RPIj+d+93zf/ctgyZb1YDAUAmx510J410JY1wqvbTeEma3vJ9uP9571yObu8rfTd6xrhSEIahFb2bXCayW1wWAwM2CvLf5XFvSMMr9fzw9kMhnEFqmVXSsMYQI3hFFJLUD7GixwZuvHU/kuoG+zsXx0CtS+Yl4runZ0fHzcvSEAtUPcEEKCWshhdYlezx44I0vV80J+AILQQgIuagdby9e1vXbm9Ogp3kmd2j45q7z1Ll/tXRuAoCEAtQzbQkE93qdLCw+Wsa9NXVXVfB6xdXftsOxauSHwszHgtfG0L6IufNkBdhm0vGul10Kk14quzQO1qqqDK7yg9Dwj682wrk+raqEgoGXUtrp2yGUI3Gt/we3T5/L+0Q+6W/mIXTvR7rWArTSEfJ5Rq+the40at5dBMTDDCC2jVhoCYjscAGo5tBC+fA0elXefhsF2dqTdOKtMyLlWvo2F3NQCtNPTiG04aZcI3B6lb6mqJZPhK2rVFrVBFATRtXKvrZw1Fh/RotXdoOzu/LwYhLj3Wo8hCGrDQG1y1jTIcbufvo2ilTJnZxFbnRsC81qxIYQ8XntRpy9SWOZ3y+dv2pevjPRaQa1pplIph87OuoxsXEulTJND6zWEjPRagDZwXqbredd94bgiqfUYgsq6Ngldi9hqmna8Qj9etw6/bMvSNIYt/MAtQ8i7DQG79rLeoPH8b75QPg8wbINyQ+CGILtW0yxLUZoE7v2RrRmKolgaUouGwL1W93gtdu1lnY57bj5IPBRei+GGAHF3rYKJ7608l82lF5lacSLxOFLLutaUXeuhNlOnOyEdkMu9VnYtJGnysrUshDYej6SLG9QBd5TZdASgjSsQhNZFrS69FoilF6+OsgDkIrauDWEWu1ZjhoDYRiKRdNohU+g4CyUnl2tRa1nSEKTXFmwi9s7kNg89G4IwBNG1SG0uZ9BVhQ4PEwzDyKWBWoEtUis2BNG19toSydc9bx81D91dC9hKaiNIrWE4dPxwy8yXnEQCoL3WtSnetQhtsklXRLv1YajNli8BraYgtozaXBqgTSQS2cl1+q1vytj6pD+bBWpF10qvFV2btIukBV2WhVRrQxDQCkNAbLNZv1N7zoeMt/jr13x+P1LLyhawlYLAX8fobl33g0ZWtE2+11oearFr/RDf3gEV7p/z6WDS5/MJaF1eqwhslSo9q3qW/vn9Y63Na7Fqs0gtpDZHhXs9/Z9r0ShC6+5aQS1C65ToEKHXmVqvRtoNwQ9BbKPR96vUGt5H1IcYg9YjCDkxIcSrNB32ONLRSg7H1msIEMA2GqNJoZWp1ckYQCuoRWwZtUYaFSFdpNHwYbOwsodde7UhtLAFaGOxl7U5eub9Ztfscd0Eoihsu8oSKJBoQpUYyYULmhSIBVjACuip0tFQpEaaagTSyLiI9GSMZArEKp4it95N7oXBk6dUr7Ln59sB4uNw7p0BTlfb3s7Wcm0fvfbbV7MveAYo7k9eEB5h+x0Aa22b9OlKb9bHP7kNgLZC2slawKTs80Bx/2sIW8DO7dy7VSt9SfuoyHMurei1k7bnt/3K8ExQXLT2Y0MA8qLwro2mRaG6hV5RTNpuuba81345v+n+E3oR6su7aAjc2hyt9cL4qN+fcNNcw9DzPJG1i7VG2dfidHlHaYW1qK0H2oauZvvz/ZEyhtLyrBUN4WzuxLweIO6HrOXWhiQa6pUupHeLkRCYrbWB2dqzZh+vPGxOl1xoW3iztYyxqNWj4KadG0URm7z9tyHoPZi+PnBJRExjk7WEEHiTrtMof9T7q7NctJYwcBaYGgJwVf/R5Sft3bkh8KydrXVV93aHzs7WklBMY2b+kob65uE0NhcEQhhaa1mWo+7VmqqzgElaRlDbKWtD0wykAg6GikJkretO2saKelt1cRyjtQAD5qw1zUBCdr2L1jIWAdzaWEVvq44+pI0AErLQs/rdyiAjm9ONiF5rATGlpaPWwUM1ZHSxFokIY9FNn12fivw4toQwkbWobemPynhbD1lW0hKtfYTtVa3PUk+q3pp7LYDW0jLL2lGJ+yP14DhZltFFW5DW6swApgbrpn1kbVmCtJnj+KP0GyFwFsCspZRLq1j70Z2qsxC0loK0qK0vd95Wne/7IC1Q8qgd9DgB1Il0dKx4CVsH8P1E3n3C7t76AM/aErKW3s1FAxVZNweUllvrIwc5V5r7MUiSWVoMW5C2NdVAXao7DmNL1vpJkgy1dH/V9W9wNmmTxdqy7OR7CMMnV2EiaxMgkGzoXjdDEKC2S0HwR3OeoD6beuBZ26K0QXC4y/Pa/7Jrx7gJw1AYx2su0iuYgYFI7sAJstiS2ZKpk8UeWfKWKyQLLJ5Qxyp34TZ9D15YOkBpm9ji/U/A8CP+HFj0styMapHtZ54bh/t5y2E9LoQNVppMXoN1uixLQns8rl9PeZ0T3O96O5T4rL2wBQkuZnCbWQ7OXdUe1zwNni8YCsh2VOuK1I/a2jtHapHtZp/J+cD9bf0HoiW1rpAp38TfYlEUgJaetWUOZwP3P3UnetYCW1ChU52JogoS1UKIlq9gT95yILSugKRKciq2VhLaEpIVm3366j2pxaSMyf07YRUlND5qTynvGG6aaDOSWgnptFiIKoQLWmQ7pLphuOkTB0lqoZDSTGiVBrXE1iT0wbgEEn0gtSEEncoNfRV1uKKN/KqL+/4C1xYSA7XapjATRGU1hGxT3NtcGnUK0UJgZf7TuDWEls1yt9wiWsja7awzYRWttYgWYrPcLbejWqua2WaCqBSixQLvWe5mi06RWqv8TDOhNUrZC9sdm+Xuu5cpUqvU+wwzYbVVkIXYLHd/olekVpmpZ8KiMYbU7ma/EXJZBW5JrZl2V9bRnNWyWe4xt8TWTPd3FdEYSEFslnsoURlAi01FqN56f2br2xeOe9ytgbyf4nErGg/hl6RN4Jc5Lt++2rVjHMdCIIqiqtoRQW2mMogIyZFjlsB2B9wjjaY1PXa3wcbSPaEDR1fP9fVt8aPai2+f2+TlWu2l0yweZHlEO5S9cyu1lDKj5T/fWCH4jLaUnXMbvFyrzby8xRrayqUM2+ZWqvuM1nmpgHWkl8F9z9yG7LNa5yEMa0n8yHb93Er1oXjnoMVyFn3KQVcP7VRpFn+sDiznaiuHNufsHnkIwy7aPA/r5jbFGW3m7S12ku55WPN7Li1PPIRhN6sjtBjTmm+KmYcwPEOKs9tHF1JDHCoHLZ5DQ8yPBic9DoHjAKvsb85qjbFxHOCprMZaf5qdhlorxwGeTsPIttvPlno0y3GAZfbHp6n3ynGAV0m99u/2J6H3znGAvW4n+J25tdY7xwFey1pvQe6/DlrjOMDLqfXW7N5pbs0YWhxgtpj0rl1uiaHFISzccSWohUCzOIemm0VKChwHOMutKCVwHOA4av/JVi0xtDiRpCRfRcvQ4lBfxSnG0OJc/+xTjKHFyVRMP38iDC0O92lZVRhanO+vcVWGFu9BRWkW7+Z3rapEizdy7ZVm8V5Gtr8AtSnix59eOmYAAAAASUVORK5CYII=";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const COMPASS_IMAGE = 'data:image/png;base64,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';
|