From 1236e2f081947757b60165c5f64033a5dbf29b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:23:01 +0200 Subject: [PATCH] Improve type safety and names - separate TelluricPlanetModel from TelluricSatelliteModel - better names for physical properties => physics info - simplify CanHaveRings interface --- src/ts/alphaTestis.ts | 7 +- src/ts/anomalies/julia/juliaSet.ts | 13 +- src/ts/anomalies/julia/juliaSetModel.ts | 4 +- src/ts/anomalies/mandelbulb/mandelbulb.ts | 13 +- .../anomalies/mandelbulb/mandelbulbModel.ts | 4 +- src/ts/architecture/canHaveRings.ts | 4 +- src/ts/architecture/orbitalObject.ts | 4 +- .../{physicalProperties.ts => physicsInfo.ts} | 12 +- src/ts/architecture/planet.ts | 37 +---- src/ts/architecture/planetaryMassObject.ts | 30 ++++ src/ts/architecture/stellarObject.ts | 4 +- src/ts/architecture/typedObject.ts | 17 +++ src/ts/blackHoleDemo.ts | 2 +- .../missions/generateSightSeeingMissions.ts | 6 +- .../sightseeing/missionAsteroidFieldNode.ts | 2 +- src/ts/planets/gasPlanet/gasPlanet.ts | 12 +- src/ts/planets/gasPlanet/gasPlanetModel.ts | 6 +- .../planets/telluricPlanet/telluricPlanet.ts | 24 +-- .../telluricPlanet/telluricPlanetMaterial.ts | 6 +- .../telluricPlanet/telluricPlanetModel.ts | 142 +++++------------- .../telluricPlanetaryMassObjectModel.ts | 29 ++++ .../telluricPlanet/telluricSatelliteModel.ts | 142 ++++++++++++++++++ .../terrain/chunks/chunkTree.ts | 6 +- .../terrain/chunks/planetChunk.ts | 6 +- src/ts/postProcesses/lensFlarePostProcess.ts | 2 +- src/ts/postProcesses/matterJetPostProcess.ts | 4 +- src/ts/postProcesses/postProcessManager.ts | 18 +-- src/ts/postProcesses/shadowPostProcess.ts | 4 +- .../uniforms/stellarObjectUniforms.ts | 2 +- src/ts/rings/ringsPostProcess.ts | 2 +- src/ts/spaceship/spaceship.ts | 4 +- src/ts/spacestation/spacestationModel.ts | 6 +- src/ts/starSystem/seededStarSystemModel.ts | 5 +- src/ts/starSystem/starSystemController.ts | 26 ++-- src/ts/starSystem/starSystemModel.ts | 15 +- src/ts/starmap/starMap.ts | 2 +- src/ts/starmap/starMapUI.ts | 2 +- src/ts/stellarObjects/blackHole/blackHole.ts | 14 +- .../blackHole/blackHoleModel.ts | 17 +-- .../stellarObjects/neutronStar/neutronStar.ts | 20 +-- .../neutronStar/neutronStarModel.ts | 6 +- src/ts/stellarObjects/star/star.ts | 12 +- src/ts/stellarObjects/star/starMaterial.ts | 2 +- src/ts/stellarObjects/star/starModel.ts | 6 +- src/ts/utils/coordinates/orbitalObjectId.ts | 4 +- src/ts/utils/physics.ts | 26 ++++ src/ts/utils/positionNearObject.ts | 2 +- .../strings/orbitalObjectTypeToDisplay.ts | 2 +- 48 files changed, 408 insertions(+), 327 deletions(-) rename src/ts/architecture/{physicalProperties.ts => physicsInfo.ts} (75%) create mode 100644 src/ts/architecture/planetaryMassObject.ts create mode 100644 src/ts/planets/telluricPlanet/telluricPlanetaryMassObjectModel.ts create mode 100644 src/ts/planets/telluricPlanet/telluricSatelliteModel.ts diff --git a/src/ts/alphaTestis.ts b/src/ts/alphaTestis.ts index 9d11165c5..8b69e7336 100644 --- a/src/ts/alphaTestis.ts +++ b/src/ts/alphaTestis.ts @@ -21,7 +21,6 @@ import { Settings } from "./settings"; import { positionNearObjectBrightSide } from "./utils/positionNearObject"; import { CosmosJourneyer } from "./cosmosJourneyer"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; -import { newSeededTelluricPlanetModel } from "./planets/telluricPlanet/telluricPlanetModel"; import { newSeededGasPlanetModel } from "./planets/gasPlanet/gasPlanetModel"; import { SpaceShipControlsInputs } from "./spaceship/spaceShipControlsInputs"; @@ -30,6 +29,8 @@ import { newSeededSpaceStationModel } from "./spacestation/spacestationModel"; import { StarSystemModel } from "./starSystem/starSystemModel"; import { StarSystemCoordinates } from "./utils/coordinates/universeCoordinates"; import { CustomSystemRegistry } from "./starSystem/customSystemRegistry"; +import { newSeededTelluricSatelliteModel } from "./planets/telluricPlanet/telluricSatelliteModel"; +import { newSeededTelluricPlanetModel } from "./planets/telluricPlanet/telluricPlanetModel"; const engine = await CosmosJourneyer.CreateAsync(); @@ -51,7 +52,7 @@ const systemCoordinates: StarSystemCoordinates = { }; const sunModel = newSeededStarModel(420, "Weierstrass", []); -sunModel.physics.temperature = 5778; +sunModel.physics.blackBodyTemperature = 5778; sunModel.orbit.period = 60 * 60 * 24; /*const secundaModel = new StarModel(-672446, sunModel); @@ -79,7 +80,7 @@ const spaceStationModel = newSeededSpaceStationModel(0, [sunModel], systemCoordi physicsViewer.showBody(landingpad.aggregate.body); }*/ -const moonModel = newSeededTelluricPlanetModel(23, "Manaleth", [hecateModel]); +const moonModel = newSeededTelluricSatelliteModel(23, "Manaleth", [hecateModel]); moonModel.physics.mass = 2; moonModel.physics.rotationPeriod = 7 * 60 * 60; moonModel.physics.minTemperature = -180; diff --git a/src/ts/anomalies/julia/juliaSet.ts b/src/ts/anomalies/julia/juliaSet.ts index 5e5d880b7..d8a011751 100644 --- a/src/ts/anomalies/julia/juliaSet.ts +++ b/src/ts/anomalies/julia/juliaSet.ts @@ -21,10 +21,8 @@ import { PostProcessType } from "../../postProcesses/postProcessTypes"; import { Axis } from "@babylonjs/core/Maths/math.axis"; import { TransformNode } from "@babylonjs/core/Meshes"; import { Scene } from "@babylonjs/core/scene"; -import { RingsUniforms } from "../../rings/ringsUniform"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; import { Cullable } from "../../utils/cullable"; -import { AsteroidField } from "../../asteroidFields/asteroidField"; import { CelestialBody } from "../../architecture/celestialBody"; import { orbitalObjectTypeToDisplay } from "../../utils/strings/orbitalObjectTypeToDisplay"; @@ -35,6 +33,9 @@ export class JuliaSet implements CelestialBody, Cullable { readonly postProcesses: PostProcessType[] = []; + readonly ringsUniforms = null; + readonly asteroidField = null; + /** * New Gas Planet * @param model The model to create the planet from or a seed for the planet in [-1, 1] @@ -58,14 +59,6 @@ export class JuliaSet implements CelestialBody, Cullable { return this.getTransform().up; } - getRingsUniforms(): RingsUniforms | null { - return null; - } - - getAsteroidField(): AsteroidField | null { - return null; - } - getRadius(): number { return this.model.radius; } diff --git a/src/ts/anomalies/julia/juliaSetModel.ts b/src/ts/anomalies/julia/juliaSetModel.ts index 3acf0cbad..ec57d0bc8 100644 --- a/src/ts/anomalies/julia/juliaSetModel.ts +++ b/src/ts/anomalies/julia/juliaSetModel.ts @@ -19,7 +19,7 @@ import { normalRandom } from "extended-random"; import { clamp } from "../../utils/math"; import { getOrbitalPeriod, getPeriapsis, Orbit } from "../../orbit/orbit"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; -import { OrbitalObjectPhysicalProperties } from "../../architecture/physicalProperties"; +import { OrbitalObjectPhysicsInfo } from "../../architecture/physicsInfo"; import { CelestialBodyModel } from "../../architecture/celestialBody"; import { GenerationSteps } from "../../utils/generationSteps"; import { Color3 } from "@babylonjs/core/Maths/math.color"; @@ -54,7 +54,7 @@ export function newSeededJuliaSetModel(seed: number, name: string, parentBodies: normalToPlane: Vector3.Up() }; - const physicalProperties: OrbitalObjectPhysicalProperties = { + const physicalProperties: OrbitalObjectPhysicsInfo = { mass: 10, rotationPeriod: 0, axialTilt: normalRandom(0, 0.4, rng, GenerationSteps.AXIAL_TILT) diff --git a/src/ts/anomalies/mandelbulb/mandelbulb.ts b/src/ts/anomalies/mandelbulb/mandelbulb.ts index a994d46cd..f19b4b993 100644 --- a/src/ts/anomalies/mandelbulb/mandelbulb.ts +++ b/src/ts/anomalies/mandelbulb/mandelbulb.ts @@ -21,10 +21,8 @@ import { PostProcessType } from "../../postProcesses/postProcessTypes"; import { Axis } from "@babylonjs/core/Maths/math.axis"; import { TransformNode } from "@babylonjs/core/Meshes"; import { Scene } from "@babylonjs/core/scene"; -import { RingsUniforms } from "../../rings/ringsUniform"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; import { Cullable } from "../../utils/cullable"; -import { AsteroidField } from "../../asteroidFields/asteroidField"; import { CelestialBody } from "../../architecture/celestialBody"; import { orbitalObjectTypeToDisplay } from "../../utils/strings/orbitalObjectTypeToDisplay"; @@ -35,6 +33,9 @@ export class Mandelbulb implements CelestialBody, Cullable { readonly postProcesses: PostProcessType[] = []; + readonly asteroidField = null; + readonly ringsUniforms = null; + /** * New Gas Planet * @param model The model to create the planet from or a seed for the planet in [-1, 1] @@ -58,14 +59,6 @@ export class Mandelbulb implements CelestialBody, Cullable { return this.getTransform().up; } - getRingsUniforms(): RingsUniforms | null { - return null; - } - - getAsteroidField(): AsteroidField | null { - return null; - } - getRadius(): number { return this.model.radius; } diff --git a/src/ts/anomalies/mandelbulb/mandelbulbModel.ts b/src/ts/anomalies/mandelbulb/mandelbulbModel.ts index 66e37f106..f29b529b9 100644 --- a/src/ts/anomalies/mandelbulb/mandelbulbModel.ts +++ b/src/ts/anomalies/mandelbulb/mandelbulbModel.ts @@ -22,7 +22,7 @@ import { getOrbitalPeriod, getPeriapsis, Orbit } from "../../orbit/orbit"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; import { CelestialBodyModel } from "../../architecture/celestialBody"; import { GenerationSteps } from "../../utils/generationSteps"; -import { OrbitalObjectPhysicalProperties } from "../../architecture/physicalProperties"; +import { OrbitalObjectPhysicsInfo } from "../../architecture/physicsInfo"; import { AnomalyModel } from "../anomaly"; import { getRngFromSeed } from "../../utils/getRngFromSeed"; @@ -56,7 +56,7 @@ export function newSeededMandelbulbModel(seed: number, name: string, parentBodie normalToPlane: Vector3.Up() }; - const physicalProperties: OrbitalObjectPhysicalProperties = { + const physicalProperties: OrbitalObjectPhysicsInfo = { mass: 10, rotationPeriod: 0, axialTilt: normalRandom(0, 0.4, rng, GenerationSteps.AXIAL_TILT) diff --git a/src/ts/architecture/canHaveRings.ts b/src/ts/architecture/canHaveRings.ts index 9782335ab..b3abedb7d 100644 --- a/src/ts/architecture/canHaveRings.ts +++ b/src/ts/architecture/canHaveRings.ts @@ -26,12 +26,12 @@ export interface CanHaveRings { /** * Returns the uniforms used to render the rings, or null if the object has no rings */ - getRingsUniforms(): RingsUniforms | null; + readonly ringsUniforms: RingsUniforms | null; /** * Returns the asteroid belt of the object's ring, or null if the object has no rings */ - getAsteroidField(): AsteroidField | null; + readonly asteroidField: AsteroidField | null; } export interface CanHaveRingsModel { diff --git a/src/ts/architecture/orbitalObject.ts b/src/ts/architecture/orbitalObject.ts index 26dc9f1e1..12ac8c138 100644 --- a/src/ts/architecture/orbitalObject.ts +++ b/src/ts/architecture/orbitalObject.ts @@ -19,7 +19,7 @@ import { Transformable } from "./transformable"; import { HasBoundingSphere } from "./hasBoundingSphere"; import { Quaternion, Vector3 } from "@babylonjs/core/Maths/math"; import { getRotationQuaternion, setRotationQuaternion, translate } from "../uberCore/transforms/basicTransform"; -import { OrbitalObjectPhysicalProperties } from "./physicalProperties"; +import { OrbitalObjectPhysicsInfo } from "./physicsInfo"; import { TypedObject } from "./typedObject"; import { getPointOnOrbit, Orbit } from "../orbit/orbit"; @@ -130,7 +130,7 @@ export type OrbitalObjectModel = { /** * Physical properties of the object */ - readonly physics: OrbitalObjectPhysicalProperties; + readonly physics: OrbitalObjectPhysicsInfo; }; export const enum OrbitalObjectType { diff --git a/src/ts/architecture/physicalProperties.ts b/src/ts/architecture/physicsInfo.ts similarity index 75% rename from src/ts/architecture/physicalProperties.ts rename to src/ts/architecture/physicsInfo.ts index 3b1a39a55..651ff257b 100644 --- a/src/ts/architecture/physicalProperties.ts +++ b/src/ts/architecture/physicsInfo.ts @@ -15,7 +15,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -export type OrbitalObjectPhysicalProperties = { +export type OrbitalObjectPhysicsInfo = { mass: number; /** * Time needed for the object to rotate on its axis in seconds @@ -24,24 +24,24 @@ export type OrbitalObjectPhysicalProperties = { axialTilt: number; }; -export type StellarObjectPhysicalProperties = OrbitalObjectPhysicalProperties & { +export type StellarObjectPhysicsInfo = OrbitalObjectPhysicsInfo & { /** * Black body temperature of the object in Kelvin */ - temperature: number; + blackBodyTemperature: number; }; -export type BlackHolePhysicalProperties = StellarObjectPhysicalProperties & { +export type BlackHolePhysicsInfo = StellarObjectPhysicsInfo & { accretionDiskRadius: number; }; -export type PlanetPhysicalProperties = OrbitalObjectPhysicalProperties & { +export type PlanetaryMassObjectPhysicsInfo = OrbitalObjectPhysicsInfo & { minTemperature: number; maxTemperature: number; pressure: number; }; -export type TelluricPlanetPhysicalProperties = PlanetPhysicalProperties & { +export type TelluricPlanetaryMassObjectPhysicsInfo = PlanetaryMassObjectPhysicsInfo & { waterAmount: number; oceanLevel: number; }; diff --git a/src/ts/architecture/planet.ts b/src/ts/architecture/planet.ts index 9d104e1ca..9a7d50999 100644 --- a/src/ts/architecture/planet.ts +++ b/src/ts/architecture/planet.ts @@ -1,37 +1,10 @@ -// This file is part of Cosmos Journeyer -// -// Copyright (C) 2024 Barthélemy Paléologue -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -import { CelestialBody, CelestialBodyModel } from "./celestialBody"; -import { PlanetPhysicalProperties } from "./physicalProperties"; -import { Transformable } from "./transformable"; +import { PlanetaryMassObject, PlanetaryMassObjectModel } from "./planetaryMassObject"; import { OrbitalObjectType } from "./orbitalObject"; -export interface Planet extends CelestialBody { - model: PlanetModel; - - updateMaterial(stellarObjects: Transformable[], deltaSeconds: number): void; +export interface Planet extends PlanetaryMassObject { + readonly model: PlanetModel; } -export type PlanetModel = CelestialBodyModel & { - readonly type: OrbitalObjectType.TELLURIC_PLANET | OrbitalObjectType.GAS_PLANET | OrbitalObjectType.TELLURIC_SATELLITE; - - physics: PlanetPhysicalProperties; +export type PlanetModel = PlanetaryMassObjectModel & { + readonly type: OrbitalObjectType.TELLURIC_PLANET | OrbitalObjectType.GAS_PLANET; }; - -export function hasAtmosphere(planetModel: PlanetModel): boolean { - return planetModel.physics.pressure > 0.05; -} diff --git a/src/ts/architecture/planetaryMassObject.ts b/src/ts/architecture/planetaryMassObject.ts new file mode 100644 index 000000000..8eca77fab --- /dev/null +++ b/src/ts/architecture/planetaryMassObject.ts @@ -0,0 +1,30 @@ +// This file is part of Cosmos Journeyer +// +// Copyright (C) 2024 Barthélemy Paléologue +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +import { CelestialBody, CelestialBodyModel } from "./celestialBody"; +import { PlanetaryMassObjectPhysicsInfo } from "./physicsInfo"; +import { Transformable } from "./transformable"; + +export interface PlanetaryMassObject extends CelestialBody { + readonly model: PlanetaryMassObjectModel; + + updateMaterial(stellarObjects: Transformable[], deltaSeconds: number): void; +} + +export type PlanetaryMassObjectModel = CelestialBodyModel & { + readonly physics: PlanetaryMassObjectPhysicsInfo; +}; \ No newline at end of file diff --git a/src/ts/architecture/stellarObject.ts b/src/ts/architecture/stellarObject.ts index b397b3846..df0839be1 100644 --- a/src/ts/architecture/stellarObject.ts +++ b/src/ts/architecture/stellarObject.ts @@ -17,7 +17,7 @@ import { PointLight } from "@babylonjs/core/Lights/pointLight"; import { CelestialBody, CelestialBodyModel } from "./celestialBody"; -import { StellarObjectPhysicalProperties } from "./physicalProperties"; +import { StellarObjectPhysicsInfo } from "./physicsInfo"; export interface StellarObject extends CelestialBody { model: StellarObjectModel; @@ -26,5 +26,5 @@ export interface StellarObject extends CelestialBody { } export type StellarObjectModel = CelestialBodyModel & { - physics: StellarObjectPhysicalProperties; + physics: StellarObjectPhysicsInfo; }; diff --git a/src/ts/architecture/typedObject.ts b/src/ts/architecture/typedObject.ts index fe3e9d077..83955b334 100644 --- a/src/ts/architecture/typedObject.ts +++ b/src/ts/architecture/typedObject.ts @@ -1,3 +1,20 @@ +// This file is part of Cosmos Journeyer +// +// Copyright (C) 2024 Barthélemy Paléologue +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + export interface TypedObject { /** * Returns the type name of the object. This is used as a short identifier in the UI Overlay of the object diff --git a/src/ts/blackHoleDemo.ts b/src/ts/blackHoleDemo.ts index f3e61bab6..6d9afb062 100644 --- a/src/ts/blackHoleDemo.ts +++ b/src/ts/blackHoleDemo.ts @@ -21,9 +21,9 @@ import { positionNearObjectBrightSide } from "./utils/positionNearObject"; import { CosmosJourneyer } from "./cosmosJourneyer"; import { newSeededBlackHoleModel } from "./stellarObjects/blackHole/blackHoleModel"; -import { newSeededTelluricPlanetModel } from "./planets/telluricPlanet/telluricPlanetModel"; import { StarSystemModel } from "./starSystem/starSystemModel"; import { CustomSystemRegistry } from "./starSystem/customSystemRegistry"; +import { newSeededTelluricPlanetModel } from "./planets/telluricPlanet/telluricPlanetModel"; const engine = await CosmosJourneyer.CreateAsync(); diff --git a/src/ts/missions/generateSightSeeingMissions.ts b/src/ts/missions/generateSightSeeingMissions.ts index 593ef6b42..ae0967211 100644 --- a/src/ts/missions/generateSightSeeingMissions.ts +++ b/src/ts/missions/generateSightSeeingMissions.ts @@ -21,7 +21,7 @@ import { newSightSeeingMission } from "./sightSeeingMission"; import { uniformRandBool } from "extended-random"; import { SystemObjectType } from "../utils/coordinates/universeCoordinates"; import { Player } from "../player/player"; -import { hasLiquidWater, TelluricPlanetModel } from "../planets/telluricPlanet/telluricPlanetModel"; +import { TelluricPlanetaryMassObjectModel } from "../planets/telluricPlanet/telluricPlanetaryMassObjectModel"; import { Mission, MissionType } from "./mission"; import { StarSystemModel, StarSystemModelUtils } from "../starSystem/starSystemModel"; import { getRngFromSeed } from "../utils/getRngFromSeed"; @@ -110,8 +110,8 @@ export function generateSightseeingMissions(spaceStationModel: SpaceStationModel } if (celestialBodyModel.type === OrbitalObjectType.TELLURIC_PLANET) { - const telluricPlanetModel = celestialBodyModel as TelluricPlanetModel; - if (!hasLiquidWater(telluricPlanetModel)) { + const telluricPlanetModel = celestialBodyModel as TelluricPlanetaryMassObjectModel; + if (telluricPlanetModel.physics.oceanLevel === 0) { terminatorLandingMissions.push( newSightSeeingMission(spaceStationModel, { type: MissionType.SIGHT_SEEING_TERMINATOR_LANDING, diff --git a/src/ts/missions/nodes/actions/sightseeing/missionAsteroidFieldNode.ts b/src/ts/missions/nodes/actions/sightseeing/missionAsteroidFieldNode.ts index d4f392fa1..991ff3a32 100644 --- a/src/ts/missions/nodes/actions/sightseeing/missionAsteroidFieldNode.ts +++ b/src/ts/missions/nodes/actions/sightseeing/missionAsteroidFieldNode.ts @@ -95,7 +95,7 @@ export class MissionAsteroidFieldNode implements MissionNode { throw new Error(`Object with ID ${JSON.stringify(this.objectId)} is not a celestial body`); } - const asteroidField = celestialBody.getAsteroidField(); + const asteroidField = celestialBody.asteroidField; if (asteroidField === null) { throw new Error(`Object with ID ${JSON.stringify(this.objectId)} does not have an asteroid field`); } diff --git a/src/ts/planets/gasPlanet/gasPlanet.ts b/src/ts/planets/gasPlanet/gasPlanet.ts index d60dd865f..28133ee48 100644 --- a/src/ts/planets/gasPlanet/gasPlanet.ts +++ b/src/ts/planets/gasPlanet/gasPlanet.ts @@ -25,7 +25,6 @@ import { isSizeOnScreenEnough } from "../../utils/isObjectVisibleOnScreen"; import { Camera } from "@babylonjs/core/Cameras/camera"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; import { PhysicsShapeSphere } from "@babylonjs/core/Physics/v2/physicsShape"; -import { Planet } from "../../architecture/planet"; import { TransformNode } from "@babylonjs/core/Meshes"; import { PhysicsAggregate } from "@babylonjs/core/Physics/v2/physicsAggregate"; import { PhysicsShapeType } from "@babylonjs/core/Physics/v2/IPhysicsEnginePlugin"; @@ -35,6 +34,7 @@ import { Transformable } from "../../architecture/transformable"; import { Scene } from "@babylonjs/core/scene"; import { AsteroidField } from "../../asteroidFields/asteroidField"; import { orbitalObjectTypeToDisplay } from "../../utils/strings/orbitalObjectTypeToDisplay"; +import { Planet } from "../../architecture/planet"; export class GasPlanet implements Planet, Cullable { private readonly mesh: Mesh; @@ -46,7 +46,7 @@ export class GasPlanet implements Planet, Cullable { postProcesses: PostProcessType[] = []; readonly ringsUniforms: RingsUniforms | null; - private readonly asteroidField: AsteroidField | null; + readonly asteroidField: AsteroidField | null; /** * New Gas Planet @@ -114,14 +114,6 @@ export class GasPlanet implements Planet, Cullable { return this.getTransform().up; } - getRingsUniforms(): RingsUniforms | null { - return this.ringsUniforms; - } - - getAsteroidField(): AsteroidField | null { - return this.asteroidField; - } - getTypeName(): string { return orbitalObjectTypeToDisplay(this.model); } diff --git a/src/ts/planets/gasPlanet/gasPlanetModel.ts b/src/ts/planets/gasPlanet/gasPlanetModel.ts index 071b61e5a..309351676 100644 --- a/src/ts/planets/gasPlanet/gasPlanetModel.ts +++ b/src/ts/planets/gasPlanet/gasPlanetModel.ts @@ -22,14 +22,14 @@ import { Axis } from "@babylonjs/core/Maths/math.axis"; import { clamp } from "../../utils/math"; import { getOrbitalPeriod, getPeriapsis, Orbit } from "../../orbit/orbit"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; -import { PlanetModel } from "../../architecture/planet"; -import { PlanetPhysicalProperties } from "../../architecture/physicalProperties"; +import { PlanetaryMassObjectPhysicsInfo } from "../../architecture/physicsInfo"; import { CelestialBodyModel } from "../../architecture/celestialBody"; import { newSeededRingsModel } from "../../rings/ringsModel"; import { GenerationSteps } from "../../utils/generationSteps"; import { getRngFromSeed } from "../../utils/getRngFromSeed"; import { OrbitalObjectType } from "../../architecture/orbitalObject"; +import { PlanetModel } from "../../architecture/planet"; export type GasPlanetModel = PlanetModel & { readonly type: OrbitalObjectType.GAS_PLANET; @@ -60,7 +60,7 @@ export function newSeededGasPlanetModel(seed: number, name: string, parentBodies normalToPlane: orbitalPlaneNormal }; - const physicalProperties: PlanetPhysicalProperties = { + const physicalProperties: PlanetaryMassObjectPhysicsInfo = { //FIXME: when Settings.Earth radius gets to 1:1 scale, change this value by a variable in settings mass: Settings.JUPITER_MASS * (radius / 69_911e3) ** 3, axialTilt: normalRandom(0, 0.4, rng, GenerationSteps.AXIAL_TILT), diff --git a/src/ts/planets/telluricPlanet/telluricPlanet.ts b/src/ts/planets/telluricPlanet/telluricPlanet.ts index d97c7f2f2..f6faee584 100644 --- a/src/ts/planets/telluricPlanet/telluricPlanet.ts +++ b/src/ts/planets/telluricPlanet/telluricPlanet.ts @@ -19,14 +19,14 @@ import { Direction } from "../../utils/direction"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; import { Axis } from "@babylonjs/core/Maths/math.axis"; import { TelluricPlanetMaterial } from "./telluricPlanetMaterial"; -import { hasLiquidWater, TelluricPlanetModel } from "./telluricPlanetModel"; +import { TelluricPlanetaryMassObjectModel } from "./telluricPlanetaryMassObjectModel"; import { PostProcessType } from "../../postProcesses/postProcessTypes"; import { Camera } from "@babylonjs/core/Cameras/camera"; import { ChunkTree } from "./terrain/chunks/chunkTree"; import { PhysicsShapeSphere } from "@babylonjs/core/Physics/v2/physicsShape"; import { Transformable } from "../../architecture/transformable"; import { ChunkForge } from "./terrain/chunks/chunkForge"; -import { hasAtmosphere, Planet } from "../../architecture/planet"; +import { PlanetaryMassObject } from "../../architecture/planetaryMassObject"; import { Cullable } from "../../utils/cullable"; import { TransformNode } from "@babylonjs/core/Meshes"; import { PhysicsAggregate } from "@babylonjs/core/Physics/v2/physicsAggregate"; @@ -38,12 +38,12 @@ import { Scene } from "@babylonjs/core/scene"; import { AsteroidField } from "../../asteroidFields/asteroidField"; import { orbitalObjectTypeToDisplay } from "../../utils/strings/orbitalObjectTypeToDisplay"; -export class TelluricPlanet implements Planet, Cullable { +export class TelluricPlanet implements PlanetaryMassObject, Cullable { readonly sides: ChunkTree[]; // stores the 6 sides of the sphere readonly material: TelluricPlanetMaterial; - readonly model: TelluricPlanetModel; + readonly model: TelluricPlanetaryMassObjectModel; private readonly transform: TransformNode; readonly aggregate: PhysicsAggregate; @@ -51,7 +51,7 @@ export class TelluricPlanet implements Planet, Cullable { readonly postProcesses: PostProcessType[] = []; readonly ringsUniforms: RingsUniforms | null; - private readonly asteroidField: AsteroidField | null; + readonly asteroidField: AsteroidField | null; readonly cloudsUniforms: CloudsUniforms | null; @@ -60,7 +60,7 @@ export class TelluricPlanet implements Planet, Cullable { * @param model The model to build the planet or a seed for the planet in [-1, 1] * @param scene */ - constructor(model: TelluricPlanetModel, scene: Scene) { + constructor(model: TelluricPlanetaryMassObjectModel, scene: Scene) { this.model = model; this.transform = new TransformNode(this.model.name, scene); @@ -84,8 +84,8 @@ export class TelluricPlanet implements Planet, Cullable { this.postProcesses.push(PostProcessType.SHADOW); - if (hasLiquidWater(this.model)) this.postProcesses.push(PostProcessType.OCEAN); - if (hasAtmosphere(this.model)) this.postProcesses.push(PostProcessType.ATMOSPHERE); + if (this.model.physics.oceanLevel > 0) this.postProcesses.push(PostProcessType.OCEAN); + if (this.model.physics.pressure > 0.05) this.postProcesses.push(PostProcessType.ATMOSPHERE); if (this.model.rings !== null) { this.postProcesses.push(PostProcessType.RING); @@ -126,14 +126,6 @@ export class TelluricPlanet implements Planet, Cullable { return this.getTransform().up; } - getRingsUniforms(): RingsUniforms | null { - return this.ringsUniforms; - } - - getAsteroidField(): AsteroidField | null { - return this.asteroidField; - } - getCloudsUniforms(): CloudsUniforms | null { return this.cloudsUniforms; } diff --git a/src/ts/planets/telluricPlanet/telluricPlanetMaterial.ts b/src/ts/planets/telluricPlanet/telluricPlanetMaterial.ts index a06183c64..9882ec54a 100644 --- a/src/ts/planets/telluricPlanet/telluricPlanetMaterial.ts +++ b/src/ts/planets/telluricPlanet/telluricPlanetMaterial.ts @@ -21,7 +21,7 @@ import surfaceMaterialFragment from "../../../shaders/telluricPlanetMaterial/fra import surfaceMaterialVertex from "../../../shaders/telluricPlanetMaterial/vertex.glsl"; import { Assets } from "../../assets/assets"; import { centeredRand } from "extended-random"; -import { TelluricPlanetModel } from "./telluricPlanetModel"; +import { TelluricPlanetaryMassObjectModel } from "./telluricPlanetaryMassObjectModel"; import { Effect } from "@babylonjs/core/Materials/effect"; import { ShaderMaterial } from "@babylonjs/core/Materials/shaderMaterial"; import lutFragment from "../../../shaders/telluricPlanetMaterial/utils/lut.glsl"; @@ -73,7 +73,7 @@ export class TelluricPlanetMaterial extends ShaderMaterial { /** * The model of the planet associated with this material */ - private readonly planetModel: TelluricPlanetModel; + private readonly planetModel: TelluricPlanetaryMassObjectModel; private readonly plainNormalMetallicMap: Texture; private readonly plainAlbedoRoughnessMap: Texture; @@ -96,7 +96,7 @@ export class TelluricPlanetMaterial extends ShaderMaterial { * @param model The model of the planet associated with this material * @param scene */ - constructor(model: TelluricPlanetModel, scene: Scene) { + constructor(model: TelluricPlanetaryMassObjectModel, scene: Scene) { const shaderName = "surfaceMaterial"; if (Effect.ShadersStore[`${shaderName}FragmentShader`] === undefined) { Effect.ShadersStore[`${shaderName}FragmentShader`] = surfaceMaterialFragment; diff --git a/src/ts/planets/telluricPlanet/telluricPlanetModel.ts b/src/ts/planets/telluricPlanet/telluricPlanetModel.ts index 9c01487a7..0330f037e 100644 --- a/src/ts/planets/telluricPlanet/telluricPlanetModel.ts +++ b/src/ts/planets/telluricPlanet/telluricPlanetModel.ts @@ -15,73 +15,46 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +import { PlanetModel } from "../../architecture/planet"; +import { OrbitalObjectType } from "../../architecture/orbitalObject"; +import { CelestialBodyModel } from "../../architecture/celestialBody"; +import { getRngFromSeed } from "../../utils/getRngFromSeed"; import { normalRandom, randRangeInt, uniformRandBool } from "extended-random"; +import { GenerationSteps } from "../../utils/generationSteps"; import { Settings } from "../../settings"; -import { TerrainSettings } from "./terrain/terrainSettings"; -import { clamp } from "terrain-generation"; -import { Axis } from "@babylonjs/core/Maths/math.axis"; -import { Quaternion } from "@babylonjs/core/Maths/math"; +import { TelluricPlanetaryMassObjectPhysicsInfo } from "../../architecture/physicsInfo"; +import { hasLiquidWater } from "../../utils/physics"; +import { CloudsModel, newCloudsModel } from "../../clouds/cloudsModel"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; -import { getOrbitalPeriod, getPeriapsis, Orbit } from "../../orbit/orbit"; -import { PlanetModel } from "../../architecture/planet"; -import { TelluricPlanetPhysicalProperties } from "../../architecture/physicalProperties"; -import { CelestialBodyModel } from "../../architecture/celestialBody"; +import { Quaternion } from "@babylonjs/core/Maths/math"; +import { Axis } from "@babylonjs/core/Maths/math.axis"; +import { getOrbitalPeriod, Orbit } from "../../orbit/orbit"; +import { clamp } from "terrain-generation"; import { newSeededRingsModel, RingsModel } from "../../rings/ringsModel"; -import { CloudsModel, newCloudsModel } from "../../clouds/cloudsModel"; -import { GenerationSteps } from "../../utils/generationSteps"; - -import { getRngFromSeed } from "../../utils/getRngFromSeed"; -import { OrbitalObjectType } from "../../architecture/orbitalObject"; -import { waterBoilingPointCelsius } from "../../utils/physics"; - -export type TelluricPlanetModel = PlanetModel & { - readonly type: OrbitalObjectType.TELLURIC_PLANET | OrbitalObjectType.TELLURIC_SATELLITE; - - readonly physics: TelluricPlanetPhysicalProperties; +import { TelluricPlanetaryMassObjectModel } from "./telluricPlanetaryMassObjectModel"; - readonly terrainSettings: TerrainSettings; - - readonly clouds: CloudsModel | null; -}; - -export function hasLiquidWater(telluricPlanetModel: TelluricPlanetModel): boolean { - return telluricPlanetModel.physics.oceanLevel > 0; -} +export type TelluricPlanetModel = PlanetModel & + TelluricPlanetaryMassObjectModel & { + readonly type: OrbitalObjectType.TELLURIC_PLANET; + }; export function newSeededTelluricPlanetModel(seed: number, name: string, parentBodies: CelestialBodyModel[]): TelluricPlanetModel { const rng = getRngFromSeed(seed); - const isSatelliteOfTelluric = parentBodies.some((parent) => parent.type === OrbitalObjectType.TELLURIC_PLANET); - const isSatelliteOfGas = parentBodies.some((parent) => parent.type === OrbitalObjectType.GAS_PLANET); - const isSatellite = isSatelliteOfTelluric || isSatelliteOfGas; - - let radius: number; - if (isSatelliteOfTelluric) { - radius = Math.max(0.03, normalRandom(0.06, 0.03, rng, GenerationSteps.RADIUS)) * Settings.EARTH_RADIUS; - } else if (isSatelliteOfGas) { - radius = Math.max(0.03, normalRandom(0.25, 0.15, rng, GenerationSteps.RADIUS)) * Settings.EARTH_RADIUS; - } else { - radius = Math.max(0.3, normalRandom(1.0, 0.1, rng, GenerationSteps.RADIUS)) * Settings.EARTH_RADIUS; - } + const radius = Math.max(0.3, normalRandom(1.0, 0.1, rng, GenerationSteps.RADIUS)) * Settings.EARTH_RADIUS; //TODO: make mass dependent on more physical properties like density - let mass; - if (isSatelliteOfTelluric) { - //FIXME: when Settings.Earth radius gets to 1:1 scale, change this value by a variable in settings - mass = Settings.MOON_MASS * (radius / 1_735e3) ** 3; - } else { - //FIXME: when Settings.Earth radius gets to 1:1 scale, change this value by a variable in settings - mass = Settings.EARTH_MASS * (radius / 6_371e3) ** 3; - } + const mass = Settings.EARTH_MASS * (radius / 6_371e3) ** 3; - const pressure = Math.max(normalRandom(0.9, 0.2, rng, GenerationSteps.PRESSURE), 0); + let pressure = Math.max(normalRandom(0.9, 0.2, rng, GenerationSteps.PRESSURE), 0); + if (radius <= 0.3 * Settings.EARTH_RADIUS) pressure = 0; //TODO: use distance to star to determine min temperature when using 1:1 scale const minTemperature = Math.max(-273, normalRandom(-20, 30, rng, 80)); // when pressure is close to 1, the max temperature is close to the min temperature (the atmosphere does thermal regulation) const maxTemperature = minTemperature + Math.exp(-pressure) * randRangeInt(30, 200, rng, 81); - const physicalProperties: TelluricPlanetPhysicalProperties = { + const physicalProperties: TelluricPlanetaryMassObjectPhysicsInfo = { mass: mass, axialTilt: normalRandom(0, 0.2, rng, GenerationSteps.AXIAL_TILT), rotationPeriod: (60 * 60 * 24) / 10, @@ -92,24 +65,23 @@ export function newSeededTelluricPlanetModel(seed: number, name: string, parentB oceanLevel: 0 }; - const isOrbitalPlaneAlignedWithParent = isSatelliteOfGas && uniformRandBool(0.05, rng, GenerationSteps.ORBITAL_PLANE_ALIGNMENT); - const orbitalPlaneNormal = isOrbitalPlaneAlignedWithParent - ? Vector3.Up() - : Vector3.Up().applyRotationQuaternionInPlace(Quaternion.RotationAxis(Axis.X, (rng(GenerationSteps.ORBIT + 20) - 0.5) * 0.2)); + physicalProperties.oceanLevel = Settings.OCEAN_DEPTH * physicalProperties.waterAmount * physicalProperties.pressure; - // Todo: do not hardcode - let orbitRadius = 2e9 + rng(GenerationSteps.ORBIT) * 15e9; + const canHaveLiquidWater = hasLiquidWater(physicalProperties.pressure, physicalProperties.minTemperature, physicalProperties.maxTemperature); + if (!canHaveLiquidWater) physicalProperties.oceanLevel = 0; - const orbitalP = 2; //clamp(normalRandom(2.0, 0.3, this.rng, GenerationSteps.Orbit + 80), 0.7, 3.0); + let clouds: CloudsModel | null = null; + if (physicalProperties.oceanLevel > 0) { + clouds = newCloudsModel(radius + physicalProperties.oceanLevel, Settings.CLOUD_LAYER_HEIGHT, physicalProperties.waterAmount, physicalProperties.pressure); + } + + const orbitalPlaneNormal = Vector3.Up().applyRotationQuaternionInPlace(Quaternion.RotationAxis(Axis.X, (rng(GenerationSteps.ORBIT + 20) - 0.5) * 0.2)); const parentMaxRadius = parentBodies.reduce((max, body) => Math.max(max, body.radius), 0); + // Todo: do not hardcode + const orbitRadius = 2e9 + rng(GenerationSteps.ORBIT) * 15e9 + parentMaxRadius * 1.5; - if (isSatelliteOfGas || isSatelliteOfTelluric) { - const minRadius = parentMaxRadius; - orbitRadius = minRadius * clamp(normalRandom(2.0, 0.3, rng, GenerationSteps.ORBIT), 1.2, 3.0); - orbitRadius += minRadius * clamp(normalRandom(10, 4, rng, GenerationSteps.ORBIT), 1, 50); - orbitRadius += 2.0 * Math.max(0, minRadius - getPeriapsis(orbitRadius, orbitalP)); - } else if (parentBodies) orbitRadius += parentMaxRadius * 1.5; + const orbitalP = 2; //clamp(normalRandom(2.0, 0.3, this.rng, GenerationSteps.Orbit + 80), 0.7, 3.0); const parentMassSum = parentBodies.reduce((sum, body) => sum + body.physics.mass, 0); const orbit: Orbit = { @@ -119,36 +91,6 @@ export function newSeededTelluricPlanetModel(seed: number, name: string, parentB normalToPlane: orbitalPlaneNormal }; - if (isSatelliteOfTelluric || isSatelliteOfGas) { - // Tidal locking for moons - physicalProperties.rotationPeriod = orbit.period; - } - - if (isSatelliteOfTelluric) { - physicalProperties.pressure = Math.max(normalRandom(0.01, 0.01, rng, GenerationSteps.PRESSURE), 0); - } - if (radius <= 0.3 * Settings.EARTH_RADIUS) physicalProperties.pressure = 0; - - physicalProperties.oceanLevel = Settings.OCEAN_DEPTH * physicalProperties.waterAmount * physicalProperties.pressure; - - const waterBoilingPoint = waterBoilingPointCelsius(physicalProperties.pressure); - const waterFreezingPoint = 0.0; - const epsilon = 0.05; - if (physicalProperties.pressure > epsilon) { - // if temperature is too high, there is no ocean (desert world) - if (physicalProperties.maxTemperature > waterBoilingPoint) physicalProperties.oceanLevel = 0; - // if temperature is too low, there is no ocean (frozen world) - if (physicalProperties.maxTemperature < waterFreezingPoint) physicalProperties.oceanLevel = 0; - } else { - // if pressure is too low, there is no ocean (sterile world) - physicalProperties.oceanLevel = 0; - } - - let clouds: CloudsModel | null = null; - if (physicalProperties.oceanLevel > 0) { - clouds = newCloudsModel(radius + physicalProperties.oceanLevel, Settings.CLOUD_LAYER_HEIGHT, physicalProperties.waterAmount, physicalProperties.pressure); - } - const terrainSettings = { continents_frequency: radius / Settings.EARTH_RADIUS, continents_fragmentation: clamp(normalRandom(0.65, 0.03, rng, GenerationSteps.TERRAIN), 0, 0.95), @@ -162,20 +104,10 @@ export function newSeededTelluricPlanetModel(seed: number, name: string, parentB mountains_frequency: (60 * radius) / 1000e3 }; - if (isSatelliteOfTelluric) { - terrainSettings.continents_fragmentation = 0; - } - if (isSatelliteOfGas && physicalProperties.pressure === 0) { - terrainSettings.continents_fragmentation = 0; - } - - let rings: RingsModel | null = null; - if (uniformRandBool(0.6, rng, GenerationSteps.RINGS) && !isSatelliteOfTelluric && !isSatelliteOfGas) { - rings = newSeededRingsModel(rng); - } + const rings: RingsModel | null = uniformRandBool(0.6, rng, GenerationSteps.RINGS) ? newSeededRingsModel(rng) : null; return { - type: isSatellite ? OrbitalObjectType.TELLURIC_SATELLITE : OrbitalObjectType.TELLURIC_PLANET, + type: OrbitalObjectType.TELLURIC_PLANET, seed: seed, name, radius: radius, @@ -185,4 +117,4 @@ export function newSeededTelluricPlanetModel(seed: number, name: string, parentB rings: rings, clouds: clouds }; -} +} \ No newline at end of file diff --git a/src/ts/planets/telluricPlanet/telluricPlanetaryMassObjectModel.ts b/src/ts/planets/telluricPlanet/telluricPlanetaryMassObjectModel.ts new file mode 100644 index 000000000..234be1f6a --- /dev/null +++ b/src/ts/planets/telluricPlanet/telluricPlanetaryMassObjectModel.ts @@ -0,0 +1,29 @@ +// This file is part of Cosmos Journeyer +// +// Copyright (C) 2024 Barthélemy Paléologue +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +import { TerrainSettings } from "./terrain/terrainSettings"; +import { PlanetaryMassObjectModel } from "../../architecture/planetaryMassObject"; +import { TelluricPlanetaryMassObjectPhysicsInfo } from "../../architecture/physicsInfo"; +import { CloudsModel } from "../../clouds/cloudsModel"; + +export type TelluricPlanetaryMassObjectModel = PlanetaryMassObjectModel & { + readonly physics: TelluricPlanetaryMassObjectPhysicsInfo; + + readonly terrainSettings: TerrainSettings; + + readonly clouds: CloudsModel | null; +}; diff --git a/src/ts/planets/telluricPlanet/telluricSatelliteModel.ts b/src/ts/planets/telluricPlanet/telluricSatelliteModel.ts new file mode 100644 index 000000000..2c70d7071 --- /dev/null +++ b/src/ts/planets/telluricPlanet/telluricSatelliteModel.ts @@ -0,0 +1,142 @@ +// This file is part of Cosmos Journeyer +// +// Copyright (C) 2024 Barthélemy Paléologue +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +import { OrbitalObjectType } from "../../architecture/orbitalObject"; +import { CelestialBodyModel } from "../../architecture/celestialBody"; +import { getRngFromSeed } from "../../utils/getRngFromSeed"; +import { normalRandom, randRangeInt } from "extended-random"; +import { GenerationSteps } from "../../utils/generationSteps"; +import { Settings } from "../../settings"; +import { TelluricPlanetaryMassObjectPhysicsInfo } from "../../architecture/physicsInfo"; +import { Vector3 } from "@babylonjs/core/Maths/math.vector"; +import { Quaternion } from "@babylonjs/core/Maths/math"; +import { Axis } from "@babylonjs/core/Maths/math.axis"; +import { clamp } from "terrain-generation"; +import { getOrbitalPeriod, getPeriapsis, Orbit } from "../../orbit/orbit"; +import { hasLiquidWater } from "../../utils/physics"; +import { CloudsModel, newCloudsModel } from "../../clouds/cloudsModel"; +import { TelluricPlanetaryMassObjectModel } from "./telluricPlanetaryMassObjectModel"; + +export type TelluricSatelliteModel = TelluricPlanetaryMassObjectModel & { + readonly type: OrbitalObjectType.TELLURIC_SATELLITE; +}; + +export function newSeededTelluricSatelliteModel(seed: number, name: string, parentBodies: CelestialBodyModel[]): TelluricSatelliteModel { + const rng = getRngFromSeed(seed); + + const isSatelliteOfTelluric = parentBodies.some((parent) => parent.type === OrbitalObjectType.TELLURIC_PLANET); + const isSatelliteOfGas = parentBodies.some((parent) => parent.type === OrbitalObjectType.GAS_PLANET); + + let radius: number; + if (isSatelliteOfTelluric) { + radius = Math.max(0.03, normalRandom(0.06, 0.03, rng, GenerationSteps.RADIUS)) * Settings.EARTH_RADIUS; + } else if (isSatelliteOfGas) { + radius = Math.max(0.03, normalRandom(0.25, 0.15, rng, GenerationSteps.RADIUS)) * Settings.EARTH_RADIUS; + } else { + throw new Error("Satellite is not around telluric or gas planet. Something is missing!"); + } + + //TODO: make mass dependent on more physical properties like density + let mass; + if (isSatelliteOfTelluric) { + //FIXME: when Settings.Earth radius gets to 1:1 scale, change this value by a variable in settings + mass = Settings.MOON_MASS * (radius / 1_735e3) ** 3; + } else { + //FIXME: when Settings.Earth radius gets to 1:1 scale, change this value by a variable in settings + mass = Settings.EARTH_MASS * (radius / 6_371e3) ** 3; + } + + let pressure = Math.max(normalRandom(0.9, 0.2, rng, GenerationSteps.PRESSURE), 0); + if (isSatelliteOfTelluric || radius <= 0.3 * Settings.EARTH_RADIUS) { + pressure = 0; + } + + //TODO: use distance to star to determine min temperature when using 1:1 scale + const minTemperature = Math.max(-273, normalRandom(-20, 30, rng, 80)); + // when pressure is close to 1, the max temperature is close to the min temperature (the atmosphere does thermal regulation) + const maxTemperature = minTemperature + Math.exp(-pressure) * randRangeInt(30, 200, rng, 81); + + const physicalProperties: TelluricPlanetaryMassObjectPhysicsInfo = { + mass: mass, + axialTilt: 0, + rotationPeriod: (60 * 60 * 24) / 10, + minTemperature: minTemperature, + maxTemperature: maxTemperature, + pressure: pressure, + waterAmount: Math.max(normalRandom(1.0, 0.3, rng, GenerationSteps.WATER_AMOUNT), 0), + oceanLevel: 0 + }; + + physicalProperties.oceanLevel = Settings.OCEAN_DEPTH * physicalProperties.waterAmount * physicalProperties.pressure; + + const orbitalPlaneNormal = Vector3.Up().applyRotationQuaternionInPlace(Quaternion.RotationAxis(Axis.X, (rng(GenerationSteps.ORBIT + 20) - 0.5) * 0.2)); + + // Todo: do not hardcode + let orbitRadius = 2e9 + rng(GenerationSteps.ORBIT) * 15e9; + + const orbitalP = 2; //clamp(normalRandom(2.0, 0.3, this.rng, GenerationSteps.Orbit + 80), 0.7, 3.0); + + const parentMaxRadius = parentBodies.reduce((max, body) => Math.max(max, body.radius), 0); + + orbitRadius = parentMaxRadius * clamp(normalRandom(2.0, 0.3, rng, GenerationSteps.ORBIT), 1.2, 3.0); + orbitRadius += parentMaxRadius * clamp(normalRandom(10, 4, rng, GenerationSteps.ORBIT), 1, 50); + orbitRadius += 2.0 * Math.max(0, parentMaxRadius - getPeriapsis(orbitRadius, orbitalP)); + + const parentMassSum = parentBodies.reduce((sum, body) => sum + body.physics.mass, 0); + const orbit: Orbit = { + radius: orbitRadius, + p: orbitalP, + period: getOrbitalPeriod(orbitRadius, parentMassSum), + normalToPlane: orbitalPlaneNormal + }; + + // tidal lock + physicalProperties.rotationPeriod = orbit.period; + + const canHaveLiquidWater = hasLiquidWater(physicalProperties.pressure, physicalProperties.minTemperature, physicalProperties.maxTemperature); + if (!canHaveLiquidWater) physicalProperties.oceanLevel = 0; + + const clouds: CloudsModel | null = + physicalProperties.oceanLevel > 0 + ? newCloudsModel(radius + physicalProperties.oceanLevel, Settings.CLOUD_LAYER_HEIGHT, physicalProperties.waterAmount, physicalProperties.pressure) + : null; + + const terrainSettings = { + continents_frequency: radius / Settings.EARTH_RADIUS, + continents_fragmentation: physicalProperties.pressure > 0 ? clamp(normalRandom(0.65, 0.03, rng, GenerationSteps.TERRAIN), 0, 0.95) : 0, + + bumps_frequency: (30 * radius) / Settings.EARTH_RADIUS, + + max_bump_height: 1.5e3, + max_mountain_height: 10e3, + continent_base_height: 5e3 + physicalProperties.oceanLevel * 1.9, + + mountains_frequency: (60 * radius) / 1000e3 + }; + + return { + type: OrbitalObjectType.TELLURIC_SATELLITE, + seed: seed, + name, + radius: radius, + physics: physicalProperties, + orbit: orbit, + terrainSettings: terrainSettings, + rings: null, + clouds: clouds + }; +} \ No newline at end of file diff --git a/src/ts/planets/telluricPlanet/terrain/chunks/chunkTree.ts b/src/ts/planets/telluricPlanet/terrain/chunks/chunkTree.ts index 616d9f1af..9e36cf7b7 100644 --- a/src/ts/planets/telluricPlanet/terrain/chunks/chunkTree.ts +++ b/src/ts/planets/telluricPlanet/terrain/chunks/chunkTree.ts @@ -21,7 +21,7 @@ import { BuildTask, TaskType } from "./taskTypes"; import { Settings } from "../../../../settings"; import { getChunkSphereSpacePositionFromPath } from "../../../../utils/chunkUtils"; import { TerrainSettings } from "../terrainSettings"; -import { TelluricPlanetModel } from "../../telluricPlanetModel"; +import { TelluricPlanetaryMassObjectModel } from "../../telluricPlanetaryMassObjectModel"; import { Material } from "@babylonjs/core/Materials/material"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; import { PhysicsAggregate } from "@babylonjs/core/Physics/v2/physicsAggregate"; @@ -56,7 +56,7 @@ export class ChunkTree implements Cullable { private deleteSemaphores: DeleteSemaphore[] = []; - readonly planetModel: TelluricPlanetModel; + readonly planetModel: TelluricPlanetaryMassObjectModel; readonly planetName: string; readonly planetSeed: number; @@ -75,7 +75,7 @@ export class ChunkTree implements Cullable { * @param material * @param scene */ - constructor(direction: Direction, planetModel: TelluricPlanetModel, parentAggregate: PhysicsAggregate, material: Material, scene: Scene) { + constructor(direction: Direction, planetModel: TelluricPlanetaryMassObjectModel, parentAggregate: PhysicsAggregate, material: Material, scene: Scene) { this.rootChunkLength = planetModel.radius * 2; this.planetName = planetModel.name; this.planetSeed = planetModel.seed; diff --git a/src/ts/planets/telluricPlanet/terrain/chunks/planetChunk.ts b/src/ts/planets/telluricPlanet/terrain/chunks/planetChunk.ts index 4956815af..a241a30cc 100644 --- a/src/ts/planets/telluricPlanet/terrain/chunks/planetChunk.ts +++ b/src/ts/planets/telluricPlanet/terrain/chunks/planetChunk.ts @@ -29,7 +29,7 @@ import { randomDownSample } from "../instancePatch/matrixBuffer"; import { isSizeOnScreenEnough } from "../../../../utils/isObjectVisibleOnScreen"; import { Camera } from "@babylonjs/core/Cameras/camera"; import { IPatch } from "../instancePatch/iPatch"; -import { TelluricPlanetModel } from "../../telluricPlanetModel"; +import { TelluricPlanetaryMassObjectModel } from "../../telluricPlanetaryMassObjectModel"; import { HasBoundingSphere } from "../../../../architecture/hasBoundingSphere"; import { PhysicsMotionType, PhysicsShapeType } from "@babylonjs/core/Physics/v2/IPhysicsEnginePlugin"; import { Transformable } from "../../../../architecture/transformable"; @@ -45,7 +45,7 @@ export class PlanetChunk implements Transformable, HasBoundingSphere, Cullable { public readonly cubePosition: Vector3; private readonly planetLocalPosition: Vector3; - private readonly planetModel: TelluricPlanetModel; + private readonly planetModel: TelluricPlanetaryMassObjectModel; private readonly chunkSideLength: number; @@ -63,7 +63,7 @@ export class PlanetChunk implements Transformable, HasBoundingSphere, Cullable { private disposed = false; - constructor(path: number[], direction: Direction, parentAggregate: PhysicsAggregate, material: Material, planetModel: TelluricPlanetModel, rootLength: number, scene: Scene) { + constructor(path: number[], direction: Direction, parentAggregate: PhysicsAggregate, material: Material, planetModel: TelluricPlanetaryMassObjectModel, rootLength: number, scene: Scene) { const id = `D${direction}P${path.join("")}`; this.depth = path.length; diff --git a/src/ts/postProcesses/lensFlarePostProcess.ts b/src/ts/postProcesses/lensFlarePostProcess.ts index 43b4753b0..86efb0821 100644 --- a/src/ts/postProcesses/lensFlarePostProcess.ts +++ b/src/ts/postProcesses/lensFlarePostProcess.ts @@ -74,7 +74,7 @@ export class LensFlarePostProcess extends PostProcess implements ObjectPostProce this.object = object; this.settings = settings; - const flareColor = getRgbFromTemperature(object.model.physics.temperature); + const flareColor = getRgbFromTemperature(object.model.physics.blackBodyTemperature); this.onActivateObservable.add((camera) => { this.activeCamera = camera; diff --git a/src/ts/postProcesses/matterJetPostProcess.ts b/src/ts/postProcesses/matterJetPostProcess.ts index 133fb272a..3a8c73d06 100644 --- a/src/ts/postProcesses/matterJetPostProcess.ts +++ b/src/ts/postProcesses/matterJetPostProcess.ts @@ -43,7 +43,7 @@ export class MatterJetPostProcess extends PostProcess implements ObjectPostProce private activeCamera: Camera | null = null; - constructor(name: string, stellarObject: StellarObject, scene: Scene) { + constructor(stellarObject: StellarObject, scene: Scene) { const shaderName = "matterjet"; if (Effect.ShadersStore[`${shaderName}FragmentShader`] === undefined) { Effect.ShadersStore[`${shaderName}FragmentShader`] = matterJetFragment; @@ -64,7 +64,7 @@ export class MatterJetPostProcess extends PostProcess implements ObjectPostProce const samplers: string[] = Object.values(SamplerUniformNames); - super(name, shaderName, uniforms, samplers, 1, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, null, Constants.TEXTURETYPE_HALF_FLOAT); + super(`${stellarObject.model.name}MatterJetPostProcess`, shaderName, uniforms, samplers, 1, null, Texture.BILINEAR_SAMPLINGMODE, scene.getEngine(), false, null, Constants.TEXTURETYPE_HALF_FLOAT); this.object = stellarObject; this.matterJetUniforms = settings; diff --git a/src/ts/postProcesses/postProcessManager.ts b/src/ts/postProcesses/postProcessManager.ts index 8d9aa6e49..8be542327 100644 --- a/src/ts/postProcesses/postProcessManager.ts +++ b/src/ts/postProcesses/postProcessManager.ts @@ -53,7 +53,7 @@ import { PostProcess } from "@babylonjs/core/PostProcesses/postProcess"; import { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh"; import { BloomEffect } from "@babylonjs/core/PostProcesses/bloomEffect"; import { Constants } from "@babylonjs/core/Engines/constants"; -import { Planet } from "../architecture/planet"; +import { PlanetaryMassObject } from "../architecture/planetaryMassObject"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; /** @@ -266,7 +266,7 @@ export class PostProcessManager { * Returns the atmosphere post process for the given planet. Throws an error if no atmosphere is found. * @param planet A gas or telluric planet */ - public getAtmosphere(planet: Planet): AtmosphericScatteringPostProcess | null { + public getAtmosphere(planet: PlanetaryMassObject): AtmosphericScatteringPostProcess | null { return this.atmospheres.find((atmosphere) => atmosphere.object === planet) ?? null; } @@ -293,8 +293,7 @@ export class PostProcessManager { * @param stellarObjects An array of stars or black holes */ public addMandelbulb(body: Mandelbulb, stellarObjects: StellarObject[]) { - const mandelbulb = new MandelbulbPostProcess(body, this.scene, stellarObjects); - this.mandelbulbs.push(mandelbulb); + this.mandelbulbs.push(new MandelbulbPostProcess(body, this.scene, stellarObjects)); } /** @@ -303,8 +302,7 @@ export class PostProcessManager { * @param stellarObjects An array of stars or black holes */ public addJuliaSet(juliaSet: JuliaSet, stellarObjects: StellarObject[]) { - const juliaSetPostProcess = new JuliaSetPostProcess(juliaSet, this.scene, stellarObjects); - this.juliaSets.push(juliaSetPostProcess); + this.juliaSets.push(new JuliaSetPostProcess(juliaSet, this.scene, stellarObjects)); } /** @@ -329,8 +327,7 @@ export class PostProcessManager { * @param blackHole A black hole */ public addBlackHole(blackHole: BlackHole) { - const blackhole = new BlackHolePostProcess(blackHole, this.scene); - this.blackHoles.push(blackhole); + this.blackHoles.push(new BlackHolePostProcess(blackHole, this.scene)); } /** @@ -346,8 +343,7 @@ export class PostProcessManager { * @param neutronStar A neutron star */ public addMatterJet(neutronStar: NeutronStar) { - console.log("add matter jet"); - this.matterJets.push(new MatterJetPostProcess(neutronStar.name, neutronStar, this.scene)); + this.matterJets.push(new MatterJetPostProcess(neutronStar, this.scene)); } /** @@ -381,7 +377,7 @@ export class PostProcessManager { * This method will also choose the appropriate rendering order and rebuild the pipeline. * @param body The closest celestial body to the active camera */ - public setBody(body: CelestialBody) { + public setCelestialBody(body: CelestialBody) { this.currentBody = body; const rings = this.getRings(body); diff --git a/src/ts/postProcesses/shadowPostProcess.ts b/src/ts/postProcesses/shadowPostProcess.ts index 5927d7fa2..873f0071a 100644 --- a/src/ts/postProcesses/shadowPostProcess.ts +++ b/src/ts/postProcesses/shadowPostProcess.ts @@ -52,7 +52,7 @@ export class ShadowPostProcess extends PostProcess implements ObjectPostProcess } const shadowUniforms: ShadowUniforms = { - hasRings: body.getRingsUniforms() !== null, + hasRings: body.ringsUniforms !== null, hasClouds: body.postProcesses.includes(PostProcessType.CLOUDS), hasOcean: body.postProcesses.includes(PostProcessType.OCEAN) }; @@ -90,7 +90,7 @@ export class ShadowPostProcess extends PostProcess implements ObjectPostProcess this.object = body; this.shadowUniforms = shadowUniforms; - this.ringsUniforms = body.getRingsUniforms(); + this.ringsUniforms = body.ringsUniforms; this.onActivateObservable.add((camera) => { this.activeCamera = camera; diff --git a/src/ts/postProcesses/uniforms/stellarObjectUniforms.ts b/src/ts/postProcesses/uniforms/stellarObjectUniforms.ts index 0a056d01f..19130b4b7 100644 --- a/src/ts/postProcesses/uniforms/stellarObjectUniforms.ts +++ b/src/ts/postProcesses/uniforms/stellarObjectUniforms.ts @@ -41,6 +41,6 @@ export function setStellarObjectUniforms(effect: Effect, stellarObjects: Transfo effect.setArray3(StellarObjectUniformNames.STAR_POSITIONS, flattenVector3Array(stellarObjects.map((stellarObject) => stellarObject.getTransform().getAbsolutePosition()))); effect.setArray3( StellarObjectUniformNames.STAR_COLORS, - flattenColor3Array(stellarObjects.map((stellarObject) => (stellarObject instanceof Star ? getRgbFromTemperature(stellarObject.model.physics.temperature) : Color3.White()))) + flattenColor3Array(stellarObjects.map((stellarObject) => (stellarObject instanceof Star ? getRgbFromTemperature(stellarObject.model.physics.blackBodyTemperature) : Color3.White()))) ); } diff --git a/src/ts/rings/ringsPostProcess.ts b/src/ts/rings/ringsPostProcess.ts index c6f313f1e..9c4078453 100644 --- a/src/ts/rings/ringsPostProcess.ts +++ b/src/ts/rings/ringsPostProcess.ts @@ -43,7 +43,7 @@ export class RingsPostProcess extends PostProcess implements ObjectPostProcess { Effect.ShadersStore[`${shaderName}FragmentShader`] = ringsFragment; } - const ringsUniforms = body.getRingsUniforms(); + const ringsUniforms = body.ringsUniforms; if (ringsUniforms === null) { throw new Error( `RingsPostProcess: ringsUniforms are null. This should not be possible as the postprocess should not be created if the body has no rings. Body: ${body.model.name}` diff --git a/src/ts/spaceship/spaceship.ts b/src/ts/spaceship/spaceship.ts index 32497f0d6..b950f1f9d 100644 --- a/src/ts/spaceship/spaceship.ts +++ b/src/ts/spaceship/spaceship.ts @@ -420,7 +420,7 @@ export class Spaceship implements Transformable { let canEngage = true; if (this.nearestCelestialBody !== null) { // if the spaceship goes too close to planetary rings, stop the warp drive to avoid collision with asteroids - const asteroidField = this.nearestCelestialBody.getAsteroidField(); + const asteroidField = this.nearestCelestialBody.asteroidField; if (asteroidField !== null) { const relativePosition = this.getTransform().getAbsolutePosition().subtract(this.nearestCelestialBody.getTransform().getAbsolutePosition()); @@ -464,7 +464,7 @@ export class Spaceship implements Transformable { if (this.nearestCelestialBody !== null) { // if the spaceship goes too close to planetary rings, stop the warp drive to avoid collision with asteroids - const asteroidField = this.nearestCelestialBody.getAsteroidField(); + const asteroidField = this.nearestCelestialBody.asteroidField; if (asteroidField !== null) { const relativePosition = this.getTransform().getAbsolutePosition().subtract(this.nearestCelestialBody.getTransform().getAbsolutePosition()); diff --git a/src/ts/spacestation/spacestationModel.ts b/src/ts/spacestation/spacestationModel.ts index 8d5f262b6..83d601ef2 100644 --- a/src/ts/spacestation/spacestationModel.ts +++ b/src/ts/spacestation/spacestationModel.ts @@ -18,7 +18,7 @@ import { getOrbitalPeriod, Orbit } from "../orbit/orbit"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; import { OrbitalObjectModel, OrbitalObjectType } from "../architecture/orbitalObject"; -import { OrbitalObjectPhysicalProperties } from "../architecture/physicalProperties"; +import { OrbitalObjectPhysicsInfo } from "../architecture/physicsInfo"; import { CelestialBodyModel } from "../architecture/celestialBody"; import { normalRandom, uniformRandBool } from "extended-random"; import { clamp } from "../utils/math"; @@ -94,7 +94,7 @@ export function newSeededSpaceStationModel( normalToPlane: Vector3.Up() }; - const physicalProperties: OrbitalObjectPhysicalProperties = { + const physicalProperties: OrbitalObjectPhysicsInfo = { mass: 1, rotationPeriod: 0, axialTilt: 2 * rng(GenerationSteps.AXIAL_TILT) * Math.PI @@ -138,7 +138,7 @@ export function newSeededSpaceStationModel( stellarObjectModels.forEach((stellarObject) => { const exposureTimeFraction = 0.5; const starRadius = stellarObject.radius; - const starTemperature = stellarObject.physics.temperature; + const starTemperature = stellarObject.physics.blackBodyTemperature; totalStellarFlux += getSphereRadiatedEnergyFlux(starTemperature, starRadius, distanceToStar) * exposureTimeFraction; }); diff --git a/src/ts/starSystem/seededStarSystemModel.ts b/src/ts/starSystem/seededStarSystemModel.ts index ce2108fd9..b33649fc1 100644 --- a/src/ts/starSystem/seededStarSystemModel.ts +++ b/src/ts/starSystem/seededStarSystemModel.ts @@ -29,7 +29,6 @@ import { Alphabet, ReversedGreekAlphabet } from "../utils/strings/parseToStrings import { newSeededStarModel } from "../stellarObjects/star/starModel"; import { newSeededBlackHoleModel } from "../stellarObjects/blackHole/blackHoleModel"; import { newSeededNeutronStarModel } from "../stellarObjects/neutronStar/neutronStarModel"; -import { newSeededTelluricPlanetModel } from "../planets/telluricPlanet/telluricPlanetModel"; import { newSeededGasPlanetModel } from "../planets/gasPlanet/gasPlanetModel"; import { newSeededMandelbulbModel } from "../anomalies/mandelbulb/mandelbulbModel"; import { newSeededJuliaSetModel } from "../anomalies/julia/juliaSetModel"; @@ -39,6 +38,8 @@ import { newSeededSpaceStationModel } from "../spacestation/spacestationModel"; import { SystemSeed } from "./systemSeed"; import { isSystemInHumanBubble } from "../society/starSystemSociety"; import { OrbitalObjectType } from "../architecture/orbitalObject"; +import { newSeededTelluricSatelliteModel } from "../planets/telluricPlanet/telluricSatelliteModel"; +import { newSeededTelluricPlanetModel } from "../planets/telluricPlanet/telluricPlanetModel"; const enum GenerationSteps { NAME, @@ -144,7 +145,7 @@ export function newSeededStarSystemModel(seed: SystemSeed): StarSystemModel { for (let j = 0; j < nbMoons; j++) { const satelliteName = `${planetarySystemName}${Alphabet[j]}`; const satelliteSeed = centeredRand(planetarySystemRng, GenerationSteps.MOONS + j) * Settings.SEED_HALF_RANGE; - const satelliteModel = newSeededTelluricPlanetModel(satelliteSeed, satelliteName, planets); + const satelliteModel = newSeededTelluricSatelliteModel(satelliteSeed, satelliteName, planets); satellites.push(satelliteModel); } }); diff --git a/src/ts/starSystem/starSystemController.ts b/src/ts/starSystem/starSystemController.ts index 7f9e45f7b..908d44b86 100644 --- a/src/ts/starSystem/starSystemController.ts +++ b/src/ts/starSystem/starSystemController.ts @@ -32,14 +32,13 @@ import { ChunkForge } from "../planets/telluricPlanet/terrain/chunks/chunkForge" import { OrbitalObject, OrbitalObjectType, OrbitalObjectUtils } from "../architecture/orbitalObject"; import { CelestialBody } from "../architecture/celestialBody"; import { StellarObject } from "../architecture/stellarObject"; -import { Planet } from "../architecture/planet"; +import { PlanetaryMassObject } from "../architecture/planetaryMassObject"; import { SystemTarget } from "../utils/systemTarget"; import { JuliaSet } from "../anomalies/julia/juliaSet"; import { StarFieldBox } from "./starFieldBox"; import { PlanetarySystemModel, StarSystemModel, SubStarSystemModel } from "./starSystemModel"; import { Settings } from "../settings"; import { getStarGalacticPosition } from "../utils/coordinates/starSystemCoordinatesUtils"; -import { TelluricPlanetModel } from "../planets/telluricPlanet/telluricPlanetModel"; import { GasPlanetModel } from "../planets/gasPlanet/gasPlanetModel"; import { MandelbulbModel } from "../anomalies/mandelbulb/mandelbulbModel"; import { JuliaSetModel } from "../anomalies/julia/juliaSetModel"; @@ -48,6 +47,8 @@ import { NeutronStarModel } from "../stellarObjects/neutronStar/neutronStarModel import { BlackHoleModel } from "../stellarObjects/blackHole/blackHoleModel"; import { StarSystemCoordinates } from "../utils/coordinates/universeCoordinates"; import { wait } from "../utils/wait"; +import { Planet } from "../architecture/planet"; +import { TelluricPlanetModel } from "../planets/telluricPlanet/telluricPlanetModel"; export type PlanetarySystem = { readonly planets: Planet[]; @@ -203,15 +204,14 @@ export class StarSystemController { switch (planetModel.type) { case OrbitalObjectType.TELLURIC_PLANET: - planet = new TelluricPlanet(planetModel as TelluricPlanetModel, this.scene); + //FIXME: TelluricPlanet and TelluricSatellite should be 2 different types to avoid casting + planet = new TelluricPlanet(planetModel as TelluricPlanetModel, this.scene) as Planet; this.telluricBodies.push(planet as TelluricPlanet); break; case OrbitalObjectType.GAS_PLANET: planet = new GasPlanet(planetModel as GasPlanetModel, this.scene); this.gasPlanets.push(planet as GasPlanet); break; - case OrbitalObjectType.TELLURIC_SATELLITE: - throw new Error("Telluric satellites must be stored in the satellites array, not in the planets array"); } planet.getTransform().setAbsolutePosition(new Vector3(this.offset * ++this.loadingIndex, 0, 0)); @@ -321,16 +321,16 @@ export class StarSystemController { /** * Returns all the planets in the star system */ - public getPlanets(): Planet[] { + public getPlanets(): PlanetaryMassObject[] { return this.subSystems.flatMap((subSystem) => subSystem.planetarySystems.flatMap((planetarySystem) => planetarySystem.planets)); } /** * Returns all the planetary mass objects in the star system. (Planets first, then satellites) */ - public getPlanetaryMassObjects(): Planet[] { - const planets: Planet[] = []; - const satellites: Planet[] = []; + public getPlanetaryMassObjects(): PlanetaryMassObject[] { + const planets: PlanetaryMassObject[] = []; + const satellites: PlanetaryMassObject[] = []; this.subSystems.forEach((subSystem) => subSystem.planetarySystems.forEach((planetarySystem) => { planets.push(...planetarySystem.planets); @@ -441,7 +441,7 @@ export class StarSystemController { } } - postProcessManager.setBody(this.getNearestCelestialBody(this.scene.getActiveControls().getTransform().getAbsolutePosition())); + postProcessManager.setCelestialBody(this.getNearestCelestialBody(this.scene.getActiveControls().getTransform().getAbsolutePosition())); postProcessManager.rebuild(); } @@ -466,7 +466,7 @@ export class StarSystemController { // The first step is to find the nearest body const nearestOrbitalObject = this.getNearestOrbitalObject(controller.getTransform().getAbsolutePosition()); const nearestCelestialBody = this.getNearestCelestialBody(controller.getTransform().getAbsolutePosition()); - const ringUniforms = nearestCelestialBody.getRingsUniforms(); + const ringUniforms = nearestCelestialBody.ringsUniforms; // Depending on the distance to the nearest body, we might have to compensate its translation and/or rotation // If we are very close, we want both translation and rotation to be compensated, so that the body appears to be fixed @@ -568,7 +568,7 @@ export class StarSystemController { controller.update(deltaSeconds); for (const object of celestialBodies) { - object.getAsteroidField()?.update(controller.getActiveCameras()[0].globalPosition, deltaSeconds); + object.asteroidField?.update(controller.getActiveCameras()[0].globalPosition, deltaSeconds); } for (const body of this.telluricBodies) { @@ -634,7 +634,7 @@ export class StarSystemController { if (stellarObject instanceof Star) stellarObject.updateMaterial(deltaSeconds); } - postProcessManager.setBody(nearestBody); + postProcessManager.setCelestialBody(nearestBody); postProcessManager.update(deltaSeconds); } diff --git a/src/ts/starSystem/starSystemModel.ts b/src/ts/starSystem/starSystemModel.ts index 85c42f002..8ae3c79e4 100644 --- a/src/ts/starSystem/starSystemModel.ts +++ b/src/ts/starSystem/starSystemModel.ts @@ -17,10 +17,11 @@ import { StarSystemCoordinates } from "../utils/coordinates/universeCoordinates"; import { StellarObjectModel } from "../architecture/stellarObject"; -import { PlanetModel } from "../architecture/planet"; +import { PlanetaryMassObjectModel } from "../architecture/planetaryMassObject"; import { AnomalyModel } from "../anomalies/anomaly"; -import { TelluricPlanetModel } from "../planets/telluricPlanet/telluricPlanetModel"; import { SpaceStationModel } from "../spacestation/spacestationModel"; +import { PlanetModel } from "../architecture/planet"; +import { TelluricSatelliteModel } from "../planets/telluricPlanet/telluricSatelliteModel"; /** * Data model for a planetary system. It holds all the information necessary to generate and render a planetary system. @@ -37,7 +38,7 @@ export type PlanetarySystemModel = { /** * The satellites of the planet. */ - satellites: TelluricPlanetModel[]; + satellites: TelluricSatelliteModel[]; /** * The space stations orbiting the planet. @@ -122,7 +123,7 @@ export class StarSystemModelUtils { * @param starSystem The star system to get the planets from. * @constructor */ - static GetPlanets(starSystem: StarSystemModel): PlanetModel[] { + static GetPlanets(starSystem: StarSystemModel): PlanetaryMassObjectModel[] { return starSystem.subSystems.flatMap((subSystem) => subSystem.planetarySystems.flatMap((planetarySystem) => planetarySystem.planets)); } @@ -143,9 +144,9 @@ export class StarSystemModelUtils { * @param starSystem The star system to get the planetary mass objects from. * @constructor */ - static GetPlanetaryMassObjects(starSystem: StarSystemModel): PlanetModel[] { - const planets: PlanetModel[] = []; - const satellites: PlanetModel[] = []; + static GetPlanetaryMassObjects(starSystem: StarSystemModel): PlanetaryMassObjectModel[] { + const planets: PlanetaryMassObjectModel[] = []; + const satellites: PlanetaryMassObjectModel[] = []; starSystem.subSystems.forEach((subSystem) => subSystem.planetarySystems.forEach((planetarySystem) => { planets.push(...planetarySystem.planets); diff --git a/src/ts/starmap/starMap.ts b/src/ts/starmap/starMap.ts index 0bb9da8e4..83028e7db 100644 --- a/src/ts/starmap/starMap.ts +++ b/src/ts/starmap/starMap.ts @@ -477,7 +477,7 @@ export class StarMap implements View { initializedInstance.position = data.position.add(this.starMapCenterPosition); - const objectColor = getRgbFromTemperature(stellarObjectModel.physics.temperature); + const objectColor = getRgbFromTemperature(stellarObjectModel.physics.blackBodyTemperature); initializedInstance.instancedBuffers.color = new Color4(objectColor.r, objectColor.g, objectColor.b, 0.0); if (!recycled) { diff --git a/src/ts/starmap/starMapUI.ts b/src/ts/starmap/starMapUI.ts index 095baa9b5..b5d82cd09 100644 --- a/src/ts/starmap/starMapUI.ts +++ b/src/ts/starmap/starMapUI.ts @@ -316,7 +316,7 @@ export class StarMapUI { this.shortHandUISystemType.textContent = orbitalObjectTypeToDisplay(starModel); this.shortHandUIBookmarkButton.setSelectedSystemSeed(targetSystemModel.coordinates); - const objectColor = getRgbFromTemperature(starModel.physics.temperature); + const objectColor = getRgbFromTemperature(starModel.physics.blackBodyTemperature); this.infoPanelStarPreview.style.background = objectColor.toHexString(); this.infoPanelStarPreview.style.boxShadow = `0 0 20px ${objectColor.toHexString()}`; diff --git a/src/ts/stellarObjects/blackHole/blackHole.ts b/src/ts/stellarObjects/blackHole/blackHole.ts index 5f9b8ec82..086f9da5b 100644 --- a/src/ts/stellarObjects/blackHole/blackHole.ts +++ b/src/ts/stellarObjects/blackHole/blackHole.ts @@ -26,8 +26,6 @@ import { BlackHoleModel } from "./blackHoleModel"; import { StellarObject } from "../../architecture/stellarObject"; import { Cullable } from "../../utils/cullable"; import { TransformNode } from "@babylonjs/core/Meshes"; -import { RingsUniforms } from "../../rings/ringsUniform"; -import { AsteroidField } from "../../asteroidFields/asteroidField"; import { orbitalObjectTypeToDisplay } from "../../utils/strings/orbitalObjectTypeToDisplay"; export class BlackHole implements StellarObject, Cullable { @@ -41,6 +39,10 @@ export class BlackHole implements StellarObject, Cullable { readonly postProcesses: PostProcessType[] = []; + readonly ringsUniforms = null; + + readonly asteroidField = null; + constructor(model: BlackHoleModel, scene: Scene) { this.model = model; @@ -70,14 +72,6 @@ export class BlackHole implements StellarObject, Cullable { return this.light; } - getRingsUniforms(): RingsUniforms | null { - return null; - } - - getAsteroidField(): AsteroidField | null { - return null; - } - getTypeName(): string { return orbitalObjectTypeToDisplay(this.model); } diff --git a/src/ts/stellarObjects/blackHole/blackHoleModel.ts b/src/ts/stellarObjects/blackHole/blackHoleModel.ts index be68280a9..419604e87 100644 --- a/src/ts/stellarObjects/blackHole/blackHoleModel.ts +++ b/src/ts/stellarObjects/blackHole/blackHoleModel.ts @@ -18,7 +18,7 @@ import { getOrbitalPeriod, Orbit } from "../../orbit/orbit"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; import { normalRandom } from "extended-random"; -import { BlackHolePhysicalProperties } from "../../architecture/physicalProperties"; +import { BlackHolePhysicsInfo } from "../../architecture/physicsInfo"; import { CelestialBodyModel } from "../../architecture/celestialBody"; import { StellarObjectModel } from "../../architecture/stellarObject"; import { Settings } from "../../settings"; @@ -35,7 +35,7 @@ export type BlackHoleModel = StellarObjectModel & { */ readonly radius: number; - readonly physics: BlackHolePhysicalProperties; + readonly physics: BlackHolePhysicsInfo; }; export function newSeededBlackHoleModel(seed: number, name: string, parentBodies: CelestialBodyModel[]): BlackHoleModel { @@ -57,14 +57,14 @@ export function newSeededBlackHoleModel(seed: number, name: string, parentBodies normalToPlane: Vector3.Up() }; - const physicalProperties: BlackHolePhysicalProperties = { + const physicalProperties: BlackHolePhysicsInfo = { mass: getMassFromSchwarzschildRadius(radius), //FIXME: do not hardcode rotationPeriod: 1.5e-19, axialTilt: normalRandom(0, 0.4, rng, GenerationSteps.AXIAL_TILT), accretionDiskRadius: radius * normalRandom(12, 3, rng, 7777), //TODO: compute temperature of accretion disk (function of rotation speed) - temperature: 7_000 + blackBodyTemperature: 7_000 }; return { @@ -78,15 +78,6 @@ export function newSeededBlackHoleModel(seed: number, name: string, parentBodies }; } -/** - * Returns the Schwarzschild radius of an object given its mass - * @param mass The mass of the object in kilograms - * @returns the Schwarzschild radius of the object in meters - */ -export function getSchwarzschildRadius(mass: number): number { - return (2 * Settings.G * mass) / (Settings.C * Settings.C); -} - /** * Returns the mass a black hole needs to posess a given Schwarzschild radius * @param radius The target radius (in meters) diff --git a/src/ts/stellarObjects/neutronStar/neutronStar.ts b/src/ts/stellarObjects/neutronStar/neutronStar.ts index b30468818..bb2ae88ee 100644 --- a/src/ts/stellarObjects/neutronStar/neutronStar.ts +++ b/src/ts/stellarObjects/neutronStar/neutronStar.ts @@ -32,21 +32,16 @@ import { Light } from "@babylonjs/core/Lights/light"; import { setRotationQuaternion } from "../../uberCore/transforms/basicTransform"; import { Quaternion } from "@babylonjs/core/Maths/math"; import { TransformNode } from "@babylonjs/core/Meshes"; -import { OrbitalObjectPhysicalProperties } from "../../architecture/physicalProperties"; import { RingsUniforms } from "../../rings/ringsUniform"; import { Camera } from "@babylonjs/core/Cameras/camera"; import { isSizeOnScreenEnough } from "../../utils/isObjectVisibleOnScreen"; import { Scene } from "@babylonjs/core/scene"; import { AsteroidField } from "../../asteroidFields/asteroidField"; -import { Orbit } from "../../orbit/orbit"; - import { orbitalObjectTypeToDisplay } from "../../utils/strings/orbitalObjectTypeToDisplay"; export class NeutronStar implements StellarObject, Cullable { readonly model: NeutronStarModel; - readonly name: string; - readonly mesh: Mesh; readonly light: PointLight; @@ -58,7 +53,7 @@ export class NeutronStar implements StellarObject, Cullable { readonly ringsUniforms: RingsUniforms | null; - private readonly asteroidField: AsteroidField | null; + readonly asteroidField: AsteroidField | null; /** * New Star @@ -67,10 +62,9 @@ export class NeutronStar implements StellarObject, Cullable { */ constructor(model: NeutronStarModel, scene: Scene) { this.model = model; - this.name = this.model.name; this.mesh = MeshBuilder.CreateSphere( - this.name, + this.model.name, { diameter: this.model.radius * 2, segments: 32 @@ -93,7 +87,7 @@ export class NeutronStar implements StellarObject, Cullable { this.aggregate.shape.addChildFromParent(this.getTransform(), physicsShape, this.mesh); this.light = new PointLight(`${name}Light`, Vector3.Zero(), scene); - this.light.diffuse.fromArray(getRgbFromTemperature(this.model.physics.temperature).asArray()); + this.light.diffuse.fromArray(getRgbFromTemperature(this.model.physics.blackBodyTemperature).asArray()); this.light.falloffType = Light.FALLOFF_STANDARD; this.light.parent = this.getTransform(); @@ -133,14 +127,6 @@ export class NeutronStar implements StellarObject, Cullable { return this.light; } - getRingsUniforms(): RingsUniforms | null { - return this.ringsUniforms; - } - - getAsteroidField(): AsteroidField | null { - return this.asteroidField; - } - public updateMaterial(deltaTime: number): void { this.material.update(deltaTime); } diff --git a/src/ts/stellarObjects/neutronStar/neutronStarModel.ts b/src/ts/stellarObjects/neutronStar/neutronStarModel.ts index 630379915..25d7e81d6 100644 --- a/src/ts/stellarObjects/neutronStar/neutronStarModel.ts +++ b/src/ts/stellarObjects/neutronStar/neutronStarModel.ts @@ -17,7 +17,7 @@ import { CelestialBodyModel } from "../../architecture/celestialBody"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; -import { StellarObjectPhysicalProperties } from "../../architecture/physicalProperties"; +import { StellarObjectPhysicsInfo } from "../../architecture/physicsInfo"; import { StellarObjectModel } from "../../architecture/stellarObject"; import { getOrbitalPeriod, Orbit } from "../../orbit/orbit"; import { normalRandom, randRangeInt, uniformRandBool } from "extended-random"; @@ -37,10 +37,10 @@ export function newSeededNeutronStarModel(seed: number, name: string, parentBodi const temperature = randRangeInt(200_000, 5_000_000_000, rng, GenerationSteps.TEMPERATURE); - const physicalProperties: StellarObjectPhysicalProperties = { + const physicalProperties: StellarObjectPhysicsInfo = { mass: 1000, rotationPeriod: 24 * 60 * 60, - temperature: temperature, + blackBodyTemperature: temperature, axialTilt: 0 }; diff --git a/src/ts/stellarObjects/star/star.ts b/src/ts/stellarObjects/star/star.ts index e5b5b9d0f..735dc454a 100644 --- a/src/ts/stellarObjects/star/star.ts +++ b/src/ts/stellarObjects/star/star.ts @@ -49,7 +49,7 @@ export class Star implements StellarObject, Cullable { readonly ringsUniforms: RingsUniforms | null; - private readonly asteroidField: AsteroidField | null; + readonly asteroidField: AsteroidField | null; readonly model: StarModel; @@ -83,7 +83,7 @@ export class Star implements StellarObject, Cullable { this.aggregate.body.disablePreStep = false; this.light = new PointLight(`${this.model.name}Light`, Vector3.Zero(), scene); - this.light.diffuse = getRgbFromTemperature(this.model.physics.temperature); + this.light.diffuse = getRgbFromTemperature(this.model.physics.blackBodyTemperature); this.light.falloffType = Light.FALLOFF_STANDARD; this.light.parent = this.getTransform(); @@ -119,14 +119,6 @@ export class Star implements StellarObject, Cullable { return this.light; } - getRingsUniforms(): RingsUniforms | null { - return this.ringsUniforms; - } - - getAsteroidField(): AsteroidField | null { - return this.asteroidField; - } - getTypeName(): string { return orbitalObjectTypeToDisplay(this.model); } diff --git a/src/ts/stellarObjects/star/starMaterial.ts b/src/ts/stellarObjects/star/starMaterial.ts index 510fbdb9d..fbd72e8ab 100644 --- a/src/ts/stellarObjects/star/starMaterial.ts +++ b/src/ts/stellarObjects/star/starMaterial.ts @@ -76,7 +76,7 @@ export class StarMaterial extends ShaderMaterial { this.starModel = model; this.starSeed = model.seed; - this.starColor = getRgbFromTemperature(model.physics.temperature); + this.starColor = getRgbFromTemperature(model.physics.blackBodyTemperature); this.onBindObservable.add(() => { this.getEffect().setFloat(StarMaterialUniformNames.TIME, this.elapsedSeconds % 100000); diff --git a/src/ts/stellarObjects/star/starModel.ts b/src/ts/stellarObjects/star/starModel.ts index 652cd6f7a..5237c69e7 100644 --- a/src/ts/stellarObjects/star/starModel.ts +++ b/src/ts/stellarObjects/star/starModel.ts @@ -19,7 +19,7 @@ import { randRange, randRangeInt, uniformRandBool } from "extended-random"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; import { Settings } from "../../settings"; import { getOrbitalPeriod, Orbit } from "../../orbit/orbit"; -import { StellarObjectPhysicalProperties } from "../../architecture/physicalProperties"; +import { StellarObjectPhysicsInfo } from "../../architecture/physicsInfo"; import { CelestialBodyModel } from "../../architecture/celestialBody"; import { wheelOfFortune } from "../../utils/random"; import { StellarObjectModel } from "../../architecture/stellarObject"; @@ -42,10 +42,10 @@ export function newSeededStarModel(seed: number, name: string, parentBodies: Cel const temperature = getRandomTemperatureFromStellarType(stellarType, rng); - const physicalProperties: StellarObjectPhysicalProperties = { + const physicalProperties: StellarObjectPhysicsInfo = { mass: 1.9885e30, //TODO: compute mass from physical properties rotationPeriod: 24 * 60 * 60, - temperature: temperature, + blackBodyTemperature: temperature, axialTilt: 0 }; diff --git a/src/ts/utils/coordinates/orbitalObjectId.ts b/src/ts/utils/coordinates/orbitalObjectId.ts index e66e87cc6..c0d0fa4af 100644 --- a/src/ts/utils/coordinates/orbitalObjectId.ts +++ b/src/ts/utils/coordinates/orbitalObjectId.ts @@ -2,7 +2,7 @@ import { OrbitalObject, OrbitalObjectModel } from "../../architecture/orbitalObj import { StarSystemController } from "../../starSystem/starSystemController"; import { StellarObject } from "../../architecture/stellarObject"; import { SystemObjectId, UniverseObjectId, SystemObjectType } from "./universeCoordinates"; -import { Planet } from "../../architecture/planet"; +import { PlanetaryMassObject } from "../../architecture/planetaryMassObject"; import { SpaceStation } from "../../spacestation/spaceStation"; import { SpaceStationModel } from "../../spacestation/spacestationModel"; import { getSystemModelFromCoordinates } from "../../starSystem/modelFromCoordinates"; @@ -19,7 +19,7 @@ export function getSystemObjectId(orbitalObject: OrbitalObject, starSystem: Star let objectIndex: number; if ((objectIndex = starSystem.getStellarObjects().indexOf(orbitalObject as StellarObject)) !== -1) { objectType = SystemObjectType.STELLAR_OBJECT; - } else if ((objectIndex = starSystem.getPlanetaryMassObjects().indexOf(orbitalObject as Planet)) !== -1) { + } else if ((objectIndex = starSystem.getPlanetaryMassObjects().indexOf(orbitalObject as PlanetaryMassObject)) !== -1) { objectType = SystemObjectType.PLANETARY_MASS_OBJECT; } else if ((objectIndex = starSystem.getAnomalies().indexOf(orbitalObject as CelestialBody)) !== -1) { objectType = SystemObjectType.ANOMALY; diff --git a/src/ts/utils/physics.ts b/src/ts/utils/physics.ts index f5aa5e77b..a67d0307c 100644 --- a/src/ts/utils/physics.ts +++ b/src/ts/utils/physics.ts @@ -107,4 +107,30 @@ export function getGravitationalLensFocalDistance(mass: number, radius: number) export function computeRingRotationPeriod(radius: number, gravity: number): number { // g = v * v / r and T = 2 * pi * r / v => v = sqrt(g * r) and T = 2 * pi * r / sqrt(g * r) = 2 * pi * sqrt(r / g) return 2 * Math.PI * Math.sqrt(radius / gravity); +} + +export function hasLiquidWater(pressure: number, minTemperature: number, maxTemperature: number): boolean { + const waterBoilingPoint = waterBoilingPointCelsius(pressure); + const waterFreezingPoint = 0.0; + const epsilon = 0.05; + if (pressure > epsilon) { + // if temperature is too high, there is no ocean (desert world) + if (maxTemperature > waterBoilingPoint) return false; + // if temperature is too low, there is no ocean (frozen world) + if (maxTemperature < waterFreezingPoint) return false; + } else { + // if pressure is too low, there is no ocean (sterile world) + return false; + } + + return true; +} + +/** + * Returns the Schwarzschild radius of an object given its mass + * @param mass The mass of the object in kilograms + * @returns the Schwarzschild radius of the object in meters + */ +export function getSchwarzschildRadius(mass: number): number { + return (2 * Settings.G * mass) / (Settings.C * Settings.C); } \ No newline at end of file diff --git a/src/ts/utils/positionNearObject.ts b/src/ts/utils/positionNearObject.ts index 59b248ad9..5269bdffd 100644 --- a/src/ts/utils/positionNearObject.ts +++ b/src/ts/utils/positionNearObject.ts @@ -121,7 +121,7 @@ export function positionNearObjectWithStarVisible(transformable: Controls, objec } export function positionNearObjectAsteroidField(body: Transformable & CanHaveRings & HasBoundingSphere, starSystem: StarSystemController): Vector3 { - const asteroidField = body.getAsteroidField(); + const asteroidField = body.asteroidField; if (asteroidField === null) { throw new Error("The body does not have an asteroid field"); } diff --git a/src/ts/utils/strings/orbitalObjectTypeToDisplay.ts b/src/ts/utils/strings/orbitalObjectTypeToDisplay.ts index 3bb6adaee..3a645f1a8 100644 --- a/src/ts/utils/strings/orbitalObjectTypeToDisplay.ts +++ b/src/ts/utils/strings/orbitalObjectTypeToDisplay.ts @@ -34,7 +34,7 @@ export function orbitalObjectTypeToDisplay(model: OrbitalObjectModel): string { case OrbitalObjectType.SPACE_STATION: return i18n.t("objectTypes:spaceStation"); case OrbitalObjectType.STAR: - return i18n.t("objectTypes:star", { stellarType: getStellarTypeFromTemperature((model as StellarObjectModel).physics.temperature) }); + return i18n.t("objectTypes:star", { stellarType: getStellarTypeFromTemperature((model as StellarObjectModel).physics.blackBodyTemperature) }); case OrbitalObjectType.NEUTRON_STAR: return i18n.t("objectTypes:neutronStar"); case OrbitalObjectType.BLACK_HOLE: