project.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. // https://codeburst.io/dynamic-modules-with-vuex-and-vue-b9c481ca792
  2. // https://www.brophy.org/post/instance-aware-vuex-modules-1/
  3. // import qs from 'querystring'
  4. // import { REST } from 'api/rest-axios'
  5. import { GRAPHQL } from 'api/graphql-axios'
  6. import * as THREE from 'three'
  7. import { ThreeBSP } from 'three-js-csg-es6'
  8. export default {
  9. namespaced: true,
  10. // initial state
  11. state: {
  12. obj3d: null,
  13. size: { x: 0, y: 0, z: 0 },
  14. position: { x: 0, y: 0, z: 0 },
  15. walls3dObj: null,
  16. wallsPos: null,
  17. top3dObj: null,
  18. topPos: null,
  19. topColor: null,
  20. floor3dObj: null,
  21. floorPos: null,
  22. florrColor: null,
  23. wall: {
  24. wallW: 0.001,
  25. // dig windows on face and back
  26. winW: 2 + Math.random() * 2,
  27. winH: 4 + Math.random() * 4,
  28. margin: 2,
  29. nbrWinX: 0,
  30. paddingX: 0,
  31. nbrWinY: 0,
  32. paddingY: 0,
  33. nbrWinZ: 0,
  34. paddingZ: 0
  35. },
  36. contents: {},
  37. grid: [],
  38. gridContentPlaced: {}
  39. },
  40. // getters
  41. getters: {
  42. position: (state) => {
  43. return state.position
  44. },
  45. size: (state) => {
  46. return state.size
  47. },
  48. createGradientCanvas: (state) => (c1, c2) => {
  49. var ctx = document.createElement('canvas').getContext('2d')
  50. ctx.canvas.width = 1024
  51. ctx.canvas.height = 1024
  52. var lingrad = ctx.createLinearGradient(0, 0, 0, 1024)
  53. lingrad.addColorStop(0, c1)
  54. lingrad.addColorStop(1, c2)
  55. ctx.fillStyle = lingrad
  56. ctx.fillRect(0, 0, 1024, 1024)
  57. return ctx.canvas
  58. }
  59. },
  60. // mutations
  61. mutations: {
  62. setSize: (state, size) => {
  63. state.size = size
  64. },
  65. setPosition: (state, pos) => {
  66. state.position = pos
  67. },
  68. setWalls3dObj: (state, obj) => { state.walls3dObj = obj },
  69. setWallsPos: (state, pos) => { state.wallsPos = pos },
  70. setTop3dObj: (state, obj) => { state.top3dObj = obj },
  71. setTopPos: (state, pos) => { state.topPos = pos },
  72. setFloor3dObj: (state, obj) => { state.floor3dObj = obj },
  73. setFloorPos: (state, pos) => { state.floorPos = pos },
  74. setTopColor: (state, col) => { state.topColor = col },
  75. setFloorColor: (state, col) => { state.floorColor = col },
  76. setContents: (state, contents) => { state.contents = contents },
  77. shiftGrid: (state, c) => {
  78. let p = state.grid.shift()
  79. if (!state.gridContentPlaced[c.type]) {
  80. state.gridContentPlaced[c.type] = {}
  81. }
  82. state.gridContentPlaced[c.type][c.id] = p
  83. }
  84. },
  85. // actions
  86. actions: {
  87. init ({ dispatch, commit, state, rootGetters }) {
  88. console.log('Init Project module', state.id)
  89. dispatch('sizingBuilding')
  90. dispatch('build3dObjs')
  91. },
  92. sizingBuilding ({ dispatch, commit, state, rootGetters }) {
  93. console.log('sizingBuilding')
  94. let totalW = rootGetters['Projects/totalW']
  95. // console.log('totalW', totalW)
  96. let margin = rootGetters['Projects/marginBetweenBuildings']
  97. // console.log('margin', margin)
  98. // positioning buildings on x regarding the widths
  99. // & setting up the window sizing
  100. // & setting up the content grid
  101. // let wall, a
  102. // let grid
  103. // X POS
  104. let x
  105. if (state.index === 0) {
  106. // if it's the first
  107. x = -1 * totalW / 2 + state.size.x / 2
  108. } else {
  109. // else get the precedent pos
  110. let prevProjID = rootGetters['Projects/projectID'](state.index - 1)
  111. // console.log('prevProjID', prevProjID)
  112. let prevProjPos = rootGetters[`project:${prevProjID}/position`]
  113. // console.log(`project:${prevProjID}/position.x`, prevProjPos.x)
  114. let prevProjSize = rootGetters[`project:${prevProjID}/size`]
  115. // console.log(`project:${prevProjID}/size.x`, prevProjSize.x)
  116. // console.log('state.size.x', state.size.x)
  117. // prev X + alf of prev size x + margin + half of current size x
  118. x = prevProjPos.x + prevProjSize.x / 2 + margin + state.size.x / 2
  119. }
  120. // console.log('x', x)
  121. commit('setPosition', {
  122. x: x,
  123. // y: -1 * state.size.y / 2 + 10 + Math.random() * 30, // -10 + Math.random() * this.size.y / 2
  124. y: -state.size.y / 4,
  125. z: -10 + Math.random() * 10
  126. })
  127. // WINDOWS
  128. let a = 0
  129. state.wall.nbrWinX = Math.floor((state.size.x - 2 * state.wall.margin) / state.wall.winW)
  130. // removing windows on X until padding is enough
  131. while (state.wall.paddingX < 0.4) {
  132. state.wall.nbrWinX -= a
  133. state.wall.paddingX = (state.size.x - 2 * state.wall.margin - state.wall.winW * state.wall.nbrWinX) / (state.wall.nbrWinX - 1)
  134. a++
  135. }
  136. a = 0
  137. state.wall.nbrWinY = Math.floor((state.size.y - 2 * state.wall.margin) / state.wall.winH)
  138. // removing windows on Y until padding is enough
  139. while (state.wall.paddingY < 0.4) {
  140. state.wall.nbrWinY -= a
  141. state.wall.paddingY = (state.size.y - 2 * state.wall.margin - state.wall.winH * state.wall.nbrWinY) / (state.wall.nbrWinY - 1)
  142. a++
  143. }
  144. // CONTENTS GRID
  145. a = 0
  146. state.wall.nbrWinZ = Math.floor((state.size.z - 2 * state.wall.margin) / state.wall.winW)
  147. while (state.wall.paddingZ < 0.4) {
  148. state.wall.nbrWinZ -= a
  149. state.wall.paddingZ = (state.size.z - 2 * state.wall.margin - state.wall.winW * state.wall.nbrWinZ) / (state.wall.nbrWinZ - 1)
  150. a++
  151. }
  152. let grid = []
  153. for (var l = 0; l < state.wall.nbrWinZ * 2; l++) { // cols
  154. for (var m = 0; m < state.wall.nbrWinY * 2; m++) { // rows
  155. grid.push({
  156. z: margin + state.wall.winW / 2 * l,
  157. y: margin + state.wall.winH / 2 * m
  158. })
  159. }
  160. }
  161. // shuffle the grid
  162. for (let n = grid.length - 1; n > 0; n--) {
  163. const o = Math.floor(Math.random() * n)
  164. const temp = grid[n]
  165. grid[n] = grid[o]
  166. grid[o] = temp
  167. }
  168. state.grid = [ ...grid ]
  169. },
  170. build3dObjs ({ dispatch, commit, state, getters, rootGetters }) {
  171. console.log('build3dObjs')
  172. // http://learningthreejs.com/blog/2011/12/10/constructive-solid-geometry-with-csg-js/
  173. let backGeom = new THREE.BoxGeometry(state.size.x, state.size.y, state.wall.wallW)
  174. let backMesh = new THREE.Mesh(backGeom)
  175. backMesh.position.z = -0.5 * state.size.z
  176. let backBSP = new ThreeBSP(backMesh)
  177. // https://medium.com/techtrument/multithreading-javascript-46156179cf9a
  178. let winGeom = new THREE.BoxGeometry(state.wall.winW, state.wall.winH, state.wall.wallW)
  179. let winMesh = new THREE.Mesh(winGeom)
  180. let windowsGeom = new THREE.Geometry()
  181. for (var i = 0; i < state.wall.nbrWinX; i++) {
  182. for (var j = 0; j < state.wall.nbrWinY; j++) {
  183. winMesh.position.z = -0.5 * state.size.z
  184. winMesh.position.x = -0.5 * state.size.x + state.wall.margin + state.wall.winW * 0.5 + i * (state.wall.winW + state.wall.paddingX)
  185. winMesh.position.y = 0.5 * state.size.y - state.wall.margin - state.wall.winH * 0.5 - j * (state.wall.winH + state.wall.paddingY)
  186. // winMesh.updateMatrix()
  187. windowsGeom.mergeMesh(winMesh)
  188. }
  189. }
  190. let windowsBSP = new ThreeBSP(windowsGeom)
  191. backBSP = backBSP.subtract(windowsBSP)
  192. // let winBSP
  193. // for (var i = 0; i < state.wall.nbrWinX; i++) {
  194. // for (var j = 0; j < state.wall.nbrWinY; j++) {
  195. // winMesh.position.z = -0.5 * state.size.z
  196. // winMesh.position.x = -0.5 * state.size.x + state.wall.margin + state.wall.winW * 0.5 + i * (state.wall.winW + state.wall.paddingX)
  197. // winMesh.position.y = 0.5 * state.size.y - state.wall.margin - state.wall.winH * 0.5 - j * (state.wall.winH + state.wall.paddingY)
  198. // winBSP = new ThreeBSP(winMesh)
  199. // backBSP = backBSP.subtract(winBSP)
  200. // }
  201. // }
  202. backMesh = backBSP.toMesh()
  203. let faceMesh = backMesh.clone()
  204. faceMesh.position.z = 0.5 * state.size.z
  205. let faceBSP = new ThreeBSP(faceMesh)
  206. let rightGeom = new THREE.BoxGeometry(state.wall.wallW, state.size.y, state.size.z)
  207. let rightMesh = new THREE.Mesh(rightGeom)
  208. rightMesh.position.x = 0.5 * state.size.x
  209. // rightMesh.position.z = 0.5 * state.size.z
  210. let rightBSP = new ThreeBSP(rightMesh)
  211. let leftMesh = rightMesh.clone()
  212. leftMesh.position.x = -0.5 * state.size.x
  213. // leftMesh.position.z = 0.5 * state.size.z
  214. let leftBSP = new ThreeBSP(leftMesh)
  215. let buildingBSP = backBSP.union(rightBSP)
  216. buildingBSP = buildingBSP.union(faceBSP)
  217. buildingBSP = buildingBSP.union(leftBSP)
  218. // buildingBSP = buildingBSP.union(topBSP)
  219. // buildingBSP = buildingBSP.union(floorBSP)
  220. // convert back to three.js mesh
  221. let building = buildingBSP.toMesh()
  222. // create a classical material for building
  223. // let topColor = `hsla(201, 100%, 95%, 1)`
  224. let hTop = Math.round(195 + Math.random() * 10)
  225. let sTop = Math.round(100)
  226. let lTop = Math.round(95)
  227. let hFloor = Math.round(205 + Math.random() * 10)
  228. let sFloor = Math.round(40 + Math.random() * 20)
  229. let lFloor = Math.round(5 + Math.random() * 15)
  230. let topColor = `hsla(${hTop}, ${sTop}%, ${lTop}%, 1)`
  231. commit('setTopColor', topColor)
  232. let floorColor = `hsla(${hFloor}, ${sFloor}%, ${lFloor}%, 1)`
  233. commit('setFloorColor', floorColor)
  234. let gradientTexture = new THREE.CanvasTexture(getters.createGradientCanvas(topColor, floorColor))
  235. let materialOpts = {
  236. color: 0xffffff,
  237. side: THREE.DoubleSide,
  238. shininess: 30,
  239. map: gradientTexture
  240. }
  241. building.material = new THREE.MeshPhongMaterial(materialOpts)
  242. // commiting walls
  243. commit('setWalls3dObj', building)
  244. let buildingPos = { ...state.position, ...{ z: state.position.z - 0.5 * state.size.z } }
  245. commit('setWallsPos', buildingPos)
  246. // TOP & FLOOR
  247. let topGeom = new THREE.BoxGeometry(state.size.x, state.wall.wallW, state.size.z)
  248. let topOpts = {
  249. color: new THREE.Color(`hsl(${hTop}, ${sTop}%, ${lTop}%)`),
  250. shininess: 30
  251. }
  252. let topMat = new THREE.MeshPhongMaterial(topOpts)
  253. let topMesh = new THREE.Mesh(topGeom, topMat)
  254. commit('setTop3dObj', topMesh)
  255. let topPosition = { ...state.position, ...{ y: state.position.y + 0.5 * state.size.y } }
  256. commit('setTopPos', topPosition)
  257. let floorOpts = {
  258. color: new THREE.Color(`hsl(${hFloor}, ${sFloor}%, ${lFloor}%)`),
  259. shininess: 10
  260. }
  261. let floorMat = new THREE.MeshPhongMaterial(floorOpts)
  262. let floorMesh = new THREE.Mesh(topGeom, floorMat)
  263. commit('setFloor3dObj', floorMesh)
  264. let floorPosition = { ...state.position, ...{ y: state.position.y - 0.5 * state.size.y } }
  265. commit('setFloorPos', floorPosition)
  266. //
  267. // // LEVELS
  268. // let levelGeom = new THREE.BoxGeometry(state.size.x, 1, state.size.z)
  269. // let levelMesh = new THREE.Mesh(levelGeom)
  270. // let levelBSP = new ThreeBSP(levelMesh)
  271. // let levelHoleGeom = new THREE.BoxGeometry(state.size.x - 3, 1, state.size.z - 3)
  272. // let levelHoleMesh = new THREE.Mesh(levelHoleGeom)
  273. // let levelHoleBSP = new ThreeBSP(levelHoleMesh)
  274. // levelBSP = levelBSP.subtract(levelHoleBSP)
  275. // levelMesh = levelBSP.toMesh()
  276. // let levelOpts = {
  277. // color: 0xff0000,
  278. // shininess: 10
  279. // }
  280. // let levelMat = new THREE.MeshPhongMaterial(levelOpts)
  281. // levelMesh.material = levelMat
  282. },
  283. loadContents ({ dispatch, commit, state }) {
  284. console.log('loadContents')
  285. // (where: { Published: "true" })
  286. GRAPHQL.post('', { query: `query {
  287. project(id: "${state.id}") {
  288. visibles{
  289. id
  290. Name
  291. Media {
  292. url
  293. size
  294. }
  295. Text2
  296. Vimeo
  297. Url
  298. categories
  299. }
  300. contexts{
  301. id
  302. Name
  303. Images {
  304. url
  305. size
  306. }
  307. Text2
  308. Vimeo
  309. Url
  310. }
  311. processes{
  312. id
  313. Name
  314. Media {
  315. url
  316. size
  317. }
  318. Text2
  319. Vimeo
  320. Url
  321. }
  322. concepts{
  323. id
  324. Name
  325. Images {
  326. url
  327. size
  328. }
  329. Text2
  330. Vimeo
  331. }
  332. }
  333. }` })
  334. .then(({ data: { data: { project } = null } }) => {
  335. console.log('graphql contents', project)
  336. commit('setContents', project)
  337. // dispatch('computeProjects', projects)
  338. })
  339. .catch((error) => {
  340. console.warn('Issue with getProjects', error)
  341. Promise.reject(error)
  342. })
  343. }
  344. // getGridPos ({ state, commit }) {
  345. // let p = state.grid[0]
  346. // commit('shiftGrid')
  347. // Promise.resolve(p)
  348. // }
  349. }
  350. }