App.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. <template>
  2. <div id="root">
  3. <header role="banner">
  4. <div class="wrapper">
  5. <h1
  6. class="site-title"
  7. tabindex="0"
  8. >
  9. Muntadas
  10. </h1>
  11. </div>
  12. </header>
  13. <section role="main-content">
  14. <div class="wrapper">
  15. <renderer :obj="myRenderer" :size="size">
  16. <scene :obj="myScene" @update:obj="handleScene">
  17. <!-- <SkyBox :size="{x:500,y:500,z:500}" :position="{x:0,y:0,z:0}" :color="0x992222" /> -->
  18. <!-- <orbit-controls ref="cam_controls" :position="init_cam_pos" :rotation="{ x: 0, y: 0, z: 0 }">
  19. <camera />
  20. </orbit-controls> -->
  21. <camera ref="camera" :position="init_cam_pos" :rotation="{x:0, y:0, z:0}" />
  22. <!-- <light :hex="0xffffff" :intensity="5" :position="{x:-100,y:150,z:50}" />
  23. <light :hex="0xffffff" :intensity="2" :position="{x:100,y:-150,z:-50}" :options="light_opts" /> -->
  24. <animation :fn="animate" :speed="3" />
  25. <template v-if="debug">
  26. <cube :size="{x:30,y:1,z:1}" :position="{x:15,y:0,z:0}" :color="0x992222" />
  27. <cube :size="{x:1,y:30,z:1}" :position="{x:0,y:15,z:0}" :color="0x00BBFF" />
  28. <cube :size="{x:1,y:1,z:30}" :position="{x:0,y:0,z:15}" :color="0x17d100" />
  29. </template>
  30. <ground :size="{w:5000,h:5000}" :position="{x:0,y:0,z:0}" :color="0x000011" :rotation="{x:90,y:0,z:0}" />
  31. <template v-if="projects.length">
  32. <project
  33. v-for="(project, index) in projects"
  34. :key="project.id"
  35. :data="project"
  36. :len="projects.length"
  37. :index="index"
  38. />
  39. </template>
  40. </scene>
  41. </renderer>
  42. </div>
  43. </section>
  44. <footer />
  45. </div>
  46. </template>
  47. <script>
  48. import { mapState, mapActions } from 'vuex'
  49. import mixins from 'components/mixins'
  50. import * as THREE from 'three'
  51. import TWEEN from '@tweenjs/tween.js'
  52. import BgVertex from 'assets/glsl/BgVertex'
  53. import SkyFragment from 'assets/glsl/SkyFragment'
  54. import WaterFragment from 'assets/glsl/WaterFragment'
  55. import Ground from './components/objects/Ground'
  56. import Cube from './components/objects/Cube'
  57. import Project from './components/objects/Project'
  58. // const TWEEN = require('@tweenjs/tween.js')
  59. const _debug = false
  60. export default {
  61. metaInfo: {
  62. // if no subcomponents specify a metaInfo.title, this title will be used
  63. title: 'Home',
  64. // all titles will be injected into this template
  65. titleTemplate: '%s | Muntadas'
  66. },
  67. components: {
  68. Cube,
  69. Project,
  70. Ground
  71. },
  72. mixins: [mixins],
  73. data () {
  74. // const envcolor = 0xffffff
  75. let renderer = new THREE.WebGLRenderer({ alpha: false, antialias: true })
  76. renderer.setClearColor(0x000000, 0)
  77. renderer.shadowMap.enabled = true
  78. // scene obj is well overwrited but background color not visible
  79. let scene = new THREE.Scene()
  80. scene.background = new THREE.Color(0x1a1a1a)
  81. // scene.fog = new THREE.Fog(new THREE.Color(0xffffff), 50, 200)
  82. // console.log('myScene', scene)
  83. // SKYDOME
  84. // https://github.com/mrdoob/three.js/blob/master/examples/webgl_lights_hemisphere.html
  85. // https://gamedevelopment.tutsplus.com/tutorials/a-beginners-guide-to-coding-graphics-shaders--cms-23313
  86. var uniforms = {
  87. 'topColor': { value: new THREE.Color(0x0077ff) },
  88. 'horizontColor': { value: new THREE.Color(0xffffff) },
  89. 'waterColor': { value: new THREE.Color(0x0000aa) },
  90. 'bottomColor': { value: new THREE.Color(0x000000) },
  91. 'offset': { value: 33 },
  92. 'wateroffset': { value: 33 },
  93. 'exponent': { value: 0.6 },
  94. 'waterexponent': { value: 0.6 }
  95. }
  96. // SphereBufferGeometry(radius : Float, widthSegments : Integer, heightSegments : Integer, phiStart : Float, phiLength : Float, thetaStart : Float, thetaLength : Float)
  97. var bgGeo = new THREE.SphereBufferGeometry(900, 32, 15, 0, 2 * Math.PI, 0, 0.5 * Math.PI)
  98. var skyMat = new THREE.ShaderMaterial({
  99. uniforms: uniforms,
  100. vertexShader: BgVertex,
  101. fragmentShader: SkyFragment,
  102. side: THREE.BackSide
  103. })
  104. var sky = new THREE.Mesh(bgGeo, skyMat)
  105. scene.add(sky)
  106. var waterMat = new THREE.ShaderMaterial({
  107. uniforms: uniforms,
  108. vertexShader: BgVertex,
  109. fragmentShader: WaterFragment,
  110. side: THREE.BackSide
  111. })
  112. var ground = new THREE.Mesh(bgGeo, waterMat)
  113. ground.rotateZ(this.deg2rad(180))
  114. scene.add(ground)
  115. // lights
  116. var sun = new THREE.PointLight(0xffffff, 5)
  117. var sunGeo = new THREE.SphereBufferGeometry(1, 16, 8)
  118. var sunMat = new THREE.MeshBasicMaterial({ color: 0xffffff })
  119. sun.add(new THREE.Mesh(sunGeo, sunMat))
  120. sun.position.set(-150, 150, 50)
  121. sun.castShadows = true
  122. // sun.target.position.set(0, 0, 0)
  123. scene.add(sun)
  124. // scene.add(sun.target)
  125. return {
  126. debug: _debug,
  127. myRenderer: renderer,
  128. myScene: scene,
  129. // mouse_start: new THREE.Vector2(),
  130. // mouse: new THREE.Vector2(),
  131. camera: null,
  132. mouse: new THREE.Vector2(),
  133. controls: {
  134. user_interact: false,
  135. mouse: new THREE.Vector2(),
  136. mouse_start: new THREE.Vector2(),
  137. lon: 0,
  138. lat: 0,
  139. lon_start: 0,
  140. lat_start: 0,
  141. phi: 0,
  142. theta: 0,
  143. cam_target: new THREE.Vector3(0, 0, 0)
  144. },
  145. // cam_controls: null,
  146. init_cam_pos: { x: 0, y: 10, z: 100 },
  147. raycaster: new THREE.Raycaster(),
  148. interactive_objects: [],
  149. light_opts: {
  150. castShadow: true
  151. }
  152. }
  153. },
  154. computed: {
  155. ...mapState({
  156. projects: state => state.Projects.projects
  157. }),
  158. size () {
  159. return {
  160. w: window.innerWidth,
  161. h: window.innerHeight
  162. }
  163. }
  164. },
  165. created () {
  166. if (!this.projects.length) {
  167. this.getProjects()
  168. }
  169. },
  170. mounted () {
  171. console.log('mounted', this)
  172. this.camera = this.$refs.camera.curObj
  173. // this.cam_controls = this.$refs.cam_controls.controls
  174. // console.log('cam_controls', this.cam_controls)
  175. // this.cam_controls = new THREE.PointerLockControls(this.camera)
  176. // console.log('this.cam_controls', this.cam_controls)
  177. this.updatedInteractiveObjects()
  178. document.addEventListener('mousedown', this.onDocMouseDown, false)
  179. document.addEventListener('mousemove', this.onDocMouseMove, false)
  180. document.addEventListener('mouseup', this.onDocMouseup, false)
  181. },
  182. updated () {
  183. this.updatedInteractiveObjects()
  184. },
  185. methods: {
  186. ...mapActions({
  187. getProjects: 'Projects/getProjects'
  188. }),
  189. handleScene (scene) {
  190. console.log('handlescene', scene)
  191. },
  192. updatedInteractiveObjects () {
  193. this.interactive_objects = []
  194. for (var i = 0; i < this.myScene.children.length; i++) {
  195. if (this.myScene.children[i].name === 'Project') {
  196. this.interactive_objects.push(this.myScene.children[i])
  197. }
  198. }
  199. // console.log('this.interactive_objects', this.interactive_objects)
  200. },
  201. onDocMouseDown (e) {
  202. // controls
  203. this.controls.mouse_start.x = e.clientX
  204. this.controls.mouse_start.y = e.clientY
  205. this.controls.lon_start = this.controls.lon
  206. this.controls.lat_start = this.controls.lat
  207. this.controls.user_interact = true
  208. },
  209. onDocMouseMove (e) {
  210. // RAY CASTING : update the mouse variable
  211. this.mouse.x = (e.clientX / window.innerWidth) * 2 - 1
  212. this.mouse.y = -(e.clientY / window.innerHeight) * 2 + 1
  213. // CONTROLS
  214. if (this.controls.user_interact) {
  215. // lon = ( onMouseDownMouseX - clientX ) * 0.1 + onMouseDownLon;
  216. this.controls.lon = (this.controls.mouse_start.x - e.clientX) * 0.1 + this.controls.lon_start
  217. // lat = ( clientY - onMouseDownMouseY ) * 0.1 + onMouseDownLat;
  218. this.controls.lat = (e.clientY - this.controls.mouse_start.y) * 0.1 + this.controls.lat_start
  219. }
  220. },
  221. onDocMouseup (e) {
  222. // console.log('onDocumentMouseup', e)
  223. // CONTROLS
  224. this.controls.user_interact = false
  225. // INTERACTIONS
  226. // TODO: check if draging
  227. // update the picking ray with the camera and mouse position
  228. this.raycaster.setFromCamera(this.mouse, this.camera)
  229. // calculate objects intersecting the picking ray
  230. var intersects = this.raycaster.intersectObjects(this.interactive_objects)
  231. // console.log('intersects', intersects)
  232. let object, vnode//, toPos
  233. // let cam = this.camera
  234. // let camPos = { ...this.camera.position }
  235. if (intersects.length) {
  236. for (var i = 0; i < intersects.length; i++) {
  237. object = intersects[i].object
  238. vnode = object.userData.vnode
  239. vnode.isOpened = true
  240. // new TWEEN.Tween(this.controls.cam_target)
  241. // .to(object.position, 400)
  242. // .start()
  243. //
  244. // toPos = { ...object.position }
  245. // toPos.z += 20
  246. // toPos.y = 5
  247. // new TWEEN.Tween(camPos)
  248. // .easing(TWEEN.Easing.Quadratic.InOut)
  249. // .to(toPos, 3000)
  250. // .onUpdate(function () {
  251. // // console.log('tween update', this._object)
  252. // cam.position.set(this._object.x, this._object.y, this._object.z)
  253. // // camControls.update()
  254. // })
  255. // .start()
  256. // console.log('tween', tween)
  257. break
  258. }
  259. } else {
  260. // new TWEEN.Tween(this.camera.position)
  261. // .to(this.init_cam_pos, 1000)
  262. // .start()
  263. }
  264. },
  265. animate (tt) {
  266. this.controls.lat = Math.max(-85, Math.min(85, this.controls.lat))
  267. this.controls.phi = this.deg2rad(90 - this.controls.lat)
  268. this.controls.theta = this.deg2rad(this.controls.lon)
  269. // if (this.controls.user_interact === false) {
  270. // this.controls.lon += 0.1
  271. // }
  272. this.controls.cam_target.x = 500 * Math.sin(this.controls.phi) * Math.cos(this.controls.theta)
  273. this.controls.cam_target.y = 500 * Math.cos(this.controls.phi)
  274. this.controls.cam_target.z = 500 * Math.sin(this.controls.phi) * Math.sin(this.controls.theta)
  275. if (this.camera && this.controls.user_interact) {
  276. this.camera.lookAt(this.controls.cam_target)
  277. }
  278. TWEEN.update()
  279. }
  280. }
  281. }
  282. </script>
  283. <style lang="scss" scoped>
  284. .container{
  285. // font-family:'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
  286. max-width: 1200px;
  287. }
  288. </style>