diff --git a/src/lib/index.ts b/src/lib/index.ts index 533950e..6929fc3 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,5 +1,6 @@ export * from './controls/MapControls.js'; export * from './controls/OrbitControls.js'; +export * from './light/SceneLight.js'; export * from './map/MapManager.js'; export * from './model/ModelManager.js'; export * from './texture/TextureManager.js'; diff --git a/src/lib/light/SceneLight.ts b/src/lib/light/SceneLight.ts new file mode 100644 index 0000000..fae9d38 --- /dev/null +++ b/src/lib/light/SceneLight.ts @@ -0,0 +1,28 @@ +import * as THREE from 'three'; + +class SceneLight { + #sunDir = new THREE.Vector3(); + #sunDirView = new THREE.Vector3(); + + #uniforms = { + sunDir: { + value: this.#sunDirView, + }, + }; + + get uniforms() { + return this.#uniforms; + } + + setSunDir(dir: THREE.Vector3) { + this.#sunDir.copy(dir); + } + + update(camera: THREE.Camera) { + const viewMatrix = camera.matrixWorldInverse; + this.#sunDirView.copy(this.#sunDir).transformDirection(viewMatrix).normalize(); + } +} + +export default SceneLight; +export { SceneLight }; diff --git a/src/lib/map/DoodadManager.ts b/src/lib/map/DoodadManager.ts index 4c98b68..fd89ed2 100644 --- a/src/lib/map/DoodadManager.ts +++ b/src/lib/map/DoodadManager.ts @@ -3,12 +3,12 @@ import ModelManager from '../model/ModelManager.js'; import TextureManager from '../texture/TextureManager.js'; import { AssetHost } from '../asset.js'; import { MapAreaSpec } from './loader/types.js'; -import DayNight from '../daynight/DayNight.js'; +import MapLight from './MapLight.js'; type DoodadManagerOptions = { host: AssetHost; textureManager?: TextureManager; - dayNight: DayNight; + mapLight: MapLight; }; class DoodadManager { @@ -21,7 +21,7 @@ class DoodadManager { this.#modelManager = new ModelManager({ host: options.host, textureManager: options.textureManager, - dayNight: options.dayNight, + sceneLight: options.mapLight, }); } diff --git a/src/lib/map/MapLight.ts b/src/lib/map/MapLight.ts new file mode 100644 index 0000000..c43025c --- /dev/null +++ b/src/lib/map/MapLight.ts @@ -0,0 +1,18 @@ +import * as THREE from 'three'; +import DayNight from './daynight/DayNight.js'; +import SceneLight from '../light/SceneLight.js'; + +class MapLight extends SceneLight { + #dayNight = new DayNight(); + + update(camera: THREE.Camera) { + this.#dayNight.update(); + + this.setSunDir(this.#dayNight.sunDir); + + super.update(camera); + } +} + +export default MapLight; +export { MapLight }; diff --git a/src/lib/map/MapManager.ts b/src/lib/map/MapManager.ts index dafe4f1..ad036f8 100644 --- a/src/lib/map/MapManager.ts +++ b/src/lib/map/MapManager.ts @@ -6,7 +6,7 @@ import DoodadManager from './DoodadManager.js'; import { AssetHost } from '../asset.js'; import MapLoader from './loader/MapLoader.js'; import { MapAreaSpec, MapSpec } from './loader/types.js'; -import DayNight from '../daynight/DayNight.js'; +import MapLight from './MapLight.js'; const DEFAULT_VIEW_DISTANCE = 1277.0; @@ -33,7 +33,7 @@ class MapManager { #terrainManager: TerrainManager; #doodadManager: DoodadManager; - #dayNight = new DayNight(); + #mapLight: MapLight; #target = new THREE.Vector2(); #targetAreaX: number; @@ -55,15 +55,17 @@ class MapManager { this.#textureManager = options.textureManager ?? new TextureManager({ host: options.host }); this.#loader = new MapLoader({ host: options.host }); + this.#mapLight = new MapLight(); + this.#terrainManager = new TerrainManager({ host: options.host, textureManager: this.#textureManager, - dayNight: this.#dayNight, + mapLight: this.#mapLight, }); this.#doodadManager = new DoodadManager({ host: options.host, textureManager: this.#textureManager, - dayNight: this.#dayNight, + mapLight: this.#mapLight, }); this.#root = new THREE.Group(); @@ -111,7 +113,7 @@ class MapManager { } update(deltaTime: number, camera: THREE.Camera) { - this.#dayNight.update(camera); + this.#mapLight.update(camera); this.#projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse); this.#cameraFrustum.setFromProjectionMatrix(this.#projScreenMatrix); diff --git a/src/lib/daynight/DayNight.ts b/src/lib/map/daynight/DayNight.ts similarity index 84% rename from src/lib/daynight/DayNight.ts rename to src/lib/map/daynight/DayNight.ts index 2ae28d8..d6a7090 100644 --- a/src/lib/daynight/DayNight.ts +++ b/src/lib/map/daynight/DayNight.ts @@ -13,14 +13,13 @@ class DayNight { #timeProgression = 0.0; #sunDir = new THREE.Vector3(); - #sunDirView = new THREE.Vector3(); - - #uniforms = { - sunDir: { value: this.#sunDirView }, - }; constructor() {} + get sunDir() { + return this.#sunDir; + } + get time() { return this.#time; } @@ -33,10 +32,6 @@ class DayNight { return this.#timeProgression; } - get uniforms() { - return this.#uniforms; - } - setTimeOverride(override: number) { this.#timeOverride = override; this.#updateTime(); @@ -47,12 +42,9 @@ class DayNight { this.#updateTime(); } - update(camera: THREE.Camera) { + update() { this.#updateTime(); this.#updateSunDirection(); - - const viewMatrix = camera.matrixWorldInverse; - this.#sunDirView.copy(this.#sunDir).transformDirection(viewMatrix).normalize(); } #updateTime() { diff --git a/src/lib/daynight/table.ts b/src/lib/map/daynight/table.ts similarity index 100% rename from src/lib/daynight/table.ts rename to src/lib/map/daynight/table.ts diff --git a/src/lib/daynight/util.ts b/src/lib/map/daynight/util.ts similarity index 100% rename from src/lib/daynight/util.ts rename to src/lib/map/daynight/util.ts diff --git a/src/lib/map/terrain/TerrainManager.ts b/src/lib/map/terrain/TerrainManager.ts index 8a78f33..2c3293b 100644 --- a/src/lib/map/terrain/TerrainManager.ts +++ b/src/lib/map/terrain/TerrainManager.ts @@ -4,26 +4,26 @@ import TerrainMaterial from './TerrainMaterial.js'; import TerrainMesh from './TerrainMesh.js'; import { AssetHost } from '../../asset.js'; import { MapAreaSpec, TerrainSpec } from '../loader/types.js'; -import DayNight from '../../daynight/DayNight.js'; +import MapLight from '../MapLight.js'; const SPLAT_TEXTURE_PLACEHOLDER = new THREE.Texture(); type TerrainManagerOptions = { host: AssetHost; textureManager?: TextureManager; - dayNight: DayNight; + mapLight: MapLight; }; class TerrainManager { #textureManager: TextureManager; - #dayNight: DayNight; + #mapLight: MapLight; #loadedAreas = new globalThis.Map(); #loadingAreas = new globalThis.Map>(); constructor(options: TerrainManagerOptions) { this.#textureManager = options.textureManager ?? new TextureManager({ host: options.host }); - this.#dayNight = options.dayNight; + this.#mapLight = options.mapLight; } getArea(areaId: number, area: MapAreaSpec): Promise { @@ -104,7 +104,7 @@ class TerrainManager { const layerTextures = await Promise.all( spec.material.layers.map((layer) => this.#textureManager.get(layer.texturePath)), ); - const uniforms = { ...this.#dayNight.uniforms }; + const uniforms = { ...this.#mapLight.uniforms }; return new TerrainMaterial(spec.material.layers.length, layerTextures, splatTexture, uniforms); } diff --git a/src/lib/model/ModelManager.ts b/src/lib/model/ModelManager.ts index 0a58bdb..3e692ac 100644 --- a/src/lib/model/ModelManager.ts +++ b/src/lib/model/ModelManager.ts @@ -9,7 +9,7 @@ import { getFragmentShader } from './shader/fragment.js'; import { M2_MATERIAL_PASS } from './const.js'; import ModelLoader from './loader/ModelLoader.js'; import { MaterialSpec, ModelSpec, TextureSpec } from './loader/types.js'; -import DayNight from '../daynight/DayNight.js'; +import SceneLight from '../light/SceneLight.js'; type ModelResources = { name: string; @@ -20,13 +20,13 @@ type ModelResources = { type ModelManagerOptions = { host: AssetHost; textureManager?: TextureManager; - dayNight?: DayNight; + sceneLight?: SceneLight; }; class ModelManager { #host: AssetHost; #textureManager: TextureManager; - #dayNight: DayNight; + #sceneLight: SceneLight; #loader: ModelLoader; #loaded = new globalThis.Map(); @@ -38,7 +38,7 @@ class ModelManager { this.#textureManager = options.textureManager ?? new TextureManager({ host: options.host }); this.#loader = new ModelLoader({ host: options.host }); - this.#dayNight = options.dayNight ?? new DayNight(); + this.#sceneLight = options.sceneLight ?? new SceneLight(); } async get(path: string) { @@ -139,7 +139,7 @@ class ModelManager { const textures = await Promise.all( spec.textures.map((textureSpec) => this.#createTexture(textureSpec)), ); - const uniforms = { ...this.#dayNight.uniforms }; + const uniforms = { ...this.#sceneLight.uniforms }; return new ModelMaterial( vertexShader,