Project.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. <template>
  2. <div>
  3. <object3d ref="block3d" name="Project" :obj="building" :position="building_position"/>
  4. <object3d ref="top" :obj="top_mesh" :position="top_position"/>
  5. <object3d ref="floor" :obj="floor_mesh" :position="floor_position"/>
  6. <!-- <light :obj="light" :position="building_position" /> -->
  7. <mesh ref="label3d" name="Label" :position="label_position">
  8. <geometry type="Plane" :args="[label_size.x, label_size.y]" />
  9. <material type="MeshLambert" :options="label_opts">
  10. <texture :options="label_texture_opts" />
  11. </material>
  12. </mesh>
  13. <div v-if="isOpened">
  14. <ContentBlock
  15. v-for="item in data.visibles"
  16. :key="item.id"
  17. :prtPosition="position"
  18. :prtSize="size"
  19. type="visible"
  20. :data="item"
  21. />
  22. <ContentBlock
  23. v-for="item in data.contexts"
  24. :key="item.id"
  25. :prtPosition="position"
  26. :prtSize="size"
  27. type="context"
  28. :data="item"
  29. />
  30. <ContentBlock
  31. v-for="item in data.processes"
  32. :key="item.id"
  33. :prtPosition="position"
  34. :prtSize="size"
  35. type="process"
  36. :data="item"
  37. />
  38. <ContentBlock
  39. v-for="item in data.concepts"
  40. :key="item.id"
  41. :prtPosition="position"
  42. :prtSize="size"
  43. type="concept"
  44. :data="item"
  45. />
  46. </div>
  47. </div>
  48. </template>
  49. <script>
  50. import * as THREE from 'three'
  51. // import { toCSG, fromCSG } from 'three-csg'
  52. import { ThreeBSP } from 'three-js-csg-es6'
  53. import mixins from 'components/mixins'
  54. import ContentBlock from 'components/objects/ContentBlock'
  55. // import BgVertex from 'assets/glsl/BgVertex'
  56. // import BuildingFragment from 'assets/glsl/BuildingFragment'
  57. export default {
  58. name: 'Project',
  59. components: {
  60. ContentBlock
  61. },
  62. mixins: [mixins],
  63. // props: { size: Object, texture: String, position: Object, color: Number },
  64. props: { data: Object, len: Number, index: Number },
  65. data () {
  66. console.log('Project data() : data', this.data)
  67. // get size and positions from project store
  68. let size = { ...this.data.size }
  69. let position = { ...this.data.position }
  70. // http://learningthreejs.com/blog/2011/12/10/constructive-solid-geometry-with-csg-js/
  71. // console.log('ThreeBSP', ThreeBSP)
  72. let wallW = 0.001
  73. let backGeom = new THREE.BoxGeometry(size.x, size.y, wallW)
  74. let backMesh = new THREE.Mesh(backGeom)
  75. backMesh.position.z = -0.5 * size.z
  76. let backBSP = new ThreeBSP(backMesh)
  77. // dig windows on face and back
  78. let winW = 2 + Math.random() * 2
  79. let winH = 4 + Math.random() * 4
  80. let margin = 2
  81. let nbrWinX = 0
  82. let paddingX = 0
  83. let a = 0
  84. // removing windows until padding is enough
  85. while (paddingX < 0.4) {
  86. nbrWinX = Math.floor((size.x - 2 * margin) / winW) - a
  87. paddingX = (size.x - 2 * margin - winW * nbrWinX) / (nbrWinX - 1)
  88. a++
  89. }
  90. // console.log('paddingX', paddingX)
  91. let nbrWinY = 0
  92. let paddingY = 0
  93. a = 0
  94. // removing windows until padding is enough
  95. while (paddingY < 0.4) {
  96. nbrWinY = Math.floor((size.y - 2 * margin) / winH) - a
  97. paddingY = (size.y - 2 * margin - winH * nbrWinY) / (nbrWinY - 1)
  98. a++
  99. }
  100. let winGeom = new THREE.BoxGeometry(winW, winH, wallW)
  101. let winMesh, winBSP
  102. for (var i = 0; i < nbrWinX; i++) {
  103. for (var j = 0; j < nbrWinY; j++) {
  104. // back
  105. winMesh = new THREE.Mesh(winGeom)
  106. winMesh.position.z = -0.5 * size.z
  107. winMesh.position.x = -0.5 * size.x + margin + winW * 0.5 + i * (winW + paddingX)
  108. winMesh.position.y = 0.5 * size.y - margin - winH * 0.5 - j * (winH + paddingY)
  109. winBSP = new ThreeBSP(winMesh)
  110. backBSP = backBSP.subtract(winBSP)
  111. }
  112. }
  113. // let abovewWaterH = position.y + size.y / 2
  114. // let underWaterHThd = (-1 * position.y - size.y / 2) / 3
  115. // let levelH = 4
  116. // let levelGeom = new THREE.BoxGeometry(size.x, levelH, wallW)
  117. // let levelMesh, levelBSP
  118. // for (var l = 0; l < 2; l++) {
  119. // levelMesh = new THREE.Mesh(levelGeom)
  120. // levelMesh.position.z = -0.5 * size.z
  121. // levelMesh.position.y = 0.5 * size.y - abovewWaterH - underWaterHThd - underWaterHThd * l + levelH * 0.5
  122. // levelBSP = new ThreeBSP(levelMesh)
  123. // backBSP = backBSP.union(levelBSP)
  124. // }
  125. backMesh = backBSP.toMesh()
  126. let faceMesh = backMesh.clone()
  127. faceMesh.position.z = 0.5 * size.z
  128. let faceBSP = new ThreeBSP(faceMesh)
  129. let rightGeom = new THREE.BoxGeometry(wallW, size.y, size.z)
  130. let rightMesh = new THREE.Mesh(rightGeom)
  131. rightMesh.position.x = 0.5 * size.x
  132. // rightMesh.position.z = 0.5 * size.z
  133. let rightBSP = new ThreeBSP(rightMesh)
  134. // WE MAY NO NEED TO DIG WINDOWS ON SIDE WALLS
  135. // // dig windows on right
  136. // let nbrWinZ = Math.floor((size.z - 2 * margin) / winW)
  137. // let paddingZ = (size.z - 2 * margin - winW * nbrWinZ) / (nbrWinX - 1)
  138. // winGeom = new THREE.BoxGeometry(wallW, winH, winW)
  139. // for (i = 0; i < nbrWinZ; i++) {
  140. // for (j = 0; j < nbrWinY; j++) {
  141. // // right
  142. // winMesh = new THREE.Mesh(winGeom)
  143. // winMesh.position.x = 0.5 * size.x
  144. // winMesh.position.z = -0.5 * size.z + margin + winW * 0.5 + i * (winW + paddingZ)
  145. // winMesh.position.y = 0.5 * size.y - margin - winH * 0.5 - j * (winH + paddingY)
  146. // winBSP = new ThreeBSP(winMesh)
  147. // rightBSP = rightBSP.subtract(winBSP)
  148. // }
  149. // }
  150. // rightMesh = rightBSP.toMesh()
  151. let leftMesh = rightMesh.clone()
  152. leftMesh.position.x = -0.5 * size.x
  153. // leftMesh.position.z = 0.5 * size.z
  154. let leftBSP = new ThreeBSP(leftMesh)
  155. //
  156. // let topGeom = new THREE.BoxGeometry(size.x, wallW, size.z)
  157. // let topMesh = new THREE.Mesh(topGeom)
  158. // // topMesh.position.y = -0.5 * size.y
  159. // // let topBSP = new ThreeBSP(topMesh)
  160. //
  161. // let floorGeom = new THREE.BoxGeometry(size.x, wallW, size.z)
  162. // let floorMesh = new THREE.Mesh(floorGeom)
  163. // // floorMesh.position.y = 0.5 * size.y
  164. // // let floorBSP = new ThreeBSP(floorMesh)
  165. let buildingBSP = backBSP.union(rightBSP)
  166. buildingBSP = buildingBSP.union(faceBSP)
  167. buildingBSP = buildingBSP.union(leftBSP)
  168. // buildingBSP = buildingBSP.union(topBSP)
  169. // buildingBSP = buildingBSP.union(floorBSP)
  170. // convert back to three.js mesh
  171. let building = buildingBSP.toMesh()
  172. console.log('building.faces', building)
  173. // create a custom shaderMaterial to had gradian colors
  174. // var uniforms = THREE.UniformsUtils.merge([
  175. // THREE.UniformsLib['lights'],
  176. // {
  177. // 'topColor': { value: new THREE.Color(0xffffff) },
  178. // 'groundColor': { value: new THREE.Color(0xbcd6e4) },
  179. // 'bottomColor': { value: new THREE.Color(0x07223b) },
  180. // // 'bottomColor': { value: new THREE.Color(0x000000) },
  181. // // 'groundColor': { value: new THREE.Color(0xff0000) },
  182. // // 'bottomColor': { value: new THREE.Color(0x00ff00) },
  183. // lightIntensity: { type: 'f', value: 1.0 }
  184. // }
  185. // ])
  186. // var buildingMat = new THREE.ShaderMaterial({
  187. // uniforms: uniforms,
  188. // vertexShader: BgVertex,
  189. // fragmentShader: BuildingFragment,
  190. // side: THREE.DoubleSide,
  191. // lights: true
  192. // })
  193. // building.material = buildingMat
  194. // create a classical material for building
  195. // let topColor = `hsla(201, 100%, 95%, 1)`
  196. let hTop = Math.round(195 + Math.random() * 10)
  197. let sTop = Math.round(100)
  198. let lTop = Math.round(95)
  199. let hFloor = Math.round(205 + Math.random() * 10)
  200. let sFloor = Math.round(40 + Math.random() * 20)
  201. let lFloor = Math.round(5 + Math.random() * 15)
  202. let topColor = `hsla(${hTop}, ${sTop}%, ${lTop}%, 1)`
  203. let bottomColor = `hsla(${hFloor}, ${sFloor}%, ${lFloor}%, 1)`
  204. let gradientTexture = new THREE.CanvasTexture(this.createGradientCanvas(topColor, bottomColor))
  205. let materialOpts = {
  206. color: 0xffffff,
  207. side: THREE.DoubleSide,
  208. shininess: 30,
  209. map: gradientTexture
  210. // wireframe: true,
  211. // transparent: true,
  212. // opacity: 0.6
  213. // renderOrder: 0
  214. }
  215. building.material = new THREE.MeshPhongMaterial(materialOpts)
  216. // building.castShadow = true
  217. // building.receiveShadow = true
  218. // let buildingGeom = fromCSG(boxCSG)
  219. // buildingGeom.computeVertexNormals()
  220. // result
  221. // let subtractCSG = boxMeshCSG.subtract(holeMeshCSG)
  222. // let building = fromCSG(boxMeshCSG) // converting CSG back into ThreeJS object
  223. //
  224. let buildingPos = { ...position }
  225. buildingPos.z -= 0.5 * size.z
  226. // let light = new THREE.PointLight(0xfcfcf9, 1)
  227. // var sun = new THREE.DirectionalLight(0xfcfcf9, 2)
  228. // sun.position.set(-150, 200, 110)
  229. let topGeom = new THREE.BoxGeometry(size.x, wallW, size.z)
  230. let topOpts = {
  231. color: new THREE.Color(`hsl(${hTop}, ${sTop}%, ${lTop}%)`),
  232. // side: THREE.DoubleSide,
  233. shininess: 30
  234. }
  235. let topMat = new THREE.MeshPhongMaterial(topOpts)
  236. let topMesh = new THREE.Mesh(topGeom, topMat)
  237. let topPosition = { ...position }
  238. topPosition.y += 0.5 * size.y
  239. let floorGeom = new THREE.BoxGeometry(size.x, wallW, size.z)
  240. let floorOpts = {
  241. color: new THREE.Color(`hsl(${hFloor}, ${sFloor}%, ${lFloor}%)`),
  242. // side: THREE.DoubleSide,
  243. shininess: 10
  244. }
  245. let floorMat = new THREE.MeshPhongMaterial(floorOpts)
  246. let floorMesh = new THREE.Mesh(floorGeom, floorMat)
  247. let floorPosition = { ...position }
  248. floorPosition.y -= 0.5 * size.y
  249. return {
  250. block3d: null,
  251. // block_opts: materialOpts,
  252. label3d: null,
  253. label_opts: {
  254. side: THREE.DoubleSide,
  255. // wireframe: false,
  256. transparent: true
  257. // opacity: 0.6
  258. // renderOrder: 0
  259. },
  260. // size and positions are defined in store project
  261. size: size,
  262. position: position,
  263. // geometry: geometry,
  264. // light: light,
  265. building: building,
  266. building_position: buildingPos,
  267. top_mesh: topMesh,
  268. top_position: topPosition,
  269. floor_mesh: floorMesh,
  270. floor_position: floorPosition,
  271. label_position: { x: 0, y: 0, z: 0 },
  272. color: 0xffffff,
  273. label_canvas: null,
  274. label_size: null,
  275. isOpened: false
  276. }
  277. },
  278. computed: {
  279. label_texture_opts () {
  280. return {
  281. canvas: this.label_canvas,
  282. minFilter: THREE.LinearFilter,
  283. wrapS: THREE.ClampToEdgeWrapping,
  284. wrapT: THREE.ClampToEdgeWrapping
  285. }
  286. }
  287. },
  288. created () {
  289. console.log('Project created: data', this, this.data)
  290. this.label_canvas = this.createLabelCanvas(this.data.Titre.replace(/ /g, '\n').toUpperCase(), 48, 21, '#000000', '#ffffff')
  291. this.label_position.x = this.position.x - this.size.x / 2 + this.label_size.x / 2 + 1
  292. this.label_position.y = this.position.y + this.size.y / 2 - this.label_size.y / 2 - 1
  293. this.label_position.z = this.position.z + this.size.z / 2 + 0.5
  294. // console.log('this.label_canvas', this.label_canvas)
  295. },
  296. mounted () {
  297. console.log('project mounted', this)
  298. // record self references
  299. this.block3d = this.$refs.block3d.curObj
  300. // this.block3d.castShadow = true
  301. // this.block3d.receiveShadow = true
  302. this.block3d.userData = {
  303. vnode: this
  304. }
  305. this.label3d = this.$refs.label3d.curObj
  306. // light
  307. // console.log('project mounted', this.$env3d)
  308. // var light = new THREE.AmbientLight(0xbf1a1a) // soft white light
  309. // this.$env3d.scene.add(light)
  310. }
  311. // ,
  312. // methods: {
  313. //
  314. // }
  315. }
  316. </script>