// from https://medium.com/nicasource/building-an-interactive-web-portfolio-with-vue-three-js-part-three-implementing-three-js-452cb375ef80 import * as TWEEN from "@tweenjs/tween.js"; import * as THREE from "three"; import { createCamera } from "./components/camera.js"; import { createLights } from "./components/lights.js"; import { createScene } from "./components/scene.js"; import { loadLandmarks } from "./components/objects/landmarks.js"; import { createTerrain } from "./components/objects/terrain.js"; import { Loop } from "./systems/Loop.js"; import { Resizer } from "./systems/Resizer.js"; import { createControls } from "./systems/controls.js"; import { createRenderer } from "./systems/renderer.js"; const COLOR1 = "#dddddd"; const COLOR2 = "#0055aa"; class World { constructor(container, vue) { this.PLATFORM_BORDER = 5; this.PLATFORM_EDGE_FOR_UNKNOWNS = 10; this.PLATFORM_SIZE = 100; // note that the loadLandmarks calculations may still assume 100 this.update = this.update.bind(this); // Instances of camera, scene, and renderer this.camera = createCamera(); this.scene = createScene(COLOR2); this.renderer = createRenderer(); // necessary for models, says https://threejs.org/docs/index.html#examples/en/loaders/GLTFLoader this.renderer.outputColorSpace = THREE.SRGBColorSpace; this.light = null; this.lights = []; this.bushes = []; // Initialize Loop this.loop = new Loop(this.camera, this.scene, this.renderer); container.append(this.renderer.domElement); // Orbit Controls const controls = createControls(this.camera, this.renderer.domElement); // Light Instance, with optional light helper const { light } = createLights(COLOR1); // Terrain Instance const terrain = createTerrain({ color: COLOR1, height: this.PLATFORM_SIZE + this.PLATFORM_BORDER * 2, width: this.PLATFORM_SIZE + this.PLATFORM_BORDER * 2 + this.PLATFORM_EDGE_FOR_UNKNOWNS * 2, }); this.loop.updatables.push(controls); this.loop.updatables.push(light); this.loop.updatables.push(terrain); this.scene.add(light, terrain); loadLandmarks(vue, this, this.scene, this.loop); requestAnimationFrame(this.update); // Responsive handler const resizer = new Resizer(container, this.camera, this.renderer); resizer.onResize = () => { this.render(); }; } update(time) { TWEEN.update(time); this.lights.forEach((light) => { light.updateMatrixWorld(); light.target.updateMatrixWorld(); }); this.lights.forEach((bush) => { bush.updateMatrixWorld(); }); requestAnimationFrame(this.update); } render() { // draw a single frame this.renderer.render(this.scene, this.camera); } // Animation handlers start() { this.loop.start(); } stop() { this.loop.stop(); } } export { World };