Skip to content
Snippets Groups Projects
Select Git revision
  • 21b85923ee95c3c4efc14313c1050fd40c5ff711
  • master default
  • fix-remote-url_v4.9.1
  • fix-remote-url_v4.8.3
  • fix-remote-url_v4.8.x
  • fix-remote-url_v4.7.x
  • fix-remote-url_v4.6.0
  • fix-remote-urls
8 results

version.php

Blame
  • Pipeline.ts 4.81 KiB
    import * as THREE from "three";
    
    import { DragControls } from "three/examples/jsm/controls/DragControls";
    import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
    import { Shape } from "./Shapes";
    
    interface PipelineObserver {
        /**
         * @breif RendererObserver is an abstract class that is used to observe the renderer.
         * The renderer calls in the rendering loop update of this observer.
         * @param {number} _deltaTime gives the time in seconds between two frames
         */
        update(_deltaTime: number): void;
    }
    
    abstract class PipelineData {
        observers: Array<PipelineObserver>;
        draggables: Array<THREE.Object3D>;
        scene: THREE.Scene;
    
        allowOrbit: boolean = true;
    
        constructor() {
            this.observers = new Array<PipelineObserver>();
            this.draggables = new Array<THREE.Object3D>();
            this.scene = new THREE.Scene();
            this.data();
        }
    
        protected addShape(shape: Shape, observer: boolean = true, draggable: boolean = false) {
            this.scene.add(shape.object3d);
            if (observer) {
                this.observers.push(shape);
            }
            if (draggable) {
                this.draggables.push(shape.object3d);
            }
        } 
    
        /**
         * @brief Should define a scenario with observers, draggables and scene.
         * It initializes the scene and adds the draggables to the scene.
         * Based on that the pipeline can be initialized.
         */
        abstract data(): void;
    }
    
    class Pipeline {
    
        public readonly renderer: THREE.WebGLRenderer;
        public readonly camera: THREE.PerspectiveCamera;
    
        public readonly orbitControls: OrbitControls;
        public readonly dragControls: DragControls;
    
        private scene?: THREE.Scene;
        private observer: Array<PipelineObserver>;
        private startTime: number;
    
        constructor() {
            // CREATE CAMERA
            this.camera = new THREE.PerspectiveCamera(75, 
                window.innerWidth / window.innerHeight, 0.1, 1000);
            this.camera.position.z = 5;
    
            window.addEventListener('resize', () => {
                this.camera.aspect = window.innerWidth / window.innerHeight
                this.camera.updateProjectionMatrix()
            }, false);
    
            // CREATE RENDERER
            this.renderer = new THREE.WebGLRenderer({
                antialias: true
            });
            this.renderer.setSize(window.innerWidth, window.innerHeight);
            this.renderer.setPixelRatio(window.devicePixelRatio);
            this.renderer.setClearColor(1);
            document.body.appendChild(this.renderer.domElement);
    
            window.addEventListener('resize', () => {
                this.renderer.setSize(window.innerWidth, window.innerHeight);
            }, false);
    
            // CREATE CONTROLS
            this.orbitControls = new OrbitControls(this.camera, this.renderer.domElement);
            this.dragControls = new DragControls([], this.camera, this.renderer.domElement);
    
            this.dragControls.addEventListener('dragstart', () => {
                this.orbitControls.enabled = false;
            });
            this.dragControls.addEventListener('dragend', () => {
                this.orbitControls.enabled = true;
            });
    
            // INITIALISE OTHER FIELDS
            this.observer = new Array<PipelineObserver>();
            this.startTime = performance.now();
        }
    
        public init(data: PipelineData): void {
            this.setScene(data.scene);
            data.draggables.forEach(draggable => { this.addDraggable(draggable); });
            data.observers.forEach(observer => { this.addPipelineObserver(observer); });
        }
    
        public addPipelineObserver(object: PipelineObserver): void {
            this.observer.push(object);
        }
    
        public removePipelineObserver(object: PipelineObserver): void {
            let index = this.observer.indexOf(object);
            if (index > -1) {
                this.observer.splice(index, 1);
            }
        }
    
        public addDraggable(object: THREE.Object3D): void {
            if (object instanceof THREE.Line) {
                console.warn('Cannot add draggable to line');
                return;
            }
            this.dragControls.getObjects().push(object);
        }
    
        public setScene(scene: THREE.Scene): void {
            this.scene = scene;
        }
    
        private update(deltaTime: number): void {
            for (let i = 0; i < this.observer.length; i++) {
                this.observer[i].update(deltaTime);
            }
        }
    
        public loop(): void {
            const now = performance.now();
            const deltaTime = (now - this.startTime) / 1000;
            this.startTime = now;
    
            this.update(deltaTime);
    
            if (this.scene) {
                this.renderer.render(this.scene, this.camera);
            }
    
            requestAnimationFrame(() => {
                this.loop();
            });
        }
    }
    
    export { Pipeline, PipelineData };
    export type { PipelineObserver };