361 lines
12 KiB
JavaScript
361 lines
12 KiB
JavaScript
// https://codeburst.io/dynamic-modules-with-vuex-and-vue-b9c481ca792
|
|
// https://www.brophy.org/post/instance-aware-vuex-modules-1/
|
|
|
|
// import qs from 'querystring'
|
|
// import { REST } from 'api/rest-axios'
|
|
import { GRAPHQL } from 'api/graphql-axios'
|
|
|
|
import * as THREE from 'three'
|
|
import { ThreeBSP } from 'three-js-csg-es6'
|
|
|
|
export default {
|
|
namespaced: true,
|
|
|
|
// initial state
|
|
state: {
|
|
obj3d: null,
|
|
size: { x: 0, y: 0, z: 0 },
|
|
position: { x: 0, y: 0, z: 0 },
|
|
walls3dObj: null,
|
|
wallsPos: null,
|
|
top3dObj: null,
|
|
topPos: null,
|
|
topColor: null,
|
|
floor3dObj: null,
|
|
floorPos: null,
|
|
florrColor: null,
|
|
wall: {
|
|
wallW: 0.001,
|
|
// dig windows on face and back
|
|
winW: 2 + Math.random() * 2,
|
|
winH: 4 + Math.random() * 4,
|
|
margin: 2,
|
|
nbrWinX: 0,
|
|
paddingX: 0,
|
|
nbrWinY: 0,
|
|
paddingY: 0,
|
|
nbrWinZ: 0,
|
|
paddingZ: 0
|
|
},
|
|
contents: {},
|
|
grid: []
|
|
},
|
|
|
|
// getters
|
|
getters: {
|
|
position: (state) => {
|
|
return state.position
|
|
},
|
|
size: (state) => {
|
|
return state.size
|
|
},
|
|
createGradientCanvas: (state) => (c1, c2) => {
|
|
var ctx = document.createElement('canvas').getContext('2d')
|
|
ctx.canvas.width = 1024
|
|
ctx.canvas.height = 1024
|
|
var lingrad = ctx.createLinearGradient(0, 0, 0, 1024)
|
|
lingrad.addColorStop(0, c1)
|
|
lingrad.addColorStop(1, c2)
|
|
ctx.fillStyle = lingrad
|
|
ctx.fillRect(0, 0, 1024, 1024)
|
|
return ctx.canvas
|
|
}
|
|
},
|
|
|
|
// mutations
|
|
mutations: {
|
|
setSize: (state, size) => {
|
|
state.size = size
|
|
},
|
|
setPosition: (state, pos) => {
|
|
state.position = pos
|
|
},
|
|
setWalls3dObj: (state, obj) => { state.walls3dObj = obj },
|
|
setWallsPos: (state, pos) => { state.wallsPos = pos },
|
|
setTop3dObj: (state, obj) => { state.top3dObj = obj },
|
|
setTopPos: (state, pos) => { state.topPos = pos },
|
|
setFloor3dObj: (state, obj) => { state.floor3dObj = obj },
|
|
setFloorPos: (state, pos) => { state.floorPos = pos },
|
|
setTopColor: (state, col) => { state.topColor = col },
|
|
setFloorColor: (state, col) => { state.floorColor = col }
|
|
},
|
|
|
|
// actions
|
|
actions: {
|
|
init ({ dispatch, commit, state, rootGetters }) {
|
|
console.log('Init Project module', state.id)
|
|
dispatch('sizingBuilding')
|
|
dispatch('build3dObjs')
|
|
},
|
|
sizingBuilding ({ dispatch, commit, state, rootGetters }) {
|
|
console.log('sizingBuilding')
|
|
let totalW = rootGetters['Projects/totalW']
|
|
// console.log('totalW', totalW)
|
|
let margin = rootGetters['Projects/marginBetweenBuildings']
|
|
// console.log('margin', margin)
|
|
|
|
// positioning buildings on x regarding the widths
|
|
// & setting up the window sizing
|
|
// & setting up the content grid
|
|
// let wall, a
|
|
// let grid
|
|
|
|
// X POS
|
|
let x
|
|
if (state.index === 0) {
|
|
// if it's the first
|
|
x = -1 * totalW / 2 + state.size.x / 2
|
|
} else {
|
|
// else get the precedent pos
|
|
let prevProjID = rootGetters['Projects/projectID'](state.index - 1)
|
|
// console.log('prevProjID', prevProjID)
|
|
let prevProjPos = rootGetters[`project:${prevProjID}/position`]
|
|
// console.log(`project:${prevProjID}/position.x`, prevProjPos.x)
|
|
let prevProjSize = rootGetters[`project:${prevProjID}/size`]
|
|
// console.log(`project:${prevProjID}/size.x`, prevProjSize.x)
|
|
// console.log('state.size.x', state.size.x)
|
|
// prev X + alf of prev size x + margin + half of current size x
|
|
x = prevProjPos.x + prevProjSize.x / 2 + margin + state.size.x / 2
|
|
}
|
|
// console.log('x', x)
|
|
commit('setPosition', {
|
|
x: x,
|
|
// y: -1 * state.size.y / 2 + 10 + Math.random() * 30, // -10 + Math.random() * this.size.y / 2
|
|
y: -state.size.y / 4,
|
|
z: -10 + Math.random() * 10
|
|
})
|
|
|
|
// WINDOWS
|
|
let a = 0
|
|
state.wall.nbrWinX = Math.floor((state.size.x - 2 * state.wall.margin) / state.wall.winW)
|
|
// removing windows on X until padding is enough
|
|
while (state.wall.paddingX < 0.4) {
|
|
state.wall.nbrWinX -= a
|
|
state.wall.paddingX = (state.size.x - 2 * state.wall.margin - state.wall.winW * state.wall.nbrWinX) / (state.wall.nbrWinX - 1)
|
|
a++
|
|
}
|
|
a = 0
|
|
state.wall.nbrWinY = Math.floor((state.size.y - 2 * state.wall.margin) / state.wall.winH)
|
|
// removing windows on Y until padding is enough
|
|
while (state.wall.paddingY < 0.4) {
|
|
state.wall.nbrWinY -= a
|
|
state.wall.paddingY = (state.size.y - 2 * state.wall.margin - state.wall.winH * state.wall.nbrWinY) / (state.wall.nbrWinY - 1)
|
|
a++
|
|
}
|
|
// state.wall = { ...wall }
|
|
//
|
|
// // CONTENTS GRID
|
|
// a = 0
|
|
// state.wall.nbrWinZ = Math.floor((state.size.z - 2 * state.wall.margin) / state.wall.winW)
|
|
// while (state.wall.paddingZ < 0.4) {
|
|
// state.wall.nbrWinZ -= a
|
|
// state.wall.paddingZ = (state.size.z - 2 * state.wall.margin - state.wall.winW * state.wall.nbrWinZ) / (state.wall.nbrWinZ - 1)
|
|
// a++
|
|
// }
|
|
//
|
|
// grid = []
|
|
// for (var l = 0; l < state.wall.nbrWinZ * 2; l++) { // cols
|
|
// for (var m = 0; m < state.wall.nbrWinY * 2; m++) { // rows
|
|
// grid.push({
|
|
// z: margin + state.wall.winW / 2 * l,
|
|
// y: margin + state.wall.winH / 2 * m
|
|
// })
|
|
// }
|
|
// }
|
|
// // shuffle the grid
|
|
// for (let n = grid.length - 1; n > 0; n--) {
|
|
// const o = Math.floor(Math.random() * n)
|
|
// const temp = grid[n]
|
|
// grid[n] = grid[o]
|
|
// grid[o] = temp
|
|
// }
|
|
// state.grid = [ ...grid ]
|
|
},
|
|
build3dObjs ({ dispatch, commit, state, getters, rootGetters }) {
|
|
console.log('build3dObjs')
|
|
// http://learningthreejs.com/blog/2011/12/10/constructive-solid-geometry-with-csg-js/
|
|
|
|
let backGeom = new THREE.BoxGeometry(state.size.x, state.size.y, state.wall.wallW)
|
|
let backMesh = new THREE.Mesh(backGeom)
|
|
backMesh.position.z = -0.5 * state.size.z
|
|
let backBSP = new ThreeBSP(backMesh)
|
|
|
|
// https://medium.com/techtrument/multithreading-javascript-46156179cf9a
|
|
let winGeom = new THREE.BoxGeometry(state.wall.winW, state.wall.winH, state.wall.wallW)
|
|
let winMesh = new THREE.Mesh(winGeom)
|
|
let windowsGeom = new THREE.Geometry()
|
|
|
|
for (var i = 0; i < state.wall.nbrWinX; i++) {
|
|
for (var j = 0; j < state.wall.nbrWinY; j++) {
|
|
winMesh.position.z = -0.5 * state.size.z
|
|
winMesh.position.x = -0.5 * state.size.x + state.wall.margin + state.wall.winW * 0.5 + i * (state.wall.winW + state.wall.paddingX)
|
|
winMesh.position.y = 0.5 * state.size.y - state.wall.margin - state.wall.winH * 0.5 - j * (state.wall.winH + state.wall.paddingY)
|
|
// winMesh.updateMatrix()
|
|
windowsGeom.mergeMesh(winMesh)
|
|
}
|
|
}
|
|
let windowsBSP = new ThreeBSP(windowsGeom)
|
|
backBSP = backBSP.subtract(windowsBSP)
|
|
|
|
// let winBSP
|
|
// for (var i = 0; i < state.wall.nbrWinX; i++) {
|
|
// for (var j = 0; j < state.wall.nbrWinY; j++) {
|
|
// winMesh.position.z = -0.5 * state.size.z
|
|
// winMesh.position.x = -0.5 * state.size.x + state.wall.margin + state.wall.winW * 0.5 + i * (state.wall.winW + state.wall.paddingX)
|
|
// winMesh.position.y = 0.5 * state.size.y - state.wall.margin - state.wall.winH * 0.5 - j * (state.wall.winH + state.wall.paddingY)
|
|
// winBSP = new ThreeBSP(winMesh)
|
|
// backBSP = backBSP.subtract(winBSP)
|
|
// }
|
|
// }
|
|
|
|
backMesh = backBSP.toMesh()
|
|
let faceMesh = backMesh.clone()
|
|
faceMesh.position.z = 0.5 * state.size.z
|
|
let faceBSP = new ThreeBSP(faceMesh)
|
|
|
|
let rightGeom = new THREE.BoxGeometry(state.wall.wallW, state.size.y, state.size.z)
|
|
let rightMesh = new THREE.Mesh(rightGeom)
|
|
rightMesh.position.x = 0.5 * state.size.x
|
|
// rightMesh.position.z = 0.5 * state.size.z
|
|
let rightBSP = new ThreeBSP(rightMesh)
|
|
|
|
let leftMesh = rightMesh.clone()
|
|
leftMesh.position.x = -0.5 * state.size.x
|
|
// leftMesh.position.z = 0.5 * state.size.z
|
|
let leftBSP = new ThreeBSP(leftMesh)
|
|
|
|
let buildingBSP = backBSP.union(rightBSP)
|
|
buildingBSP = buildingBSP.union(faceBSP)
|
|
buildingBSP = buildingBSP.union(leftBSP)
|
|
// buildingBSP = buildingBSP.union(topBSP)
|
|
// buildingBSP = buildingBSP.union(floorBSP)
|
|
|
|
// convert back to three.js mesh
|
|
let building = buildingBSP.toMesh()
|
|
|
|
// create a classical material for building
|
|
// let topColor = `hsla(201, 100%, 95%, 1)`
|
|
let hTop = Math.round(195 + Math.random() * 10)
|
|
let sTop = Math.round(100)
|
|
let lTop = Math.round(95)
|
|
let hFloor = Math.round(205 + Math.random() * 10)
|
|
let sFloor = Math.round(40 + Math.random() * 20)
|
|
let lFloor = Math.round(5 + Math.random() * 15)
|
|
let topColor = `hsla(${hTop}, ${sTop}%, ${lTop}%, 1)`
|
|
commit('setTopColor', topColor)
|
|
let floorColor = `hsla(${hFloor}, ${sFloor}%, ${lFloor}%, 1)`
|
|
commit('setFloorColor', floorColor)
|
|
let gradientTexture = new THREE.CanvasTexture(getters.createGradientCanvas(topColor, floorColor))
|
|
let materialOpts = {
|
|
color: 0xffffff,
|
|
side: THREE.DoubleSide,
|
|
shininess: 30,
|
|
map: gradientTexture
|
|
}
|
|
building.material = new THREE.MeshPhongMaterial(materialOpts)
|
|
// commiting walls
|
|
commit('setWalls3dObj', building)
|
|
let buildingPos = { ...state.position, ...{ z: state.position.z - 0.5 * state.size.z } }
|
|
commit('setWallsPos', buildingPos)
|
|
|
|
// TOP & FLOOR
|
|
let topGeom = new THREE.BoxGeometry(state.size.x, state.wall.wallW, state.size.z)
|
|
let topOpts = {
|
|
color: new THREE.Color(`hsl(${hTop}, ${sTop}%, ${lTop}%)`),
|
|
shininess: 30
|
|
}
|
|
let topMat = new THREE.MeshPhongMaterial(topOpts)
|
|
let topMesh = new THREE.Mesh(topGeom, topMat)
|
|
commit('setTop3dObj', topMesh)
|
|
let topPosition = { ...state.position, ...{ y: state.position.y + 0.5 * state.size.y } }
|
|
commit('setTopPos', topPosition)
|
|
|
|
let floorOpts = {
|
|
color: new THREE.Color(`hsl(${hFloor}, ${sFloor}%, ${lFloor}%)`),
|
|
shininess: 10
|
|
}
|
|
let floorMat = new THREE.MeshPhongMaterial(floorOpts)
|
|
let floorMesh = new THREE.Mesh(topGeom, floorMat)
|
|
commit('setFloor3dObj', floorMesh)
|
|
let floorPosition = { ...state.position, ...{ y: state.position.y - 0.5 * state.size.y } }
|
|
commit('setFloorPos', floorPosition)
|
|
|
|
//
|
|
// // LEVELS
|
|
// let levelGeom = new THREE.BoxGeometry(state.size.x, 1, state.size.z)
|
|
// let levelMesh = new THREE.Mesh(levelGeom)
|
|
// let levelBSP = new ThreeBSP(levelMesh)
|
|
// let levelHoleGeom = new THREE.BoxGeometry(state.size.x - 3, 1, state.size.z - 3)
|
|
// let levelHoleMesh = new THREE.Mesh(levelHoleGeom)
|
|
// let levelHoleBSP = new ThreeBSP(levelHoleMesh)
|
|
// levelBSP = levelBSP.subtract(levelHoleBSP)
|
|
// levelMesh = levelBSP.toMesh()
|
|
// let levelOpts = {
|
|
// color: 0xff0000,
|
|
// shininess: 10
|
|
// }
|
|
// let levelMat = new THREE.MeshPhongMaterial(levelOpts)
|
|
// levelMesh.material = levelMat
|
|
},
|
|
loadContents ({ dispatch, commit, state }) {
|
|
console.log('loadContents')
|
|
GRAPHQL.post('', { query: `query {
|
|
project(id: "${state.id}") {
|
|
visibles(where: { Published: "true" }){
|
|
id
|
|
Name
|
|
Media {
|
|
url
|
|
size
|
|
}
|
|
Text2
|
|
Vimeo
|
|
Url
|
|
categories
|
|
}
|
|
contexts(where: { Published: "true" }){
|
|
id
|
|
Name
|
|
Images {
|
|
url
|
|
size
|
|
}
|
|
Text2
|
|
Vimeo
|
|
Url
|
|
}
|
|
processes(where: { Published: "true" }){
|
|
id
|
|
Name
|
|
Media {
|
|
url
|
|
size
|
|
}
|
|
Text2
|
|
Vimeo
|
|
Url
|
|
}
|
|
concepts(where: { Published: "true" }){
|
|
id
|
|
Name
|
|
Images {
|
|
url
|
|
size
|
|
}
|
|
Text2
|
|
Vimeo
|
|
}
|
|
}
|
|
}` })
|
|
.then(({ data: { data: { project } = null } }) => {
|
|
console.log('graphql visibles', project)
|
|
// dispatch('computeProjects', projects)
|
|
})
|
|
.catch((error) => {
|
|
console.warn('Issue with getProjects', error)
|
|
Promise.reject(error)
|
|
})
|
|
}
|
|
}
|
|
}
|