├── .gitignore ├── Experience ├── Camera.js ├── Controls.js ├── Experience.js ├── Preloader.js ├── Renderer.js ├── Theme.js ├── Utils │ ├── Debug.js │ ├── Resources.js │ ├── Sizes.js │ ├── Time.js │ ├── assets.js │ └── convertDivsToSpans.js └── World │ ├── Bike.js │ ├── Environment.js │ ├── Floor.js │ └── World.js ├── README.md ├── favicon.svg ├── index.html ├── main.js ├── package-lock.json ├── package.json ├── public ├── draco │ ├── README.md │ ├── draco_decoder.js │ ├── draco_decoder.wasm │ ├── draco_encoder.js │ ├── draco_wasm_wrapper.js │ └── gltf │ │ ├── draco_decoder.js │ │ ├── draco_decoder.wasm │ │ ├── draco_encoder.js │ │ └── draco_wasm_wrapper.js ├── fonts │ ├── FormulaCondensed-Black.otf │ ├── FormulaCondensed-Bold.otf │ ├── FormulaCondensed-Light.otf │ └── FormulaCondensed-Regular.otf ├── images │ ├── bike.jpeg │ ├── bike.webp │ ├── cockpit.jpeg │ ├── cockpit.webp │ ├── drivetrain.jpeg │ └── drivetrain.webp ├── models │ └── bike-model.glb └── textures │ ├── environmentMap │ ├── nx.png │ ├── ny.png │ ├── nz.png │ ├── px.png │ ├── py.png │ └── pz.png │ └── kda.mp4 └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /Experience/Camera.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three' 2 | import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' 3 | 4 | import Experience from './Experience.js' 5 | 6 | export default class Camera { 7 | constructor() { 8 | this.experience = new Experience() 9 | this.sizes = this.experience.sizes 10 | this.scene = this.experience.scene 11 | this.canvas = this.experience.canvas 12 | this.debug = this.experience.debug 13 | 14 | // Debug 15 | if(this.debug.active) { 16 | this.debugFolder = this.debug.ui.addFolder('camera') 17 | } 18 | 19 | // // Grid Helper 20 | // const size = 20; 21 | // const divisions = 20; 22 | 23 | // const gridHelper = new THREE.GridHelper( size, divisions ); 24 | // this.scene.add(gridHelper) 25 | 26 | // // Axes Helper 27 | // const axesHelper = new THREE.AxesHelper(10); 28 | // this.scene.add(axesHelper); 29 | 30 | // Setup 31 | this.createPerspectiveCamera() 32 | this.createOrthographicCamera() 33 | // this.setOrbitControls() 34 | } 35 | 36 | createPerspectiveCamera() { 37 | this.perspectiveCamera = new THREE.PerspectiveCamera( 38 | 35, 39 | this.sizes.aspect, 40 | 0.1, 41 | 1000 42 | ) 43 | this.scene.add(this.perspectiveCamera) 44 | 45 | this.perspectiveCamera.position.y = 0.5 46 | this.perspectiveCamera.position.z = 4 47 | this.perspectiveCamera.lookAt(0, 0.65, 0); 48 | 49 | // // Perspective Camera Helper 50 | // this.perspectiveCameraHelper = new THREE.CameraHelper(this.perspectiveCamera) 51 | // this.scene.add(this.perspectiveCameraHelper) 52 | 53 | // Debug 54 | if(this.debug.active) { 55 | this.debugFolder 56 | .add(this.perspectiveCamera.position, 'x') 57 | .name('camPosX') 58 | .min(-30) 59 | .max(30) 60 | .step(0.001) 61 | 62 | this.debugFolder 63 | .add(this.perspectiveCamera.position, 'y') 64 | .name('camPosY') 65 | .min(-30) 66 | .max(30) 67 | .step(0.001) 68 | 69 | this.debugFolder 70 | .add(this.perspectiveCamera.position, 'z') 71 | .name('camPosZ') 72 | .min(-30) 73 | .max(30) 74 | .step(0.001) 75 | } 76 | } 77 | 78 | createOrthographicCamera() { 79 | this.orthographicCamera = new THREE.OrthographicCamera( 80 | (-this.sizes.aspect * this.sizes.frustum) / 2, 81 | (this.sizes.aspect * this.sizes.frustum) / 2, 82 | this.sizes.frustum / 2, 83 | -this.sizes.frustum / 2, 84 | -10, 85 | 10 86 | ) 87 | 88 | this.orthographicCamera.position.y = 1.25 89 | this.orthographicCamera.rotation.x = -Math.PI / 24 90 | 91 | this.scene.add(this.orthographicCamera) 92 | 93 | // // Orthographic Camera Helper 94 | // this.orthographicCameraHelper = new THREE.CameraHelper(this.orthographicCamera) 95 | // this.scene.add(this.orthographicCameraHelper) 96 | } 97 | 98 | // setOrbitControls() { 99 | // this.controls = new OrbitControls(this.orthographicCamera, this.canvas) 100 | // this.controls.enableDamping = true 101 | // this.controls.enableZoom = true 102 | // } 103 | 104 | resize() { 105 | // Updating Perspective Camera on Resize 106 | this.perspectiveCamera.aspect = this.sizes.aspect 107 | this.perspectiveCamera.updateProjectionMatrix() 108 | 109 | // Updating Orthographic Camera on Resize 110 | this.orthographicCamera.left = (-this.sizes.aspect * this.sizes.frustum) / 2 111 | this.orthographicCamera.right = (this.sizes.aspect * this.sizes.frustum) / 2 112 | this.orthographicCamera.top = this.sizes.frustum / 2 113 | this.orthographicCamera.bottom = -this.sizes.frustum / 2 114 | this.orthographicCamera.updateProjectionMatrix() 115 | } 116 | 117 | update() { 118 | // this.controls.update() 119 | 120 | // // Updating Orthographic Camera Helper 121 | // this.orthographicCameraHelper.matrixWorldNeedsUpdate = true 122 | // this.orthographicCameraHelper.update() 123 | // this.orthographicCameraHelper.position.copy(this.orthographicCamera.position) 124 | // this.orthographicCameraHelper.position.copy(this.orthographicCamera.rotation) 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /Experience/Controls.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three' 2 | import GSAP from 'gsap' 3 | import { ScrollTrigger } from 'gsap/ScrollTrigger.js' 4 | import ASScroll from '@ashthornton/asscroll' 5 | import Experience from './Experience.js' 6 | 7 | export default class Controls { 8 | constructor() { 9 | this.experience = new Experience() 10 | this.scene = this.experience.scene 11 | this.resources = this.experience.resources 12 | this.sizes = this.experience.sizes 13 | this.time = this.experience.time 14 | this.camera = this.experience.camera 15 | this.actualBike = this.experience.world.bike.actualBike 16 | this.bikeChildren = this.experience.world.bike.bikeChildren 17 | this.zoom = { 18 | zoomValue: this.camera.perspectiveCamera.zoom 19 | } 20 | 21 | GSAP.registerPlugin(ScrollTrigger) 22 | 23 | document.querySelector('.page').style.overflow = 'visible' 24 | 25 | if (!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { 26 | console.log('desktop') 27 | this.setSmoothScroll() 28 | } 29 | this.setScrollTrigger() 30 | } 31 | 32 | setupASScroll() { 33 | // https://github.com/ashthornton/asscroll 34 | const asscroll = new ASScroll({ 35 | // ease: 0.5, 36 | disableRaf: true 37 | }) 38 | 39 | 40 | GSAP.ticker.add(asscroll.update) 41 | 42 | ScrollTrigger.defaults({ 43 | scroller: asscroll.containerElement }) 44 | 45 | 46 | ScrollTrigger.scrollerProxy(asscroll.containerElement, { 47 | scrollTop(value) { 48 | if (arguments.length) { 49 | asscroll.currentPos = value 50 | return 51 | } 52 | return asscroll.currentPos 53 | }, 54 | getBoundingClientRect() { 55 | return { 56 | top: 0, 57 | left: 0, 58 | width: window.innerWidth, 59 | height: window.innerHeight 60 | } 61 | }, 62 | fixedMarkers: true }) 63 | 64 | 65 | asscroll.on('update', ScrollTrigger.update) 66 | ScrollTrigger.addEventListener('refresh', asscroll.resize) 67 | 68 | requestAnimationFrame(() => { 69 | asscroll.enable({ 70 | newScrollElements: document.querySelectorAll('.gsap-marker-start, .gsap-marker-end, [asscroll]') 71 | }) 72 | }) 73 | return asscroll; 74 | } 75 | 76 | setSmoothScroll() { 77 | this.asscroll = this.setupASScroll() 78 | } 79 | 80 | reset() { 81 | this.actualBike.scale.set(0.65, 0.65, 0.65) 82 | this.actualBike.position.set(0, 0, 0) 83 | this.actualBike.rotation.y = 0 84 | this.camera.perspectiveCamera.position.x = 0 85 | this.camera.perspectiveCamera.position.y = 0.5 86 | this.camera.perspectiveCamera.position.z = 4 87 | this.camera.perspectiveCamera.zoom = 1 88 | this.zoom.zoomValue = 1 89 | } 90 | 91 | resetMobile() { 92 | this.actualBike.scale.set(0.5, 0.5, 0.5) 93 | this.actualBike.rotation.set(0, -Math.PI/2 , 0) 94 | this.actualBike.position.set(0, 0, 0) 95 | this.camera.perspectiveCamera.position.x = 0 96 | this.camera.perspectiveCamera.position.y = 0.4 97 | this.camera.perspectiveCamera.position.z = 4 98 | this.camera.perspectiveCamera.zoom = 1 99 | this.zoom.zoomValue = 1 100 | } 101 | 102 | setScrollTrigger() { 103 | ScrollTrigger.matchMedia({ 104 | // Desktop 105 | '(min-width: 969px)': () => { 106 | 107 | // Resets 108 | this.reset() 109 | 110 | // First Section 111 | this.firstMoveTimeline = new GSAP.timeline({ 112 | scrollTrigger: { 113 | trigger: '.first-move', 114 | start: 'top top', 115 | end: 'bottom bottom', 116 | scrub: 0.6, 117 | invalidateOnRefresh: true 118 | } 119 | }) 120 | .fromTo(this.actualBike.rotation, { 121 | y: 0 122 | }, 123 | { 124 | y: Math.PI 125 | }, 'same') 126 | .fromTo(this.camera.perspectiveCamera.position, { 127 | x: 0, 128 | y: 0.5, 129 | z: 4 130 | }, 131 | { 132 | x: () => { 133 | if(this.sizes.width > 1300 && this.sizes.height < 1000) { 134 | return -5.2 135 | } else { 136 | return -5 137 | } 138 | }, 139 | y: 6, 140 | }, 'same') 141 | .fromTo(this.camera.perspectiveCamera.rotation, { 142 | x: 0.0374824366916615, 143 | y: 0, 144 | z: -0 145 | }, 146 | { 147 | x: -0.81, 148 | y: -0.5324252706006514, 149 | z: -0.45011986145587835 150 | }, 'same') 151 | .to(this.zoom, { 152 | zoomValue: 3, 153 | onUpdate: () => { 154 | this.camera.perspectiveCamera.zoom = this.zoom.zoomValue 155 | this.camera.perspectiveCamera.updateProjectionMatrix() 156 | } 157 | }, 'same') 158 | 159 | // Second Section 160 | this.secondMoveTimeline = new GSAP.timeline({ 161 | scrollTrigger: { 162 | trigger: '.second-move', 163 | start: 'top top', 164 | end: 'bottom bottom', 165 | scrub: 0.6, 166 | invalidateOnRefresh: true, 167 | }, 168 | }) 169 | .to(this.actualBike.rotation, { 170 | y: -Math.PI / 4, 171 | }, 'same') 172 | .to(this.camera.perspectiveCamera.position, { 173 | x: () => { 174 | if(this.sizes.width > 1300 && this.sizes.height < 1000) { 175 | return -6.7 176 | } else { 177 | return -7 178 | } 179 | }, 180 | y: 2, 181 | }, 'same') 182 | .to(this.camera.perspectiveCamera.rotation, { 183 | x: -0.3340156231020234, 184 | y: -1.0505564481189775, 185 | z: -0.2924724024454449, 186 | }, 'same') 187 | .to(this.zoom, { 188 | zoomValue: 3, 189 | onUpdate: () => { 190 | this.camera.perspectiveCamera.zoom = this.zoom.zoomValue; 191 | this.camera.perspectiveCamera.updateProjectionMatrix(); 192 | }, 193 | }, 'same') 194 | 195 | // Third Section 196 | this.thirdMoveTimeline = new GSAP.timeline({ 197 | scrollTrigger: { 198 | trigger: '.third-move', 199 | start: 'top top', 200 | end: 'bottom bottom', 201 | scrub: 0.6, 202 | invalidateOnRefresh: true 203 | }, 204 | }) 205 | .to(this.actualBike.rotation, { 206 | y: -Math.PI, 207 | }, 'same') 208 | .to(this.camera.perspectiveCamera.position, { 209 | x: () => { 210 | if(this.sizes.width > 1300 && this.sizes.height < 1000) { 211 | return -4.25 212 | } else { 213 | return -4.1 214 | } 215 | }, 216 | y: 3 217 | }, 'same') 218 | .to(this.camera.perspectiveCamera.rotation, { 219 | x: -0.33669463959268153, 220 | y: -0.700986700755924, 221 | z: -0.22203253193071731, 222 | }, 'same') 223 | .to(this.zoom, { 224 | zoomValue: 2.5, 225 | onUpdate: () => { 226 | this.camera.perspectiveCamera.zoom = this.zoom.zoomValue 227 | this.camera.perspectiveCamera.updateProjectionMatrix() 228 | }, 229 | }, 'same') 230 | 231 | // Fourth Section 232 | this.fourthMoveTimeline = new GSAP.timeline({ 233 | scrollTrigger: { 234 | trigger: '.fourth-move', 235 | start: 'top top', 236 | end: 'bottom bottom', 237 | scrub: 0.6, 238 | invalidateOnRefresh: true 239 | } 240 | }) 241 | .to(this.actualBike.rotation, { 242 | y: -Math.PI / 2, 243 | }, 'same') 244 | .to(this.camera.perspectiveCamera.position, { 245 | x: () => { 246 | if(this.sizes.width > 1300 && this.sizes.height < 1000) { 247 | return 2.2 248 | } else { 249 | return 2 250 | } 251 | }, 252 | y: 1, 253 | z: 4, 254 | }, 'same') 255 | .to(this.camera.perspectiveCamera.rotation, { 256 | x: -0.02845135092188762, 257 | y: 0.29416856071633857, 258 | z: 0.008251344278639 259 | }, 'same') 260 | .to(this.zoom, { 261 | zoomValue: 1, 262 | onUpdate: () => { 263 | this.camera.perspectiveCamera.zoom = this.zoom.zoomValue 264 | this.camera.perspectiveCamera.updateProjectionMatrix() 265 | }, 266 | }, 'same') 267 | }, 268 | 269 | // Mobile 270 | '(max-width: 968px)': () => { 271 | 272 | // Resets 273 | this.resetMobile() 274 | 275 | // First Section - Mobile 276 | this.firstMoveTimeline = new GSAP.timeline({ 277 | scrollTrigger: { 278 | trigger: '.first-move', 279 | start: 'top top', 280 | end: 'bottom bottom', 281 | scrub: 0.6, 282 | invalidateOnRefresh: true 283 | } 284 | }) 285 | .fromTo(this.actualBike.rotation, { 286 | y: -Math.PI / 2 287 | }, 288 | { 289 | y: Math.PI / 1, 290 | }, 'same') 291 | .fromTo(this.camera.perspectiveCamera.position, { 292 | x: 0, 293 | y: 0.4, 294 | z: 4, 295 | }, 296 | { 297 | x: -4.82, 298 | y: 3, 299 | z: 4, 300 | }, 'same') 301 | .fromTo(this.camera.perspectiveCamera.rotation, { 302 | x: 0.0374824366916615, 303 | y: 0, 304 | z: -0 305 | }, 306 | { 307 | x: -0.4826867099146418, 308 | y: -0.7487373908008822, 309 | z: -0.3426445418872183 310 | }, 'same') 311 | .to(this.zoom, { 312 | zoomValue: 2.3, 313 | onUpdate: () => { 314 | this.camera.perspectiveCamera.zoom = this.zoom.zoomValue 315 | this.camera.perspectiveCamera.updateProjectionMatrix() 316 | } 317 | }, 'same') 318 | 319 | // Second Section - Mobile 320 | this.secondMoveTimeline = new GSAP.timeline({ 321 | scrollTrigger: { 322 | trigger: '.second-move', 323 | start: 'top top', 324 | end: 'bottom bottom', 325 | scrub: 0.6, 326 | invalidateOnRefresh: true 327 | } 328 | }) 329 | .to(this.actualBike.rotation, { 330 | y: -Math.PI / 4, 331 | }, 'same') 332 | .to(this.camera.perspectiveCamera.position, { 333 | x: -7, 334 | y: 2 335 | }, 'same') 336 | .to(this.camera.perspectiveCamera.rotation, { 337 | x: -0.36830437274233147, 338 | y: -0.975248930241726, 339 | z: -0.30922701986576173, 340 | }, 'same') 341 | .to(this.zoom, { 342 | zoomValue: 2.5, 343 | onUpdate: () => { 344 | this.camera.perspectiveCamera.zoom = this.zoom.zoomValue 345 | this.camera.perspectiveCamera.updateProjectionMatrix() 346 | } 347 | }, 'same') 348 | 349 | // Third Section - Mobile 350 | this.thirdMoveTimeline = new GSAP.timeline({ 351 | scrollTrigger: { 352 | trigger: '.third-move', 353 | start: 'top top', 354 | end: 'bottom bottom', 355 | // markers: true, 356 | scrub: 0.6, 357 | invalidateOnRefresh: true 358 | } 359 | }) 360 | .to(this.actualBike.rotation, { 361 | y: -Math.PI, 362 | }, 'same') 363 | .to(this.camera.perspectiveCamera.position, { 364 | x: -4.15, 365 | y: 1.7, 366 | }, 'same') 367 | .to(this.camera.perspectiveCamera.rotation, { 368 | x: -0.15, 369 | y: -0.82433683382151, 370 | z: -0.17595910659449646, 371 | }, 'same') 372 | .to(this.zoom, { 373 | zoomValue: 3.5, 374 | onUpdate: () => { 375 | this.camera.perspectiveCamera.zoom = this.zoom.zoomValue 376 | this.camera.perspectiveCamera.updateProjectionMatrix() 377 | } 378 | }, 'same') 379 | 380 | // Fourth Section - Mobile 381 | this.fourthMoveTimeline = new GSAP.timeline({ 382 | scrollTrigger: { 383 | trigger: '.fourth-move', 384 | start: 'top top', 385 | end: 'bottom bottom', 386 | // markers: true, 387 | scrub: 0.6, 388 | invalidateOnRefresh: true 389 | } 390 | }) 391 | .to(this.actualBike.rotation, { 392 | y: -Math.PI / 1.5, 393 | }, 'same') 394 | .to(this.camera.perspectiveCamera.position, { 395 | x: -4.1, 396 | y: 0.5, 397 | }, 'same') 398 | .to(this.zoom, { 399 | zoomValue: 1.5, 400 | onUpdate: () => { 401 | this.camera.perspectiveCamera.zoom = this.zoom.zoomValue 402 | this.camera.perspectiveCamera.updateProjectionMatrix() 403 | } 404 | }, 'same') 405 | .to(this.camera.perspectiveCamera.rotation, { 406 | x: -0.0212333950806064, 407 | y: -0.81785674319681, 408 | z: -0.015494714435393457, 409 | }, 'same') 410 | }, 411 | 412 | // all 413 | 'all': () => { 414 | this.sections = document.querySelectorAll('.section') 415 | this.sections.forEach(section => { 416 | this.progressWrapper = section.querySelector('.progress-wrapper') 417 | this.progressBar = section.querySelector('.progress-bar') 418 | 419 | if(section.classList.contains('right')) { 420 | GSAP.to(section, { 421 | borderTopLeftRadius: 10, 422 | scrollTrigger: { 423 | trigger: section, 424 | start: 'top bottom', 425 | end: 'top top', 426 | scrub: 0.6 427 | } 428 | }) 429 | GSAP.to(section, { 430 | borderBottomLeftRadius: 700, 431 | scrollTrigger: { 432 | trigger: section, 433 | start: 'bottom bottom', 434 | end: 'bottom top', 435 | scrub: 0.6 436 | } 437 | }) 438 | } else { 439 | GSAP.to(section, { 440 | borderTopRightRadius: 10, 441 | scrollTrigger: { 442 | trigger: section, 443 | start: 'top bottom', 444 | end: 'top top', 445 | scrub: 0.6 446 | } 447 | }) 448 | GSAP.to(section, { 449 | borderBottomRightRadius: 700, 450 | scrollTrigger: { 451 | trigger: section, 452 | start: 'bottom bottom', 453 | end: 'bottom top', 454 | scrub: 0.6 455 | } 456 | }) 457 | } 458 | 459 | GSAP.from(this.progressBar, { 460 | scaleY: 0, 461 | scrollTrigger: { 462 | trigger: section, 463 | start: 'top top', 464 | end: 'bottom bottom', 465 | scrub: 0.4, 466 | pin: this.progressWrapper, 467 | pinSpacing: false 468 | } 469 | }) 470 | }) 471 | } 472 | 473 | }); 474 | } 475 | 476 | resize() {} 477 | 478 | update() {} 479 | } 480 | -------------------------------------------------------------------------------- /Experience/Experience.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three' 2 | 3 | import Sizes from './Utils/Sizes.js' 4 | import Time from './Utils/Time.js' 5 | import Resources from './Utils/Resources.js' 6 | import Debug from './Utils/Debug.js' 7 | import assets from './Utils/assets.js' 8 | 9 | import Camera from './Camera.js' 10 | import Renderer from './Renderer.js' 11 | import Preloader from './Preloader.js' 12 | import Theme from './Theme.js' 13 | 14 | import World from './World/World.js' 15 | import Controls from './Controls.js' 16 | 17 | export default class Experience { 18 | static instance 19 | constructor(canvas) { 20 | if(Experience.instance) { 21 | return Experience.instance 22 | } 23 | Experience.instance = this 24 | this.canvas = canvas 25 | this.scene = new THREE.Scene() 26 | this.debug = new Debug() 27 | this.sizes = new Sizes() 28 | this.time = new Time() 29 | this.camera = new Camera() 30 | this.renderer = new Renderer() 31 | this.resources = new Resources(assets) 32 | this.theme = new Theme() 33 | this.world = new World() 34 | this.preloader = new Preloader() 35 | 36 | this.preloader.on('enableControls', () => { 37 | this.controls = new Controls() 38 | }) 39 | 40 | this.sizes.on('resize', () => { 41 | this.resize() 42 | }) 43 | 44 | this.time.on('update', () => { 45 | this.update() 46 | }) 47 | } 48 | 49 | resize() { 50 | this.camera.resize() 51 | this.world.resize() 52 | this.renderer.resize() 53 | } 54 | 55 | update() { 56 | this.preloader.update() 57 | this.camera.update() 58 | this.world.update() 59 | this.renderer.update() 60 | 61 | if(this.controls) { 62 | this.controls.update() 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Experience/Preloader.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three' 2 | import GSAP from 'gsap' 3 | import { EventEmitter } from 'events' 4 | import convert from './Utils/convertDivsToSpans' 5 | 6 | import Experience from "./Experience" 7 | 8 | export default class Preloader extends EventEmitter { 9 | constructor() { 10 | super() 11 | this.experience = new Experience() 12 | this.scene = this.experience.scene 13 | this.resources = this.experience.resources 14 | this.sizes = this.experience.sizes 15 | this.camera = this.experience.camera 16 | this.world = this.experience.world 17 | this.device = this.sizes.device 18 | 19 | this.sizes.on('switchdevice', (device) => { 20 | this.device = device 21 | }) 22 | 23 | this.world.on('worldready', () => { 24 | this.setAssets() 25 | this.playIntro() 26 | }) 27 | } 28 | 29 | setAssets() { 30 | convert(document.querySelector('.intro-text')) 31 | convert(document.querySelector('.hero-main-title')) 32 | convert(document.querySelector('.hero-main-description')) 33 | convert(document.querySelector('.hero-second-subheading')) 34 | convert(document.querySelector('.second-sub')) 35 | this.group = this.experience.world.bike.group 36 | this.actualBike = this.experience.world.bike.actualBike 37 | this.bikeChildren = this.experience.world.bike.bikeChildren 38 | } 39 | 40 | firstIntro() { 41 | return new Promise((resolve) => { 42 | this.timeline = new GSAP.timeline() 43 | this.timeline.set('.animatethis', { y: 0, yPercent: 100 }) 44 | this.timeline.to('.preloader', { 45 | opacity: 0, 46 | delay: 1, 47 | onComplete: () => { 48 | document.querySelector('.preloader').classList.add('hidden') 49 | } 50 | }) 51 | 52 | if (this.device === 'desktop') { 53 | this.timeline.to(this.actualBike.scale, { 54 | x: 0.5, 55 | y: 0.5, 56 | z: 0.5, 57 | ease: 'back.out(1.5)', 58 | duration: 0.7 59 | }) 60 | } else { 61 | this.timeline.to(this.actualBike.scale, { 62 | x: 0.175, 63 | y: 0.175, 64 | z: 0.175, 65 | ease: 'back.out(2.5)', 66 | duration: 0.7 67 | }, 'same') 68 | .to(this.camera.perspectiveCamera.position, { 69 | y: 0.1 70 | }, 'same') 71 | } 72 | 73 | this.timeline.to('.intro-text .animatethis', { 74 | yPercent: 0, 75 | stagger: 0.04, 76 | ease: 'back.out(1.5)', 77 | onComplete: resolve 78 | }) 79 | .to('.arrow-svg-wrapper', { 80 | opacity: 1 81 | }, 'fadein') 82 | .to('.navbar', { 83 | opacity: 1, 84 | onComplete: resolve 85 | }, 'fadein') 86 | }) 87 | } 88 | 89 | secondIntro() { 90 | return new Promise((resolve) => { 91 | this.secondTimeline = new GSAP.timeline() 92 | 93 | this.secondTimeline.to('.intro-text .animatethis', { 94 | yPercent: 100, 95 | stagger: 0.04, 96 | ease: 'back.in(1.5)' 97 | }, 'fadeout') 98 | .to('.arrow-svg-wrapper', { 99 | opacity: 0 100 | }, 'fadeout') 101 | 102 | if (this.device === 'desktop') { 103 | this.secondTimeline.to(this.actualBike.scale, { 104 | x: 0.65, 105 | y: 0.65, 106 | z: 0.65, 107 | stagger: 2, 108 | ease: 'power1.out' 109 | }, 'introtext') 110 | } else { 111 | this.secondTimeline.to(this.actualBike.scale, { 112 | x: 0.50, 113 | y: 0.50, 114 | z: 0.50, 115 | stagger: 1, 116 | ease: 'power1.out' 117 | }, 'introtext') 118 | .to(this.actualBike.rotation, { 119 | y: -Math.PI * 0.5 120 | }, 'introtext') 121 | .to(this.camera.perspectiveCamera.position, { 122 | y: 0.4 123 | }, 'introtext') 124 | } 125 | 126 | this.secondTimeline.to(this.bikeChildren.boxface1.rotation, { 127 | x: 0, 128 | y: 0, 129 | z: -Math.PI, 130 | duration: 2 131 | }, 'introtext') 132 | .to(this.bikeChildren.boxface2.rotation, { 133 | x: -Math.PI, 134 | y: 0, 135 | z: 0, 136 | duration: 2 137 | }, 'introtext') 138 | .to(this.bikeChildren.boxface3.rotation, { 139 | x: Math.PI, 140 | y: 0, 141 | z: 0, 142 | duration: 2 143 | }, 'introtext') 144 | .to(this.bikeChildren.boxface4.rotation, { 145 | x: 0, 146 | y: 0, 147 | z: Math.PI, 148 | duration: 2 149 | }, 'introtext') 150 | .to('.hero-main-title .animatethis', { 151 | yPercent: 0, 152 | stagger: 0.02, 153 | ease: 'back.out(1.5)' 154 | }, 'introtext') 155 | .to('.hero-main-description .animatethis', { 156 | yPercent: 0, 157 | stagger: 0.02, 158 | ease: 'back.out(1.5)' 159 | }, 'introtext') 160 | .to('.first-sub .animatethis', { 161 | yPercent: 0, 162 | stagger: 0.02, 163 | ease: 'back.out(1.5)' 164 | }, 'introtext') 165 | .to('.second-sub .animatethis', { 166 | yPercent: 0, 167 | stagger: 0.02, 168 | ease: 'back.out(1.5)' 169 | }, 'introtext') 170 | .to('.arrow-svg-wrapper', { 171 | opacity: 1, 172 | onComplete: resolve 173 | }) 174 | }) 175 | } 176 | 177 | onScroll(e) { 178 | if(e.deltaY > 0) { 179 | this.removeEventListeners() 180 | this.playSecondIntro() 181 | } 182 | } 183 | 184 | onTouch(e) { 185 | this.initialY = e.touches[0].clientY 186 | } 187 | 188 | onTouchMove(e) { 189 | let currentY = e.touches[0].clientY 190 | let difference = this.initialY - currentY 191 | if(difference > 0) { 192 | console.log('swipped up') 193 | this.removeEventListeners() 194 | this.playSecondIntro() 195 | } 196 | this.initialY = null 197 | } 198 | 199 | removeEventListeners() { 200 | window.removeEventListener('wheel', this.scrollOnceEvent) 201 | window.removeEventListener('touchstart', this.touchStart) 202 | window.removeEventListener('touchmove', this.touchMove) 203 | } 204 | 205 | async playIntro() { 206 | await this.firstIntro() 207 | this.moveFlag = true 208 | 209 | // Mouse 210 | this.scrollOnceEvent = this.onScroll.bind(this) 211 | 212 | // Touch 213 | this.touchStart = this.onTouch.bind(this) 214 | this.touchMove = this.onTouchMove.bind(this) 215 | 216 | window.addEventListener('wheel', this.scrollOnceEvent) 217 | window.addEventListener('touchstart', this.touchStart) 218 | window.addEventListener('touchmove', this.touchMove) 219 | } 220 | 221 | async playSecondIntro() { 222 | this.moveFlag = false 223 | this.scaleFlag = true 224 | 225 | await this.secondIntro() 226 | this.scaleFlag = false 227 | this.emit('enableControls') 228 | } 229 | 230 | move() { 231 | if(this.device === 'desktop') { 232 | this.group.position.set(0, 0, 0) // same values as provided to gsap 233 | } else { 234 | this.group.position.set(0, 0, 0) // same values as provided to gsap 235 | } 236 | } 237 | 238 | scale() { 239 | if(this.device === 'desktop') { 240 | this.group.scale.set(1, 1, 1) // same values as provided to gsap 241 | } else { 242 | this.group.scale.set(1, 1, 1) // same values as provided to gsap 243 | } 244 | } 245 | 246 | update() { 247 | if(this.moveFlag) { 248 | this.move() 249 | } 250 | 251 | if(this.scaleFlag) { 252 | this.scale() 253 | } 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /Experience/Renderer.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three' 2 | import Experience from "./Experience.js" 3 | 4 | export default class Renderer { 5 | constructor() { 6 | this.experience = new Experience() 7 | this.sizes = this.experience.sizes 8 | this.scene = this.experience.scene 9 | this.canvas = this.experience.canvas 10 | this.camera = this.experience.camera 11 | 12 | this.setRenderer() 13 | } 14 | 15 | setRenderer() { 16 | this.renderer = new THREE.WebGLRenderer({ 17 | canvas: this.canvas, 18 | antialias: true, 19 | }) 20 | 21 | this.renderer.physicallyCorrectLights = true 22 | this.renderer.outputEncoding = THREE.sRGBEncoding 23 | this.renderer.toneMapping = THREE.ACESFilmicToneMapping 24 | this.renderer.toneMappingExposure = 1.75 25 | this.renderer.shadowMap.enabled = true 26 | this.renderer.shadowMap.type = THREE.PCFSoftShadowMap 27 | this.renderer.setSize(this.sizes.width, this.sizes.height) 28 | this.renderer.setPixelRatio(this.sizes.pixelRatio) 29 | } 30 | 31 | resize() { 32 | this.renderer.setSize(this.sizes.width, this.sizes.height) 33 | this.renderer.setPixelRatio(this.sizes.pixelRatio) 34 | } 35 | 36 | update() { 37 | this.renderer.setViewport(0, 0, this.sizes.width, this.sizes.height) 38 | this.renderer.render(this.scene, this.camera.perspectiveCamera) 39 | 40 | // // Second Screen 41 | // this.renderer.setScissorTest(true) 42 | // this.renderer.setViewport( 43 | // this.sizes.width - this.sizes.width / 2, 44 | // this.sizes.height - this.sizes.height / 2, 45 | // this.sizes.width / 2, 46 | // this.sizes.height / 2 47 | // ) 48 | 49 | // this.renderer.setScissor( 50 | // this.sizes.width - this.sizes.width / 2, 51 | // this.sizes.height - this.sizes.height / 2, 52 | // this.sizes.width / 2, 53 | // this.sizes.height / 2 54 | // ) 55 | 56 | // this.renderer.render(this.scene, this.camera.orthographicCamera) 57 | 58 | // this.renderer.setScissorTest(false) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Experience/Theme.js: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'events' 2 | 3 | export default class Theme extends EventEmitter { 4 | constructor() { 5 | super() 6 | 7 | this.theme = 'dark' 8 | 9 | this.toggleButton = document.querySelector('.toggle-button') 10 | this.toggleCircle = document.querySelector('.toggle-circle') 11 | 12 | this.setEventListeners() 13 | } 14 | 15 | setEventListeners() { 16 | this.toggleButton.addEventListener('click', () => { 17 | this.toggleCircle.classList.toggle('slide') 18 | this.theme = this.theme === 'dark' ? 'light' : 'dark' 19 | document.body.classList.toggle('dark-theme') 20 | document.body.classList.toggle('light-theme') 21 | 22 | this.emit('switch', this.theme) 23 | }) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Experience/Utils/Debug.js: -------------------------------------------------------------------------------- 1 | import * as dat from 'lil-gui' 2 | 3 | export default class Debug 4 | { 5 | constructor() { 6 | this.active = window.location.hash === '#debug' 7 | 8 | if(this.active) { 9 | this.ui = new dat.GUI({ container: document.querySelector('.debug') }) 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Experience/Utils/Resources.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three' 2 | import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js" 3 | import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js" 4 | import { EventEmitter } from 'events' 5 | import Experience from "../Experience.js" 6 | 7 | export default class Resources extends EventEmitter { 8 | constructor(assets) { 9 | super() 10 | this.experience = new Experience() 11 | this.renderer = this.experience.renderer 12 | 13 | this.assets = assets 14 | 15 | this.items = {} 16 | this.queue = this.assets.length 17 | this.loaded = 0 18 | 19 | this.setLoaders() 20 | this.startLoading() 21 | } 22 | 23 | setLoaders() { 24 | this.loaders = {} 25 | this.loaders.gltfLoader = new GLTFLoader() 26 | this.loaders.dracoLoader = new DRACOLoader() 27 | this.loaders.dracoLoader.setDecoderPath("/draco/") 28 | this.loaders.gltfLoader.setDRACOLoader(this.loaders.dracoLoader) 29 | this.loaders.cubeTextureLoader = new THREE.CubeTextureLoader() 30 | } 31 | 32 | startLoading() { 33 | for(const asset of this.assets) { 34 | if (asset.type === 'glbModel') { 35 | this.loaders.gltfLoader.load(asset.path, (file) => { 36 | this.singleAssetLoaded(asset, file) 37 | }) 38 | } else if (asset.type === 'cubeTexture') { 39 | this.loaders.cubeTextureLoader.load(asset.path, (file => { 40 | this.singleAssetLoaded(asset, file) 41 | })) 42 | // } else if (asset.type === 'videoTexture') { 43 | // this.video = {} 44 | // this.videoTexture = {} 45 | 46 | // this.video[asset.name] = document.createElement("video") 47 | // this.video[asset.name].src = asset.path 48 | // this.video[asset.name].playInline = true 49 | // this.video[asset.name].muted = true 50 | // this.video[asset.name].autoplay = true 51 | // this.video[asset.name].loop = true 52 | // this.video[asset.name].play() 53 | 54 | // this.videoTexture[asset.name] = new THREE.VideoTexture( 55 | // this.video[asset.name] 56 | // ) 57 | // this.videoTexture[asset.name].flipY = true 58 | // this.videoTexture[asset.name].minFilter = THREE.NearestFilter 59 | // this.videoTexture[asset.name].mageFilter = THREE.NearestFilter 60 | // this.videoTexture[asset.name].generateMipmaps = false 61 | // this.videoTexture[asset.name].encoding = THREE.sRGBEncoding 62 | 63 | // this.singleAssetLoaded(asset, this.videoTexture[asset.name]) 64 | } 65 | } 66 | } 67 | 68 | singleAssetLoaded(asset, file) { 69 | this.items[asset.name] = file 70 | this.loaded++ 71 | 72 | if (this.loaded === this.queue) { 73 | this.emit('ready') 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Experience/Utils/Sizes.js: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'events' 2 | 3 | export default class Sizes extends EventEmitter { 4 | constructor() { 5 | super() 6 | this.width = window.innerWidth 7 | this.height = window.innerHeight 8 | this.aspect = this.width / this.height 9 | this.pixelRatio = Math.min(window.devicePixelRatio, 2) 10 | this.frustum = 5 11 | if(this.width < 968) { 12 | this.device = 'mobile' 13 | } else { 14 | this.device = 'desktop' 15 | } 16 | 17 | window.addEventListener('resize', () => { 18 | this.width = window.innerWidth 19 | this.height = window.innerHeight 20 | this.aspect = this.width / this.height 21 | this.pixelRatio = Math.min(window.devicePixelRatio, 2) 22 | this.emit('resize') 23 | 24 | if(this.width < 968 && this.device !== 'mobile') { 25 | this.device = 'mobile' 26 | this.emit('switchdevice', this.device) 27 | } else if (this.width >= 968 && this.device !== 'desktop') { 28 | this.device = 'desktop' 29 | this.emit('switchdevice', this.device) 30 | } 31 | }) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Experience/Utils/Time.js: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'events' 2 | 3 | export default class Time extends EventEmitter { 4 | constructor() { 5 | super() 6 | this.start = Date.now() 7 | this.current = this.start 8 | this.elapsed = 0 9 | this.delta = 16 10 | 11 | this.update() 12 | } 13 | 14 | update() { 15 | const currentTime = Date.now() 16 | this.delta = currentTime - this.current 17 | this.current = currentTime 18 | this.elapsed = this.current - this.start 19 | 20 | this.emit('update') 21 | window.requestAnimationFrame(() => this.update()) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Experience/Utils/assets.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | name: 'bike', 4 | type: 'glbModel', 5 | path: '/models/bike-model.glb' 6 | }, 7 | { 8 | name: 'environmentMapTexture', 9 | type: 'cubeTexture', 10 | path: [ 11 | 'textures/environmentMap/px.png', 12 | 'textures/environmentMap/nx.png', 13 | 'textures/environmentMap/py.png', 14 | 'textures/environmentMap/ny.png', 15 | 'textures/environmentMap/pz.png', 16 | 'textures/environmentMap/nz.png' 17 | ] 18 | } 19 | // { 20 | // name: 'screen', 21 | // type: 'videoTexture', 22 | // path: '/textures/kda.mp4' 23 | // } 24 | ] 25 | -------------------------------------------------------------------------------- /Experience/Utils/convertDivsToSpans.js: -------------------------------------------------------------------------------- 1 | export default function (element) { 2 | element.style.overflow = 'hidden' 3 | element.innerHTML = element.innerText.split('').map((char) => { 4 | if(char === ' ') { 5 | return `${char}` 6 | } 7 | return `${char}` 8 | }) 9 | .join('') 10 | 11 | return element 12 | } 13 | -------------------------------------------------------------------------------- /Experience/World/Bike.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three' 2 | import { DirectionalLightHelper } from 'three' 3 | import GSAP from 'gsap' 4 | import Experience from '../Experience.js' 5 | 6 | export default class Bike { 7 | constructor() { 8 | this.experience = new Experience() 9 | this.scene = this.experience.scene 10 | this.resources = this.experience.resources 11 | this.debug = this.experience.debug 12 | this.bike = this.resources.items.bike 13 | this.actualBike = this.bike.scene 14 | this.bikeChildren = {} 15 | 16 | this.lerp = { 17 | current: 0, 18 | target: 0, 19 | ease: 0.1 20 | } 21 | 22 | // Debug 23 | if(this.debug.active) { 24 | this.debugFolder = this.debug.ui.addFolder('bike') 25 | this.obj = { 26 | colorObj: {r:0 , g: 0, b: 0} 27 | } 28 | } 29 | 30 | this.setBikeModel() 31 | this.onMouseMove() 32 | this.setBikeGroup() 33 | } 34 | 35 | setBikeModel() { 36 | this.actualBike.scale.set(0, 0, 0) 37 | 38 | this.actualBike.traverse((child) => { 39 | if(child instanceof THREE.Mesh) { 40 | // Shadows 41 | child.castShadow = true 42 | child.receiveShadow = true 43 | 44 | // Material 45 | this.bikeMaterial = new THREE.MeshStandardMaterial({ 46 | color: 0xd7d8d9, 47 | envMapIntensity: 0.1 48 | }) 49 | child.material = this.bikeMaterial 50 | } 51 | 52 | if(child.name === 'BoxFace1') { 53 | child.material.side = THREE.BackSide 54 | child.material.color.set(0x111111) 55 | } 56 | if(child.name === 'BoxFace2') { 57 | child.material.side = THREE.BackSide 58 | child.material.color.set(0x111111) 59 | } 60 | if(child.name === 'BoxFace3') { 61 | child.material.side = THREE.BackSide 62 | child.material.color.set(0x111111) 63 | } 64 | if(child.name === 'BoxFace4') { 65 | child.material.side = THREE.BackSide 66 | child.material.color.set(0x111111) 67 | } 68 | 69 | if(child.name === 'BrakeF') { 70 | child.material.color.set(0x050505) 71 | } 72 | 73 | if(child.name === 'BrakeB') { 74 | child.material.color.set(0x050505) 75 | } 76 | 77 | if(child.name === 'BrakePadsF') { 78 | child.material.color.set(0x050505) 79 | } 80 | 81 | if(child.name === 'BrakePadsB') { 82 | child.material.color.set(0x050505) 83 | } 84 | 85 | if(child.name === 'BrakeCableF') { 86 | child.material.color.set(0xff8c00) 87 | } 88 | 89 | if(child.name === 'BrakeCableB') { 90 | child.material.color.set(0xff8c00) 91 | } 92 | 93 | if(child.name === 'BrakeDetailF') { 94 | child.material.color.set(0xff8c00) 95 | } 96 | 97 | if(child.name === 'BrakeDetailB') { 98 | child.material.color.set(0xff8c00) 99 | } 100 | 101 | if(child.name === 'Frame') { 102 | child.material.metalness = 0.9 103 | child.material.roughness = 0 104 | } 105 | 106 | if(child.name === 'Chain1') { 107 | child.material.color.set(0x050505) 108 | child.material.metalness = 0.9 109 | child.material.roughness = 0 110 | } 111 | 112 | if(child.name === 'Chain2') { 113 | child.material.color.set(0x050505) 114 | child.material.metalness = 0.9 115 | child.material.roughness = 0 116 | } 117 | 118 | if(child.name === 'ChainringsCover') { 119 | child.material.color.set(0x050505) 120 | child.material.metalness = 0.9 121 | child.material.roughness = 0 122 | } 123 | 124 | if(child.name === 'CrankArm') { 125 | child.material.metalness = 0.9 126 | child.material.roughness = 0 127 | } 128 | 129 | if(child.name === 'Cassette') { 130 | child.material.metalness = 0.9 131 | child.material.roughness = 0 132 | } 133 | 134 | if(child.name === 'PedalL') { 135 | child.material.color.set(0x050505) 136 | } 137 | 138 | if(child.name === 'PedalR') { 139 | child.material.color.set(0x050505) 140 | } 141 | 142 | if(child.name === 'PedalGripL') { 143 | child.material.color.set(0x050505) 144 | } 145 | 146 | if(child.name === 'PedalGripR') { 147 | child.material.color.set(0x050505) 148 | } 149 | 150 | if(child.name === 'CockpitStem') { 151 | child.material.color.set(0x050505) 152 | child.material.metalness = 0.5 153 | child.material.roughness = 0 154 | } 155 | 156 | if(child.name === 'CockpitHandlebar') { 157 | child.material.color.set(0x050505) 158 | child.material.roughness = 1 159 | } 160 | 161 | if(child.name === 'TireF') { 162 | child.material.color.set(0x050505) 163 | child.material.roughness = 1 164 | } 165 | 166 | if(child.name === 'TireB') { 167 | child.material.color.set(0x050505) 168 | child.material.roughness = 1 169 | } 170 | 171 | if(child.name === 'RimF') { 172 | child.material.metalness = 0.5 173 | child.material.roughness = 0 174 | } 175 | 176 | if(child.name === 'RimB') { 177 | child.material.metalness = 0.5 178 | child.material.roughness = 0 179 | } 180 | 181 | if(child.name === 'RimInnerF') { 182 | child.material.color.set(0xff8c00) 183 | child.material.roughness = 0 184 | } 185 | 186 | if(child.name === 'RimInnerB') { 187 | child.material.color.set(0xff8c00) 188 | child.material.roughness = 0 189 | } 190 | 191 | if(child.name === 'SpokesF') { 192 | child.material.metalness = 0.9 193 | child.material.roughness = 0 194 | } 195 | 196 | if(child.name === 'SpokesB') { 197 | child.material.metalness = 0.9 198 | child.material.roughness = 0 199 | } 200 | 201 | if(child.name === 'FasteningF') { 202 | child.material.color.set(0x050505) 203 | child.material.metalness = 0.5 204 | child.material.roughness = 0 205 | } 206 | 207 | if(child.name === 'FasteningB') { 208 | child.material.color.set(0x050505) 209 | child.material.metalness = 0.5 210 | child.material.roughness = 0 211 | } 212 | 213 | if(child.name === 'HubF') { 214 | child.material.color.set(0x050505) 215 | child.material.metalness = 0.5 216 | child.material.roughness = 0 217 | } 218 | 219 | if(child.name === 'HubB') { 220 | child.material.color.set(0x050505) 221 | child.material.metalness = 0.5 222 | child.material.roughness = 0 223 | } 224 | 225 | if(child.name === 'Seat') { 226 | child.material.color.set(0x050505) 227 | child.material.roughness = 1 228 | } 229 | 230 | this.bikeChildren[child.name.toLowerCase()] = child 231 | }) 232 | } 233 | 234 | switchTheme(theme) { 235 | if(theme === 'dark') { 236 | this.toDarkTimeline = new GSAP.timeline() 237 | 238 | this.actualBike.traverse((child) => { 239 | if(child instanceof THREE.Mesh && child.material instanceof THREE.MeshStandardMaterial) { 240 | this.toDarkTimeline.to(child.material, { 241 | envMapIntensity: 0.1 242 | }, 'same') 243 | } 244 | 245 | if(child.name === 'BoxFace1') { 246 | child.material.color.set(0x111111) 247 | } else if (child.name === 'BoxFace2') { 248 | child.material.color.set(0x111111) 249 | } else if (child.name === 'BoxFace3') { 250 | child.material.color.set(0x111111) 251 | } else if (child.name === 'BoxFace4') { 252 | child.material.color.set(0x111111) 253 | } 254 | }) 255 | } else { 256 | this.toLightTimeline = new GSAP.timeline() 257 | 258 | this.actualBike.traverse((child) => { 259 | if(child instanceof THREE.Mesh && child.material instanceof THREE.MeshStandardMaterial) { 260 | this.toLightTimeline.to(child.material, { 261 | envMapIntensity: 1 262 | }, 'same') 263 | } 264 | 265 | if(child.name === 'BoxFace1') { 266 | child.material.color.set(0xd7d8d9) 267 | } else if (child.name === 'BoxFace2') { 268 | child.material.color.set(0xd7d8d9) 269 | } else if (child.name === 'BoxFace3') { 270 | child.material.color.set(0xd7d8d9) 271 | } else if (child.name === 'BoxFace4') { 272 | child.material.color.set(0xd7d8d9) 273 | } 274 | }) 275 | } 276 | } 277 | 278 | onMouseMove() { 279 | window.addEventListener('mousemove', (e) => { 280 | this.rotation = ((e.clientX - window.innerWidth / 2) * 2) / window.innerWidth // makes the position of the cursor from -1 to 1 281 | this.lerp.target = this.rotation * 0.3 282 | }) 283 | } 284 | 285 | setBikeGroup() { 286 | // New group so we can rotate the bike with GSAP without intefering with our mouse rotation lerping 287 | // Like a spinning plateform that can spin independetly from others 288 | this.group = new THREE.Group() 289 | this.group.add(this.actualBike) 290 | this.scene.add(this.group) 291 | } 292 | 293 | resize() {} 294 | 295 | update() { 296 | this.lerp.current = GSAP.utils.interpolate( 297 | this.lerp.current, 298 | this.lerp.target, 299 | this.lerp.ease 300 | ) 301 | 302 | this.group.rotation.y = this.lerp.current 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /Experience/World/Environment.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three' 2 | import { DirectionalLightHelper } from 'three' 3 | import GSAP from 'gsap' 4 | import Experience from '../Experience.js' 5 | 6 | export default class Environment { 7 | constructor() { 8 | this.experience = new Experience() 9 | this.scene = this.experience.scene 10 | this.resources = this.experience.resources 11 | this.debug = this.experience.debug 12 | 13 | // Debug 14 | if(this.debug.active) { 15 | this.debugFolder = this.debug.ui.addFolder('environment') 16 | this.obj = { 17 | colorObj: {r:0 , g: 0, b: 0} 18 | } 19 | } 20 | 21 | // Setup 22 | this.setBackground() 23 | this.setLights() 24 | this.setEnvironmentMap() 25 | } 26 | 27 | setBackground() { 28 | this.bgColor = 0x222222 29 | this.scene.background = new THREE.Color(this.bgColor) 30 | this.scene.fog = new THREE.Fog(this.bgColor, 5, 20) 31 | } 32 | 33 | setLights() { 34 | // Sun Light 35 | this.sunLight = new THREE.DirectionalLight("#222222", 0.2) 36 | this.sunLight.castShadow = true 37 | this.sunLight.shadow.camera.far = 20 38 | this.sunLight.shadow.mapSize.set(1024, 1024) 39 | this.sunLight.shadow.normalBias = 0.05 40 | this.sunLight.position.set(3, 7, 3) 41 | this.scene.add(this.sunLight) 42 | 43 | // // Sun Light Helper 44 | // this.sunLightHelper = new THREE.DirectionalLightHelper(this.sunLight, 5) 45 | // this.scene.add(this.sunLightHelper) 46 | 47 | // Ambient Light 48 | this.ambientLight = new THREE.AmbientLight('#222222', 0.2) 49 | this.scene.add(this.ambientLight) 50 | 51 | // Directional Light 52 | const color = 0xffffff 53 | const intensity = 1 54 | 55 | const targetObject = new THREE.Object3D(); 56 | targetObject.position.set(0, 0.5, 0) 57 | this.scene.add(targetObject); 58 | 59 | this.directionalLight = new THREE.DirectionalLight( color, intensity ) 60 | this.directionalLight.position.set( 0, 1.5, 3 ) 61 | this.directionalLight.target = targetObject; 62 | this.scene.add( this.directionalLight ) 63 | 64 | this.directionalLight2 = new THREE.DirectionalLight( color, intensity ) 65 | this.directionalLight2.position.set( -2, 2, 3 ) 66 | this.directionalLight2.target = targetObject; 67 | this.scene.add( this.directionalLight2 ) 68 | 69 | this.directionalLight3 = new THREE.DirectionalLight( color, intensity ) 70 | this.directionalLight3.position.set( 2, 2, 3 ) 71 | this.directionalLight3.target = targetObject; 72 | this.directionalLight3.castShadow = true 73 | this.directionalLight3.shadow.camera.far = 20 74 | this.directionalLight3.shadow.mapSize.set(1024, 1024) 75 | this.directionalLight3.shadow.normalBias = 0.05 76 | this.scene.add( this.directionalLight3 ) 77 | 78 | // // Directional Light Helpers 79 | // this.directionalLightHelper = new DirectionalLightHelper( this.directionalLight ) 80 | // this.directionalLight.add( this.directionalLightHelper ) 81 | // this.directionalLightHelper2 = new DirectionalLightHelper( this.directionalLight2 ) 82 | // this.directionalLight2.add( this.directionalLightHelper2 ) 83 | // this.directionalLightHelper3 = new DirectionalLightHelper( this.directionalLight3 ) 84 | // this.directionalLight3.add( this.directionalLightHelper3 ) 85 | 86 | // Debug 87 | if(this.debug.active) { 88 | // All Lights 89 | this.debugFolder 90 | .addColor(this.obj, 'colorObj') 91 | .name('lightsColor') 92 | .onChange(() => { 93 | this.sunLight.color.copy(this.obj.colorObj) 94 | this.ambientLight.color.copy(this.obj.colorObj) 95 | this.directionalLight.color.copy(this.obj.colorObj) 96 | this.directionalLight2.color.copy(this.obj.colorObj) 97 | this.directionalLight3.color.copy(this.obj.colorObj) 98 | }) 99 | 100 | // Sun Light 101 | this.debugFolder 102 | .add(this.sunLight, 'intensity') 103 | .name('sunLightIntensity') 104 | .min(0) 105 | .max(10) 106 | .step(0.001) 107 | 108 | this.debugFolder 109 | .add(this.sunLight.position, 'x') 110 | .name('sunLightX') 111 | .min(- 5) 112 | .max(5) 113 | .step(0.001) 114 | 115 | this.debugFolder 116 | .add(this.sunLight.position, 'y') 117 | .name('sunLightY') 118 | .min(- 5) 119 | .max(5) 120 | .step(0.001) 121 | 122 | this.debugFolder 123 | .add(this.sunLight.position, 'z') 124 | .name('sunLightZ') 125 | .min(- 5) 126 | .max(5) 127 | .step(0.001) 128 | 129 | this.debugFolder 130 | .add(this.sunLight.rotation, 'x') 131 | .name('sunRotationX') 132 | .min(- 5) 133 | .max(5) 134 | .step(0.001) 135 | 136 | this.debugFolder 137 | .add(this.sunLight.rotation, 'y') 138 | .name('sunRotationY') 139 | .min(- 5) 140 | .max(5) 141 | .step(0.001) 142 | 143 | this.debugFolder 144 | .add(this.sunLight.rotation, 'z') 145 | .name('sunRotationZ') 146 | .min(- 5) 147 | .max(5) 148 | .step(0.001) 149 | 150 | // Ambient Light 151 | this.debugFolder 152 | .add(this.ambientLight, 'intensity') 153 | .name('ambLightIntensity') 154 | .min(0) 155 | .max(10) 156 | .step(0.001) 157 | 158 | // Directional Lights 159 | // 1 160 | this.debugFolder 161 | .add(this.directionalLight, 'intensity') 162 | .name('directionalLightIntensity') 163 | .min(0) 164 | .max(10) 165 | .step(0.001) 166 | 167 | this.debugFolder 168 | .add(this.directionalLight.position, 'x') 169 | .name('directionalLightX') 170 | .min(- 10) 171 | .max(10) 172 | .step(0.001) 173 | 174 | this.debugFolder 175 | .add(this.directionalLight.position, 'y') 176 | .name('directionalLightY') 177 | .min(- 10) 178 | .max(10) 179 | .step(0.001) 180 | 181 | this.debugFolder 182 | .add(this.directionalLight.position, 'z') 183 | .name('directionalLightZ') 184 | .min(- 10) 185 | .max(10) 186 | .step(0.001) 187 | 188 | this.debugFolder 189 | .add(this.directionalLight.rotation, 'x') 190 | .name('directionalLightRotX') 191 | .min(- 10) 192 | .max(10) 193 | .step(0.001) 194 | 195 | this.debugFolder 196 | .add(this.directionalLight.rotation, 'y') 197 | .name('directionalLightRotY') 198 | .min(- 10) 199 | .max(10) 200 | .step(0.001) 201 | 202 | this.debugFolder 203 | .add(this.directionalLight.rotation, 'z') 204 | .name('directionalLightRotZ') 205 | .min(- 10) 206 | .max(10) 207 | .step(0.001) 208 | 209 | // 2 210 | this.debugFolder 211 | .add(this.directionalLight2, 'intensity') 212 | .name('directionalLight2Intensity') 213 | .min(0) 214 | .max(10) 215 | .step(0.001) 216 | 217 | this.debugFolder 218 | .add(this.directionalLight2.position, 'x') 219 | .name('directionalLight2X') 220 | .min(- 10) 221 | .max(10) 222 | .step(0.001) 223 | 224 | this.debugFolder 225 | .add(this.directionalLight2.position, 'y') 226 | .name('directionalLight2Y') 227 | .min(- 10) 228 | .max(10) 229 | .step(0.001) 230 | 231 | this.debugFolder 232 | .add(this.directionalLight2.position, 'z') 233 | .name('directionalLight2Z') 234 | .min(- 10) 235 | .max(10) 236 | .step(0.001) 237 | 238 | this.debugFolder 239 | .add(this.directionalLight2.rotation, 'x') 240 | .name('directionalLight2RotX') 241 | .min(- 10) 242 | .max(10) 243 | .step(0.001) 244 | 245 | this.debugFolder 246 | .add(this.directionalLight2.rotation, 'y') 247 | .name('directionalLight2RotY') 248 | .min(- 10) 249 | .max(10) 250 | .step(0.001) 251 | 252 | this.debugFolder 253 | .add(this.directionalLight2.rotation, 'z') 254 | .name('directionalLight2RotZ') 255 | .min(- 10) 256 | .max(10) 257 | .step(0.001) 258 | 259 | // 3 260 | this.debugFolder 261 | .add(this.directionalLight3, 'intensity') 262 | .name('directionalLight3Intensity') 263 | .min(0) 264 | .max(10) 265 | .step(0.001) 266 | 267 | this.debugFolder 268 | .add(this.directionalLight3.position, 'x') 269 | .name('directionalLight3X') 270 | .min(- 10) 271 | .max(10) 272 | .step(0.001) 273 | 274 | this.debugFolder 275 | .add(this.directionalLight3.position, 'y') 276 | .name('directionalLight3Y') 277 | .min(- 10) 278 | .max(10) 279 | .step(0.001) 280 | 281 | this.debugFolder 282 | .add(this.directionalLight3.position, 'z') 283 | .name('directionalLight3Z') 284 | .min(- 10) 285 | .max(10) 286 | .step(0.001) 287 | 288 | this.debugFolder 289 | .add(this.directionalLight3.rotation, 'x') 290 | .name('directionalLight3RotX') 291 | .min(- 10) 292 | .max(10) 293 | .step(0.001) 294 | 295 | this.debugFolder 296 | .add(this.directionalLight3.rotation, 'y') 297 | .name('directionalLight3RotY') 298 | .min(- 10) 299 | .max(10) 300 | .step(0.001) 301 | 302 | this.debugFolder 303 | .add(this.directionalLight3.rotation, 'z') 304 | .name('directionalLight3RotZ') 305 | .min(- 10) 306 | .max(10) 307 | .step(0.001) 308 | } 309 | } 310 | 311 | setEnvironmentMap() { 312 | this.environmentMap = {} 313 | this.environmentMap.intensity = 1 314 | this.environmentMap.texture = this.resources.items.environmentMapTexture 315 | this.environmentMap.texture.encoding = THREE.sRGBEncoding 316 | 317 | this.scene.environment = this.environmentMap.texture 318 | 319 | this.environmentMap.updateMaterials = () => { 320 | this.scene.traverse((child) => { 321 | if(child instanceof THREE.Mesh && child.material instanceof THREE.MeshStandardMaterial) 322 | { 323 | child.material.envMap = this.environmentMap.texture 324 | child.material.envMapIntensity = this.environmentMap.intensity 325 | child.material.needsUpdate = true 326 | } 327 | }) 328 | } 329 | this.environmentMap.updateMaterials() 330 | } 331 | 332 | switchTheme(theme) { 333 | if(theme === 'dark') { 334 | this.toDarkTimeline = new GSAP.timeline() 335 | .to(this.scene.background, { 336 | r: 34 / 255, 337 | g: 34 / 255, 338 | b: 34 / 255 339 | }, 'same') 340 | .to(this.scene.fog.color, { 341 | r: 34 / 255, 342 | g: 34 / 255, 343 | b: 34 / 255 344 | }, 'same') 345 | .to(this.sunLight.color, { 346 | r: 34 / 255, 347 | g: 34 / 255, 348 | b: 34 / 255 349 | }, 'same') 350 | .to(this.ambientLight.color, { 351 | r: 34 / 255, 352 | g: 34 / 255, 353 | b: 34 / 255 354 | }, 'same') 355 | .to(this.sunLight, { 356 | intensity: 0.2 357 | }, 'same') 358 | .to(this.ambientLight, { 359 | intensity: 0.2 360 | }, 'same') 361 | .to(this.directionalLight, { 362 | intensity: 1 363 | }, 'same') 364 | .to(this.directionalLight2, { 365 | intensity: 1 366 | }, 'same') 367 | .to(this.directionalLight3, { 368 | intensity: 1 369 | }, 'same') 370 | } else { 371 | this.toLightTimeline = new GSAP.timeline() 372 | .to(this.scene.background, { 373 | r: 215 / 255, 374 | g: 216 / 255, 375 | b: 217 / 255 376 | }, 'same') 377 | .to(this.scene.fog.color, { 378 | r: 215 / 255, 379 | g: 216 / 255, 380 | b: 217 / 255 381 | }, 'same') 382 | .to(this.sunLight.color, { 383 | r: 215 / 255, 384 | g: 216 / 255, 385 | b: 217 / 255 386 | }, 'same') 387 | .to(this.ambientLight.color, { 388 | r: 215 / 255, 389 | g: 216 / 255, 390 | b: 217 / 255 391 | }, 'same') 392 | .to(this.sunLight, { 393 | intensity: 3 394 | }, 'same') 395 | .to(this.ambientLight, { 396 | intensity: 1 397 | }, 'same') 398 | .to(this.directionalLight, { 399 | intensity: 0 400 | }, 'same') 401 | .to(this.directionalLight2, { 402 | intensity: 0 403 | }, 'same') 404 | .to(this.directionalLight3, { 405 | intensity: 0 406 | }, 'same') 407 | } 408 | } 409 | 410 | resize() {} 411 | 412 | update() {} 413 | } 414 | -------------------------------------------------------------------------------- /Experience/World/Floor.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three' 2 | import GSAP from 'gsap' 3 | import Experience from '../Experience.js' 4 | 5 | export default class Floor { 6 | constructor() { 7 | this.experience = new Experience() 8 | this.scene = this.experience.scene 9 | 10 | this.setFloor() 11 | } 12 | 13 | setFloor() { 14 | this.geometry = new THREE.PlaneGeometry(100, 100) 15 | this.material = new THREE.MeshStandardMaterial({ 16 | color: 0x020202, 17 | side: THREE.BackSide, 18 | }) 19 | this.plane = new THREE.Mesh(this.geometry, this.material) 20 | this.plane.rotation.x = Math.PI / 2 21 | this.plane.receiveShadow= true 22 | 23 | this.scene.add(this.plane) 24 | } 25 | 26 | switchTheme(theme) { 27 | if(theme === 'dark') { 28 | GSAP.to(this.plane.material.color, { 29 | r: 2 / 255, 30 | g: 2 / 255, 31 | b: 2 / 255 32 | }) 33 | } else { 34 | GSAP.to(this.plane.material.color, { 35 | r: 215 / 255, 36 | g: 216 / 255, 37 | b: 217 / 255 38 | }) 39 | } 40 | } 41 | 42 | resize() {} 43 | 44 | update() {} 45 | } 46 | -------------------------------------------------------------------------------- /Experience/World/World.js: -------------------------------------------------------------------------------- 1 | import * as THREE from 'three' 2 | import Experience from "../Experience.js" 3 | 4 | import { EventEmitter } from 'events' 5 | 6 | import Environment from './Environment.js' 7 | import Bike from './Bike.js' 8 | import Floor from './Floor.js' 9 | // import Controls from '../Controls.js' 10 | 11 | 12 | export default class World extends EventEmitter { 13 | constructor() { 14 | super() 15 | this.experience = new Experience() 16 | this.sizes = this.experience.sizes 17 | this.scene = this.experience.scene 18 | this.canvas = this.experience.canvas 19 | this.camera = this.experience.camera 20 | this.resources = this.experience.resources 21 | this.theme = this.experience.theme 22 | 23 | this.resources.on('ready', () => { 24 | this.environment = new Environment() 25 | this.floor = new Floor() 26 | this.bike = new Bike() 27 | // this.controls = new Controls() 28 | this.emit('worldready') 29 | }) 30 | 31 | this.theme.on('switch', (theme) => { 32 | theme = this.theme.theme 33 | this.switchTheme(theme) 34 | }) 35 | } 36 | 37 | switchTheme(theme) { 38 | if(this.environment) { 39 | this.environment.switchTheme(theme) 40 | } 41 | if(this.bike) { 42 | this.bike.switchTheme(theme) 43 | } 44 | if(this.floor) { 45 | this.floor.switchTheme(theme) 46 | } 47 | } 48 | 49 | resize() { 50 | 51 | } 52 | 53 | update() { 54 | if(this.bike) { 55 | this.bike.update() 56 | } 57 | 58 | if(this.controls) { 59 | this.controls.update() 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bike Demo Three.js 2 | 3 | This fictive project was created to showcase my current skills using Three.js and GSAP. It was inspired by the [tutorial](https://www.youtube.com/watch?v=rxTb9ys834w&t=9266s) created by Andrew Woan based on Bokoko33's [portfolio](https://bokoko33.me/). 4 | 5 | **[> View the live demo](https://bike-demo-threejs.vercel.app/)** 6 | 7 | 8 | ## Overview 9 | 10 | bike-demo-threejs1 11 | bike-demo-threejs2 12 | bike-demo-threejs3 13 | 14 | ### Built with 15 | 16 | - HTML, CSS, Javascript 17 | - Three.js 18 | - GSAP 19 | - ASScroll 20 | - Vite 21 | 22 | ## Authors 23 | 24 | - [Kiril Bernard Tucker](https://github.com/Kirilbt) 25 | 26 | Special thanks to Andrew Woan, Bruno Simon and everyone on the Three.Js Journey's discord who helped me. 27 | -------------------------------------------------------------------------------- /favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vitesse - AIR-008 8 | 9 | 10 |
11 | 12 |
13 | 14 | 15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | 25 |
26 | 27 | 28 | 46 | 47 |
48 | 49 | 50 | 51 |
52 |
53 | 54 | 55 |
Scroll down to unbox
56 |
57 | 58 |
59 | 60 |
61 |

AIR-008

62 |

Pure Speed | Built to Win

63 |
64 | 65 |
66 |

Limited Edition

67 |

• 100

68 |
69 |
70 |
71 | 72 | 73 | 74 |
75 | 76 |
77 |
78 |
79 |
80 | 81 |
82 |

83 | Cockpit 84 |

85 | 01 86 |
87 | 88 |
89 | Cockpit picture 90 |

A pro-level cockpit

91 |

This cockpit features thicker walls in key positions for extra strength and stability where it matters most. You can adjust the fit quickly, easily, and precisely, thanks to height and width adjustment without using spacers or cutting the steerer tube.

92 |

Vitesse VTS022 Aerocockpit

93 |

Now with reinforced carbon walls for added stiffness and improved durability, this is the latest generation of aerodynamically optimised, Vitesse-developed WorldTour-level cockpits. With complete cable and wire integration, get super-clean optics and reduced drag at the same time. And with single-tool adjustable height and width, big spacer stacks are a thing of the past.

94 |

Vitesse Ergospeed Gel

95 |

Bar tape with EVA foam and elastomer gel mix for optimal comfort

96 |
97 |
98 | 99 | 100 | 101 |
102 | 103 |
104 |
105 |
106 |
107 | 108 |
109 |

110 | Drivetrain 111 |

112 | 02 113 |
114 | 115 |
116 | Drivetain picture 117 |

SRAM Force AXS Powermeter

118 |

When only the very highest levels of performance will do, then you need a power meter. This model is seamlessly integrated in the crank and connects wirelessly with all common GPS units and SRAM’s AXS system, so you can measure your training and racing efforts in real time with pinpoint accuracy.

119 |

Pedals

120 |

The PD-V8000 pedals from Vitesse combine the two most desired qualities for road cyclists: stiffness and light weight. With a carbon-composite body, an extra-wide platform and a reduced stack height, you get the power transfer you’ve always dreamed about. Perfect for racers!

121 |

Chain

122 |

SRAM FORCE D1 12-speed with signature flat-top design for quieter operation, increased strength and durability. Hard chrome plated inner link plates and rollers for reduced wear.

123 |
124 |
125 | 126 | 127 | 128 |
129 | 130 |
131 |
132 |
133 |
134 | 135 |
136 |

137 | Seat 138 |

139 | 03 140 |
141 | 142 |
143 | Bike picture 144 |

Selle Italia SLR Boost Superflow S

145 |

Saddle with modern short-nose design and unisex ergonomics.

146 |

Vitesse SP0046 Aero Seatpost

147 |

This lightweight Vitesse-developed carbon seatpost now features a new sleeve bearing that creates a seal and reduces seatpost and seat tube friction and prevents dirt from entering. It’s lightweight and also gives you extra aero gains, thanks to its aerodynamically optimised tube profile. The new, lower mounted clamping mechanism and unique double-chamber design increase comfort, and we combine it with a Selle Italia saddle, for incredible performance.

148 |
149 |
150 | 151 | 152 | 153 |
154 | 155 |
156 |
157 |
158 |
159 | 160 |
161 |

162 | About This Project 163 |

164 | 04 165 |
166 | 167 |
168 |

The Goal

169 |

This fictive project was created to showcase my current skills using Three.js and GSAP.
170 | Last update: 23 Aug 2022

171 |

Special Thanks to:

172 |
    173 |
  • Andrew Woan for all your help and your amazing tutorial inspired by Bokoko33's portfolio.
  • 174 |
  • Bruno Simon for all the knowledge I've learned with Three.js Journey
  • 175 |
  • And to all the people from the Three.js Journey's discord who helped me
  • 176 |
177 |

Credits:

178 | 183 |
184 | 185 | 193 |
194 |
195 | 196 | 197 |
198 |
199 | 200 | 201 | 202 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | import './style.css' 2 | import Experience from './Experience/Experience.js' 3 | 4 | const experience = new Experience(document.querySelector(".experience-canvas")) 5 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bike-demo-threejs", 3 | "version": "0.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "bike-demo-threejs", 9 | "version": "0.0.0", 10 | "devDependencies": { 11 | "@ashthornton/asscroll": "^2.0.11", 12 | "events": "^3.3.0", 13 | "gsap": "^3.10.4", 14 | "lil-gui": "^0.17.0", 15 | "three": "^0.142.0", 16 | "vite": "^2.9.9" 17 | } 18 | }, 19 | "node_modules/@ashthornton/asscroll": { 20 | "version": "2.0.11", 21 | "resolved": "https://registry.npmjs.org/@ashthornton/asscroll/-/asscroll-2.0.11.tgz", 22 | "integrity": "sha512-X7Z+0aePdxn2WeKTx+sX/U9KNwjRSlY+ZeoGO7ZQy4uKRZ2cSHZi5ho9WiuDAPTPj97Smb2aZ7XC8goR73SmPA==", 23 | "dev": true, 24 | "dependencies": { 25 | "@unseenco/e": "^2.2.2" 26 | } 27 | }, 28 | "node_modules/@unseenco/e": { 29 | "version": "2.2.2", 30 | "resolved": "https://registry.npmjs.org/@unseenco/e/-/e-2.2.2.tgz", 31 | "integrity": "sha512-7d+CKXw5rJDz1zkKiAQQGBLOUZ1JqV+c9pTTERSKwfwjjq6sJkoDbo+L0usmu7kDzIUxJKWOtm1JoCTrYNHIZw==", 32 | "dev": true, 33 | "dependencies": { 34 | "selector-set": "^1.1.5" 35 | } 36 | }, 37 | "node_modules/esbuild": { 38 | "version": "0.14.48", 39 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.48.tgz", 40 | "integrity": "sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA==", 41 | "dev": true, 42 | "hasInstallScript": true, 43 | "bin": { 44 | "esbuild": "bin/esbuild" 45 | }, 46 | "engines": { 47 | "node": ">=12" 48 | }, 49 | "optionalDependencies": { 50 | "esbuild-android-64": "0.14.48", 51 | "esbuild-android-arm64": "0.14.48", 52 | "esbuild-darwin-64": "0.14.48", 53 | "esbuild-darwin-arm64": "0.14.48", 54 | "esbuild-freebsd-64": "0.14.48", 55 | "esbuild-freebsd-arm64": "0.14.48", 56 | "esbuild-linux-32": "0.14.48", 57 | "esbuild-linux-64": "0.14.48", 58 | "esbuild-linux-arm": "0.14.48", 59 | "esbuild-linux-arm64": "0.14.48", 60 | "esbuild-linux-mips64le": "0.14.48", 61 | "esbuild-linux-ppc64le": "0.14.48", 62 | "esbuild-linux-riscv64": "0.14.48", 63 | "esbuild-linux-s390x": "0.14.48", 64 | "esbuild-netbsd-64": "0.14.48", 65 | "esbuild-openbsd-64": "0.14.48", 66 | "esbuild-sunos-64": "0.14.48", 67 | "esbuild-windows-32": "0.14.48", 68 | "esbuild-windows-64": "0.14.48", 69 | "esbuild-windows-arm64": "0.14.48" 70 | } 71 | }, 72 | "node_modules/esbuild-android-64": { 73 | "version": "0.14.48", 74 | "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.48.tgz", 75 | "integrity": "sha512-3aMjboap/kqwCUpGWIjsk20TtxVoKck8/4Tu19rubh7t5Ra0Yrpg30Mt1QXXlipOazrEceGeWurXKeFJgkPOUg==", 76 | "cpu": [ 77 | "x64" 78 | ], 79 | "dev": true, 80 | "optional": true, 81 | "os": [ 82 | "android" 83 | ], 84 | "engines": { 85 | "node": ">=12" 86 | } 87 | }, 88 | "node_modules/esbuild-android-arm64": { 89 | "version": "0.14.48", 90 | "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.48.tgz", 91 | "integrity": "sha512-vptI3K0wGALiDq+EvRuZotZrJqkYkN5282iAfcffjI5lmGG9G1ta/CIVauhY42MBXwEgDJkweiDcDMRLzBZC4g==", 92 | "cpu": [ 93 | "arm64" 94 | ], 95 | "dev": true, 96 | "optional": true, 97 | "os": [ 98 | "android" 99 | ], 100 | "engines": { 101 | "node": ">=12" 102 | } 103 | }, 104 | "node_modules/esbuild-darwin-64": { 105 | "version": "0.14.48", 106 | "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.48.tgz", 107 | "integrity": "sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA==", 108 | "cpu": [ 109 | "x64" 110 | ], 111 | "dev": true, 112 | "optional": true, 113 | "os": [ 114 | "darwin" 115 | ], 116 | "engines": { 117 | "node": ">=12" 118 | } 119 | }, 120 | "node_modules/esbuild-darwin-arm64": { 121 | "version": "0.14.48", 122 | "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.48.tgz", 123 | "integrity": "sha512-bFjnNEXjhZT+IZ8RvRGNJthLWNHV5JkCtuOFOnjvo5pC0sk2/QVk0Qc06g2PV3J0TcU6kaPC3RN9yy9w2PSLEA==", 124 | "cpu": [ 125 | "arm64" 126 | ], 127 | "dev": true, 128 | "optional": true, 129 | "os": [ 130 | "darwin" 131 | ], 132 | "engines": { 133 | "node": ">=12" 134 | } 135 | }, 136 | "node_modules/esbuild-freebsd-64": { 137 | "version": "0.14.48", 138 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.48.tgz", 139 | "integrity": "sha512-1NOlwRxmOsnPcWOGTB10JKAkYSb2nue0oM1AfHWunW/mv3wERfJmnYlGzL3UAOIUXZqW8GeA2mv+QGwq7DToqA==", 140 | "cpu": [ 141 | "x64" 142 | ], 143 | "dev": true, 144 | "optional": true, 145 | "os": [ 146 | "freebsd" 147 | ], 148 | "engines": { 149 | "node": ">=12" 150 | } 151 | }, 152 | "node_modules/esbuild-freebsd-arm64": { 153 | "version": "0.14.48", 154 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.48.tgz", 155 | "integrity": "sha512-gXqKdO8wabVcYtluAbikDH2jhXp+Klq5oCD5qbVyUG6tFiGhrC9oczKq3vIrrtwcxDQqK6+HDYK8Zrd4bCA9Gw==", 156 | "cpu": [ 157 | "arm64" 158 | ], 159 | "dev": true, 160 | "optional": true, 161 | "os": [ 162 | "freebsd" 163 | ], 164 | "engines": { 165 | "node": ">=12" 166 | } 167 | }, 168 | "node_modules/esbuild-linux-32": { 169 | "version": "0.14.48", 170 | "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.48.tgz", 171 | "integrity": "sha512-ghGyDfS289z/LReZQUuuKq9KlTiTspxL8SITBFQFAFRA/IkIvDpnZnCAKTCjGXAmUqroMQfKJXMxyjJA69c/nQ==", 172 | "cpu": [ 173 | "ia32" 174 | ], 175 | "dev": true, 176 | "optional": true, 177 | "os": [ 178 | "linux" 179 | ], 180 | "engines": { 181 | "node": ">=12" 182 | } 183 | }, 184 | "node_modules/esbuild-linux-64": { 185 | "version": "0.14.48", 186 | "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.48.tgz", 187 | "integrity": "sha512-vni3p/gppLMVZLghI7oMqbOZdGmLbbKR23XFARKnszCIBpEMEDxOMNIKPmMItQrmH/iJrL1z8Jt2nynY0bE1ug==", 188 | "cpu": [ 189 | "x64" 190 | ], 191 | "dev": true, 192 | "optional": true, 193 | "os": [ 194 | "linux" 195 | ], 196 | "engines": { 197 | "node": ">=12" 198 | } 199 | }, 200 | "node_modules/esbuild-linux-arm": { 201 | "version": "0.14.48", 202 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.48.tgz", 203 | "integrity": "sha512-+VfSV7Akh1XUiDNXgqgY1cUP1i2vjI+BmlyXRfVz5AfV3jbpde8JTs5Q9sYgaoq5cWfuKfoZB/QkGOI+QcL1Tw==", 204 | "cpu": [ 205 | "arm" 206 | ], 207 | "dev": true, 208 | "optional": true, 209 | "os": [ 210 | "linux" 211 | ], 212 | "engines": { 213 | "node": ">=12" 214 | } 215 | }, 216 | "node_modules/esbuild-linux-arm64": { 217 | "version": "0.14.48", 218 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.48.tgz", 219 | "integrity": "sha512-3CFsOlpoxlKPRevEHq8aAntgYGYkE1N9yRYAcPyng/p4Wyx0tPR5SBYsxLKcgPB9mR8chHEhtWYz6EZ+H199Zw==", 220 | "cpu": [ 221 | "arm64" 222 | ], 223 | "dev": true, 224 | "optional": true, 225 | "os": [ 226 | "linux" 227 | ], 228 | "engines": { 229 | "node": ">=12" 230 | } 231 | }, 232 | "node_modules/esbuild-linux-mips64le": { 233 | "version": "0.14.48", 234 | "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.48.tgz", 235 | "integrity": "sha512-cs0uOiRlPp6ymknDnjajCgvDMSsLw5mST2UXh+ZIrXTj2Ifyf2aAP3Iw4DiqgnyYLV2O/v/yWBJx+WfmKEpNLA==", 236 | "cpu": [ 237 | "mips64el" 238 | ], 239 | "dev": true, 240 | "optional": true, 241 | "os": [ 242 | "linux" 243 | ], 244 | "engines": { 245 | "node": ">=12" 246 | } 247 | }, 248 | "node_modules/esbuild-linux-ppc64le": { 249 | "version": "0.14.48", 250 | "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.48.tgz", 251 | "integrity": "sha512-+2F0vJMkuI0Wie/wcSPDCqXvSFEELH7Jubxb7mpWrA/4NpT+/byjxDz0gG6R1WJoeDefcrMfpBx4GFNN1JQorQ==", 252 | "cpu": [ 253 | "ppc64" 254 | ], 255 | "dev": true, 256 | "optional": true, 257 | "os": [ 258 | "linux" 259 | ], 260 | "engines": { 261 | "node": ">=12" 262 | } 263 | }, 264 | "node_modules/esbuild-linux-riscv64": { 265 | "version": "0.14.48", 266 | "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.48.tgz", 267 | "integrity": "sha512-BmaK/GfEE+5F2/QDrIXteFGKnVHGxlnK9MjdVKMTfvtmudjY3k2t8NtlY4qemKSizc+QwyombGWTBDc76rxePA==", 268 | "cpu": [ 269 | "riscv64" 270 | ], 271 | "dev": true, 272 | "optional": true, 273 | "os": [ 274 | "linux" 275 | ], 276 | "engines": { 277 | "node": ">=12" 278 | } 279 | }, 280 | "node_modules/esbuild-linux-s390x": { 281 | "version": "0.14.48", 282 | "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.48.tgz", 283 | "integrity": "sha512-tndw/0B9jiCL+KWKo0TSMaUm5UWBLsfCKVdbfMlb3d5LeV9WbijZ8Ordia8SAYv38VSJWOEt6eDCdOx8LqkC4g==", 284 | "cpu": [ 285 | "s390x" 286 | ], 287 | "dev": true, 288 | "optional": true, 289 | "os": [ 290 | "linux" 291 | ], 292 | "engines": { 293 | "node": ">=12" 294 | } 295 | }, 296 | "node_modules/esbuild-netbsd-64": { 297 | "version": "0.14.48", 298 | "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.48.tgz", 299 | "integrity": "sha512-V9hgXfwf/T901Lr1wkOfoevtyNkrxmMcRHyticybBUHookznipMOHoF41Al68QBsqBxnITCEpjjd4yAos7z9Tw==", 300 | "cpu": [ 301 | "x64" 302 | ], 303 | "dev": true, 304 | "optional": true, 305 | "os": [ 306 | "netbsd" 307 | ], 308 | "engines": { 309 | "node": ">=12" 310 | } 311 | }, 312 | "node_modules/esbuild-openbsd-64": { 313 | "version": "0.14.48", 314 | "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.48.tgz", 315 | "integrity": "sha512-+IHf4JcbnnBl4T52egorXMatil/za0awqzg2Vy6FBgPcBpisDWT2sVz/tNdrK9kAqj+GZG/jZdrOkj7wsrNTKA==", 316 | "cpu": [ 317 | "x64" 318 | ], 319 | "dev": true, 320 | "optional": true, 321 | "os": [ 322 | "openbsd" 323 | ], 324 | "engines": { 325 | "node": ">=12" 326 | } 327 | }, 328 | "node_modules/esbuild-sunos-64": { 329 | "version": "0.14.48", 330 | "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz", 331 | "integrity": "sha512-77m8bsr5wOpOWbGi9KSqDphcq6dFeJyun8TA+12JW/GAjyfTwVtOnN8DOt6DSPUfEV+ltVMNqtXUeTeMAxl5KA==", 332 | "cpu": [ 333 | "x64" 334 | ], 335 | "dev": true, 336 | "optional": true, 337 | "os": [ 338 | "sunos" 339 | ], 340 | "engines": { 341 | "node": ">=12" 342 | } 343 | }, 344 | "node_modules/esbuild-windows-32": { 345 | "version": "0.14.48", 346 | "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.48.tgz", 347 | "integrity": "sha512-EPgRuTPP8vK9maxpTGDe5lSoIBHGKO/AuxDncg5O3NkrPeLNdvvK8oywB0zGaAZXxYWfNNSHskvvDgmfVTguhg==", 348 | "cpu": [ 349 | "ia32" 350 | ], 351 | "dev": true, 352 | "optional": true, 353 | "os": [ 354 | "win32" 355 | ], 356 | "engines": { 357 | "node": ">=12" 358 | } 359 | }, 360 | "node_modules/esbuild-windows-64": { 361 | "version": "0.14.48", 362 | "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.48.tgz", 363 | "integrity": "sha512-YmpXjdT1q0b8ictSdGwH3M8VCoqPpK1/UArze3X199w6u8hUx3V8BhAi1WjbsfDYRBanVVtduAhh2sirImtAvA==", 364 | "cpu": [ 365 | "x64" 366 | ], 367 | "dev": true, 368 | "optional": true, 369 | "os": [ 370 | "win32" 371 | ], 372 | "engines": { 373 | "node": ">=12" 374 | } 375 | }, 376 | "node_modules/esbuild-windows-arm64": { 377 | "version": "0.14.48", 378 | "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.48.tgz", 379 | "integrity": "sha512-HHaOMCsCXp0rz5BT2crTka6MPWVno121NKApsGs/OIW5QC0ggC69YMGs1aJct9/9FSUF4A1xNE/cLvgB5svR4g==", 380 | "cpu": [ 381 | "arm64" 382 | ], 383 | "dev": true, 384 | "optional": true, 385 | "os": [ 386 | "win32" 387 | ], 388 | "engines": { 389 | "node": ">=12" 390 | } 391 | }, 392 | "node_modules/events": { 393 | "version": "3.3.0", 394 | "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", 395 | "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", 396 | "dev": true, 397 | "engines": { 398 | "node": ">=0.8.x" 399 | } 400 | }, 401 | "node_modules/fsevents": { 402 | "version": "2.3.2", 403 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 404 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 405 | "dev": true, 406 | "hasInstallScript": true, 407 | "optional": true, 408 | "os": [ 409 | "darwin" 410 | ], 411 | "engines": { 412 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 413 | } 414 | }, 415 | "node_modules/function-bind": { 416 | "version": "1.1.1", 417 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 418 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 419 | "dev": true 420 | }, 421 | "node_modules/gsap": { 422 | "version": "3.10.4", 423 | "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.10.4.tgz", 424 | "integrity": "sha512-6QatdkKxXCMfvCW4rM++0RqyLQAzFX5nwl3yHS0XPgkZBkiSEY3VZVbMltrdtsbER/xZonLtyHt684wRp4erlQ==", 425 | "dev": true 426 | }, 427 | "node_modules/has": { 428 | "version": "1.0.3", 429 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 430 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 431 | "dev": true, 432 | "dependencies": { 433 | "function-bind": "^1.1.1" 434 | }, 435 | "engines": { 436 | "node": ">= 0.4.0" 437 | } 438 | }, 439 | "node_modules/is-core-module": { 440 | "version": "2.9.0", 441 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", 442 | "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", 443 | "dev": true, 444 | "dependencies": { 445 | "has": "^1.0.3" 446 | }, 447 | "funding": { 448 | "url": "https://github.com/sponsors/ljharb" 449 | } 450 | }, 451 | "node_modules/lil-gui": { 452 | "version": "0.17.0", 453 | "resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.17.0.tgz", 454 | "integrity": "sha512-MVBHmgY+uEbmJNApAaPbtvNh1RCAeMnKym82SBjtp5rODTYKWtM+MXHCifLe2H2Ti1HuBGBtK/5SyG4ShQ3pUQ==", 455 | "dev": true 456 | }, 457 | "node_modules/nanoid": { 458 | "version": "3.3.4", 459 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", 460 | "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", 461 | "dev": true, 462 | "bin": { 463 | "nanoid": "bin/nanoid.cjs" 464 | }, 465 | "engines": { 466 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 467 | } 468 | }, 469 | "node_modules/path-parse": { 470 | "version": "1.0.7", 471 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 472 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 473 | "dev": true 474 | }, 475 | "node_modules/picocolors": { 476 | "version": "1.0.0", 477 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 478 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 479 | "dev": true 480 | }, 481 | "node_modules/postcss": { 482 | "version": "8.4.14", 483 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", 484 | "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", 485 | "dev": true, 486 | "funding": [ 487 | { 488 | "type": "opencollective", 489 | "url": "https://opencollective.com/postcss/" 490 | }, 491 | { 492 | "type": "tidelift", 493 | "url": "https://tidelift.com/funding/github/npm/postcss" 494 | } 495 | ], 496 | "dependencies": { 497 | "nanoid": "^3.3.4", 498 | "picocolors": "^1.0.0", 499 | "source-map-js": "^1.0.2" 500 | }, 501 | "engines": { 502 | "node": "^10 || ^12 || >=14" 503 | } 504 | }, 505 | "node_modules/resolve": { 506 | "version": "1.22.1", 507 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", 508 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", 509 | "dev": true, 510 | "dependencies": { 511 | "is-core-module": "^2.9.0", 512 | "path-parse": "^1.0.7", 513 | "supports-preserve-symlinks-flag": "^1.0.0" 514 | }, 515 | "bin": { 516 | "resolve": "bin/resolve" 517 | }, 518 | "funding": { 519 | "url": "https://github.com/sponsors/ljharb" 520 | } 521 | }, 522 | "node_modules/rollup": { 523 | "version": "2.76.0", 524 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.76.0.tgz", 525 | "integrity": "sha512-9jwRIEY1jOzKLj3nsY/yot41r19ITdQrhs+q3ggNWhr9TQgduHqANvPpS32RNpzGklJu3G1AJfvlZLi/6wFgWA==", 526 | "dev": true, 527 | "bin": { 528 | "rollup": "dist/bin/rollup" 529 | }, 530 | "engines": { 531 | "node": ">=10.0.0" 532 | }, 533 | "optionalDependencies": { 534 | "fsevents": "~2.3.2" 535 | } 536 | }, 537 | "node_modules/selector-set": { 538 | "version": "1.1.5", 539 | "resolved": "https://registry.npmjs.org/selector-set/-/selector-set-1.1.5.tgz", 540 | "integrity": "sha512-6SQw6yMew5iOZ8/cDHDEnJWRM4ot2mxP6szZyF5ptrBogw4AcS4EXRj/8BUfgAMwVfdL84qpModlBMOl2NVrsQ==", 541 | "dev": true 542 | }, 543 | "node_modules/source-map-js": { 544 | "version": "1.0.2", 545 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 546 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 547 | "dev": true, 548 | "engines": { 549 | "node": ">=0.10.0" 550 | } 551 | }, 552 | "node_modules/supports-preserve-symlinks-flag": { 553 | "version": "1.0.0", 554 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 555 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 556 | "dev": true, 557 | "engines": { 558 | "node": ">= 0.4" 559 | }, 560 | "funding": { 561 | "url": "https://github.com/sponsors/ljharb" 562 | } 563 | }, 564 | "node_modules/three": { 565 | "version": "0.142.0", 566 | "resolved": "https://registry.npmjs.org/three/-/three-0.142.0.tgz", 567 | "integrity": "sha512-ESjPO+3geFr+ZUfVMpMnF/eVU2uJPOh0e2ZpMFqjNca1wApS9lJb7E4MjwGIczgt9iuKd8PEm6Pfgp2bJ92Xtg==", 568 | "dev": true 569 | }, 570 | "node_modules/vite": { 571 | "version": "2.9.14", 572 | "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.14.tgz", 573 | "integrity": "sha512-P/UCjSpSMcE54r4mPak55hWAZPlyfS369svib/gpmz8/01L822lMPOJ/RYW6tLCe1RPvMvOsJ17erf55bKp4Hw==", 574 | "dev": true, 575 | "dependencies": { 576 | "esbuild": "^0.14.27", 577 | "postcss": "^8.4.13", 578 | "resolve": "^1.22.0", 579 | "rollup": "^2.59.0" 580 | }, 581 | "bin": { 582 | "vite": "bin/vite.js" 583 | }, 584 | "engines": { 585 | "node": ">=12.2.0" 586 | }, 587 | "optionalDependencies": { 588 | "fsevents": "~2.3.2" 589 | }, 590 | "peerDependencies": { 591 | "less": "*", 592 | "sass": "*", 593 | "stylus": "*" 594 | }, 595 | "peerDependenciesMeta": { 596 | "less": { 597 | "optional": true 598 | }, 599 | "sass": { 600 | "optional": true 601 | }, 602 | "stylus": { 603 | "optional": true 604 | } 605 | } 606 | } 607 | }, 608 | "dependencies": { 609 | "@ashthornton/asscroll": { 610 | "version": "2.0.11", 611 | "resolved": "https://registry.npmjs.org/@ashthornton/asscroll/-/asscroll-2.0.11.tgz", 612 | "integrity": "sha512-X7Z+0aePdxn2WeKTx+sX/U9KNwjRSlY+ZeoGO7ZQy4uKRZ2cSHZi5ho9WiuDAPTPj97Smb2aZ7XC8goR73SmPA==", 613 | "dev": true, 614 | "requires": { 615 | "@unseenco/e": "^2.2.2" 616 | } 617 | }, 618 | "@unseenco/e": { 619 | "version": "2.2.2", 620 | "resolved": "https://registry.npmjs.org/@unseenco/e/-/e-2.2.2.tgz", 621 | "integrity": "sha512-7d+CKXw5rJDz1zkKiAQQGBLOUZ1JqV+c9pTTERSKwfwjjq6sJkoDbo+L0usmu7kDzIUxJKWOtm1JoCTrYNHIZw==", 622 | "dev": true, 623 | "requires": { 624 | "selector-set": "^1.1.5" 625 | } 626 | }, 627 | "esbuild": { 628 | "version": "0.14.48", 629 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.48.tgz", 630 | "integrity": "sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA==", 631 | "dev": true, 632 | "requires": { 633 | "esbuild-android-64": "0.14.48", 634 | "esbuild-android-arm64": "0.14.48", 635 | "esbuild-darwin-64": "0.14.48", 636 | "esbuild-darwin-arm64": "0.14.48", 637 | "esbuild-freebsd-64": "0.14.48", 638 | "esbuild-freebsd-arm64": "0.14.48", 639 | "esbuild-linux-32": "0.14.48", 640 | "esbuild-linux-64": "0.14.48", 641 | "esbuild-linux-arm": "0.14.48", 642 | "esbuild-linux-arm64": "0.14.48", 643 | "esbuild-linux-mips64le": "0.14.48", 644 | "esbuild-linux-ppc64le": "0.14.48", 645 | "esbuild-linux-riscv64": "0.14.48", 646 | "esbuild-linux-s390x": "0.14.48", 647 | "esbuild-netbsd-64": "0.14.48", 648 | "esbuild-openbsd-64": "0.14.48", 649 | "esbuild-sunos-64": "0.14.48", 650 | "esbuild-windows-32": "0.14.48", 651 | "esbuild-windows-64": "0.14.48", 652 | "esbuild-windows-arm64": "0.14.48" 653 | } 654 | }, 655 | "esbuild-android-64": { 656 | "version": "0.14.48", 657 | "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.48.tgz", 658 | "integrity": "sha512-3aMjboap/kqwCUpGWIjsk20TtxVoKck8/4Tu19rubh7t5Ra0Yrpg30Mt1QXXlipOazrEceGeWurXKeFJgkPOUg==", 659 | "dev": true, 660 | "optional": true 661 | }, 662 | "esbuild-android-arm64": { 663 | "version": "0.14.48", 664 | "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.48.tgz", 665 | "integrity": "sha512-vptI3K0wGALiDq+EvRuZotZrJqkYkN5282iAfcffjI5lmGG9G1ta/CIVauhY42MBXwEgDJkweiDcDMRLzBZC4g==", 666 | "dev": true, 667 | "optional": true 668 | }, 669 | "esbuild-darwin-64": { 670 | "version": "0.14.48", 671 | "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.48.tgz", 672 | "integrity": "sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA==", 673 | "dev": true, 674 | "optional": true 675 | }, 676 | "esbuild-darwin-arm64": { 677 | "version": "0.14.48", 678 | "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.48.tgz", 679 | "integrity": "sha512-bFjnNEXjhZT+IZ8RvRGNJthLWNHV5JkCtuOFOnjvo5pC0sk2/QVk0Qc06g2PV3J0TcU6kaPC3RN9yy9w2PSLEA==", 680 | "dev": true, 681 | "optional": true 682 | }, 683 | "esbuild-freebsd-64": { 684 | "version": "0.14.48", 685 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.48.tgz", 686 | "integrity": "sha512-1NOlwRxmOsnPcWOGTB10JKAkYSb2nue0oM1AfHWunW/mv3wERfJmnYlGzL3UAOIUXZqW8GeA2mv+QGwq7DToqA==", 687 | "dev": true, 688 | "optional": true 689 | }, 690 | "esbuild-freebsd-arm64": { 691 | "version": "0.14.48", 692 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.48.tgz", 693 | "integrity": "sha512-gXqKdO8wabVcYtluAbikDH2jhXp+Klq5oCD5qbVyUG6tFiGhrC9oczKq3vIrrtwcxDQqK6+HDYK8Zrd4bCA9Gw==", 694 | "dev": true, 695 | "optional": true 696 | }, 697 | "esbuild-linux-32": { 698 | "version": "0.14.48", 699 | "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.48.tgz", 700 | "integrity": "sha512-ghGyDfS289z/LReZQUuuKq9KlTiTspxL8SITBFQFAFRA/IkIvDpnZnCAKTCjGXAmUqroMQfKJXMxyjJA69c/nQ==", 701 | "dev": true, 702 | "optional": true 703 | }, 704 | "esbuild-linux-64": { 705 | "version": "0.14.48", 706 | "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.48.tgz", 707 | "integrity": "sha512-vni3p/gppLMVZLghI7oMqbOZdGmLbbKR23XFARKnszCIBpEMEDxOMNIKPmMItQrmH/iJrL1z8Jt2nynY0bE1ug==", 708 | "dev": true, 709 | "optional": true 710 | }, 711 | "esbuild-linux-arm": { 712 | "version": "0.14.48", 713 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.48.tgz", 714 | "integrity": "sha512-+VfSV7Akh1XUiDNXgqgY1cUP1i2vjI+BmlyXRfVz5AfV3jbpde8JTs5Q9sYgaoq5cWfuKfoZB/QkGOI+QcL1Tw==", 715 | "dev": true, 716 | "optional": true 717 | }, 718 | "esbuild-linux-arm64": { 719 | "version": "0.14.48", 720 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.48.tgz", 721 | "integrity": "sha512-3CFsOlpoxlKPRevEHq8aAntgYGYkE1N9yRYAcPyng/p4Wyx0tPR5SBYsxLKcgPB9mR8chHEhtWYz6EZ+H199Zw==", 722 | "dev": true, 723 | "optional": true 724 | }, 725 | "esbuild-linux-mips64le": { 726 | "version": "0.14.48", 727 | "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.48.tgz", 728 | "integrity": "sha512-cs0uOiRlPp6ymknDnjajCgvDMSsLw5mST2UXh+ZIrXTj2Ifyf2aAP3Iw4DiqgnyYLV2O/v/yWBJx+WfmKEpNLA==", 729 | "dev": true, 730 | "optional": true 731 | }, 732 | "esbuild-linux-ppc64le": { 733 | "version": "0.14.48", 734 | "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.48.tgz", 735 | "integrity": "sha512-+2F0vJMkuI0Wie/wcSPDCqXvSFEELH7Jubxb7mpWrA/4NpT+/byjxDz0gG6R1WJoeDefcrMfpBx4GFNN1JQorQ==", 736 | "dev": true, 737 | "optional": true 738 | }, 739 | "esbuild-linux-riscv64": { 740 | "version": "0.14.48", 741 | "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.48.tgz", 742 | "integrity": "sha512-BmaK/GfEE+5F2/QDrIXteFGKnVHGxlnK9MjdVKMTfvtmudjY3k2t8NtlY4qemKSizc+QwyombGWTBDc76rxePA==", 743 | "dev": true, 744 | "optional": true 745 | }, 746 | "esbuild-linux-s390x": { 747 | "version": "0.14.48", 748 | "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.48.tgz", 749 | "integrity": "sha512-tndw/0B9jiCL+KWKo0TSMaUm5UWBLsfCKVdbfMlb3d5LeV9WbijZ8Ordia8SAYv38VSJWOEt6eDCdOx8LqkC4g==", 750 | "dev": true, 751 | "optional": true 752 | }, 753 | "esbuild-netbsd-64": { 754 | "version": "0.14.48", 755 | "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.48.tgz", 756 | "integrity": "sha512-V9hgXfwf/T901Lr1wkOfoevtyNkrxmMcRHyticybBUHookznipMOHoF41Al68QBsqBxnITCEpjjd4yAos7z9Tw==", 757 | "dev": true, 758 | "optional": true 759 | }, 760 | "esbuild-openbsd-64": { 761 | "version": "0.14.48", 762 | "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.48.tgz", 763 | "integrity": "sha512-+IHf4JcbnnBl4T52egorXMatil/za0awqzg2Vy6FBgPcBpisDWT2sVz/tNdrK9kAqj+GZG/jZdrOkj7wsrNTKA==", 764 | "dev": true, 765 | "optional": true 766 | }, 767 | "esbuild-sunos-64": { 768 | "version": "0.14.48", 769 | "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz", 770 | "integrity": "sha512-77m8bsr5wOpOWbGi9KSqDphcq6dFeJyun8TA+12JW/GAjyfTwVtOnN8DOt6DSPUfEV+ltVMNqtXUeTeMAxl5KA==", 771 | "dev": true, 772 | "optional": true 773 | }, 774 | "esbuild-windows-32": { 775 | "version": "0.14.48", 776 | "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.48.tgz", 777 | "integrity": "sha512-EPgRuTPP8vK9maxpTGDe5lSoIBHGKO/AuxDncg5O3NkrPeLNdvvK8oywB0zGaAZXxYWfNNSHskvvDgmfVTguhg==", 778 | "dev": true, 779 | "optional": true 780 | }, 781 | "esbuild-windows-64": { 782 | "version": "0.14.48", 783 | "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.48.tgz", 784 | "integrity": "sha512-YmpXjdT1q0b8ictSdGwH3M8VCoqPpK1/UArze3X199w6u8hUx3V8BhAi1WjbsfDYRBanVVtduAhh2sirImtAvA==", 785 | "dev": true, 786 | "optional": true 787 | }, 788 | "esbuild-windows-arm64": { 789 | "version": "0.14.48", 790 | "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.48.tgz", 791 | "integrity": "sha512-HHaOMCsCXp0rz5BT2crTka6MPWVno121NKApsGs/OIW5QC0ggC69YMGs1aJct9/9FSUF4A1xNE/cLvgB5svR4g==", 792 | "dev": true, 793 | "optional": true 794 | }, 795 | "events": { 796 | "version": "3.3.0", 797 | "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", 798 | "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", 799 | "dev": true 800 | }, 801 | "fsevents": { 802 | "version": "2.3.2", 803 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 804 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 805 | "dev": true, 806 | "optional": true 807 | }, 808 | "function-bind": { 809 | "version": "1.1.1", 810 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 811 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 812 | "dev": true 813 | }, 814 | "gsap": { 815 | "version": "3.10.4", 816 | "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.10.4.tgz", 817 | "integrity": "sha512-6QatdkKxXCMfvCW4rM++0RqyLQAzFX5nwl3yHS0XPgkZBkiSEY3VZVbMltrdtsbER/xZonLtyHt684wRp4erlQ==", 818 | "dev": true 819 | }, 820 | "has": { 821 | "version": "1.0.3", 822 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 823 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 824 | "dev": true, 825 | "requires": { 826 | "function-bind": "^1.1.1" 827 | } 828 | }, 829 | "is-core-module": { 830 | "version": "2.9.0", 831 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", 832 | "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", 833 | "dev": true, 834 | "requires": { 835 | "has": "^1.0.3" 836 | } 837 | }, 838 | "lil-gui": { 839 | "version": "0.17.0", 840 | "resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.17.0.tgz", 841 | "integrity": "sha512-MVBHmgY+uEbmJNApAaPbtvNh1RCAeMnKym82SBjtp5rODTYKWtM+MXHCifLe2H2Ti1HuBGBtK/5SyG4ShQ3pUQ==", 842 | "dev": true 843 | }, 844 | "nanoid": { 845 | "version": "3.3.4", 846 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", 847 | "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", 848 | "dev": true 849 | }, 850 | "path-parse": { 851 | "version": "1.0.7", 852 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 853 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 854 | "dev": true 855 | }, 856 | "picocolors": { 857 | "version": "1.0.0", 858 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 859 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 860 | "dev": true 861 | }, 862 | "postcss": { 863 | "version": "8.4.14", 864 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", 865 | "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", 866 | "dev": true, 867 | "requires": { 868 | "nanoid": "^3.3.4", 869 | "picocolors": "^1.0.0", 870 | "source-map-js": "^1.0.2" 871 | } 872 | }, 873 | "resolve": { 874 | "version": "1.22.1", 875 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", 876 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", 877 | "dev": true, 878 | "requires": { 879 | "is-core-module": "^2.9.0", 880 | "path-parse": "^1.0.7", 881 | "supports-preserve-symlinks-flag": "^1.0.0" 882 | } 883 | }, 884 | "rollup": { 885 | "version": "2.76.0", 886 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.76.0.tgz", 887 | "integrity": "sha512-9jwRIEY1jOzKLj3nsY/yot41r19ITdQrhs+q3ggNWhr9TQgduHqANvPpS32RNpzGklJu3G1AJfvlZLi/6wFgWA==", 888 | "dev": true, 889 | "requires": { 890 | "fsevents": "~2.3.2" 891 | } 892 | }, 893 | "selector-set": { 894 | "version": "1.1.5", 895 | "resolved": "https://registry.npmjs.org/selector-set/-/selector-set-1.1.5.tgz", 896 | "integrity": "sha512-6SQw6yMew5iOZ8/cDHDEnJWRM4ot2mxP6szZyF5ptrBogw4AcS4EXRj/8BUfgAMwVfdL84qpModlBMOl2NVrsQ==", 897 | "dev": true 898 | }, 899 | "source-map-js": { 900 | "version": "1.0.2", 901 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 902 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 903 | "dev": true 904 | }, 905 | "supports-preserve-symlinks-flag": { 906 | "version": "1.0.0", 907 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 908 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 909 | "dev": true 910 | }, 911 | "three": { 912 | "version": "0.142.0", 913 | "resolved": "https://registry.npmjs.org/three/-/three-0.142.0.tgz", 914 | "integrity": "sha512-ESjPO+3geFr+ZUfVMpMnF/eVU2uJPOh0e2ZpMFqjNca1wApS9lJb7E4MjwGIczgt9iuKd8PEm6Pfgp2bJ92Xtg==", 915 | "dev": true 916 | }, 917 | "vite": { 918 | "version": "2.9.14", 919 | "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.14.tgz", 920 | "integrity": "sha512-P/UCjSpSMcE54r4mPak55hWAZPlyfS369svib/gpmz8/01L822lMPOJ/RYW6tLCe1RPvMvOsJ17erf55bKp4Hw==", 921 | "dev": true, 922 | "requires": { 923 | "esbuild": "^0.14.27", 924 | "fsevents": "~2.3.2", 925 | "postcss": "^8.4.13", 926 | "resolve": "^1.22.0", 927 | "rollup": "^2.59.0" 928 | } 929 | } 930 | } 931 | } 932 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bike-demo-threejs", 3 | "private": true, 4 | "version": "0.0.0", 5 | "scripts": { 6 | "dev": "vite --host", 7 | "build": "vite build", 8 | "preview": "vite preview" 9 | }, 10 | "devDependencies": { 11 | "@ashthornton/asscroll": "^2.0.11", 12 | "events": "^3.3.0", 13 | "gsap": "^3.10.4", 14 | "lil-gui": "^0.17.0", 15 | "three": "^0.142.0", 16 | "vite": "^2.9.9" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /public/draco/README.md: -------------------------------------------------------------------------------- 1 | # Draco 3D Data Compression 2 | 3 | Draco is an open-source library for compressing and decompressing 3D geometric meshes and point clouds. It is intended to improve the storage and transmission of 3D graphics. 4 | 5 | [Website](https://google.github.io/draco/) | [GitHub](https://github.com/google/draco) 6 | 7 | ## Contents 8 | 9 | This folder contains three utilities: 10 | 11 | * `draco_decoder.js` — Emscripten-compiled decoder, compatible with any modern browser. 12 | * `draco_decoder.wasm` — WebAssembly decoder, compatible with newer browsers and devices. 13 | * `draco_wasm_wrapper.js` — JavaScript wrapper for the WASM decoder. 14 | 15 | Each file is provided in two variations: 16 | 17 | * **Default:** Latest stable builds, tracking the project's [master branch](https://github.com/google/draco). 18 | * **glTF:** Builds targeted by the [glTF mesh compression extension](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression), tracking the [corresponding Draco branch](https://github.com/google/draco/tree/gltf_2.0_draco_extension). 19 | 20 | Either variation may be used with `THREE.DRACOLoader`: 21 | 22 | ```js 23 | var dracoLoader = new THREE.DRACOLoader(); 24 | dracoLoader.setDecoderPath('path/to/decoders/'); 25 | dracoLoader.setDecoderConfig({type: 'js'}); // (Optional) Override detection of WASM support. 26 | ``` 27 | 28 | Further [documentation on GitHub](https://github.com/google/draco/tree/master/javascript/example#static-loading-javascript-decoder). 29 | 30 | ## License 31 | 32 | [Apache License 2.0](https://github.com/google/draco/blob/master/LICENSE) 33 | -------------------------------------------------------------------------------- /public/draco/draco_decoder.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kirilbt/bike-demo-threejs/40f4ef7169c8db1391862d7182a5a19773008a86/public/draco/draco_decoder.wasm -------------------------------------------------------------------------------- /public/draco/draco_wasm_wrapper.js: -------------------------------------------------------------------------------- 1 | var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.arrayIteratorImpl=function(f){var m=0;return function(){return m=d);)++b;if(16k?d+=String.fromCharCode(k):(k-=65536,d+=String.fromCharCode(55296|k>>10,56320|k&1023))}}else d+=String.fromCharCode(k)}return d}function X(a,c){return a?h(ca,a,c):""}function e(a,c){0=d&&(d=65536+((d&1023)<<10)|a.charCodeAt(++b)&1023);127>=d?++c:c=2047>=d?c+2:65535>=d?c+3:c+4}c=Array(c+1);b=0;d=c.length;if(0=e){var f=a.charCodeAt(++k);e=65536+((e&1023)<<10)|f&1023}if(127>=e){if(b>=d)break;c[b++]=e}else{if(2047>=e){if(b+1>=d)break;c[b++]=192|e>>6}else{if(65535>=e){if(b+2>=d)break;c[b++]=224|e>>12}else{if(b+3>=d)break;c[b++]=240|e>>18;c[b++]=128|e>>12&63}c[b++]=128|e>>6&63}c[b++]=128| 18 | e&63}}c[b]=0}a=n.alloc(c,T);n.copy(c,T,a)}return a}function x(){throw"cannot construct a Status, no constructor in IDL";}function A(){this.ptr=Oa();u(A)[this.ptr]=this}function B(){this.ptr=Pa();u(B)[this.ptr]=this}function C(){this.ptr=Qa();u(C)[this.ptr]=this}function D(){this.ptr=Ra();u(D)[this.ptr]=this}function E(){this.ptr=Sa();u(E)[this.ptr]=this}function q(){this.ptr=Ta();u(q)[this.ptr]=this}function J(){this.ptr=Ua();u(J)[this.ptr]=this}function w(){this.ptr=Va();u(w)[this.ptr]=this}function F(){this.ptr= 19 | Wa();u(F)[this.ptr]=this}function r(){this.ptr=Xa();u(r)[this.ptr]=this}function G(){this.ptr=Ya();u(G)[this.ptr]=this}function H(){this.ptr=Za();u(H)[this.ptr]=this}function O(){this.ptr=$a();u(O)[this.ptr]=this}function K(){this.ptr=ab();u(K)[this.ptr]=this}function g(){this.ptr=bb();u(g)[this.ptr]=this}function y(){this.ptr=cb();u(y)[this.ptr]=this}function Q(){throw"cannot construct a VoidPtr, no constructor in IDL";}function I(){this.ptr=db();u(I)[this.ptr]=this}function L(){this.ptr=eb();u(L)[this.ptr]= 20 | this}m=m||{};var a="undefined"!==typeof m?m:{},Ga=!1,Ha=!1;a.onRuntimeInitialized=function(){Ga=!0;if(Ha&&"function"===typeof a.onModuleLoaded)a.onModuleLoaded(a)};a.onModuleParsed=function(){Ha=!0;if(Ga&&"function"===typeof a.onModuleLoaded)a.onModuleLoaded(a)};a.isVersionSupported=function(a){if("string"!==typeof a)return!1;a=a.split(".");return 2>a.length||3=a[1]?!0:0!=a[0]||10>2]},getStr:function(){return X(R.get())}, 26 | get64:function(){var a=R.get();R.get();return a},getZero:function(){R.get()}},Ka={__cxa_allocate_exception:function(a){return ib(a)},__cxa_throw:function(a,c,b){"uncaught_exception"in ta?ta.uncaught_exceptions++:ta.uncaught_exceptions=1;throw a;},abort:function(){z()},emscripten_get_sbrk_ptr:function(){return 18416},emscripten_memcpy_big:function(a,c,b){ca.set(ca.subarray(c,c+b),a)},emscripten_resize_heap:function(a){if(2147418112= 27 | c?e(2*c,65536):Math.min(e((3*c+2147483648)/4,65536),2147418112);a:{try{ia.grow(c-ka.byteLength+65535>>16);l(ia.buffer);var b=1;break a}catch(d){}b=void 0}return b?!0:!1},environ_get:function(a,c){var b=0;ba().forEach(function(d,e){var f=c+b;e=P[a+4*e>>2]=f;for(f=0;f>0]=d.charCodeAt(f);T[e>>0]=0;b+=d.length+1});return 0},environ_sizes_get:function(a,c){var b=ba();P[a>>2]=b.length;var d=0;b.forEach(function(a){d+=a.length+1});P[c>>2]=d;return 0},fd_close:function(a){return 0},fd_seek:function(a, 28 | c,b,d,e){return 0},fd_write:function(a,c,b,d){try{for(var e=0,f=0;f>2],k=P[c+(8*f+4)>>2],h=0;h>2]=e;return 0}catch(ua){return"undefined"!==typeof FS&&ua instanceof FS.ErrnoError||z(ua),ua.errno}},memory:ia,setTempRet0:function(a){},table:gb},La=function(){function e(c,b){a.asm=c.exports;aa--;a.monitorRunDependencies&&a.monitorRunDependencies(aa);0==aa&&(null!==sa&&(clearInterval(sa),sa=null),ja&&(c=ja,ja=null,c()))}function c(a){e(a.instance)} 29 | function b(a){return Ma().then(function(a){return WebAssembly.instantiate(a,d)}).then(a,function(a){Y("failed to asynchronously prepare wasm: "+a);z(a)})}var d={env:Ka,wasi_unstable:Ka};aa++;a.monitorRunDependencies&&a.monitorRunDependencies(aa);if(a.instantiateWasm)try{return a.instantiateWasm(d,e)}catch(Na){return Y("Module.instantiateWasm callback failed with error: "+Na),!1}(function(){if(da||"function"!==typeof WebAssembly.instantiateStreaming||va(U)||"function"!==typeof fetch)return b(c);fetch(U, 30 | {credentials:"same-origin"}).then(function(a){return WebAssembly.instantiateStreaming(a,d).then(c,function(a){Y("wasm streaming compile failed: "+a);Y("falling back to ArrayBuffer instantiation");b(c)})})})();return{}}();a.asm=La;var hb=a.___wasm_call_ctors=function(){return a.asm.__wasm_call_ctors.apply(null,arguments)},jb=a._emscripten_bind_Status_code_0=function(){return a.asm.emscripten_bind_Status_code_0.apply(null,arguments)},kb=a._emscripten_bind_Status_ok_0=function(){return a.asm.emscripten_bind_Status_ok_0.apply(null, 31 | arguments)},lb=a._emscripten_bind_Status_error_msg_0=function(){return a.asm.emscripten_bind_Status_error_msg_0.apply(null,arguments)},mb=a._emscripten_bind_Status___destroy___0=function(){return a.asm.emscripten_bind_Status___destroy___0.apply(null,arguments)},Oa=a._emscripten_bind_DracoUInt16Array_DracoUInt16Array_0=function(){return a.asm.emscripten_bind_DracoUInt16Array_DracoUInt16Array_0.apply(null,arguments)},nb=a._emscripten_bind_DracoUInt16Array_GetValue_1=function(){return a.asm.emscripten_bind_DracoUInt16Array_GetValue_1.apply(null, 32 | arguments)},ob=a._emscripten_bind_DracoUInt16Array_size_0=function(){return a.asm.emscripten_bind_DracoUInt16Array_size_0.apply(null,arguments)},pb=a._emscripten_bind_DracoUInt16Array___destroy___0=function(){return a.asm.emscripten_bind_DracoUInt16Array___destroy___0.apply(null,arguments)},Pa=a._emscripten_bind_PointCloud_PointCloud_0=function(){return a.asm.emscripten_bind_PointCloud_PointCloud_0.apply(null,arguments)},qb=a._emscripten_bind_PointCloud_num_attributes_0=function(){return a.asm.emscripten_bind_PointCloud_num_attributes_0.apply(null, 33 | arguments)},rb=a._emscripten_bind_PointCloud_num_points_0=function(){return a.asm.emscripten_bind_PointCloud_num_points_0.apply(null,arguments)},sb=a._emscripten_bind_PointCloud___destroy___0=function(){return a.asm.emscripten_bind_PointCloud___destroy___0.apply(null,arguments)},Qa=a._emscripten_bind_DracoUInt8Array_DracoUInt8Array_0=function(){return a.asm.emscripten_bind_DracoUInt8Array_DracoUInt8Array_0.apply(null,arguments)},tb=a._emscripten_bind_DracoUInt8Array_GetValue_1=function(){return a.asm.emscripten_bind_DracoUInt8Array_GetValue_1.apply(null, 34 | arguments)},ub=a._emscripten_bind_DracoUInt8Array_size_0=function(){return a.asm.emscripten_bind_DracoUInt8Array_size_0.apply(null,arguments)},vb=a._emscripten_bind_DracoUInt8Array___destroy___0=function(){return a.asm.emscripten_bind_DracoUInt8Array___destroy___0.apply(null,arguments)},Ra=a._emscripten_bind_DracoUInt32Array_DracoUInt32Array_0=function(){return a.asm.emscripten_bind_DracoUInt32Array_DracoUInt32Array_0.apply(null,arguments)},wb=a._emscripten_bind_DracoUInt32Array_GetValue_1=function(){return a.asm.emscripten_bind_DracoUInt32Array_GetValue_1.apply(null, 35 | arguments)},xb=a._emscripten_bind_DracoUInt32Array_size_0=function(){return a.asm.emscripten_bind_DracoUInt32Array_size_0.apply(null,arguments)},yb=a._emscripten_bind_DracoUInt32Array___destroy___0=function(){return a.asm.emscripten_bind_DracoUInt32Array___destroy___0.apply(null,arguments)},Sa=a._emscripten_bind_AttributeOctahedronTransform_AttributeOctahedronTransform_0=function(){return a.asm.emscripten_bind_AttributeOctahedronTransform_AttributeOctahedronTransform_0.apply(null,arguments)},zb=a._emscripten_bind_AttributeOctahedronTransform_InitFromAttribute_1= 36 | function(){return a.asm.emscripten_bind_AttributeOctahedronTransform_InitFromAttribute_1.apply(null,arguments)},Ab=a._emscripten_bind_AttributeOctahedronTransform_quantization_bits_0=function(){return a.asm.emscripten_bind_AttributeOctahedronTransform_quantization_bits_0.apply(null,arguments)},Bb=a._emscripten_bind_AttributeOctahedronTransform___destroy___0=function(){return a.asm.emscripten_bind_AttributeOctahedronTransform___destroy___0.apply(null,arguments)},Ta=a._emscripten_bind_PointAttribute_PointAttribute_0= 37 | function(){return a.asm.emscripten_bind_PointAttribute_PointAttribute_0.apply(null,arguments)},Cb=a._emscripten_bind_PointAttribute_size_0=function(){return a.asm.emscripten_bind_PointAttribute_size_0.apply(null,arguments)},Db=a._emscripten_bind_PointAttribute_GetAttributeTransformData_0=function(){return a.asm.emscripten_bind_PointAttribute_GetAttributeTransformData_0.apply(null,arguments)},Eb=a._emscripten_bind_PointAttribute_attribute_type_0=function(){return a.asm.emscripten_bind_PointAttribute_attribute_type_0.apply(null, 38 | arguments)},Fb=a._emscripten_bind_PointAttribute_data_type_0=function(){return a.asm.emscripten_bind_PointAttribute_data_type_0.apply(null,arguments)},Gb=a._emscripten_bind_PointAttribute_num_components_0=function(){return a.asm.emscripten_bind_PointAttribute_num_components_0.apply(null,arguments)},Hb=a._emscripten_bind_PointAttribute_normalized_0=function(){return a.asm.emscripten_bind_PointAttribute_normalized_0.apply(null,arguments)},Ib=a._emscripten_bind_PointAttribute_byte_stride_0=function(){return a.asm.emscripten_bind_PointAttribute_byte_stride_0.apply(null, 39 | arguments)},Jb=a._emscripten_bind_PointAttribute_byte_offset_0=function(){return a.asm.emscripten_bind_PointAttribute_byte_offset_0.apply(null,arguments)},Kb=a._emscripten_bind_PointAttribute_unique_id_0=function(){return a.asm.emscripten_bind_PointAttribute_unique_id_0.apply(null,arguments)},Lb=a._emscripten_bind_PointAttribute___destroy___0=function(){return a.asm.emscripten_bind_PointAttribute___destroy___0.apply(null,arguments)},Ua=a._emscripten_bind_AttributeTransformData_AttributeTransformData_0= 40 | function(){return a.asm.emscripten_bind_AttributeTransformData_AttributeTransformData_0.apply(null,arguments)},Mb=a._emscripten_bind_AttributeTransformData_transform_type_0=function(){return a.asm.emscripten_bind_AttributeTransformData_transform_type_0.apply(null,arguments)},Nb=a._emscripten_bind_AttributeTransformData___destroy___0=function(){return a.asm.emscripten_bind_AttributeTransformData___destroy___0.apply(null,arguments)},Va=a._emscripten_bind_AttributeQuantizationTransform_AttributeQuantizationTransform_0= 41 | function(){return a.asm.emscripten_bind_AttributeQuantizationTransform_AttributeQuantizationTransform_0.apply(null,arguments)},Ob=a._emscripten_bind_AttributeQuantizationTransform_InitFromAttribute_1=function(){return a.asm.emscripten_bind_AttributeQuantizationTransform_InitFromAttribute_1.apply(null,arguments)},Pb=a._emscripten_bind_AttributeQuantizationTransform_quantization_bits_0=function(){return a.asm.emscripten_bind_AttributeQuantizationTransform_quantization_bits_0.apply(null,arguments)}, 42 | Qb=a._emscripten_bind_AttributeQuantizationTransform_min_value_1=function(){return a.asm.emscripten_bind_AttributeQuantizationTransform_min_value_1.apply(null,arguments)},Rb=a._emscripten_bind_AttributeQuantizationTransform_range_0=function(){return a.asm.emscripten_bind_AttributeQuantizationTransform_range_0.apply(null,arguments)},Sb=a._emscripten_bind_AttributeQuantizationTransform___destroy___0=function(){return a.asm.emscripten_bind_AttributeQuantizationTransform___destroy___0.apply(null,arguments)}, 43 | Wa=a._emscripten_bind_DracoInt8Array_DracoInt8Array_0=function(){return a.asm.emscripten_bind_DracoInt8Array_DracoInt8Array_0.apply(null,arguments)},Tb=a._emscripten_bind_DracoInt8Array_GetValue_1=function(){return a.asm.emscripten_bind_DracoInt8Array_GetValue_1.apply(null,arguments)},Ub=a._emscripten_bind_DracoInt8Array_size_0=function(){return a.asm.emscripten_bind_DracoInt8Array_size_0.apply(null,arguments)},Vb=a._emscripten_bind_DracoInt8Array___destroy___0=function(){return a.asm.emscripten_bind_DracoInt8Array___destroy___0.apply(null, 44 | arguments)},Xa=a._emscripten_bind_MetadataQuerier_MetadataQuerier_0=function(){return a.asm.emscripten_bind_MetadataQuerier_MetadataQuerier_0.apply(null,arguments)},Wb=a._emscripten_bind_MetadataQuerier_HasEntry_2=function(){return a.asm.emscripten_bind_MetadataQuerier_HasEntry_2.apply(null,arguments)},Xb=a._emscripten_bind_MetadataQuerier_GetIntEntry_2=function(){return a.asm.emscripten_bind_MetadataQuerier_GetIntEntry_2.apply(null,arguments)},Yb=a._emscripten_bind_MetadataQuerier_GetIntEntryArray_3= 45 | function(){return a.asm.emscripten_bind_MetadataQuerier_GetIntEntryArray_3.apply(null,arguments)},Zb=a._emscripten_bind_MetadataQuerier_GetDoubleEntry_2=function(){return a.asm.emscripten_bind_MetadataQuerier_GetDoubleEntry_2.apply(null,arguments)},$b=a._emscripten_bind_MetadataQuerier_GetStringEntry_2=function(){return a.asm.emscripten_bind_MetadataQuerier_GetStringEntry_2.apply(null,arguments)},ac=a._emscripten_bind_MetadataQuerier_NumEntries_1=function(){return a.asm.emscripten_bind_MetadataQuerier_NumEntries_1.apply(null, 46 | arguments)},bc=a._emscripten_bind_MetadataQuerier_GetEntryName_2=function(){return a.asm.emscripten_bind_MetadataQuerier_GetEntryName_2.apply(null,arguments)},cc=a._emscripten_bind_MetadataQuerier___destroy___0=function(){return a.asm.emscripten_bind_MetadataQuerier___destroy___0.apply(null,arguments)},Ya=a._emscripten_bind_DracoInt16Array_DracoInt16Array_0=function(){return a.asm.emscripten_bind_DracoInt16Array_DracoInt16Array_0.apply(null,arguments)},dc=a._emscripten_bind_DracoInt16Array_GetValue_1= 47 | function(){return a.asm.emscripten_bind_DracoInt16Array_GetValue_1.apply(null,arguments)},ec=a._emscripten_bind_DracoInt16Array_size_0=function(){return a.asm.emscripten_bind_DracoInt16Array_size_0.apply(null,arguments)},fc=a._emscripten_bind_DracoInt16Array___destroy___0=function(){return a.asm.emscripten_bind_DracoInt16Array___destroy___0.apply(null,arguments)},Za=a._emscripten_bind_DracoFloat32Array_DracoFloat32Array_0=function(){return a.asm.emscripten_bind_DracoFloat32Array_DracoFloat32Array_0.apply(null, 48 | arguments)},gc=a._emscripten_bind_DracoFloat32Array_GetValue_1=function(){return a.asm.emscripten_bind_DracoFloat32Array_GetValue_1.apply(null,arguments)},hc=a._emscripten_bind_DracoFloat32Array_size_0=function(){return a.asm.emscripten_bind_DracoFloat32Array_size_0.apply(null,arguments)},ic=a._emscripten_bind_DracoFloat32Array___destroy___0=function(){return a.asm.emscripten_bind_DracoFloat32Array___destroy___0.apply(null,arguments)},$a=a._emscripten_bind_GeometryAttribute_GeometryAttribute_0=function(){return a.asm.emscripten_bind_GeometryAttribute_GeometryAttribute_0.apply(null, 49 | arguments)},jc=a._emscripten_bind_GeometryAttribute___destroy___0=function(){return a.asm.emscripten_bind_GeometryAttribute___destroy___0.apply(null,arguments)},ab=a._emscripten_bind_DecoderBuffer_DecoderBuffer_0=function(){return a.asm.emscripten_bind_DecoderBuffer_DecoderBuffer_0.apply(null,arguments)},kc=a._emscripten_bind_DecoderBuffer_Init_2=function(){return a.asm.emscripten_bind_DecoderBuffer_Init_2.apply(null,arguments)},lc=a._emscripten_bind_DecoderBuffer___destroy___0=function(){return a.asm.emscripten_bind_DecoderBuffer___destroy___0.apply(null, 50 | arguments)},bb=a._emscripten_bind_Decoder_Decoder_0=function(){return a.asm.emscripten_bind_Decoder_Decoder_0.apply(null,arguments)},mc=a._emscripten_bind_Decoder_GetEncodedGeometryType_1=function(){return a.asm.emscripten_bind_Decoder_GetEncodedGeometryType_1.apply(null,arguments)},nc=a._emscripten_bind_Decoder_DecodeBufferToPointCloud_2=function(){return a.asm.emscripten_bind_Decoder_DecodeBufferToPointCloud_2.apply(null,arguments)},oc=a._emscripten_bind_Decoder_DecodeBufferToMesh_2=function(){return a.asm.emscripten_bind_Decoder_DecodeBufferToMesh_2.apply(null, 51 | arguments)},pc=a._emscripten_bind_Decoder_GetAttributeId_2=function(){return a.asm.emscripten_bind_Decoder_GetAttributeId_2.apply(null,arguments)},qc=a._emscripten_bind_Decoder_GetAttributeIdByName_2=function(){return a.asm.emscripten_bind_Decoder_GetAttributeIdByName_2.apply(null,arguments)},rc=a._emscripten_bind_Decoder_GetAttributeIdByMetadataEntry_3=function(){return a.asm.emscripten_bind_Decoder_GetAttributeIdByMetadataEntry_3.apply(null,arguments)},sc=a._emscripten_bind_Decoder_GetAttribute_2= 52 | function(){return a.asm.emscripten_bind_Decoder_GetAttribute_2.apply(null,arguments)},tc=a._emscripten_bind_Decoder_GetAttributeByUniqueId_2=function(){return a.asm.emscripten_bind_Decoder_GetAttributeByUniqueId_2.apply(null,arguments)},uc=a._emscripten_bind_Decoder_GetMetadata_1=function(){return a.asm.emscripten_bind_Decoder_GetMetadata_1.apply(null,arguments)},vc=a._emscripten_bind_Decoder_GetAttributeMetadata_2=function(){return a.asm.emscripten_bind_Decoder_GetAttributeMetadata_2.apply(null, 53 | arguments)},wc=a._emscripten_bind_Decoder_GetFaceFromMesh_3=function(){return a.asm.emscripten_bind_Decoder_GetFaceFromMesh_3.apply(null,arguments)},xc=a._emscripten_bind_Decoder_GetTriangleStripsFromMesh_2=function(){return a.asm.emscripten_bind_Decoder_GetTriangleStripsFromMesh_2.apply(null,arguments)},yc=a._emscripten_bind_Decoder_GetTrianglesUInt16Array_3=function(){return a.asm.emscripten_bind_Decoder_GetTrianglesUInt16Array_3.apply(null,arguments)},zc=a._emscripten_bind_Decoder_GetTrianglesUInt32Array_3= 54 | function(){return a.asm.emscripten_bind_Decoder_GetTrianglesUInt32Array_3.apply(null,arguments)},Ac=a._emscripten_bind_Decoder_GetAttributeFloat_3=function(){return a.asm.emscripten_bind_Decoder_GetAttributeFloat_3.apply(null,arguments)},Bc=a._emscripten_bind_Decoder_GetAttributeFloatForAllPoints_3=function(){return a.asm.emscripten_bind_Decoder_GetAttributeFloatForAllPoints_3.apply(null,arguments)},Cc=a._emscripten_bind_Decoder_GetAttributeIntForAllPoints_3=function(){return a.asm.emscripten_bind_Decoder_GetAttributeIntForAllPoints_3.apply(null, 55 | arguments)},Dc=a._emscripten_bind_Decoder_GetAttributeInt8ForAllPoints_3=function(){return a.asm.emscripten_bind_Decoder_GetAttributeInt8ForAllPoints_3.apply(null,arguments)},Ec=a._emscripten_bind_Decoder_GetAttributeUInt8ForAllPoints_3=function(){return a.asm.emscripten_bind_Decoder_GetAttributeUInt8ForAllPoints_3.apply(null,arguments)},Fc=a._emscripten_bind_Decoder_GetAttributeInt16ForAllPoints_3=function(){return a.asm.emscripten_bind_Decoder_GetAttributeInt16ForAllPoints_3.apply(null,arguments)}, 56 | Gc=a._emscripten_bind_Decoder_GetAttributeUInt16ForAllPoints_3=function(){return a.asm.emscripten_bind_Decoder_GetAttributeUInt16ForAllPoints_3.apply(null,arguments)},Hc=a._emscripten_bind_Decoder_GetAttributeInt32ForAllPoints_3=function(){return a.asm.emscripten_bind_Decoder_GetAttributeInt32ForAllPoints_3.apply(null,arguments)},Ic=a._emscripten_bind_Decoder_GetAttributeUInt32ForAllPoints_3=function(){return a.asm.emscripten_bind_Decoder_GetAttributeUInt32ForAllPoints_3.apply(null,arguments)},Jc= 57 | a._emscripten_bind_Decoder_GetAttributeDataArrayForAllPoints_5=function(){return a.asm.emscripten_bind_Decoder_GetAttributeDataArrayForAllPoints_5.apply(null,arguments)},Kc=a._emscripten_bind_Decoder_SkipAttributeTransform_1=function(){return a.asm.emscripten_bind_Decoder_SkipAttributeTransform_1.apply(null,arguments)},Lc=a._emscripten_bind_Decoder___destroy___0=function(){return a.asm.emscripten_bind_Decoder___destroy___0.apply(null,arguments)},cb=a._emscripten_bind_Mesh_Mesh_0=function(){return a.asm.emscripten_bind_Mesh_Mesh_0.apply(null, 58 | arguments)},Mc=a._emscripten_bind_Mesh_num_faces_0=function(){return a.asm.emscripten_bind_Mesh_num_faces_0.apply(null,arguments)},Nc=a._emscripten_bind_Mesh_num_attributes_0=function(){return a.asm.emscripten_bind_Mesh_num_attributes_0.apply(null,arguments)},Oc=a._emscripten_bind_Mesh_num_points_0=function(){return a.asm.emscripten_bind_Mesh_num_points_0.apply(null,arguments)},Pc=a._emscripten_bind_Mesh___destroy___0=function(){return a.asm.emscripten_bind_Mesh___destroy___0.apply(null,arguments)}, 59 | Qc=a._emscripten_bind_VoidPtr___destroy___0=function(){return a.asm.emscripten_bind_VoidPtr___destroy___0.apply(null,arguments)},db=a._emscripten_bind_DracoInt32Array_DracoInt32Array_0=function(){return a.asm.emscripten_bind_DracoInt32Array_DracoInt32Array_0.apply(null,arguments)},Rc=a._emscripten_bind_DracoInt32Array_GetValue_1=function(){return a.asm.emscripten_bind_DracoInt32Array_GetValue_1.apply(null,arguments)},Sc=a._emscripten_bind_DracoInt32Array_size_0=function(){return a.asm.emscripten_bind_DracoInt32Array_size_0.apply(null, 60 | arguments)},Tc=a._emscripten_bind_DracoInt32Array___destroy___0=function(){return a.asm.emscripten_bind_DracoInt32Array___destroy___0.apply(null,arguments)},eb=a._emscripten_bind_Metadata_Metadata_0=function(){return a.asm.emscripten_bind_Metadata_Metadata_0.apply(null,arguments)},Uc=a._emscripten_bind_Metadata___destroy___0=function(){return a.asm.emscripten_bind_Metadata___destroy___0.apply(null,arguments)},Vc=a._emscripten_enum_draco_StatusCode_OK=function(){return a.asm.emscripten_enum_draco_StatusCode_OK.apply(null, 61 | arguments)},Wc=a._emscripten_enum_draco_StatusCode_DRACO_ERROR=function(){return a.asm.emscripten_enum_draco_StatusCode_DRACO_ERROR.apply(null,arguments)},Xc=a._emscripten_enum_draco_StatusCode_IO_ERROR=function(){return a.asm.emscripten_enum_draco_StatusCode_IO_ERROR.apply(null,arguments)},Yc=a._emscripten_enum_draco_StatusCode_INVALID_PARAMETER=function(){return a.asm.emscripten_enum_draco_StatusCode_INVALID_PARAMETER.apply(null,arguments)},Zc=a._emscripten_enum_draco_StatusCode_UNSUPPORTED_VERSION= 62 | function(){return a.asm.emscripten_enum_draco_StatusCode_UNSUPPORTED_VERSION.apply(null,arguments)},$c=a._emscripten_enum_draco_StatusCode_UNKNOWN_VERSION=function(){return a.asm.emscripten_enum_draco_StatusCode_UNKNOWN_VERSION.apply(null,arguments)},ad=a._emscripten_enum_draco_DataType_DT_INVALID=function(){return a.asm.emscripten_enum_draco_DataType_DT_INVALID.apply(null,arguments)},bd=a._emscripten_enum_draco_DataType_DT_INT8=function(){return a.asm.emscripten_enum_draco_DataType_DT_INT8.apply(null, 63 | arguments)},cd=a._emscripten_enum_draco_DataType_DT_UINT8=function(){return a.asm.emscripten_enum_draco_DataType_DT_UINT8.apply(null,arguments)},dd=a._emscripten_enum_draco_DataType_DT_INT16=function(){return a.asm.emscripten_enum_draco_DataType_DT_INT16.apply(null,arguments)},ed=a._emscripten_enum_draco_DataType_DT_UINT16=function(){return a.asm.emscripten_enum_draco_DataType_DT_UINT16.apply(null,arguments)},fd=a._emscripten_enum_draco_DataType_DT_INT32=function(){return a.asm.emscripten_enum_draco_DataType_DT_INT32.apply(null, 64 | arguments)},gd=a._emscripten_enum_draco_DataType_DT_UINT32=function(){return a.asm.emscripten_enum_draco_DataType_DT_UINT32.apply(null,arguments)},hd=a._emscripten_enum_draco_DataType_DT_INT64=function(){return a.asm.emscripten_enum_draco_DataType_DT_INT64.apply(null,arguments)},id=a._emscripten_enum_draco_DataType_DT_UINT64=function(){return a.asm.emscripten_enum_draco_DataType_DT_UINT64.apply(null,arguments)},jd=a._emscripten_enum_draco_DataType_DT_FLOAT32=function(){return a.asm.emscripten_enum_draco_DataType_DT_FLOAT32.apply(null, 65 | arguments)},kd=a._emscripten_enum_draco_DataType_DT_FLOAT64=function(){return a.asm.emscripten_enum_draco_DataType_DT_FLOAT64.apply(null,arguments)},ld=a._emscripten_enum_draco_DataType_DT_BOOL=function(){return a.asm.emscripten_enum_draco_DataType_DT_BOOL.apply(null,arguments)},md=a._emscripten_enum_draco_DataType_DT_TYPES_COUNT=function(){return a.asm.emscripten_enum_draco_DataType_DT_TYPES_COUNT.apply(null,arguments)},nd=a._emscripten_enum_draco_EncodedGeometryType_INVALID_GEOMETRY_TYPE=function(){return a.asm.emscripten_enum_draco_EncodedGeometryType_INVALID_GEOMETRY_TYPE.apply(null, 66 | arguments)},od=a._emscripten_enum_draco_EncodedGeometryType_POINT_CLOUD=function(){return a.asm.emscripten_enum_draco_EncodedGeometryType_POINT_CLOUD.apply(null,arguments)},pd=a._emscripten_enum_draco_EncodedGeometryType_TRIANGULAR_MESH=function(){return a.asm.emscripten_enum_draco_EncodedGeometryType_TRIANGULAR_MESH.apply(null,arguments)},qd=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_INVALID_TRANSFORM=function(){return a.asm.emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_INVALID_TRANSFORM.apply(null, 67 | arguments)},rd=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_NO_TRANSFORM=function(){return a.asm.emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_NO_TRANSFORM.apply(null,arguments)},sd=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_QUANTIZATION_TRANSFORM=function(){return a.asm.emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_QUANTIZATION_TRANSFORM.apply(null,arguments)},td=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_OCTAHEDRON_TRANSFORM=function(){return a.asm.emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_OCTAHEDRON_TRANSFORM.apply(null, 68 | arguments)},ud=a._emscripten_enum_draco_GeometryAttribute_Type_INVALID=function(){return a.asm.emscripten_enum_draco_GeometryAttribute_Type_INVALID.apply(null,arguments)},vd=a._emscripten_enum_draco_GeometryAttribute_Type_POSITION=function(){return a.asm.emscripten_enum_draco_GeometryAttribute_Type_POSITION.apply(null,arguments)},wd=a._emscripten_enum_draco_GeometryAttribute_Type_NORMAL=function(){return a.asm.emscripten_enum_draco_GeometryAttribute_Type_NORMAL.apply(null,arguments)},xd=a._emscripten_enum_draco_GeometryAttribute_Type_COLOR= 69 | function(){return a.asm.emscripten_enum_draco_GeometryAttribute_Type_COLOR.apply(null,arguments)},yd=a._emscripten_enum_draco_GeometryAttribute_Type_TEX_COORD=function(){return a.asm.emscripten_enum_draco_GeometryAttribute_Type_TEX_COORD.apply(null,arguments)},zd=a._emscripten_enum_draco_GeometryAttribute_Type_GENERIC=function(){return a.asm.emscripten_enum_draco_GeometryAttribute_Type_GENERIC.apply(null,arguments)};a._setThrew=function(){return a.asm.setThrew.apply(null,arguments)};var ta=a.__ZSt18uncaught_exceptionv= 70 | function(){return a.asm._ZSt18uncaught_exceptionv.apply(null,arguments)};a._free=function(){return a.asm.free.apply(null,arguments)};var ib=a._malloc=function(){return a.asm.malloc.apply(null,arguments)};a.stackSave=function(){return a.asm.stackSave.apply(null,arguments)};a.stackAlloc=function(){return a.asm.stackAlloc.apply(null,arguments)};a.stackRestore=function(){return a.asm.stackRestore.apply(null,arguments)};a.__growWasmMemory=function(){return a.asm.__growWasmMemory.apply(null,arguments)}; 71 | a.dynCall_ii=function(){return a.asm.dynCall_ii.apply(null,arguments)};a.dynCall_vi=function(){return a.asm.dynCall_vi.apply(null,arguments)};a.dynCall_iii=function(){return a.asm.dynCall_iii.apply(null,arguments)};a.dynCall_vii=function(){return a.asm.dynCall_vii.apply(null,arguments)};a.dynCall_iiii=function(){return a.asm.dynCall_iiii.apply(null,arguments)};a.dynCall_v=function(){return a.asm.dynCall_v.apply(null,arguments)};a.dynCall_viii=function(){return a.asm.dynCall_viii.apply(null,arguments)}; 72 | a.dynCall_viiii=function(){return a.asm.dynCall_viiii.apply(null,arguments)};a.dynCall_iiiiiii=function(){return a.asm.dynCall_iiiiiii.apply(null,arguments)};a.dynCall_iidiiii=function(){return a.asm.dynCall_iidiiii.apply(null,arguments)};a.dynCall_jiji=function(){return a.asm.dynCall_jiji.apply(null,arguments)};a.dynCall_viiiiii=function(){return a.asm.dynCall_viiiiii.apply(null,arguments)};a.dynCall_viiiii=function(){return a.asm.dynCall_viiiii.apply(null,arguments)};a.asm=La;var fa;a.then=function(e){if(fa)e(a); 73 | else{var c=a.onRuntimeInitialized;a.onRuntimeInitialized=function(){c&&c();e(a)}}return a};ja=function c(){fa||ma();fa||(ja=c)};a.run=ma;if(a.preInit)for("function"==typeof a.preInit&&(a.preInit=[a.preInit]);0=n.size?(t(0>=1;break;case 4:d>>=2;break;case 8:d>>=3}for(var c=0;c