@eturnity/eturnity_3d 7.20.1 → 7.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/EventManager/EventManager.js +48 -0
- package/src/Item/Item.js +12 -0
- package/src/Layer/Layer.js +119 -0
- package/src/Overlay/AirTeamOverlay.js +605 -0
- package/src/Overlay/ImageOverlay.js +309 -0
- package/src/Overlay/Overlay.js +255 -0
- package/src/Overlay/OverlayFactory.js +19 -0
- package/src/Overlay/OverlayLayer.js +36 -0
- package/src/components/ThreeCanvasViewer.vue +17 -6
- package/src/config.js +120 -17
- package/src/helper/UpdateRoofModuleFieldRelations.js +65 -25
- package/src/helper/cameraMixin.js +25 -0
- package/src/helper/materialMixin.js +14 -1
- package/src/helper/projectedMaterial.js +662 -0
- package/src/helper/render/base.js +5 -5
- package/src/helper/render/clear.js +0 -17
- package/src/helper/render/edge.js +2 -0
- package/src/helper/render/geometryHandler.js +60 -31
- package/src/helper/render/imageOverlay.js +25 -144
- package/src/helper/render/index.js +2 -0
- package/src/helper/render/mergedGeometry.js +11 -2
- package/src/helper/render/obstacle.js +2 -1
- package/src/helper/render/overlay.js +41 -0
- package/src/helper/render/projectionMaterial.js +17 -19
- package/src/helper/render/roof.js +49 -52
- package/src/helper/render/texture.js +25 -0
- package/src/helper/render/tile.js +84 -24
- package/src/helper/render/tileProjection.js +23 -14
- package/src/helper/renderMixin.js +22 -8
- package/src/helper/threeMixin.js +5 -2
- package/src/store/hydrateData.js +23 -11
- package/src/store/nodesEdgesCreation.js +78 -4
- package/src/store/three-d-module.js +1 -1
- package/dist/css/app.58568098.css +0 -1
- package/dist/img/reneSola_Virtus_2_JC320S_24_Bbw.85a0cb6d.png +0 -0
- package/dist/index.html +0 -15
- package/dist/js/app-legacy.aa792c98.js +0 -2
- package/dist/js/app-legacy.aa792c98.js.map +0 -1
- package/dist/js/chunk-vendors-legacy.9bb3863d.js +0 -41
- package/dist/js/chunk-vendors-legacy.9bb3863d.js.map +0 -1
|
@@ -0,0 +1,662 @@
|
|
|
1
|
+
import * as THREE from 'three'
|
|
2
|
+
|
|
3
|
+
var id = 0
|
|
4
|
+
|
|
5
|
+
function _classPrivateFieldLooseKey(name) {
|
|
6
|
+
return '__private_' + id++ + '_' + name
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function _classPrivateFieldLooseBase(receiver, privateKey) {
|
|
10
|
+
if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
|
|
11
|
+
throw new TypeError('attempted to use private field on non-instance')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return receiver
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function monkeyPatch(shader, _ref) {
|
|
18
|
+
let { defines = '', header = '', main = '', ...replaces } = _ref
|
|
19
|
+
let patchedShader = shader
|
|
20
|
+
|
|
21
|
+
const replaceAll = (str, find, rep) => str.split(find).join(rep)
|
|
22
|
+
|
|
23
|
+
Object.keys(replaces).forEach((key) => {
|
|
24
|
+
patchedShader = replaceAll(patchedShader, key, replaces[key])
|
|
25
|
+
})
|
|
26
|
+
patchedShader = patchedShader.replace(
|
|
27
|
+
'void main() {',
|
|
28
|
+
`
|
|
29
|
+
${header}
|
|
30
|
+
void main() {
|
|
31
|
+
${main}
|
|
32
|
+
`
|
|
33
|
+
)
|
|
34
|
+
const stringDefines = Object.keys(defines)
|
|
35
|
+
.map((d) => `#define ${d} ${defines[d]}`)
|
|
36
|
+
.join('\n')
|
|
37
|
+
return `
|
|
38
|
+
${stringDefines}
|
|
39
|
+
${patchedShader}
|
|
40
|
+
`
|
|
41
|
+
} // run the callback when the image will be loaded
|
|
42
|
+
|
|
43
|
+
function addLoadListener(texture, callback) {
|
|
44
|
+
// return if it's already loaded
|
|
45
|
+
if (
|
|
46
|
+
texture.image &&
|
|
47
|
+
texture.image.videoWidth !== 0 &&
|
|
48
|
+
texture.image.videoHeight !== 0
|
|
49
|
+
) {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const interval = setInterval(() => {
|
|
54
|
+
if (
|
|
55
|
+
texture.image &&
|
|
56
|
+
texture.image.videoWidth !== 0 &&
|
|
57
|
+
texture.image.videoHeight !== 0
|
|
58
|
+
) {
|
|
59
|
+
clearInterval(interval)
|
|
60
|
+
return callback(texture)
|
|
61
|
+
}
|
|
62
|
+
}, 16)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
var _camera = /*#__PURE__*/ _classPrivateFieldLooseKey('camera')
|
|
66
|
+
|
|
67
|
+
var _cover = /*#__PURE__*/ _classPrivateFieldLooseKey('cover')
|
|
68
|
+
|
|
69
|
+
var _textureScale = /*#__PURE__*/ _classPrivateFieldLooseKey('textureScale')
|
|
70
|
+
|
|
71
|
+
var _saveCameraProjectionMatrix = /*#__PURE__*/ _classPrivateFieldLooseKey(
|
|
72
|
+
'saveCameraProjectionMatrix'
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
var _saveDimensions = /*#__PURE__*/ _classPrivateFieldLooseKey('saveDimensions')
|
|
76
|
+
|
|
77
|
+
var _saveCameraMatrices =
|
|
78
|
+
/*#__PURE__*/ _classPrivateFieldLooseKey('saveCameraMatrices')
|
|
79
|
+
|
|
80
|
+
class ProjectedMaterial extends THREE.MeshPhysicalMaterial {
|
|
81
|
+
// internal values... they are exposed via getters
|
|
82
|
+
get camera() {
|
|
83
|
+
return _classPrivateFieldLooseBase(this, _camera)[_camera]
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
set camera(camera) {
|
|
87
|
+
if (!camera || !camera.isCamera) {
|
|
88
|
+
throw new Error('Invalid camera set to the ProjectedMaterial')
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (
|
|
92
|
+
camera.type !== _classPrivateFieldLooseBase(this, _camera)[_camera].type
|
|
93
|
+
) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
'Cannot change camera type after the material has been created. Use another material.'
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
_classPrivateFieldLooseBase(this, _camera)[_camera] = camera
|
|
100
|
+
|
|
101
|
+
_classPrivateFieldLooseBase(this, _saveDimensions)[_saveDimensions]()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
get texture() {
|
|
105
|
+
return this.uniforms.projectedTexture.value
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
set texture(texture) {
|
|
109
|
+
if (!(texture != null && texture.isTexture)) {
|
|
110
|
+
throw new Error('Invalid texture set to the ProjectedMaterial')
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
this.uniforms.projectedTexture.value = texture
|
|
114
|
+
this.uniforms.isTextureLoaded.value = Boolean(texture.image)
|
|
115
|
+
|
|
116
|
+
if (!this.uniforms.isTextureLoaded.value) {
|
|
117
|
+
addLoadListener(texture, () => {
|
|
118
|
+
this.uniforms.isTextureLoaded.value = true
|
|
119
|
+
this.dispatchEvent({
|
|
120
|
+
type: 'textureload'
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
_classPrivateFieldLooseBase(this, _saveDimensions)[_saveDimensions]()
|
|
124
|
+
})
|
|
125
|
+
} else {
|
|
126
|
+
_classPrivateFieldLooseBase(this, _saveDimensions)[_saveDimensions]()
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
get textureScale() {
|
|
131
|
+
return _classPrivateFieldLooseBase(this, _textureScale)[_textureScale]
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
set textureScale(textureScale) {
|
|
135
|
+
_classPrivateFieldLooseBase(this, _textureScale)[_textureScale] =
|
|
136
|
+
textureScale
|
|
137
|
+
|
|
138
|
+
_classPrivateFieldLooseBase(this, _saveDimensions)[_saveDimensions]()
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
get textureOffset() {
|
|
142
|
+
return this.uniforms.textureOffset.value
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
set textureOffset(textureOffset) {
|
|
146
|
+
this.uniforms.textureOffset.value = textureOffset
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
get cover() {
|
|
150
|
+
return _classPrivateFieldLooseBase(this, _cover)[_cover]
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
set cover(cover) {
|
|
154
|
+
_classPrivateFieldLooseBase(this, _cover)[_cover] = cover
|
|
155
|
+
|
|
156
|
+
_classPrivateFieldLooseBase(this, _saveDimensions)[_saveDimensions]()
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
constructor(_temp) {
|
|
160
|
+
let {
|
|
161
|
+
camera = new THREE.OrthographicCamera(),
|
|
162
|
+
texture = new THREE.Texture(),
|
|
163
|
+
textureScale = 1,
|
|
164
|
+
textureOffset = new THREE.Vector2(),
|
|
165
|
+
cover = false,
|
|
166
|
+
...options
|
|
167
|
+
} = _temp === void 0 ? {} : _temp
|
|
168
|
+
|
|
169
|
+
if (!texture.isTexture) {
|
|
170
|
+
throw new Error('Invalid texture passed to the ProjectedMaterial')
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (!camera.isCamera) {
|
|
174
|
+
throw new Error('Invalid camera passed to the ProjectedMaterial')
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
super(options)
|
|
178
|
+
Object.defineProperty(this, _saveCameraMatrices, {
|
|
179
|
+
value: _saveCameraMatrices2
|
|
180
|
+
})
|
|
181
|
+
Object.defineProperty(this, _saveDimensions, {
|
|
182
|
+
value: _saveDimensions2
|
|
183
|
+
})
|
|
184
|
+
Object.defineProperty(this, _camera, {
|
|
185
|
+
writable: true,
|
|
186
|
+
value: void 0
|
|
187
|
+
})
|
|
188
|
+
Object.defineProperty(this, _cover, {
|
|
189
|
+
writable: true,
|
|
190
|
+
value: void 0
|
|
191
|
+
})
|
|
192
|
+
Object.defineProperty(this, _textureScale, {
|
|
193
|
+
writable: true,
|
|
194
|
+
value: void 0
|
|
195
|
+
})
|
|
196
|
+
Object.defineProperty(this, _saveCameraProjectionMatrix, {
|
|
197
|
+
writable: true,
|
|
198
|
+
value: () => {
|
|
199
|
+
this.uniforms.projectionMatrixCamera.value.copy(
|
|
200
|
+
this.camera.projectionMatrix
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
_classPrivateFieldLooseBase(this, _saveDimensions)[_saveDimensions]()
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
Object.defineProperty(this, 'isProjectedMaterial', {
|
|
207
|
+
value: true
|
|
208
|
+
}) // save the private variables
|
|
209
|
+
_classPrivateFieldLooseBase(this, _camera)[_camera] = camera
|
|
210
|
+
_classPrivateFieldLooseBase(this, _cover)[_cover] = cover
|
|
211
|
+
_classPrivateFieldLooseBase(this, _textureScale)[_textureScale] =
|
|
212
|
+
textureScale // scale to keep the image proportions and apply textureScale
|
|
213
|
+
|
|
214
|
+
const [_widthScaled, _heightScaled] = computeScaledDimensions(
|
|
215
|
+
texture,
|
|
216
|
+
camera,
|
|
217
|
+
textureScale,
|
|
218
|
+
cover
|
|
219
|
+
)
|
|
220
|
+
this.uniforms = {
|
|
221
|
+
projectedTexture: {
|
|
222
|
+
value: texture
|
|
223
|
+
},
|
|
224
|
+
// this avoids rendering black if the texture
|
|
225
|
+
// hasn't loaded yet
|
|
226
|
+
isTextureLoaded: {
|
|
227
|
+
value: Boolean(texture.image)
|
|
228
|
+
},
|
|
229
|
+
// don't show the texture if we haven't called project()
|
|
230
|
+
isTextureProjected: {
|
|
231
|
+
value: false
|
|
232
|
+
},
|
|
233
|
+
// if we have multiple materials we want to show the
|
|
234
|
+
// background only of the first material
|
|
235
|
+
backgroundOpacity: {
|
|
236
|
+
value: 1
|
|
237
|
+
},
|
|
238
|
+
// these will be set on project()
|
|
239
|
+
viewMatrixCamera: {
|
|
240
|
+
value: new THREE.Matrix4()
|
|
241
|
+
},
|
|
242
|
+
projectionMatrixCamera: {
|
|
243
|
+
value: new THREE.Matrix4()
|
|
244
|
+
},
|
|
245
|
+
projPosition: {
|
|
246
|
+
value: new THREE.Vector3()
|
|
247
|
+
},
|
|
248
|
+
projDirection: {
|
|
249
|
+
value: new THREE.Vector3(0, 0, -1)
|
|
250
|
+
},
|
|
251
|
+
// we will set this later when we will have positioned the object
|
|
252
|
+
savedModelMatrix: {
|
|
253
|
+
value: new THREE.Matrix4()
|
|
254
|
+
},
|
|
255
|
+
widthScaled: {
|
|
256
|
+
value: _widthScaled
|
|
257
|
+
},
|
|
258
|
+
heightScaled: {
|
|
259
|
+
value: _heightScaled
|
|
260
|
+
},
|
|
261
|
+
textureOffset: {
|
|
262
|
+
value: textureOffset
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
this.onBeforeCompile = (shader) => {
|
|
267
|
+
// expose also the material's uniforms
|
|
268
|
+
Object.assign(this.uniforms, shader.uniforms)
|
|
269
|
+
shader.uniforms = this.uniforms
|
|
270
|
+
|
|
271
|
+
if (this.camera.isOrthographicCamera) {
|
|
272
|
+
shader.defines.ORTHOGRAPHIC = ''
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
shader.vertexShader = monkeyPatch(shader.vertexShader, {
|
|
276
|
+
header:
|
|
277
|
+
/* glsl */
|
|
278
|
+
`
|
|
279
|
+
uniform mat4 viewMatrixCamera;
|
|
280
|
+
uniform mat4 projectionMatrixCamera;
|
|
281
|
+
|
|
282
|
+
#ifdef USE_INSTANCING
|
|
283
|
+
attribute vec4 savedModelMatrix0;
|
|
284
|
+
attribute vec4 savedModelMatrix1;
|
|
285
|
+
attribute vec4 savedModelMatrix2;
|
|
286
|
+
attribute vec4 savedModelMatrix3;
|
|
287
|
+
#else
|
|
288
|
+
uniform mat4 savedModelMatrix;
|
|
289
|
+
#endif
|
|
290
|
+
|
|
291
|
+
varying vec3 vSavedNormal;
|
|
292
|
+
varying vec4 vTexCoords;
|
|
293
|
+
#ifndef ORTHOGRAPHIC
|
|
294
|
+
varying vec4 vWorldPosition;
|
|
295
|
+
#endif
|
|
296
|
+
`,
|
|
297
|
+
main:
|
|
298
|
+
/* glsl */
|
|
299
|
+
`
|
|
300
|
+
#ifdef USE_INSTANCING
|
|
301
|
+
mat4 savedModelMatrix = mat4(
|
|
302
|
+
savedModelMatrix0,
|
|
303
|
+
savedModelMatrix1,
|
|
304
|
+
savedModelMatrix2,
|
|
305
|
+
savedModelMatrix3
|
|
306
|
+
);
|
|
307
|
+
#endif
|
|
308
|
+
|
|
309
|
+
vSavedNormal = mat3(savedModelMatrix) * normal;
|
|
310
|
+
vTexCoords = projectionMatrixCamera * viewMatrixCamera * savedModelMatrix * vec4(position, 1.0);
|
|
311
|
+
#ifndef ORTHOGRAPHIC
|
|
312
|
+
vWorldPosition = savedModelMatrix * vec4(position, 1.0);
|
|
313
|
+
#endif
|
|
314
|
+
`
|
|
315
|
+
})
|
|
316
|
+
shader.fragmentShader = monkeyPatch(shader.fragmentShader, {
|
|
317
|
+
header:
|
|
318
|
+
/* glsl */
|
|
319
|
+
`
|
|
320
|
+
uniform sampler2D projectedTexture;
|
|
321
|
+
uniform bool isTextureLoaded;
|
|
322
|
+
uniform bool isTextureProjected;
|
|
323
|
+
uniform float backgroundOpacity;
|
|
324
|
+
uniform vec3 projPosition;
|
|
325
|
+
uniform vec3 projDirection;
|
|
326
|
+
uniform float widthScaled;
|
|
327
|
+
uniform float heightScaled;
|
|
328
|
+
uniform vec2 textureOffset;
|
|
329
|
+
|
|
330
|
+
varying vec3 vSavedNormal;
|
|
331
|
+
varying vec4 vTexCoords;
|
|
332
|
+
#ifndef ORTHOGRAPHIC
|
|
333
|
+
varying vec4 vWorldPosition;
|
|
334
|
+
#endif
|
|
335
|
+
|
|
336
|
+
float mapRange(float value, float min1, float max1, float min2, float max2) {
|
|
337
|
+
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
|
|
338
|
+
}
|
|
339
|
+
`,
|
|
340
|
+
'vec4 diffuseColor = vec4( diffuse, opacity );':
|
|
341
|
+
/* glsl */
|
|
342
|
+
`
|
|
343
|
+
// clamp the w to make sure we don't project behind
|
|
344
|
+
float w = max(vTexCoords.w, 0.0);
|
|
345
|
+
|
|
346
|
+
vec2 uv = (vTexCoords.xy / w) * 0.5 + 0.5;
|
|
347
|
+
|
|
348
|
+
uv += textureOffset;
|
|
349
|
+
|
|
350
|
+
// apply the corrected width and height
|
|
351
|
+
uv.x = mapRange(uv.x, 0.0, 1.0, 0.5 - widthScaled / 2.0, 0.5 + widthScaled / 2.0);
|
|
352
|
+
uv.y = mapRange(uv.y, 0.0, 1.0, 0.5 - heightScaled / 2.0, 0.5 + heightScaled / 2.0);
|
|
353
|
+
|
|
354
|
+
// this makes sure we don't sample out of the texture
|
|
355
|
+
bool isInTexture = (max(uv.x, uv.y) <= 1.0 && min(uv.x, uv.y) >= 0.0);
|
|
356
|
+
|
|
357
|
+
// this makes sure we don't render also the back of the object
|
|
358
|
+
#ifdef ORTHOGRAPHIC
|
|
359
|
+
vec3 projectorDirection = projDirection;
|
|
360
|
+
#else
|
|
361
|
+
vec3 projectorDirection = normalize(projPosition - vWorldPosition.xyz);
|
|
362
|
+
#endif
|
|
363
|
+
float dotProduct = dot(vSavedNormal, projectorDirection);
|
|
364
|
+
bool isFacingProjector = dotProduct > 0.0000001;
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
vec4 diffuseColor = vec4(diffuse, opacity * backgroundOpacity);
|
|
368
|
+
|
|
369
|
+
if (isFacingProjector && isInTexture && isTextureLoaded && isTextureProjected) {
|
|
370
|
+
vec4 textureColor = texture2D(projectedTexture, uv);
|
|
371
|
+
|
|
372
|
+
// apply the material opacity
|
|
373
|
+
textureColor.a *= opacity;
|
|
374
|
+
|
|
375
|
+
// https://learnopengl.com/Advanced-OpenGL/Blending
|
|
376
|
+
diffuseColor = textureColor * textureColor.a + diffuseColor * (1.0 - textureColor.a);
|
|
377
|
+
}
|
|
378
|
+
`
|
|
379
|
+
})
|
|
380
|
+
} // Listen on resize if the camera used for the projection
|
|
381
|
+
// is the same used to render.
|
|
382
|
+
// We do this on window resize because there is no way to
|
|
383
|
+
// listen for the resize of the renderer
|
|
384
|
+
|
|
385
|
+
window.addEventListener(
|
|
386
|
+
'resize',
|
|
387
|
+
_classPrivateFieldLooseBase(this, _saveCameraProjectionMatrix)[
|
|
388
|
+
_saveCameraProjectionMatrix
|
|
389
|
+
]
|
|
390
|
+
) // If the image texture passed hasn't loaded yet,
|
|
391
|
+
// wait for it to load and compute the correct proportions.
|
|
392
|
+
// This avoids rendering black while the texture is loading
|
|
393
|
+
|
|
394
|
+
addLoadListener(texture, () => {
|
|
395
|
+
this.uniforms.isTextureLoaded.value = true
|
|
396
|
+
this.dispatchEvent({
|
|
397
|
+
type: 'textureload'
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
_classPrivateFieldLooseBase(this, _saveDimensions)[_saveDimensions]()
|
|
401
|
+
})
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
project(mesh) {
|
|
405
|
+
if (
|
|
406
|
+
!(Array.isArray(mesh.material)
|
|
407
|
+
? mesh.material.some((m) => m.isProjectedMaterial)
|
|
408
|
+
: mesh.material.isProjectedMaterial)
|
|
409
|
+
) {
|
|
410
|
+
throw new Error(`The mesh material must be a ProjectedMaterial`)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (
|
|
414
|
+
!(Array.isArray(mesh.material)
|
|
415
|
+
? mesh.material.some((m) => m === this)
|
|
416
|
+
: mesh.material === this)
|
|
417
|
+
) {
|
|
418
|
+
throw new Error(
|
|
419
|
+
`The provided mesh doesn't have the same material as where project() has been called from`
|
|
420
|
+
)
|
|
421
|
+
} // make sure the matrix is updated
|
|
422
|
+
|
|
423
|
+
mesh.updateWorldMatrix(true, false) // we save the object model matrix so it's projected relative
|
|
424
|
+
// to that position, like a snapshot
|
|
425
|
+
|
|
426
|
+
this.uniforms.savedModelMatrix.value.copy(mesh.matrixWorld) // if the material is not the first, output just the texture
|
|
427
|
+
|
|
428
|
+
if (Array.isArray(mesh.material)) {
|
|
429
|
+
const materialIndex = mesh.material.indexOf(this)
|
|
430
|
+
|
|
431
|
+
if (!mesh.material[materialIndex].transparent) {
|
|
432
|
+
throw new Error(
|
|
433
|
+
`You have to pass "transparent: true" to the ProjectedMaterial if you're working with multiple materials.`
|
|
434
|
+
)
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (materialIndex > 0) {
|
|
438
|
+
this.uniforms.backgroundOpacity.value = 0
|
|
439
|
+
}
|
|
440
|
+
} // persist also the current camera position and matrices
|
|
441
|
+
|
|
442
|
+
_classPrivateFieldLooseBase(this, _saveCameraMatrices)[
|
|
443
|
+
_saveCameraMatrices
|
|
444
|
+
]()
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
projectInstanceAt(index, instancedMesh, matrixWorld, _temp2) {
|
|
448
|
+
let { forceCameraSave = false } = _temp2 === void 0 ? {} : _temp2
|
|
449
|
+
|
|
450
|
+
if (!instancedMesh.isInstancedMesh) {
|
|
451
|
+
throw new Error(`The provided mesh is not an InstancedMesh`)
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (
|
|
455
|
+
!(Array.isArray(instancedMesh.material)
|
|
456
|
+
? instancedMesh.material.every((m) => m.isProjectedMaterial)
|
|
457
|
+
: instancedMesh.material.isProjectedMaterial)
|
|
458
|
+
) {
|
|
459
|
+
throw new Error(`The InstancedMesh material must be a ProjectedMaterial`)
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (
|
|
463
|
+
!(Array.isArray(instancedMesh.material)
|
|
464
|
+
? instancedMesh.material.some((m) => m === this)
|
|
465
|
+
: instancedMesh.material === this)
|
|
466
|
+
) {
|
|
467
|
+
throw new Error(
|
|
468
|
+
`The provided InstancedMeshhave't i samenclude thas e material where project() has been called from`
|
|
469
|
+
)
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (
|
|
473
|
+
!instancedMesh.geometry.attributes[`savedModelMatrix0`] ||
|
|
474
|
+
!instancedMesh.geometry.attributes[`savedModelMatrix1`] ||
|
|
475
|
+
!instancedMesh.geometry.attributes[`savedModelMatrix2`] ||
|
|
476
|
+
!instancedMesh.geometry.attributes[`savedModelMatrix3`]
|
|
477
|
+
) {
|
|
478
|
+
throw new Error(
|
|
479
|
+
`No allocated data found on the geometry, please call 'allocateProjectionData(geometry, instancesCount)'`
|
|
480
|
+
)
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
instancedMesh.geometry.attributes[`savedModelMatrix0`].setXYZW(
|
|
484
|
+
index,
|
|
485
|
+
matrixWorld.elements[0],
|
|
486
|
+
matrixWorld.elements[1],
|
|
487
|
+
matrixWorld.elements[2],
|
|
488
|
+
matrixWorld.elements[3]
|
|
489
|
+
)
|
|
490
|
+
instancedMesh.geometry.attributes[`savedModelMatrix1`].setXYZW(
|
|
491
|
+
index,
|
|
492
|
+
matrixWorld.elements[4],
|
|
493
|
+
matrixWorld.elements[5],
|
|
494
|
+
matrixWorld.elements[6],
|
|
495
|
+
matrixWorld.elements[7]
|
|
496
|
+
)
|
|
497
|
+
instancedMesh.geometry.attributes[`savedModelMatrix2`].setXYZW(
|
|
498
|
+
index,
|
|
499
|
+
matrixWorld.elements[8],
|
|
500
|
+
matrixWorld.elements[9],
|
|
501
|
+
matrixWorld.elements[10],
|
|
502
|
+
matrixWorld.elements[11]
|
|
503
|
+
)
|
|
504
|
+
instancedMesh.geometry.attributes[`savedModelMatrix3`].setXYZW(
|
|
505
|
+
index,
|
|
506
|
+
matrixWorld.elements[12],
|
|
507
|
+
matrixWorld.elements[13],
|
|
508
|
+
matrixWorld.elements[14],
|
|
509
|
+
matrixWorld.elements[15]
|
|
510
|
+
) // if the material is not the first, output just the texture
|
|
511
|
+
|
|
512
|
+
if (Array.isArray(instancedMesh.material)) {
|
|
513
|
+
const materialIndex = instancedMesh.material.indexOf(this)
|
|
514
|
+
|
|
515
|
+
if (!instancedMesh.material[materialIndex].transparent) {
|
|
516
|
+
throw new Error(
|
|
517
|
+
`You have to pass "transparent: true" to the ProjectedMaterial if you're working with multiple materials.`
|
|
518
|
+
)
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (materialIndex > 0) {
|
|
522
|
+
this.uniforms.backgroundOpacity.value = 0
|
|
523
|
+
}
|
|
524
|
+
} // persist the current camera position and matrices
|
|
525
|
+
// only if it's the first instance since most surely
|
|
526
|
+
// in all other instances the camera won't change
|
|
527
|
+
|
|
528
|
+
if (index === 0 || forceCameraSave) {
|
|
529
|
+
_classPrivateFieldLooseBase(this, _saveCameraMatrices)[
|
|
530
|
+
_saveCameraMatrices
|
|
531
|
+
]()
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
copy(source) {
|
|
536
|
+
super.copy(source)
|
|
537
|
+
this.camera = source.camera
|
|
538
|
+
this.texture = source.texture
|
|
539
|
+
this.textureScale = source.textureScale
|
|
540
|
+
this.textureOffset = source.textureOffset
|
|
541
|
+
this.cover = source.cover
|
|
542
|
+
return this
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
dispose() {
|
|
546
|
+
super.dispose()
|
|
547
|
+
window.removeEventListener(
|
|
548
|
+
'resize',
|
|
549
|
+
_classPrivateFieldLooseBase(this, _saveCameraProjectionMatrix)[
|
|
550
|
+
_saveCameraProjectionMatrix
|
|
551
|
+
]
|
|
552
|
+
)
|
|
553
|
+
}
|
|
554
|
+
} // get camera ratio from different types of cameras
|
|
555
|
+
|
|
556
|
+
function _saveDimensions2() {
|
|
557
|
+
const [widthScaled, heightScaled] = computeScaledDimensions(
|
|
558
|
+
this.texture,
|
|
559
|
+
this.camera,
|
|
560
|
+
this.textureScale,
|
|
561
|
+
this.cover
|
|
562
|
+
)
|
|
563
|
+
this.uniforms.widthScaled.value = widthScaled
|
|
564
|
+
this.uniforms.heightScaled.value = heightScaled
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
function _saveCameraMatrices2() {
|
|
568
|
+
// make sure the camera matrices are updated
|
|
569
|
+
this.camera.updateProjectionMatrix()
|
|
570
|
+
this.camera.updateMatrixWorld()
|
|
571
|
+
this.camera.updateWorldMatrix() // update the uniforms from the camera so they're
|
|
572
|
+
// fixed in the camera's position at the projection time
|
|
573
|
+
|
|
574
|
+
const viewMatrixCamera = this.camera.matrixWorldInverse
|
|
575
|
+
const projectionMatrixCamera = this.camera.projectionMatrix
|
|
576
|
+
const modelMatrixCamera = this.camera.matrixWorld
|
|
577
|
+
this.uniforms.viewMatrixCamera.value.copy(viewMatrixCamera)
|
|
578
|
+
this.uniforms.projectionMatrixCamera.value.copy(projectionMatrixCamera)
|
|
579
|
+
this.uniforms.projPosition.value.setFromMatrixPosition(modelMatrixCamera)
|
|
580
|
+
this.uniforms.projDirection.value.set(0, 0, 1).applyMatrix4(modelMatrixCamera) // tell the shader we've projected
|
|
581
|
+
|
|
582
|
+
this.uniforms.isTextureProjected.value = true
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
function getCameraRatio(camera) {
|
|
586
|
+
switch (camera.type) {
|
|
587
|
+
case 'PerspectiveCamera': {
|
|
588
|
+
return camera.aspect
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
case 'OrthographicCamera': {
|
|
592
|
+
const width = Math.abs(camera.right - camera.left)
|
|
593
|
+
const height = Math.abs(camera.top - camera.bottom)
|
|
594
|
+
return width / height
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
default: {
|
|
598
|
+
throw new Error(
|
|
599
|
+
`${camera.type} is currently not supported in ProjectedMaterial`
|
|
600
|
+
)
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
} // scale to keep the image proportions and apply textureScale
|
|
604
|
+
|
|
605
|
+
function computeScaledDimensions(texture, camera, textureScale, cover) {
|
|
606
|
+
// return some default values if the image hasn't loaded yet
|
|
607
|
+
if (!texture.image) {
|
|
608
|
+
return [1, 1]
|
|
609
|
+
} // return if it's a video and if the video hasn't loaded yet
|
|
610
|
+
|
|
611
|
+
if (texture.image.videoWidth === 0 && texture.image.videoHeight === 0) {
|
|
612
|
+
return [1, 1]
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
const sourceWidth =
|
|
616
|
+
texture.image.naturalWidth ||
|
|
617
|
+
texture.image.videoWidth ||
|
|
618
|
+
texture.image.clientWidth
|
|
619
|
+
const sourceHeight =
|
|
620
|
+
texture.image.naturalHeight ||
|
|
621
|
+
texture.image.videoHeight ||
|
|
622
|
+
texture.image.clientHeight
|
|
623
|
+
const ratio = sourceWidth / sourceHeight
|
|
624
|
+
const ratioCamera = getCameraRatio(camera)
|
|
625
|
+
const widthCamera = 1
|
|
626
|
+
const heightCamera = widthCamera * (1 / ratioCamera)
|
|
627
|
+
let widthScaled
|
|
628
|
+
let heightScaled
|
|
629
|
+
|
|
630
|
+
if (cover ? ratio > ratioCamera : ratio < ratioCamera) {
|
|
631
|
+
const width = heightCamera * ratio
|
|
632
|
+
widthScaled = 1 / ((width / widthCamera) * textureScale)
|
|
633
|
+
heightScaled = 1 / textureScale
|
|
634
|
+
} else {
|
|
635
|
+
const height = widthCamera * (1 / ratio)
|
|
636
|
+
heightScaled = 1 / ((height / heightCamera) * textureScale)
|
|
637
|
+
widthScaled = 1 / textureScale
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
return [widthScaled, heightScaled]
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
function allocateProjectionData(geometry, instancesCount) {
|
|
644
|
+
geometry.setAttribute(
|
|
645
|
+
`savedModelMatrix0`,
|
|
646
|
+
new THREE.InstancedBufferAttribute(new Float32Array(instancesCount * 4), 4)
|
|
647
|
+
)
|
|
648
|
+
geometry.setAttribute(
|
|
649
|
+
`savedModelMatrix1`,
|
|
650
|
+
new THREE.InstancedBufferAttribute(new Float32Array(instancesCount * 4), 4)
|
|
651
|
+
)
|
|
652
|
+
geometry.setAttribute(
|
|
653
|
+
`savedModelMatrix2`,
|
|
654
|
+
new THREE.InstancedBufferAttribute(new Float32Array(instancesCount * 4), 4)
|
|
655
|
+
)
|
|
656
|
+
geometry.setAttribute(
|
|
657
|
+
`savedModelMatrix3`,
|
|
658
|
+
new THREE.InstancedBufferAttribute(new Float32Array(instancesCount * 4), 4)
|
|
659
|
+
)
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
export { allocateProjectionData, ProjectedMaterial as default }
|
|
@@ -5,9 +5,9 @@ import {
|
|
|
5
5
|
} from './geometryHandler'
|
|
6
6
|
export default {
|
|
7
7
|
methods: {
|
|
8
|
-
data(){
|
|
8
|
+
data() {
|
|
9
9
|
return {
|
|
10
|
-
mergedBaseMesh:null
|
|
10
|
+
mergedBaseMesh: null
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
13
|
renderBase() {
|
|
@@ -15,7 +15,7 @@ export default {
|
|
|
15
15
|
this.clearRemovedOnes('baseMeshes')
|
|
16
16
|
let geometry
|
|
17
17
|
let mesh
|
|
18
|
-
let baseGeometries=[]
|
|
18
|
+
let baseGeometries = []
|
|
19
19
|
this.roofs.forEach((roofPolygon) => {
|
|
20
20
|
//everythime the essencials data are changed, version goes up. we compare polygon version and mesh version to know if we have to rerender
|
|
21
21
|
if (
|
|
@@ -44,12 +44,12 @@ export default {
|
|
|
44
44
|
baseGeometries.push(this.meshes.baseMeshes[roofPolygon.id].geometry)
|
|
45
45
|
})
|
|
46
46
|
|
|
47
|
-
this.mergedBaseMesh=this.updateOrCreateMergedMesh(
|
|
47
|
+
this.mergedBaseMesh = this.updateOrCreateMergedMesh(
|
|
48
48
|
this.mergedBaseMesh,
|
|
49
49
|
baseGeometries,
|
|
50
50
|
this.material.wall
|
|
51
51
|
)
|
|
52
|
-
|
|
52
|
+
this.mergedBaseMesh.renderOrder = 10
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
}
|