@eturnity/eturnity_3d 6.31.0 → 6.31.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@eturnity/eturnity_3d",
3
3
  "private": false,
4
- "version": "6.31.0",
4
+ "version": "6.31.2",
5
5
  "main": "dist/main.js",
6
6
  "scripts": {
7
7
  "dev": "vue-cli-service serve --skip-plugins @vue/cli-plugin-eslint",
8
8
  "build": "vue-cli-service build --skip-plugins @vue/cli-plugin-eslint"
9
9
  },
10
10
  "dependencies": {
11
- "@eturnity/eturnity_maths": "6.31.0",
11
+ "@eturnity/eturnity_maths": "6.31.1",
12
12
  "axios": "^1.3.2",
13
13
  "core-js": "^2.6.12",
14
14
  "cors": "^2.8.5",
@@ -9,7 +9,7 @@ import { addVector, multiplyVector } from '@eturnity/eturnity_maths'
9
9
  import { updateComputedGeometryPolygon } from '@eturnity/eturnity_maths'
10
10
 
11
11
  import threeMixin from '../helper/threeMixin'
12
- import { material } from '../helper/materials'
12
+ import materialMixin from '../helper/materialMixin'
13
13
  import renderMixin from '../helper/renderMixin'
14
14
  export default {
15
15
  name: 'ThreeCanvas',
@@ -28,7 +28,6 @@ export default {
28
28
  provider:null,
29
29
  cameraprojection: null,
30
30
  texture: null,
31
- material: material,
32
31
  renderer: new THREE.WebGLRenderer({
33
32
  antialias: true,
34
33
  preserveDrawingBuffer: true
@@ -57,21 +56,21 @@ export default {
57
56
  areModuleFieldsVisible:false
58
57
  }
59
58
  },
60
- mixins: [renderMixin,threeMixin],
59
+ mixins: [renderMixin,threeMixin,materialMixin],
61
60
  async mounted() {
62
61
  await this.hydrateData(this.geometryData)
63
62
  this.renderer.domElement.style.width = '100%'
64
63
  this.renderer.domElement.style.height = '100%'
65
64
 
66
65
  this.initialiseThree(this.isInteractive)
67
- this.loadProjectionMaterial()
68
66
  this.initialiseThreeMap()
69
- await this.loadTextureFromModuleFields()
67
+ await this.loadPanelsTexture()
70
68
  this.renderGeometry()
71
69
  this.onWindowResize()
70
+ // this.updateProjectionMaterials()
72
71
  this.animate()
73
72
  this.$root.$on('on-roofSelected',(polygon)=>this.setCameraOrthogonalTo(polygon))
74
- this.updateProjectionMaterial()
73
+ this.initializeProjectionMaterial()
75
74
 
76
75
  const polygon = this.polygons.find((p) => p.id == this.uuid)
77
76
  this.setCamera(polygon, this.view_mode)
@@ -83,6 +82,7 @@ export default {
83
82
  uuid: (state) => state.threeDModule.uuid,
84
83
  view_mode: (state) => state.threeDModule.view_mode,
85
84
  isInteractive: (state) => state.threeDModule.isInteractive,
85
+ imageOverlay: (state) => state.threeDModule.imageOverlay,
86
86
  }),
87
87
  ...mapGetters({
88
88
  polygons: 'getPolygons',
@@ -91,7 +91,6 @@ export default {
91
91
  mapConfig: 'getMapConfig',
92
92
  roofsBounds: 'getRoofsBounds',
93
93
  layoutSettings: 'getLayoutSettings',
94
-
95
94
  roofs: 'getRoofs',
96
95
  obstacles: 'getObstacles',
97
96
  moduleFields: 'getModuleFields',
package/src/config.js CHANGED
@@ -65,7 +65,7 @@ export const maxMargin=2500
65
65
  export const node3DRadius=0.05
66
66
  export const beamColor="#ffffff"
67
67
  export const node3DColor="white"
68
- export const beamOpacity=0.3
68
+ export const beamOpacity=0.4
69
69
  export const node3dOpacity=0.3
70
70
  export const dimMarginColor='#ff000020'
71
71
  export const defaultTextureUrl=require('./assets/images/panels/reneSola_Virtus_2_JC320S_24_Bbw.png')
@@ -0,0 +1,75 @@
1
+ import * as THREE from 'three'
2
+ import {beamColor,beamOpacity,node3DColor,node3dOpacity,defaultTextureUrls} from '../config'
3
+ export default {
4
+ data(){
5
+ return {
6
+ material:{}
7
+ }
8
+ },
9
+ created(){
10
+ let wallColor=0xdddddd
11
+ if(this.wallColor){
12
+ wallColor = new THREE.Color(this.wallColor)
13
+ }
14
+ this.material.wall = new THREE.MeshLambertMaterial({
15
+ color: wallColor,
16
+ side:THREE.DoubleSide
17
+ })
18
+
19
+ this.material.obstacle = new THREE.MeshPhongMaterial({
20
+ color: 0xff0000,
21
+ side:THREE.DoubleSide,
22
+ })
23
+
24
+ this.material.edge=new THREE.MeshPhongMaterial({ color: beamColor,transparent:true,opacity:beamOpacity })
25
+ this.material.node=new THREE.PointsMaterial( { size: 0.05, sizeAttenuation: true,color: node3DColor, opacity:node3dOpacity, transparent: true } );
26
+ const loader = new THREE.TextureLoader()
27
+ // loader.crossOrigin = 'anonymous'
28
+ // texture.minFilter = THREE.LinearFilter
29
+ this.material.panel={}
30
+
31
+ for(let k=0;k<defaultTextureUrls.length;k++){
32
+ let texture=loader.load(defaultTextureUrls[k], function (texture) {})
33
+ this.material.panel['default_'+k] = new THREE.MeshBasicMaterial({
34
+ map: texture,
35
+ side: THREE.DoubleSide,
36
+ })
37
+ }
38
+ this.material.roof=[this.material.wall]
39
+
40
+ this.material.flatRoof = new THREE.MeshPhongMaterial({
41
+ color: 0x00ff00,
42
+ specular: 0x009900,
43
+ shininess: 0,
44
+ flatShading: true,
45
+ side:THREE.DoubleSide,
46
+ transparent:true,
47
+ opacity:0.5
48
+ })
49
+
50
+ this.material.moduleField = new THREE.MeshPhongMaterial({
51
+ color: 0xfc9d03,
52
+ specular: 0x000000,
53
+ shininess: 0,
54
+ flatShading: true,
55
+ side:THREE.DoubleSide,
56
+ transparent:true,
57
+ opacity:0.8
58
+ })
59
+ this.material.curvedRoof = new THREE.MeshPhongMaterial({
60
+ color: 0xffff00,
61
+ specular: 0x009900,
62
+ shininess: 0,
63
+ flatShading: true,
64
+ side:THREE.DoubleSide,
65
+ transparent:true,
66
+ opacity:0.5
67
+ })
68
+ },
69
+ watch: {
70
+ wallColor(color) {
71
+ let wallColor = new THREE.Color(color)
72
+ this.material.wall.color.set(wallColor)
73
+ },
74
+ }
75
+ }
@@ -1,40 +1,8 @@
1
1
  import * as THREE from 'three'
2
2
 
3
+
3
4
  export default {
4
5
  methods:{
5
- renderBackground() {
6
- // if(this.meshes.backgroundMesh){
7
- // let sizeInMm={width:2000000,height:2000000}
8
- // let positionInMm={x:0,y:0}
9
- // if(this.layoutSettings.background_map_settings && this.layoutSettings.background_map_settings.sizeInMm){
10
- // sizeInMm=this.layoutSettings.background_map_settings.sizeInMm
11
- // positionInMm=this.layoutSettings.background_map_settings.positionInMm
12
- // }
13
-
14
- // this.meshes.backgroundMesh.geometry.dispose()
15
- // let xMin=positionInMm.x/1000-sizeInMm.width/2000
16
- // let xMax=positionInMm.x/1000+sizeInMm.width/2000
17
- // let yMin=positionInMm.y/1000-sizeInMm.height/2000
18
- // let yMax=positionInMm.y/1000+sizeInMm.height/2000
19
- // let c1=[xMin,yMax,0.1]
20
- // let c2=[xMax,yMax,0.1]
21
- // let c3=[xMax,yMin,0.1]
22
- // let c4=[xMin,yMin,0.1]
23
- // let geometry = new THREE.BufferGeometry();
24
- // const vertices = new Float32Array( [
25
- // ...c1,
26
- // ...c4,
27
- // ...c3,
28
- // ...c3,
29
- // ...c2,
30
- // ...c1
31
- // ] );
32
- // geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
33
- // geometry.computeVertexNormals()
34
- // this.meshes.backgroundMesh.geometry=geometry
35
- // }else{
36
- // this.initialiseThreeMap()
37
- // }
38
- },
6
+
39
7
  }
40
8
  }
@@ -12,13 +12,13 @@ export default {
12
12
  //in case of map, bumpMap, normalMap, envMap ...
13
13
  Object.keys(obj.material).forEach((prop) => {
14
14
  if (!obj.material[prop]) return
15
- if (
15
+ if (false &&
16
16
  obj.material[prop] !== null &&
17
17
  typeof obj.material[prop].dispose === 'function'
18
18
  )
19
19
  obj.material[prop].dispose()
20
20
  })
21
- obj.material.dispose()
21
+ if(obj.material.dispose) obj.material.dispose()
22
22
  }
23
23
  },
24
24
  clearPanelsFromChangingRoofs(roofIds){
@@ -1,6 +1,43 @@
1
1
  import * as THREE from 'three'
2
2
  export default {
3
3
  methods:{
4
+ setCylinderPosition(cylinder,edge){
5
+ const point_0 = new THREE.Vector3(
6
+ edge.outline[0].x / 1000,
7
+ edge.outline[0].y / 1000,
8
+ edge.outline[0].z / 1000
9
+ )
10
+ const point_1 = new THREE.Vector3(
11
+ edge.outline[1].x / 1000,
12
+ edge.outline[1].y / 1000,
13
+ edge.outline[1].z / 1000
14
+ )
15
+
16
+ const midPoint = point_0.clone().add(point_1).multiplyScalar(0.5)
17
+ var direction = new THREE.Vector3().subVectors(point_1, point_0)
18
+ let length = direction.length()
19
+
20
+
21
+
22
+
23
+
24
+ //cylinder.rotation.set(arrow.rotation)
25
+ var axis = new THREE.Vector3(0, 1, 0)
26
+ cylinder.quaternion.setFromUnitVectors(
27
+ axis,
28
+ direction.clone().normalize()
29
+ )
30
+ //cylinder.position.set(new THREE.Vector3().addVectors( pointX, direction.multiplyScalar(0.5) ))
31
+ cylinder.position.copy(midPoint.clone())
32
+ let oldLength = cylinder.userData.cylinderLength
33
+ let newLength = length
34
+ if (!oldLength || oldLength != 0) {
35
+ cylinder.scale.set(1, newLength, 1)
36
+ cylinder.userData.cylinderLength = newLength
37
+ }
38
+ cylinder.updateMatrix()
39
+ return cylinder
40
+ },
4
41
  renderEdges() {
5
42
  this.clearEdgesRemovedOnes('edgeMeshes')
6
43
  let cylinder
@@ -14,67 +51,16 @@ export default {
14
51
  cylinder = this.meshes.edgeMeshes[edge.id]
15
52
  if (cylinder) {
16
53
  //update
17
- const point_0 = new THREE.Vector3(
18
- edge.outline[0].x / 1000,
19
- edge.outline[0].y / 1000,
20
- edge.outline[0].z / 1000
21
- )
22
- const point_1 = new THREE.Vector3(
23
- edge.outline[1].x / 1000,
24
- edge.outline[1].y / 1000,
25
- edge.outline[1].z / 1000
26
- )
27
- const midPoint = point_0.clone().add(point_1).multiplyScalar(0.5)
28
- var direction = new THREE.Vector3().subVectors(point_1, point_0)
29
- let length = direction.length()
30
- //cylinder.rotation.set(arrow.rotation)
31
- var axis = new THREE.Vector3(0, 1, 0)
32
- cylinder.quaternion.setFromUnitVectors(
33
- axis,
34
- direction.clone().normalize()
35
- )
36
- //cylinder.position.set(new THREE.Vector3().addVectors( pointX, direction.multiplyScalar(0.5) ))
37
- cylinder.position.copy(midPoint.clone())
38
- let oldLength = cylinder.userData.cylinderLength
39
- let newLength = length
40
- if (oldLength != 0) {
41
- let scaleRatio = newLength / oldLength
42
- //let scaleVector=direction.multiplyScalar(scaleRatio-1)
43
- cylinder.scale.set(1, newLength, 1)
44
- cylinder.userData.cylinderLength = newLength
45
- }
46
- cylinder.updateMatrix()
54
+ this.setCylinderPosition(cylinder,edge)
47
55
  //change cylinder length
48
56
  } else {
49
- const point_0 = new THREE.Vector3(
50
- edge.outline[0].x / 1000,
51
- edge.outline[0].y / 1000,
52
- edge.outline[0].z / 1000
53
- )
54
- const point_1 = new THREE.Vector3(
55
- edge.outline[1].x / 1000,
56
- edge.outline[1].y / 1000,
57
- edge.outline[1].z / 1000
58
- )
59
-
60
- const midPoint = point_0.clone().add(point_1).multiplyScalar(0.5)
61
- var direction = new THREE.Vector3().subVectors(point_1, point_0)
62
- let length = direction.length()
57
+
63
58
  const geometry = new THREE.CylinderGeometry(0.1, 0.1, 1, 6)
64
59
  cylinder = new THREE.Mesh(geometry, material)
65
- cylinder.scale.set(1, length, 1)
66
- cylinder.userData.cylinderLength = length
67
- //cylinder.rotation.set(arrow.rotation)
68
- var axis = new THREE.Vector3(0, 1, 0)
69
- cylinder.quaternion.setFromUnitVectors(
70
- axis,
71
- direction.clone().normalize()
72
- )
73
- //cylinder.position.set(new THREE.Vector3().addVectors( pointX, direction.multiplyScalar(0.5) ))
74
- cylinder.position.copy(midPoint.clone())
75
- //cylinder.position.set(edge.outline[0].x/1000, edge.outline[0].y/1000, edge.outline[0].z/1000);
60
+ cylinder=this.setCylinderPosition(cylinder,edge)
61
+
76
62
  cylinder.userData.edgeId = edge.id
77
- cylinder.matrixAutoUpdate = false
63
+
78
64
  this.meshes.edgeMeshes[edge.id] = cylinder
79
65
  this.scene.add(cylinder)
80
66
 
@@ -375,6 +375,56 @@ export function getBufferModuleFieldGeometry(moduleFieldPolygon) {
375
375
  return geometry
376
376
  }
377
377
 
378
+ export function getBufferImageOverlayGeometry(corners){
379
+ corners.forEach(p=>p.z=0)
380
+ let normalVector = getNormalVectorFrom3Points(
381
+ corners[0],
382
+ corners[1],
383
+ corners[2]
384
+ )
385
+ if (normalVector.z < 0) {
386
+ normalVector = multiplyVector(-1, normalVector)
387
+ }
388
+
389
+ const geometry = new THREE.BufferGeometry()
390
+ //Calcul of triangles using cutear algo
391
+ const trianglesVertices = []
392
+ trianglesVertices.push(...getTriangleVerticesFromOutline(corners))
393
+ if(hasNaN(trianglesVertices)){return null}
394
+ const vertices = new Float32Array(trianglesVertices)
395
+ var A = corners[2]
396
+ var B = corners[3]
397
+ var C = corners[1]
398
+ var D = corners[0]
399
+ const AB = getDistanceBetweenPoints(A, B)
400
+ const AC = getDistanceBetweenPoints(A, C)
401
+ let uvs
402
+ if (AB < AC) {
403
+ uvs = new Float32Array([
404
+ 0, 1,
405
+ 0, 0,
406
+ 1, 0,
407
+
408
+ 0, 1,
409
+ 1, 0,
410
+ 1, 1
411
+ ])
412
+ }else{
413
+ uvs = new Float32Array([
414
+ 0, 0,
415
+ 1, 0,
416
+ 1, 1,
417
+
418
+ 1, 0,
419
+ 0, 1,
420
+ 1, 1
421
+ ])
422
+ }
423
+ geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))
424
+ geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2))
425
+ geometry.computeVertexNormals()
426
+ return geometry
427
+ }
378
428
  export function getBufferPanelGeometry(panelPolygon) {
379
429
  let panelNormalVector = getNormalVectorFrom3Points(
380
430
  panelPolygon.outline[0],
@@ -384,7 +434,6 @@ export function getBufferPanelGeometry(panelPolygon) {
384
434
  if (panelNormalVector.z < 0) {
385
435
  panelNormalVector = multiplyVector(-1, panelNormalVector)
386
436
  }
387
- const roofPolygon = panelPolygon.roof
388
437
  const panelHeight = parseInt(panelPolygon.height || 50)
389
438
  //get lowest verticalProjection
390
439
 
@@ -0,0 +1,126 @@
1
+ import * as THREE from 'three'
2
+ import {mapGetters} from 'vuex'
3
+ import ProjectedMaterial from 'three-projected-material'
4
+ import {
5
+ substractVector,
6
+ addVector,
7
+ multiplyVector,
8
+ getDistanceBetweenPoints,
9
+ getAngleInDegFromCanvasVector
10
+ } from '@eturnity/eturnity_maths'
11
+ import {getBufferImageOverlayGeometry,updateBufferRoofGeometry} from './geometryHandler'
12
+
13
+ export default {
14
+ data(){
15
+ return {
16
+ imageOverlayProjectionCamera: new THREE.PerspectiveCamera(1, 300 / 300, 100, 1000),
17
+ imageOverlayTexture:null,
18
+ imageOverlayMaterial:null,
19
+ }
20
+ },
21
+ computed:{
22
+ ...mapGetters({
23
+ imageOverlay: 'getImageOverlay',
24
+ }),
25
+ },
26
+ methods:{
27
+ renderImageOverlayOnBackground() {
28
+ if(!this.imageOverlay || !this.imageOverlayMaterial){
29
+ this.clearMesh(this.meshes.backgroundMesh)
30
+ this.meshes.backgroundMesh=null
31
+ return
32
+ }
33
+ let corners=this.imageOverlay.corners.map(p=>{return {...p,z:100}})
34
+ if(this.meshes.backgroundMesh && this.meshes.backgroundMesh.geometry){
35
+ let geometry=this.meshes.backgroundMesh.geometry
36
+ geometry=updateBufferRoofGeometry(corners,[],geometry)
37
+ //updateBufferRoofGeometry(corners,[],geometry)
38
+ this.meshes.backgroundMesh.geometry=geometry
39
+
40
+ }else{
41
+ let planeGeometry = getBufferImageOverlayGeometry(corners)
42
+ let planeMaterial = this.imageOverlayMaterial
43
+
44
+ this.meshes.backgroundMesh = new THREE.Mesh(planeGeometry, planeMaterial)
45
+ this.scene.add(this.meshes.backgroundMesh)
46
+ }
47
+ this.meshes.backgroundMesh.position.z=0.15
48
+ if(this.imageOverlayMaterial){
49
+ this.applyTextureOnMesh([this.imageOverlayMaterial],this.meshes.backgroundMesh)
50
+ }
51
+ this.meshes.backgroundMesh.visible=true
52
+ },
53
+ async changeImageOverlay(){
54
+ if(this.imageOverlayMaterial){
55
+ this.imageOverlayMaterial.dispose()
56
+ this.imageOverlayMaterial=null
57
+ }
58
+ await this.updateProjectionMaterials()
59
+ },
60
+ async getImageOverlayMaterial(){
61
+ if(!this.imageOverlay || !this.imageOverlay.url){
62
+ if(this.imageOverlayMaterial){
63
+ this.imageOverlayMaterial.dispose()
64
+ }
65
+ this.imageOverlayMaterial=null
66
+ return null
67
+ }
68
+
69
+ if(!this.imageOverlayMaterial || this.imageOverlay.url!= this.imageOverlayMaterial.userData.url){
70
+ this.imageOverlayMaterial = await this.newImageOverlayMaterial()
71
+ }else{
72
+ this.setImageOverlayCameraPosition()
73
+ }
74
+ return this.imageOverlayMaterial
75
+ },
76
+ removeImageOverlay(){
77
+ if(this.imageOverlayMaterial && this.imageOverlayMaterial.dispose)
78
+ this.imageOverlayMaterial.dispose()
79
+ this.imageOverlayMaterial=null
80
+ this.material.roof=this.material.roof.filter(material=>material.userData.type!='imageOverlayMaterial')
81
+ },
82
+ async newImageOverlayMaterial(){
83
+ return new Promise((resolve)=>{this.loader.load(this.imageOverlay.url,(texture)=>{
84
+ this.imageOverlayTexture=texture
85
+ this.setImageOverlayCameraPosition()
86
+ let imageOverlayProjectionMaterial = new ProjectedMaterial({
87
+ camera: this.imageOverlayProjectionCamera,
88
+ texture: this.imageOverlayTexture,
89
+ transparent: true,
90
+ side: THREE.DoubleSide,
91
+ depthWrite: false
92
+ })
93
+ imageOverlayProjectionMaterial.userData={}
94
+ imageOverlayProjectionMaterial.userData.type="imageOverlayMaterial"
95
+ imageOverlayProjectionMaterial.userData.priority=2
96
+ imageOverlayProjectionMaterial.userData.url=this.imageOverlay.url
97
+ resolve(imageOverlayProjectionMaterial)
98
+ })
99
+ })
100
+ },
101
+ setImageOverlayCameraPosition(){
102
+ if(!this.imageOverlay || !this.imageOverlay.url) return
103
+ let height=getDistanceBetweenPoints(this.imageOverlay.corners[1],this.imageOverlay.corners[2])
104
+ let width=getDistanceBetweenPoints(this.imageOverlay.corners[0],this.imageOverlay.corners[1])
105
+ this.imageOverlayProjectionCamera.aspect =
106
+ width / height
107
+ let projectionAltitude = height /(2 * Math.tan((this.imageOverlayProjectionCamera.fov * Math.PI) / 360))
108
+
109
+
110
+ //set projection camera over background_map_center
111
+ let imageOverlayProjectionCameraPosition={x:0,y:0,z:projectionAltitude / 1000}
112
+
113
+ let positionInMm=multiplyVector(0.5,addVector(this.imageOverlay.corners[0],this.imageOverlay.corners[2]))
114
+ imageOverlayProjectionCameraPosition.x=positionInMm.x/1000
115
+ imageOverlayProjectionCameraPosition.y=positionInMm.y/1000
116
+
117
+ this.imageOverlayProjectionCamera.position.set(imageOverlayProjectionCameraPosition.x, imageOverlayProjectionCameraPosition.y, projectionAltitude / 1000)
118
+ this.imageOverlayProjectionCamera.lookAt(imageOverlayProjectionCameraPosition.x, imageOverlayProjectionCameraPosition.y,0)
119
+ let zAngle=getAngleInDegFromCanvasVector(substractVector(this.imageOverlay.corners[3],this.imageOverlay.corners[0]))
120
+ this.imageOverlayProjectionCamera.rotation.set(0, 0, zAngle*Math.PI/180)
121
+ this.imageOverlayProjectionCamera.far = projectionAltitude * 1.5
122
+ this.imageOverlayProjectionCamera.near = projectionAltitude * 0.8
123
+ this.imageOverlayProjectionCamera.updateProjectionMatrix()
124
+ },
125
+ }
126
+ }
@@ -9,8 +9,12 @@ import moduleField from './moduleField'
9
9
  import obstacle from './obstacle'
10
10
  import panel from './panel'
11
11
  import roof from './roof'
12
+ import imageOverlay from './imageOverlay'
13
+ import mapProjection from './mapProjection'
14
+ import texture from './texture'
15
+ import projectionMaterial from './projectionMaterial'
12
16
 
13
17
  export default {
14
18
  //mixins:[node,background,clear,edge,loader,margin,moduleField,obstacle,panel,roof,base]
15
- mixins:[margin,node,background, base,roof,edge,obstacle,moduleField,panel,clear,loader]
19
+ mixins:[margin,node,background, base,roof,edge,obstacle,moduleField,panel,clear,loader,imageOverlay,texture,mapProjection,projectionMaterial]
16
20
  }
@@ -1,8 +1,9 @@
1
1
  import * as THREE from 'three'
2
2
  import ProjectedMaterial from 'three-projected-material'
3
+
3
4
  export default {
4
5
  methods:{
5
- loadNewTexture(){
6
+ loadNewPanelTextures(){
6
7
  Object.values(this.pvDataMemo).forEach((component) => {
7
8
  const pvId = component.id
8
9
  if (!this.material.panel[pvId]) {
@@ -19,7 +20,7 @@ export default {
19
20
  }
20
21
  })
21
22
  },
22
- async loadTextureFromModuleFields(){
23
+ async loadPanelsTexture(){
23
24
  for(let k=0;k<this.moduleFields.length;k++){
24
25
  let mf=this.moduleFields[k]
25
26
  const pvId = mf.data.component_id_pv_module
@@ -37,63 +38,5 @@ export default {
37
38
  }
38
39
  }
39
40
  },
40
- async loadProjectionMaterial() {
41
- const _this=this
42
- if(!this.layoutSettings.base64_image_url)
43
- {
44
- this.loader.load(require("../../assets/images/white_tile.png"),(texture)=>{
45
- let projectionMaterial = new ProjectedMaterial({
46
- camera: _this.cameraprojection,
47
- texture: texture
48
- })
49
- this.material.roof = projectionMaterial
50
- })
51
- return
52
- }
53
- let projectedMaterialLoaded= await new Promise((resolve,reject) => {
54
- this.loader.load(this.layoutSettings.base64_image_url,(texture)=>{
55
- let backgroundImageZoomLvl=_this.layoutSettings.map_zoom
56
- let backgroundImageCenter={
57
- lat:_this.layoutSettings.layout_latitude,
58
- lng:_this.layoutSettings.layout_longitude
59
- }
60
- if(_this.layoutSettings.background_map_settings){
61
- backgroundImageZoomLvl=_this.layoutSettings.background_map_settings.zoom_lvl
62
- backgroundImageCenter={
63
- lat:_this.layoutSettings.background_map_settings.lat,
64
- lng:_this.layoutSettings.background_map_settings.lng
65
- }
66
- }
67
- _this.backgroundImagesizeInMm=_this.layoutSettings.background_map_settings.sizeInMm
68
- if (_this.backgroundImagesizeInMm) {
69
- _this.cameraprojection.aspect =
70
- _this.backgroundImagesizeInMm.width / _this.backgroundImagesizeInMm.height
71
- let projectionAltitude =
72
- _this.backgroundImagesizeInMm.height /
73
- (2 * Math.tan((_this.cameraprojection.fov * Math.PI) / 360))
74
-
75
-
76
- //set projection camera over background_map_center
77
- let cameraProjectionPosition={x:0,y:0,z:projectionAltitude / 1000}
78
- if(_this.layoutSettings.background_map_settings && _this.layoutSettings.background_map_settings.positionInMm){
79
- let positionInMm=this.layoutSettings.background_map_settings.positionInMm
80
- cameraProjectionPosition.x=positionInMm.x/1000
81
- cameraProjectionPosition.y=positionInMm.y/1000
82
- }
83
-
84
- _this.cameraprojection.position.set(cameraProjectionPosition.x, cameraProjectionPosition.y, projectionAltitude / 1000)
85
- _this.cameraprojection.far = projectionAltitude * 16
86
- _this.cameraprojection.updateProjectionMatrix()
87
- }
88
-
89
- let projectionMaterial = new ProjectedMaterial({
90
- camera: _this.cameraprojection,
91
- texture: texture
92
- })
93
- resolve(projectionMaterial)
94
- })
95
- })
96
- this.material.roof =projectedMaterialLoaded
97
- },
98
41
  }
99
42
  }
@@ -0,0 +1,86 @@
1
+ import * as THREE from 'three'
2
+ import ProjectedMaterial from 'three-projected-material'
3
+
4
+ export default {
5
+ data(){
6
+ return {
7
+ mapProjectionTexture:null,
8
+ mapProjectionMaterial:null
9
+ }
10
+ },
11
+ methods:{
12
+ async changeMapProjection(){
13
+ if(this.mapProjectionMaterial){
14
+ this.mapProjectionMaterial.dispose()
15
+ this.mapProjectionMaterial=null
16
+ }
17
+ await this.updateProjectionMaterials()
18
+ },
19
+ async getMapProjectionMaterial(){
20
+ if(!this.layoutSettings.base64_image_url){
21
+ return null
22
+ }else{
23
+ if(!this.mapProjectionMaterial){
24
+ this.mapProjectionMaterial = await this.newMapProjectionMaterial()
25
+ }else{
26
+ this.setMapProjectionCameraPosition()
27
+ }
28
+ }
29
+ return this.mapProjectionMaterial
30
+ },
31
+
32
+ async newMapProjectionMaterial() {
33
+ return new Promise((resolve,reject) => {
34
+ this.loader.load(this.layoutSettings.base64_image_url,(texture)=>{
35
+ this.mapProjectionTexture=texture
36
+ this.setMapProjectionCameraPosition()
37
+ let mapProjectionMaterial = new ProjectedMaterial({
38
+ camera: this.cameraprojection,
39
+ texture: texture,
40
+ transparent: true,
41
+ side: THREE.DoubleSide,
42
+ })
43
+ mapProjectionMaterial.userData={}
44
+ mapProjectionMaterial.userData.type="mapProjectionMaterial"
45
+ mapProjectionMaterial.userData.priority=1
46
+ mapProjectionMaterial.userData.url=this.layoutSettings.base64_image_url
47
+ resolve(mapProjectionMaterial)
48
+ })
49
+ })
50
+ },
51
+ setMapProjectionCameraPosition(){
52
+ let backgroundImageCenter={
53
+ lat:this.layoutSettings.layout_latitude,
54
+ lng:this.layoutSettings.layout_longitude
55
+ }
56
+ if(this.layoutSettings.background_map_settings){
57
+ backgroundImageCenter={
58
+ lat:this.layoutSettings.background_map_settings.lat,
59
+ lng:this.layoutSettings.background_map_settings.lng
60
+ }
61
+ }
62
+ this.backgroundImagesizeInMm=this.layoutSettings.background_map_settings.sizeInMm
63
+ if (this.backgroundImagesizeInMm) {
64
+ this.cameraprojection.aspect =
65
+ this.backgroundImagesizeInMm.width / this.backgroundImagesizeInMm.height
66
+ let projectionAltitude =
67
+ this.backgroundImagesizeInMm.height /
68
+ (2 * Math.tan((this.cameraprojection.fov * Math.PI) / 360))
69
+
70
+ //set projection camera over background_map_center
71
+ let cameraProjectionPosition={x:0,y:0,z:projectionAltitude / 1000}
72
+ if(this.layoutSettings.background_map_settings && this.layoutSettings.background_map_settings.positionInMm){
73
+ let positionInMm=this.layoutSettings.background_map_settings.positionInMm
74
+ cameraProjectionPosition.x=positionInMm.x/1000
75
+ cameraProjectionPosition.y=positionInMm.y/1000
76
+ }
77
+
78
+ this.cameraprojection.position.set(cameraProjectionPosition.x, cameraProjectionPosition.y, projectionAltitude / 1000)
79
+ this.cameraprojection.far = projectionAltitude * 1.5
80
+ this.cameraprojection.near = projectionAltitude * 0.5
81
+ this.cameraprojection.updateProjectionMatrix()
82
+ }
83
+ },
84
+
85
+ }
86
+ }
@@ -3,7 +3,6 @@ import {
3
3
  getBufferObstacleGeometry,
4
4
  getBufferObstacleSideGeometry,
5
5
  } from './geometryHandler'
6
- import { material } from '../materials'
7
6
  export default {
8
7
  methods:{
9
8
  renderObstacles() {
@@ -24,13 +23,8 @@ export default {
24
23
  )
25
24
  if (geometry && geometrySide) {
26
25
  const mesh = new THREE.Mesh(geometry, this.material.roof)
27
- const meshSide = new THREE.Mesh(geometrySide, material.wall)
28
- mesh.material=this.material.roof
29
- if(this.material.roof && this.material.roof.project){
30
- this.material.roof.project(mesh)
31
- }else{
32
- mesh.material=this.material.wall
33
- }
26
+ const meshSide = new THREE.Mesh(geometrySide, this.material.wall)
27
+ this.applyTextureOnMesh(this.material.roof,mesh)
34
28
 
35
29
  mesh.userData.version = obstaclePolygon.version
36
30
  mesh.userData.type = 'obstacleMeshes'
@@ -0,0 +1,57 @@
1
+ export default {
2
+ methods:{
3
+ reorderRoofMaterials(){
4
+ this.material.roof.sort((a,b)=>{
5
+ let aPrio=a.priority || 0
6
+ let bPrio=b.priority || 0
7
+ return aPrio-bPrio
8
+ })
9
+ },
10
+ async updateProjectionMaterials(){
11
+ this.setImageOverlayCameraPosition()
12
+ let materialPromises=[
13
+ this.getMapProjectionMaterial(),
14
+ this.getImageOverlayMaterial()
15
+ ]
16
+ let materials = await Promise.all(materialPromises)
17
+ this.mapProjectionMaterial = materials[0]
18
+ this.imageOverlayMaterial= materials[1]
19
+
20
+ let index=this.material.roof.findIndex(material=>material.userData.type=="mapProjectionMaterial")
21
+ if(this.mapProjectionMaterial){
22
+ if(index>=0){
23
+ this.material.roof[index]=this.mapProjectionMaterial
24
+ this.material.roof=[...this.material.roof]
25
+ }else{
26
+ this.material.roof=[...this.material.roof,this.mapProjectionMaterial]
27
+ this.reorderRoofMaterials()
28
+ }
29
+ }else if(index>=0){
30
+ this.material.roof[index].dispose()
31
+ this.material.roof.splice(index,1)
32
+ this.material.roof=[...this.material.roof]
33
+ this.reorderRoofMaterials()
34
+ }
35
+
36
+ index=this.material.roof.findIndex(material=> material.userData.type=="imageOverlayMaterial")
37
+ if(this.imageOverlayMaterial){
38
+ if(index>=0){
39
+ this.material.roof[index]=this.imageOverlayMaterial
40
+ this.material.roof=[...this.material.roof]
41
+ }else{
42
+ this.material.roof=[...this.material.roof,this.imageOverlayMaterial]
43
+ this.reorderRoofMaterials()
44
+ }
45
+ }else if(index>=0){
46
+ this.material.roof[index].dispose()
47
+ this.material.roof.splice(index,1)
48
+ this.material.roof=[...this.material.roof]
49
+ this.reorderRoofMaterials()
50
+ }
51
+ this.renderImageOverlayOnBackground()
52
+ this.applyTextureOnRoofs()
53
+ },
54
+
55
+
56
+ }
57
+ }
@@ -68,6 +68,19 @@ export default {
68
68
 
69
69
  return geometry
70
70
  },
71
+
72
+ applyTextureOnRoofs(){
73
+ this.roofs.forEach(roof=>{
74
+ //roofs
75
+ let mesh=this.meshes.roofMeshes[roof.id]
76
+ this.applyTextureOnMesh(this.material.roof,mesh)
77
+ //obstacle on roof
78
+ roof.holes.filter(p=>p.layer=="obstacle").forEach(obstacle=>{
79
+ let meshObstacle=this.meshes.obstacleMeshes[obstacle.id + '-' + roof.id + '_top']
80
+ this.applyTextureOnMesh(this.material.roof,meshObstacle)
81
+ })
82
+ })
83
+ },
71
84
  renderRoofs() {
72
85
  this.clearRemovedOnes('roofMeshes')
73
86
  this.roofs.forEach((roofPolygon) => {
@@ -82,17 +95,18 @@ export default {
82
95
  mesh = this.meshes.roofMeshes[roofPolygon.id]
83
96
  geometry = mesh.geometry
84
97
  geometry = this.updateRoofGeometry(geometry, roofPolygon)
98
+ //in order to be able to render multiple material on it (background and image overlay)
99
+
85
100
  mesh.geometry = geometry
86
- if(this.material.roof){
87
- mesh.material=this.material.roof
88
- if(this.material.roof && this.material.roof.project) this.material.roof.project(mesh)
89
- }
101
+ this.applyTextureOnMesh(this.material.roof,mesh)
102
+
90
103
  mesh.frustumCulled = false
91
104
  mesh.updateMatrix()
92
105
  }
93
106
  if (!this.meshes.roofMeshes[roofPolygon.id]) {
94
107
  //create
95
108
  geometry = this.createRoofGeometry(roofPolygon)
109
+
96
110
  if (geometry) {
97
111
  mesh = new THREE.Mesh(geometry, this.material.roof)
98
112
  mesh.userData.version = roofPolygon.version
@@ -101,10 +115,7 @@ export default {
101
115
  mesh.userData.polygonId = roofPolygon.id
102
116
  mesh.matrixAutoUpdate = false
103
117
  this.scene.add(mesh)
104
- if(this.material.roof){
105
- mesh.material=this.material.roof
106
- if(this.material.roof.project) this.material.roof.project(mesh)
107
- }
118
+ this.applyTextureOnMesh(this.material.roof,mesh)
108
119
  mesh.frustumCulled = false
109
120
  this.meshes.roofMeshes[roofPolygon.id] = mesh
110
121
  }
@@ -0,0 +1,19 @@
1
+ export default {
2
+ methods:{
3
+ applyTextureOnMesh(materials,mesh){
4
+ if(materials && materials.length>0){
5
+ let geometry=mesh.geometry
6
+ geometry.clearGroups();
7
+ for(let k=0;k<materials.length;k++){
8
+ geometry.addGroup( 0, Infinity, k )
9
+ }
10
+ mesh.material=materials
11
+ for(let m=0;m<materials.length;m++){
12
+ if(materials[m].project) {
13
+ materials[m].project(mesh)
14
+ }
15
+ }
16
+ }
17
+ },
18
+ }
19
+ }
@@ -36,10 +36,6 @@ export default {
36
36
  roofMarginMeshes: {},
37
37
  moduleFieldsMeshes: {}
38
38
  }
39
- if (this.wallColor) {
40
- let wallColor = new THREE.Color(this.wallColor)
41
- this.material.wall.color.set(wallColor)
42
- }
43
39
  },
44
40
 
45
41
  computed: {
@@ -206,9 +202,41 @@ export default {
206
202
  method: this.initialiseThreeMap,
207
203
  arg: []
208
204
  })
205
+ break
206
+ case 'changeMapProjection':
207
+ methodList.push({
208
+ name: 'changeMapProjection',
209
+ method: this.changeMapProjection,
210
+ arg: []
211
+ })
209
212
  methodList.push({
210
- name: 'updateProjectionMaterial',
211
- method: this.updateProjectionMaterial,
213
+ name: 'applyTextureOnRoofs',
214
+ method: this.applyTextureOnRoofs,
215
+ arg: []
216
+ })
217
+ break
218
+ // methodList.push({
219
+ // name: 'removeImageOverlay',
220
+ // method: this.removeImageOverlay,
221
+ // arg: []
222
+ // })
223
+ // methodList.push({
224
+ // name: 'applyTextureOnBackground',
225
+ // method: this.renderImageOverlayOnBackground,
226
+ // arg: []
227
+ // })
228
+ // methodList.push({
229
+ // name: 'applyTextureOnRoofs',
230
+ // method: this.applyTextureOnRoofs,
231
+ // arg: []
232
+ // })
233
+ // break
234
+ case 'removeImageOverlay':
235
+ case 'changeImageOverlay':
236
+ case 'updateImageOverlay':
237
+ methodList.push({
238
+ name: 'updateProjectionMaterials()',
239
+ method: this.updateProjectionMaterials,
212
240
  arg: []
213
241
  })
214
242
  break
@@ -228,11 +256,11 @@ export default {
228
256
  }
229
257
  },
230
258
  renderGeometry() {
231
- this.renderBackground()
232
259
  this.renderBuilding()
233
260
  this.renderModuleFields()
234
261
  this.renderPanels()
235
262
  this.renderRoofsMargin()
263
+ this.updateProjectionMaterials()
236
264
  },
237
265
  renderBuilding() {
238
266
  this.renderBase()
@@ -242,32 +270,10 @@ export default {
242
270
  this.renderEdges()
243
271
  this.renderFlatRoofs()
244
272
  },
245
-
246
- applyTextureOnRoofs() {
247
- this.roofs.forEach((roof) => {
248
- //roofs
249
- let mesh = this.meshes.roofMeshes[roof.id]
250
- mesh.material = this.material.roof
251
- if (this.material.roof && this.material.roof.project) {
252
- this.material.roof.project(mesh)
253
- }
254
- //obstacle on roof
255
- roof.holes
256
- .filter((p) => p.layer == 'obstacle')
257
- .forEach((obstacle) => {
258
- let meshObstacle =
259
- this.meshes.obstacleMeshes[obstacle.id + '-' + roof.id + '_top']
260
- meshObstacle.material = this.material.roof
261
- if (this.material.roof && this.material.roof.project)
262
- this.material.roof.project(meshObstacle)
263
- })
264
- })
265
- },
266
-
267
- async updateProjectionMaterial() {
268
- await this.loadProjectionMaterial()
273
+
274
+ async initializeProjectionMaterial(){
275
+ await this.updateProjectionMaterials()
269
276
  this.applyTextureOnRoofs()
270
- this.renderBackground()
271
277
  },
272
278
 
273
279
  getCanvasOffset() {
@@ -320,13 +326,9 @@ export default {
320
326
  }
321
327
  },
322
328
  watch: {
323
- wallColor(color) {
324
- let wallColor = new THREE.Color(color)
325
- this.material.wall.color.set(wallColor)
326
- },
327
329
  pvDataMemo: {
328
330
  handler(val) {
329
- this.loadNewTexture()
331
+ this.loadNewPanelTextures()
330
332
  }
331
333
  },
332
334
  'material.panel': {
@@ -360,7 +362,10 @@ export default {
360
362
  this.scene = null
361
363
  this.camera = null
362
364
  this.cameraprojection = null
363
- this.material.forEach((m) => m.dispose())
365
+ Object.values(this.material).forEach((m) =>{
366
+ if(m && m.dispose)
367
+ m.dispose()
368
+ } )
364
369
  this.material = null
365
370
  this.orbitControl = null
366
371
  this.raycaster = null
@@ -15,6 +15,7 @@ export async function hydrateData({ state, commit }, data) {
15
15
  let obstaclesResponse = data.obstacles
16
16
  let moduleFieldsResponse = data.moduleFields
17
17
  const layoutSettingResponse = data.layoutSettings
18
+ const imageOverlayResponse = data.imageOverlay
18
19
  //removing empty roof,obstacle and modulefield generated by BE on variant creation
19
20
  roofsResponse=roofsResponse.reduce((acc,cur)=>{
20
21
  if(cur.roof_outline.length>0){acc.push(cur)}
@@ -29,9 +30,17 @@ export async function hydrateData({ state, commit }, data) {
29
30
  return acc
30
31
  },[])
31
32
 
33
+ if (imageOverlayResponse && imageOverlayResponse.image_overlay_url) {
34
+ let imageOverlay = {
35
+ url: imageOverlayResponse.image_overlay_url,
36
+ uuid: imageOverlayResponse.image_overlay_uuid,
37
+ corners: imageOverlayResponse.image_overlay_settings.corners
38
+ }
39
+ commit('mutate_imageOverlay', imageOverlay)
40
+ }
41
+
32
42
  if (!!layoutSettingResponse) {
33
43
  const layoutSetting = layoutSettingResponse
34
- console.log(layoutSetting)
35
44
  const moduleTextureVersionId=layoutSetting.module_texture_version_id || 0
36
45
  commit('mutate_layoutSettings', layoutSetting)
37
46
  commit('mutate_moduleTextureVersionId',moduleTextureVersionId)
@@ -19,6 +19,7 @@ const init_state = {
19
19
  cancelTokenGlobal: '',
20
20
  globalProjectProperties: [],
21
21
  buildingLocation: null,
22
+ imageOverlay:null,
22
23
  layoutSettings: {
23
24
  base64_image_url: null,
24
25
  layout_latitude: null,
@@ -35,6 +36,7 @@ const init_state = {
35
36
  panelOpacity:1,
36
37
  selectedMapLayer:null,
37
38
  globalProjectProperties: [],
39
+ imageOverlay:null
38
40
  }
39
41
 
40
42
  const state = init_state
@@ -87,7 +89,9 @@ const getters = {
87
89
  getBuildingLocation(state) {
88
90
  return state.buildingLocation
89
91
  },
90
-
92
+ getImageOverlay(state){
93
+ return state.imageOverlay
94
+ },
91
95
  getLayoutSettings(state) {
92
96
  return state.layoutSettings
93
97
  },
@@ -116,6 +120,9 @@ const mutations = {
116
120
  mutate_layoutSettings(state, value) {
117
121
  state.layoutSettings = value
118
122
  },
123
+ mutate_imageOverlay(state, value) {
124
+ state.imageOverlay = value
125
+ },
119
126
  mutate_selectedZoom(state, value) {
120
127
  state.selectedZoom = value
121
128
  },