mirror of
https://github.com/guezoloic/website.git
synced 2026-03-28 18:03:50 +00:00
109 lines
3.6 KiB
TypeScript
109 lines
3.6 KiB
TypeScript
import * as THREE from "three";
|
|
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
|
|
|
import Model from "./model";
|
|
import Camera from "./camera";
|
|
import Animation from "./animation";
|
|
|
|
import assets from "@app/data/assets.json"
|
|
import AnimationQueue from "./animQueue";
|
|
|
|
export default class Main {
|
|
private element!: HTMLElement;
|
|
private loadingManager?: THREE.LoadingManager;
|
|
|
|
private scene!: THREE.Scene;
|
|
private renderer!: THREE.WebGLRenderer;
|
|
private camera!: THREE.PerspectiveCamera;
|
|
|
|
private controls!: OrbitControls;
|
|
private loader!: GLTFLoader;
|
|
private clock: THREE.Clock;
|
|
|
|
private animation!: Animation;
|
|
|
|
constructor(htmlelement: HTMLElement, loadingManager?: THREE.LoadingManager) {
|
|
this.element = htmlelement;
|
|
this.loadingManager = loadingManager;
|
|
this.clock = new THREE.Clock();
|
|
|
|
this.init();
|
|
}
|
|
|
|
private async init() {
|
|
this.scene = new THREE.Scene();
|
|
|
|
this.camera = new THREE.PerspectiveCamera(
|
|
75, // fov
|
|
this.element.clientWidth / this.element.clientHeight, // aspect
|
|
0.1, 1000 // near, far
|
|
);
|
|
|
|
this.renderer = new THREE.WebGLRenderer({
|
|
antialias: true,
|
|
alpha: true
|
|
});
|
|
this.renderer.setSize(
|
|
this.element.clientWidth,
|
|
this.element.clientHeight
|
|
);
|
|
this.element.appendChild(this.renderer.domElement);
|
|
|
|
const ambientLight = new THREE.AmbientLight(0xffffff, 1.5);
|
|
this.scene.add(ambientLight);
|
|
|
|
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5);
|
|
directionalLight.position.set(5, 5, 5);
|
|
this.scene.add(directionalLight);
|
|
|
|
this.controls = new OrbitControls(this.camera, this.element);
|
|
this.controls.minPolarAngle = Math.PI / 2;
|
|
this.controls.maxPolarAngle = Math.PI / 2;
|
|
this.controls.enableZoom = false;
|
|
this.controls.enablePan = false;
|
|
|
|
this.renderer.domElement.style.touchAction = 'pan-y';
|
|
|
|
this.loader = new GLTFLoader(this.loadingManager);
|
|
|
|
window.addEventListener("resize", () => {
|
|
const WIDTH = window.innerWidth;
|
|
const HEIGHT = window.innerHeight;
|
|
|
|
this.camera.aspect = WIDTH / HEIGHT;
|
|
this.camera.updateProjectionMatrix();
|
|
this.renderer.setSize(WIDTH, HEIGHT);
|
|
});
|
|
|
|
const MODEL = await (new Model(this.loader)).init(assets.model, this.scene);
|
|
|
|
const CAMERA = new Camera(this.camera, MODEL);
|
|
CAMERA.centerCamera((_box: any, size: any, center: any) => {
|
|
MODEL.position.sub(center);
|
|
MODEL.position.y -= size.y * 0.3;
|
|
});
|
|
CAMERA.positionCamera();
|
|
|
|
// Animation
|
|
this.animation = new Animation(MODEL, this.loader, assets.idle_animation);
|
|
|
|
const ANIMATION_QUEUE = new AnimationQueue(this.animation);
|
|
ANIMATION_QUEUE.onqueue(await this.animation.loadAnimation(assets.welcome_animation));
|
|
ANIMATION_QUEUE.startRandom();
|
|
|
|
this.animate();
|
|
}
|
|
|
|
// animate must be an arrow key so that "this"
|
|
// can be pointed to the Main instance
|
|
private animate = () => {
|
|
requestAnimationFrame(this.animate);
|
|
|
|
const delta = this.clock.getDelta();
|
|
if (this.animation) this.animation.update(delta);
|
|
|
|
this.controls.update();
|
|
this.renderer.render(this.scene, this.camera);
|
|
}
|
|
} |