You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
2.9 KiB
104 lines
2.9 KiB
// 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 };
|
|
|