日常生活的交流与学习

首页 新随笔 联系 管理

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + TS</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\main.ts

import "./style.css";

import Base from "./threejs/Base";

((document) => {
  const oApp = document.getElementById("app")!;
  const oCanvas = document.createElement("canvas");
  oCanvas.style.position = "absolute";
  Base.getInstance(oCanvas);
  oApp.appendChild(oCanvas);
})(document);

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\main_单例模式_constructor.ts

import "./style.css";

import Base from "./threejs/Base";

((document) => {
  const oApp = document.getElementById("app")!;
  const oCanvas = document.createElement("canvas");
  new Base(oCanvas);
  oApp.appendChild(oCanvas);
})(document);

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\main_单例模式_getInstance.ts

import "./style.css";

import Base from "./threejs/Base";

((document) => {
  const oApp = document.getElementById("app")!;
  const oCanvas = document.createElement("canvas");
  oCanvas.style.position = "absolute";
  Base.getInstance(oCanvas);
  oApp.appendChild(oCanvas);
})(document);

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs\Base.ts

import { Scene } from "three";

import Camera from "./Camera";
import Helper from "./Helper";
import Renderer from "./Renderer";
import Size from "./Size";
import Time from "./Time";
import World from "./World/World";
import Car from "./World/Car";

export default class Base {
  public static base: Base;
  public canvas: HTMLCanvasElement;
  public scene: Scene;
  public camera: Camera;
  public size: Size;
  public time: Time;
  public renderer: Renderer;

  public world: World;

  constructor(canvas: HTMLCanvasElement) {
    Base.base = this;

    this.canvas = canvas as HTMLCanvasElement;
    this.scene = new Scene();
    this.size = new Size();
    this.camera = new Camera();
    this.time = new Time();
    this.renderer = new Renderer();
    new Helper();

    this.world = new World();
    new Car();

    this.time.on("update", () => {
      this.update();
    });
    this.size.on("resize", () => {
      this.resize();
    });
  }

  public static getInstance(canvas?: HTMLCanvasElement) {
    if (canvas === undefined && Base.base !== undefined) {
      return Base.base;
    }
    Base.base = new Base(canvas as HTMLCanvasElement);
    return Base.base;
  }

  private resize() {
    this.camera.resize();
    this.renderer.resize();
  }

  private update() {
    this.camera.update();
    this.renderer.update();
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs\Camera.ts

import { PerspectiveCamera, Scene } from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import Base from "./Base";
import type Size from "./Size";

export default class Camera {
  private size: Size;
  private scene: Scene;
  private canvas: HTMLCanvasElement;
  public perspectiveCamera: PerspectiveCamera;
  private controls: OrbitControls;

  constructor() {
    const base = Base.getInstance();
    this.size = base.size;
    this.scene = base.scene;
    this.canvas = base.canvas;

    this.perspectiveCamera = this.createPerspectiveCamera();
    this.scene.add(this.perspectiveCamera);

    this.controls = this.createOrbitControls();
  }
  private createPerspectiveCamera() {
    const perspectiveCamera = new PerspectiveCamera(
      35,
      this.size.aspect,
      0.1,
      1000
    );
    perspectiveCamera.position.set(15, 30, 20);
    return perspectiveCamera;
  }
  private createOrbitControls() {
    const controls = new OrbitControls(this.perspectiveCamera, this.canvas);
    controls.enableDamping = true;
    controls.enableZoom = true;
    return controls;
  }
  public update() {
    this.controls.update();
  }
  public resize() {
    // Updating Perspective Camera on Resize
    this.perspectiveCamera.aspect = this.size.aspect;
    this.perspectiveCamera.updateProjectionMatrix();
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs\Helper.ts

import { AxesHelper, GridHelper } from "three";
import Base from "./Base";

export default class {
  constructor() {
    const base = Base.getInstance();
    const axesHelper = new AxesHelper(5);
    base.scene.add(axesHelper);

    const size = 10;
    const divisions = 10;

    const gridHelper = new GridHelper(size, divisions);
    base.scene.add(gridHelper);
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs\Renderer.ts

import * as THREE from "three";
import Base from "./Base";
import { Scene, WebGLRenderer } from "three";
import Camera from "./Camera";
import Size from "./Size";

export default class Renderer {
  private size: Size;
  private scene: Scene;
  private canvas: HTMLCanvasElement;
  private camera: Camera;
  private renderer: WebGLRenderer;

  constructor() {
    const base = Base.getInstance();

    this.size = base.size;
    this.scene = base.scene;
    this.canvas = base.canvas;
    this.camera = base.camera;

    this.renderer = this.setRenderer();
  }

  setRenderer() {
    const renderer = new WebGLRenderer({
      canvas: this.canvas,
      antialias: true,
    });

    renderer.physicallyCorrectLights = true;
    renderer.outputEncoding = THREE.sRGBEncoding;
    renderer.toneMapping = THREE.CineonToneMapping;
    renderer.toneMappingExposure = 1.75;
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    renderer.setSize(this.size.width, this.size.height);
    renderer.setPixelRatio(this.size.pixelRatio);

    return renderer;
  }

  resize() {
    this.renderer.setSize(this.size.width, this.size.height);
    this.renderer.setPixelRatio(this.size.pixelRatio);
  }

  update() {
    this.renderer.render(this.scene, this.camera.perspectiveCamera);
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs\Size.ts

import EventEmitter from "eventemitter2";
export default class Size extends EventEmitter {
  public width: number;
  public height: number;
  public aspect: number;
  public pixelRatio: number;

  constructor() {
    super();
    this.width = window.innerWidth;
    this.height = window.innerHeight;
    this.aspect = this.width / this.height;
    this.pixelRatio = Math.min(window.devicePixelRatio, 2);

    window.addEventListener("resize", () => {
      this.width = window.innerWidth;
      this.height = window.innerHeight;
      this.aspect = this.width / this.height;
      this.pixelRatio = Math.min(window.devicePixelRatio, 2);
      this.emit("resize");
    });
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs\Time.ts

import EventEmitter from "eventemitter2";
import { Clock } from "three";

export default class Time extends EventEmitter {
  public clock: Clock;
  constructor() {
    super();
    this.clock = new Clock();

    this.update();
  }

  update() {
    this.emit("update");
    window.requestAnimationFrame(() => this.update());
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs\World\Car.ts

import { BoxGeometry, MeshBasicMaterial, Mesh } from "three";
import Base from "../Base";

export default class Car {
  constructor() {
    const base = Base.getInstance();

    const cube = new Mesh(
      new BoxGeometry(1, 1, 1),
      new MeshBasicMaterial({ color: 0x00ff00 })
    );
    cube.position.y = 0.5;
    base.scene.add(cube);
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs\World\Environment.ts

import { AmbientLight, DirectionalLight } from "three";
import Base from "../Base";

export default class Environment {
  private sunLight: DirectionalLight;
  private ambientLight: AmbientLight;
  constructor() {
    const base = Base.getInstance();
    this.sunLight = new DirectionalLight("#ffffff", 3);
    this.sunLight.castShadow = true;
    this.sunLight.shadow.camera.far = 20;
    this.sunLight.shadow.mapSize.set(2048, 2048);
    this.sunLight.shadow.normalBias = 0.05;
    // const helper = new THREE.CameraHelper(this.sunLight.shadow.camera);
    // this.scene.add(helper);

    this.sunLight.position.set(-1.5, 7, 3);
    base.scene.add(this.sunLight);

    this.ambientLight = new AmbientLight("#ffffff", 1);
    base.scene.add(this.ambientLight);
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs\World\World.ts

import { BackSide, Mesh, MeshBasicMaterial, PlaneGeometry } from "three";
import Base from "../Base";

export default class World {
  private plane: Mesh;
  constructor() {
    const base = Base.getInstance();
    const geometry = new PlaneGeometry(10, 10);
    const material = new MeshBasicMaterial({
      color: 0xfefefe,
      side: BackSide,
    });
    this.plane = new Mesh(geometry, material);
    this.plane.rotateX(Math.PI * 0.5);

    base.scene.add(this.plane);
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs_单例模式_constructor\Base.ts

import { Scene } from "three";

import Camera from "./Camera";

export default class Base {
  public static base: Base;
  public canvas!: HTMLCanvasElement;
  public scene!: Scene;
  public camera!: Camera;

  constructor(canvas?: HTMLCanvasElement) {
    if (canvas === undefined && Base.base !== undefined) {
      return Base.base;
    }
    Base.base = this;

    this.canvas = canvas as HTMLCanvasElement;
    this.scene = new Scene();
    this.camera = new Camera();
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs_单例模式_constructor\Camera.ts

import Base from "./Base";

export default class Camera {
  constructor() {
    const base = new Base();
    console.log(base.canvas);
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs_单例模式_getInstance\Base.ts

import { Scene } from "three";

import Camera from "./Camera";
import Helper from "./Helper";
import Renderer from "./Renderer";
import Size from "./Size";
import Time from "./Time";
import World from "./World/World";

export default class Base {
  public static base: Base;
  public canvas: HTMLCanvasElement;
  public scene: Scene;
  public camera: Camera;
  public size: Size;
  public time: Time;
  public renderer: Renderer;

  public world: World;

  constructor(canvas: HTMLCanvasElement) {
    Base.base = this;

    this.canvas = canvas as HTMLCanvasElement;
    this.scene = new Scene();
    this.size = new Size();
    this.camera = new Camera();
    this.time = new Time();
    this.renderer = new Renderer();
    new Helper();

    this.world = new World();

    this.time.on("update", () => {
      this.update();
    });
    this.size.on("resize", () => {
      this.resize();
    });
  }

  public static getInstance(canvas?: HTMLCanvasElement) {
    if (canvas === undefined && Base.base !== undefined) {
      return Base.base;
    }
    Base.base = new Base(canvas as HTMLCanvasElement);
    return Base.base;
  }

  private resize() {
    this.camera.resize();
    this.renderer.resize();
  }

  private update() {
    this.camera.update();
    this.renderer.update();
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs_单例模式_getInstance\Camera.ts

import { PerspectiveCamera, Scene } from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import Base from "./Base";
import type Size from "./Size";

export default class Camera {
  private size: Size;
  private scene: Scene;
  private canvas: HTMLCanvasElement;
  public perspectiveCamera: PerspectiveCamera;
  private controls: OrbitControls;

  constructor() {
    const base = Base.getInstance();
    this.size = base.size;
    this.scene = base.scene;
    this.canvas = base.canvas;

    this.perspectiveCamera = this.createPerspectiveCamera();
    this.scene.add(this.perspectiveCamera);

    this.controls = this.createOrbitControls();
  }
  private createPerspectiveCamera() {
    const perspectiveCamera = new PerspectiveCamera(
      35,
      this.size.aspect,
      0.1,
      1000
    );
    perspectiveCamera.position.set(15, 30, 20);
    return perspectiveCamera;
  }
  private createOrbitControls() {
    const controls = new OrbitControls(this.perspectiveCamera, this.canvas);
    controls.enableDamping = true;
    controls.enableZoom = true;
    return controls;
  }
  public update() {
    this.controls.update();
  }
  public resize() {
    // Updating Perspective Camera on Resize
    this.perspectiveCamera.aspect = this.size.aspect;
    this.perspectiveCamera.updateProjectionMatrix();
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs_单例模式_getInstance\Helper.ts

import { AxesHelper, GridHelper } from "three";
import Base from "./Base";

export default class {
  constructor() {
    const base = Base.getInstance();
    const axesHelper = new AxesHelper(5);
    base.scene.add(axesHelper);

    const size = 10;
    const divisions = 10;

    const gridHelper = new GridHelper(size, divisions);
    base.scene.add(gridHelper);
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs_单例模式_getInstance\Renderer.ts

import * as THREE from "three";
import Base from "./Base";
import { Scene, WebGLRenderer } from "three";
import Camera from "./Camera";
import Size from "./Size";

export default class Renderer {
  private size: Size;
  private scene: Scene;
  private canvas: HTMLCanvasElement;
  private camera: Camera;
  private renderer: WebGLRenderer;

  constructor() {
    const base = Base.getInstance();

    this.size = base.size;
    this.scene = base.scene;
    this.canvas = base.canvas;
    this.camera = base.camera;

    this.renderer = this.setRenderer();
  }

  setRenderer() {
    const renderer = new WebGLRenderer({
      canvas: this.canvas,
      antialias: true,
    });

    renderer.physicallyCorrectLights = true;
    renderer.outputEncoding = THREE.sRGBEncoding;
    renderer.toneMapping = THREE.CineonToneMapping;
    renderer.toneMappingExposure = 1.75;
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    renderer.setSize(this.size.width, this.size.height);
    renderer.setPixelRatio(this.size.pixelRatio);

    return renderer;
  }

  resize() {
    this.renderer.setSize(this.size.width, this.size.height);
    this.renderer.setPixelRatio(this.size.pixelRatio);
  }

  update() {
    this.renderer.render(this.scene, this.camera.perspectiveCamera);
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs_单例模式_getInstance\Size.ts

import EventEmitter from "eventemitter2";
export default class Size extends EventEmitter {
  public width: number;
  public height: number;
  public aspect: number;
  public pixelRatio: number;

  constructor() {
    super();
    this.width = window.innerWidth;
    this.height = window.innerHeight;
    this.aspect = this.width / this.height;
    this.pixelRatio = Math.min(window.devicePixelRatio, 2);

    window.addEventListener("resize", () => {
      this.width = window.innerWidth;
      this.height = window.innerHeight;
      this.aspect = this.width / this.height;
      this.pixelRatio = Math.min(window.devicePixelRatio, 2);
      this.emit("resize");
    });
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs_单例模式_getInstance\Time.ts

import EventEmitter from "eventemitter2";
import { Clock } from "three";

export default class Time extends EventEmitter {
  public clock: Clock;
  constructor() {
    super();
    this.clock = new Clock();

    this.update();
  }

  update() {
    this.emit("update");
    window.requestAnimationFrame(() => this.update());
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs_单例模式_getInstance\World\Environment.ts

import { AmbientLight, DirectionalLight } from "three";
import Base from "../Base";

export default class Environment {
  private sunLight: DirectionalLight;
  private ambientLight: AmbientLight;
  constructor() {
    const base = Base.getInstance();
    this.sunLight = new DirectionalLight("#ffffff", 3);
    this.sunLight.castShadow = true;
    this.sunLight.shadow.camera.far = 20;
    this.sunLight.shadow.mapSize.set(2048, 2048);
    this.sunLight.shadow.normalBias = 0.05;
    // const helper = new THREE.CameraHelper(this.sunLight.shadow.camera);
    // this.scene.add(helper);

    this.sunLight.position.set(-1.5, 7, 3);
    base.scene.add(this.sunLight);

    this.ambientLight = new AmbientLight("#ffffff", 1);
    base.scene.add(this.ambientLight);
  }
}

D:\code_gitee\threejs_learn_vanilla_class_singleton\threejs_learn_vanilla_ts_class_singleton\src\threejs_单例模式_getInstance\World\World.ts

import { BackSide, Mesh, MeshBasicMaterial, PlaneGeometry } from "three";
import Base from "../Base";

export default class World {
  private plane: Mesh;
  constructor() {
    const base = Base.getInstance();
    const geometry = new PlaneGeometry(10, 10);
    const material = new MeshBasicMaterial({
      color: 0xfefefe,
      side: BackSide,
    });
    this.plane = new Mesh(geometry, material);
    this.plane.rotateX(Math.PI * 0.5);

    base.scene.add(this.plane);
  }
}

posted on 2022-12-27 09:25  lazycookie  阅读(48)  评论(0编辑  收藏  举报