diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index fad70a65a..9e692d113 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,6 +1,6 @@
# These are supported funding model platforms
-github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+github: [BarthPaleologue] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: cosmosjourneyer
diff --git a/package.json b/package.json
index 5ac9d1ac9..d954635d0 100644
--- a/package.json
+++ b/package.json
@@ -46,7 +46,7 @@
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
},
- "version": "1.4.0",
+ "version": "1.4.1",
"description": "CosmosJourneyer",
"name": "cosmos-journeyer",
"scripts": {
diff --git a/src/html/pauseMenu.html b/src/html/pauseMenu.html
index a5ce2f97d..bafc2dc2c 100644
--- a/src/html/pauseMenu.html
+++ b/src/html/pauseMenu.html
@@ -1,11 +1,12 @@
-
+
+
- Share Position
-
\ No newline at end of file
diff --git a/src/shaders/blackhole.glsl b/src/shaders/blackhole.glsl
index 793142e19..79cdcf2be 100644
--- a/src/shaders/blackhole.glsl
+++ b/src/shaders/blackhole.glsl
@@ -170,13 +170,13 @@ void main() {
vec4 colOut = vec4(0.0);
- vec3 positionBHS = camera_position - object_position;// position of the camera in blackhole space
+ vec3 rayPositionBlackHoleSpace = camera_position - object_position;// position of the camera in blackhole space
bool suckedInBH = false;
bool escapedBH = false;
bool occluded = false;
- if (maximumDistance < length(positionBHS)) occluded = true;
+ if (maximumDistance < length(rayPositionBlackHoleSpace)) occluded = true;
vec4 col = vec4(0.0);
vec4 glow = vec4(0.0);
@@ -193,12 +193,12 @@ void main() {
for (int h = 0; h < 6; h++) {
//reduces tests for exit conditions (to minimise branching)
- distanceToCenter = customLength(positionBHS);//distance to BH
- vec3 blackholeDir = -positionBHS / distanceToCenter;//direction to BH
+ distanceToCenter = customLength(rayPositionBlackHoleSpace);//distance to BH
+ vec3 blackholeDir = -rayPositionBlackHoleSpace / distanceToCenter;//direction to BH
float distanceToCenter2 = distanceToCenter * distanceToCenter;
- projectedPosition = projectOnPlane(positionBHS, object_rotationAxis);
- projectedDistance = length(projectedPosition - positionBHS);
+ projectedPosition = projectOnPlane(rayPositionBlackHoleSpace, object_rotationAxis);
+ projectedDistance = length(projectedPosition - rayPositionBlackHoleSpace);
projectedRayDir = projectOnPlane(rayDir, object_rotationAxis);
rayDirProjectedDistance = length(projectedRayDir - rayDir);
@@ -209,7 +209,7 @@ void main() {
stepSize = min(stepSize, min(farLimit, closeLimit));
rayDir = bendRay(rayDir, blackholeDir, distanceToCenter2, maxBendDistance, stepSize);
- positionBHS += stepSize * rayDir;
+ rayPositionBlackHoleSpace += stepSize * rayDir;
//TODO: improve glow
//glow += vec4(1.2,1.1,1, 1.0) * (0.2 * (object_radius / distanceToCenter2) * stepSize * clamp(distanceToCenter / object_radius - 1.2, 0.0, 1.0)); //adds fairly cheap glow
@@ -223,8 +223,8 @@ void main() {
break;
} else if (projectedDistance <= accretionDiskHeight) {
//ray hit accretion disk //FIXME: Break when rotate around edge of disk
- vec4 diskCol = raymarchDisk(rayDir, positionBHS);//render disk
- positionBHS += accretionDiskHeight * rayDir / rayDirProjectedDistance;// we get out of the disk
+ vec4 diskCol = raymarchDisk(rayDir, rayPositionBlackHoleSpace);//render disk
+ rayPositionBlackHoleSpace += accretionDiskHeight * rayDir / rayDirProjectedDistance;// we get out of the disk
col += diskCol * (1.0 - col.a);
}
@@ -233,7 +233,7 @@ void main() {
}
// getting the screen coordinate of the end of the bended ray
- vec2 uv = uvFromWorld(positionBHS, camera_projection, camera_view);
+ vec2 uv = uvFromWorld(rayPositionBlackHoleSpace, camera_projection, camera_view);
// check if there is an object occlusion
vec3 pixelWorldPositionEndRay = worldFromUV(uv, camera_inverseProjection, camera_inverseView);// the pixel position in world space (near plane)
vec3 rayDirToEndRay = normalize(pixelWorldPositionEndRay - camera_position);// normalized direction of the ray
@@ -249,8 +249,10 @@ void main() {
float maximumDistanceEndRay = length(closestPointEndRay);// the maxium ray length due to occlusion
float BHDistance = length(camera_position - object_position);
+ bool behindBH = dot(closestPointEndRay - camera_position, closestPointEndRay - object_position) >= 0.0;
+
vec4 bg = vec4(0.0);
- if(uv.x >= 0.0 && uv.x <= 1.0 && uv.y >= 0.0 && uv.y <= 1.0 && maximumDistanceEndRay > BHDistance - object_radius) {
+ if(uv.x >= 0.0 && uv.x <= 1.0 && uv.y >= 0.0 && uv.y <= 1.0 && behindBH) {
bg = texture2D(textureSampler, uv);
} else {
rayDir = vec3(starfieldRotation * vec4(rayDir, 1.0));
diff --git a/src/styles/pauseMenu/index.scss b/src/styles/pauseMenu/index.scss
index 43d35a1f6..0cc616bb0 100644
--- a/src/styles/pauseMenu/index.scss
+++ b/src/styles/pauseMenu/index.scss
@@ -16,16 +16,12 @@
// along with this program. If not, see .
#pauseMask {
- z-index: 40;
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
- background: transparent;
- backdrop-filter: blur(4px);
-}
-
-#pauseMenu {
- z-index: 41;
+ z-index: 40;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ background: rgba(0, 0, 0, 0.2);
+ backdrop-filter: blur(4px);
}
\ No newline at end of file
diff --git a/src/ts/alphaTestis.ts b/src/ts/alphaTestis.ts
index 03b5c84a3..72b60b0e4 100644
--- a/src/ts/alphaTestis.ts
+++ b/src/ts/alphaTestis.ts
@@ -35,11 +35,9 @@ import { RingsUniforms } from "./postProcesses/rings/ringsUniform";
import { getMoonSeed } from "./planets/common";
import { SystemSeed } from "./utils/systemSeed";
-const engine = new CosmosJourneyer();
+const engine = await CosmosJourneyer.CreateAsync();
-await engine.setup();
-
-const starSystemView = engine.getStarSystemView();
+const starSystemView = engine.starSystemView;
const spaceshipController = starSystemView.getSpaceshipControls();
@@ -54,7 +52,7 @@ const starSystemSeed = new SystemSeed(0, 0, 0, 0);
const starSystem = new StarSystemController(starSystemSeed, starSystemView.scene);
starSystem.model.setName("Alpha Testis");
-engine.getStarSystemView().setStarSystem(starSystem, false);
+starSystemView.setStarSystem(starSystem, false);
const sunModel = new StarModel(0.51);
const sun = StarSystemHelper.makeStar(starSystem, sunModel);
diff --git a/src/ts/assets.ts b/src/ts/assets.ts
index 7dc40980e..7ff397b63 100644
--- a/src/ts/assets.ts
+++ b/src/ts/assets.ts
@@ -71,6 +71,8 @@ import { MeshBuilder } from "@babylonjs/core/Meshes/meshBuilder";
import { ProceduralTexture } from "@babylonjs/core/Materials/Textures/Procedurals/proceduralTexture";
import { createButterfly } from "./proceduralAssets/butterfly/butterfly";
import { createGrassBlade } from "./proceduralAssets/grass/grassBlade";
+import { ButterflyMaterial } from "./proceduralAssets/butterfly/butterflyMaterial";
+import { GrassMaterial } from "./proceduralAssets/grass/grassMaterial";
export class Assets {
static IS_READY = false;
@@ -114,6 +116,9 @@ export class Assets {
public static Butterfly: Mesh;
public static GrassBlade: Mesh;
+ public static ButterflyMaterial: ButterflyMaterial;
+ public static GrassMaterial: GrassMaterial;
+
public static OuchSound: Sound;
public static EngineRunningSound: Sound;
@@ -212,6 +217,7 @@ export class Assets {
Assets.Rock.position.y = 0.1;
Assets.Rock.scaling.scaleInPlace(0.2);
Assets.Rock.bakeCurrentTransformIntoVertices();
+ Assets.Rock.checkCollisions = true;
Assets.Rock.isVisible = false;
console.log("Rock loaded");
@@ -235,6 +241,7 @@ export class Assets {
Assets.Tree.position.y = -1;
Assets.Tree.scaling.scaleInPlace(3);
Assets.Tree.bakeCurrentTransformIntoVertices();
+ Assets.Tree.checkCollisions = true;
const treeMaterial = new StandardMaterial("treeMaterial", scene);
@@ -255,8 +262,12 @@ export class Assets {
};
Assets.Butterfly = createButterfly(scene);
+ Assets.ButterflyMaterial = new ButterflyMaterial(scene);
+ Assets.Butterfly.material = Assets.ButterflyMaterial;
Assets.GrassBlade = createGrassBlade(scene, 3);
+ Assets.GrassMaterial = new GrassMaterial(scene);
+ Assets.GrassBlade.material = Assets.GrassMaterial;
const ouchSoundTask = Assets.manager.addBinaryFileTask("ouchSoundTask", ouchSound);
ouchSoundTask.onSuccess = function (task) {
diff --git a/src/ts/blackHoleDemo.ts b/src/ts/blackHoleDemo.ts
index 9bca9d067..568394f01 100644
--- a/src/ts/blackHoleDemo.ts
+++ b/src/ts/blackHoleDemo.ts
@@ -24,11 +24,9 @@ import { CosmosJourneyer } from "./cosmosJourneyer";
import { StarSystemHelper } from "./starSystem/starSystemHelper";
import { SystemSeed } from "./utils/systemSeed";
-const engine = new CosmosJourneyer();
+const engine = await CosmosJourneyer.CreateAsync();
-await engine.setup();
-
-const starSystemView = engine.getStarSystemView();
+const starSystemView = engine.starSystemView;
const scene = starSystemView.scene;
diff --git a/src/ts/cosmosJourneyer.ts b/src/ts/cosmosJourneyer.ts
index f6ab36e8c..302feaa9f 100644
--- a/src/ts/cosmosJourneyer.ts
+++ b/src/ts/cosmosJourneyer.ts
@@ -40,10 +40,11 @@ import { Vector3 } from "@babylonjs/core/Maths/math.vector";
import { Quaternion } from "@babylonjs/core/Maths/math";
import { setRotationQuaternion } from "./uberCore/transforms/basicTransform";
import { ShipControls } from "./spaceship/shipControls";
-import { PhysicsMotionType } from "@babylonjs/core";
-import { setMaxLinVel } from "./utils/havok";
+import { encodeBase64 } from "./utils/base64";
+import { UniverseCoordinates } from "./saveFile/universeCoordinates";
enum EngineState {
+ UNINITIALIZED,
RUNNING,
PAUSED
}
@@ -54,40 +55,71 @@ enum EngineState {
* It also handles the pause menu.
*/
export class CosmosJourneyer {
- private readonly pauseMenu: PauseMenu;
- private videoRecorder: VideoRecorder | null = null;
+ readonly engine: Engine;
+
+ readonly starSystemView: StarSystemView;
+ readonly starMap: StarMap;
- readonly canvas: HTMLCanvasElement;
- private engine: Engine | null = null;
+ readonly mainMenu: MainMenu;
+ readonly pauseMenu: PauseMenu;
- private mainMenu: MainMenu | null = null;
- private starSystemView: StarSystemView | null = null;
- private starMap: StarMap | null = null;
+ private activeScene: Scene;
- private activeScene: Scene | null = null;
+ private state = EngineState.UNINITIALIZED;
- private state = EngineState.RUNNING;
+ private videoRecorder: VideoRecorder | null = null;
readonly onToggleStarMapObservable = new Observable();
- constructor() {
+ private constructor(engine: Engine, starSystemView: StarSystemView, starMap: StarMap) {
+ this.engine = engine;
+
+ this.starSystemView = starSystemView;
+ this.starMap = starMap;
+ this.starMap.onWarpObservable.add((seed: SystemSeed) => {
+ this.starSystemView.setStarSystem(new StarSystemController(seed, this.starSystemView.scene), true);
+ this.starSystemView.initStarSystem();
+ this.toggleStarMap();
+
+ const activeControls = this.starSystemView.scene.getActiveController();
+ if (activeControls instanceof ShipControls) {
+ activeControls.spaceship.enableWarpDrive();
+ activeControls.thirdPersonCamera.radius = 30;
+ }
+ });
+
+ // Init the active scene
+ this.starMap.scene.detachControl();
+ this.starSystemView.scene.attachControl();
+ this.activeScene = this.starSystemView.scene;
+
+ this.mainMenu = new MainMenu(starSystemView);
+ this.mainMenu.onStartObservable.add(() => {
+ this.starMap.setCurrentStarSystem(this.starSystemView.getStarSystem().model.seed);
+ this.starSystemView.switchToSpaceshipControls();
+ this.starSystemView.getSpaceshipControls().spaceship.enableWarpDrive();
+ this.starSystemView.showUI();
+ this.starSystemView.ui.setEnabled(true);
+ });
+
+ this.mainMenu.onLoadSaveObservable.add((saveData: SaveFileData) => {
+ this.loadSaveData(saveData);
+ });
+
this.pauseMenu = new PauseMenu();
this.pauseMenu.onResume.add(() => this.resume());
this.pauseMenu.onScreenshot.add(() => this.takeScreenshot());
this.pauseMenu.onShare.add(() => {
const saveData = this.generateSaveData();
- const starSystem = saveData.starSystem;
- const payload = `starMapX=${starSystem.starSectorX}&starMapY=${starSystem.starSectorY}&starMapZ=${starSystem.starSectorZ}&index=${starSystem.starSectorIndex}&objectIndex=${saveData.nearestOrbitalObjectIndex}&positionX=${saveData.positionX}&positionY=${saveData.positionY}&positionZ=${saveData.positionZ}&rotationQuaternionX=${saveData.rotationQuaternionX}&rotationQuaternionY=${saveData.rotationQuaternionY}&rotationQuaternionZ=${saveData.rotationQuaternionZ}&rotationQuaternionW=${saveData.rotationQuaternionW}`;
- const url = new URL(`https://barthpaleologue.github.io/CosmosJourneyer/random.html?${payload}`);
+ const urlData = encodeBase64(JSON.stringify(saveData.universeCoordinates));
+
+ const payload = `universeCoordinates=${urlData}`;
+ const url = new URL(`https://barthpaleologue.github.io/CosmosJourneyer/?${payload}`);
navigator.clipboard.writeText(url.toString()).then(() => console.log("Copied to clipboard"));
});
this.pauseMenu.onSave.add(() => this.downloadSaveFile());
- this.canvas = document.getElementById("renderer") as HTMLCanvasElement;
- this.canvas.width = window.innerWidth;
- this.canvas.height = window.innerHeight;
-
window.addEventListener("blur", () => {
if (!this.mainMenu?.isVisible()) this.pause();
});
@@ -114,68 +146,47 @@ export class CosmosJourneyer {
* Creates the engine and the scenes and loads the assets async
* @returns A promise that resolves when the engine and the scenes are created and the assets are loaded
*/
- public async setup(): Promise {
+ public static async CreateAsync(): Promise {
+ const canvas = document.getElementById("renderer") as HTMLCanvasElement;
+ canvas.width = window.innerWidth;
+ canvas.height = window.innerHeight;
+
// Init BabylonJS engine (use webgpu if ?webgpu is in the url)
- this.engine = window.location.search.includes("webgpu")
- ? await EngineFactory.CreateAsync(this.canvas, {
+ const engine = window.location.search.includes("webgpu")
+ ? await EngineFactory.CreateAsync(canvas, {
twgslOptions: {
wasmPath: new URL("./utils/TWGSL/twgsl.wasm", import.meta.url).href,
jsPath: new URL("./utils/TWGSL/twgsl.js", import.meta.url).href
}
})
- : new Engine(this.canvas, true, {
- // the preserveDrawingBuffer option is required for the screenshot feature to work
- preserveDrawingBuffer: true
- });
+ : new Engine(canvas, true, {
+ // the preserveDrawingBuffer option is required for the screenshot feature to work
+ preserveDrawingBuffer: true
+ });
- //this.engine = new Engine(this.canvas); //await EngineFactory.CreateAsync(this.canvas, { enableAllFeatures: true });
- this.engine.useReverseDepthBuffer = true;
- this.engine.loadingScreen.displayLoadingUI();
+ engine.useReverseDepthBuffer = true;
+ engine.loadingScreen.displayLoadingUI();
window.addEventListener("resize", () => {
- this.getEngine().resize(true);
+ engine.resize(true);
});
// Log informations about the gpu and the api used
- console.log(`API: ${this.engine.isWebGPU ? "WebGPU" : "WebGL" + this.engine.webGLVersion}`);
- console.log(`GPU detected: ${this.engine.getGlInfo().renderer}`);
+ console.log(`API: ${engine.isWebGPU ? "WebGPU" : "WebGL" + engine.version}`);
+ console.log(`GPU detected: ${engine.getGlInfo().renderer}`);
// Init Havok physics engine
const havokInstance = await HavokPhysics();
console.log(`Havok initialized`);
// Init starmap view
- this.starMap = new StarMap(this.engine);
- this.starMap.onWarpObservable.add((seed: SystemSeed) => {
- this.getStarSystemView().setStarSystem(new StarSystemController(seed, this.getStarSystemView().scene), true);
- this.getStarSystemView().initStarSystem();
- this.toggleStarMap();
-
- const activeControls = this.getStarSystemView().scene.getActiveController();
- if (activeControls instanceof ShipControls) {
- activeControls.spaceship.enableWarpDrive();
- activeControls.thirdPersonCamera.radius = 30;
- }
- });
+ const starMap = new StarMap(engine);
// Init star system view
- this.starSystemView = new StarSystemView(this.engine, havokInstance);
- await this.starSystemView.initAssets();
-
- this.mainMenu = new MainMenu(this.starSystemView);
- this.mainMenu.onStartObservable.add(() => {
- this.getStarMap().setCurrentStarSystem(this.getStarSystemView().getStarSystem().model.seed);
- this.getStarSystemView().switchToSpaceshipControls();
- this.getStarSystemView().getSpaceshipControls().spaceship.enableWarpDrive();
- this.getStarSystemView().showUI();
- this.getStarSystemView().ui.setEnabled(true);
- });
+ const starSystemView = new StarSystemView(engine, havokInstance);
- this.mainMenu.onLoadSaveObservable.add((saveData: SaveFileData) => {
- this.loadSaveData(saveData);
- });
+ await starSystemView.initAssets();
- // Init the active scene
- this.activeScene = this.starSystemView.scene;
+ return new CosmosJourneyer(engine, starSystemView, starMap);
}
public pause(): void {
@@ -196,81 +207,46 @@ export class CosmosJourneyer {
* Inits the current star system
*/
public init(skipMainMenu = false): void {
- if (!skipMainMenu) this.getMainMenu().init();
- this.getStarSystemView().initStarSystem();
+ if (!skipMainMenu) this.mainMenu.init();
+ this.starSystemView.initStarSystem();
- this.getEngine().runRenderLoop(() => {
+ this.engine.runRenderLoop(() => {
if (this.isPaused()) return;
this.getActiveScene().render();
});
- }
-
- /**
- * Registers a callback to be called before the star system scene is rendered
- * @param callback the callback to be called before the star system scene is rendered
- */
- public registerStarSystemUpdateCallback(callback: () => void): void {
- this.getStarSystemView().scene.onBeforeRenderObservable.add(callback);
- }
-
- public getMainMenu(): MainMenu {
- if (this.mainMenu === null) throw new Error("Main menu is null");
- return this.mainMenu;
- }
-
- public getStarSystemView(): StarSystemView {
- if (this.starSystemView === null) throw new Error("Star system view is null");
- return this.starSystemView;
- }
-
- public getStarMap(): StarMap {
- if (this.starMap === null) throw new Error("Star map is null");
- return this.starMap;
+ this.state = EngineState.RUNNING;
}
/**
* Toggles the star map
- * @throws Error if the star map is null
*/
public toggleStarMap(): void {
- if (this.activeScene === this.getStarSystemView().scene) {
- this.getStarSystemView().unZoom(() => {
- if (this.activeScene !== null) this.activeScene.detachControl();
- this.getStarMap().scene.attachControl();
- const starMap = this.getStarMap();
+ if (this.activeScene === this.starSystemView.scene) {
+ this.starSystemView.unZoom(() => {
+ this.activeScene.detachControl();
+ this.starMap.scene.attachControl();
+ const starMap = this.starMap;
this.activeScene = starMap.scene;
starMap.focusOnCurrentSystem();
});
} else {
- if (this.activeScene !== null) this.activeScene.detachControl();
- this.getStarSystemView().scene.attachControl();
- this.activeScene = this.getStarSystemView().scene;
- this.getStarSystemView().showUI();
+ this.activeScene.detachControl();
+ this.starSystemView.scene.attachControl();
+ this.activeScene = this.starSystemView.scene;
+ this.starSystemView.showUI();
}
- this.onToggleStarMapObservable.notifyObservers(this.activeScene === this.getStarMap().scene);
+ this.onToggleStarMapObservable.notifyObservers(this.activeScene === this.starMap.scene);
}
/**
* Returns the active scene (star system or star map)
* @returns the active scene (star system or star map)
- * @throws Error if the active scene is null
*/
public getActiveScene(): Scene {
- if (this.activeScene === null) throw new Error("Active scene is null");
return this.activeScene;
}
- /**
- * Returns the BabylonJS engine
- * @returns the BabylonJS engine
- * @throws Error if the engine is null
- */
- public getEngine(): Engine {
- if (this.engine === null) throw new Error("Engine is null");
- return this.engine;
- }
-
/**
* Takes a screenshot of the current scene. By default, the screenshot is taken at a 4x the resolution of the canvas
* @param precision The resolution multiplier of the screenshot
@@ -278,17 +254,17 @@ export class CosmosJourneyer {
public takeScreenshot(precision = 4): void {
const camera = this.getActiveScene().activeCamera;
if (camera === null) throw new Error("Cannot take screenshot: camera is null");
- Tools.CreateScreenshot(this.getEngine(), camera, { precision: precision });
+ Tools.CreateScreenshot(this.engine, camera, { precision: precision });
}
public takeVideoCapture(): void {
- if (!VideoRecorder.IsSupported(this.getEngine())) {
+ if (!VideoRecorder.IsSupported(this.engine)) {
console.warn("Your browser does not support video recording!");
return;
}
if (this.videoRecorder === null) {
- this.videoRecorder = new VideoRecorder(this.getEngine(), {
+ this.videoRecorder = new VideoRecorder(this.engine, {
fps: 60,
recordChunckSize: 3000000,
mimeType: "video/webm;codecs=h264"
@@ -306,7 +282,7 @@ export class CosmosJourneyer {
* Generates a save file data object from the current star system and the player's position
*/
public generateSaveData(): SaveFileData {
- const currentStarSystem = this.getStarSystemView().getStarSystem();
+ const currentStarSystem = this.starSystemView.getStarSystem();
const seed = currentStarSystem.model.seed;
// Finding the index of the nearest orbital object
@@ -315,31 +291,28 @@ export class CosmosJourneyer {
if (nearestOrbitalObjectIndex === -1) throw new Error("Nearest orbital object not found");
// Finding the position of the player in the nearest orbital object's frame of reference
- const currentWorldPosition = this.getStarSystemView().scene.getActiveController().getTransform().getAbsolutePosition();
+ const currentWorldPosition = this.starSystemView.scene.getActiveController().getTransform().getAbsolutePosition();
const nearestOrbitalObjectInverseWorld = nearestOrbitalObject.getTransform().getWorldMatrix().clone().invert();
const currentLocalPosition = Vector3.TransformCoordinates(currentWorldPosition, nearestOrbitalObjectInverseWorld);
// Finding the rotation of the player in the nearest orbital object's frame of reference
- const currentWorldRotation = this.getStarSystemView().scene.getActiveController().getTransform().absoluteRotationQuaternion;
+ const currentWorldRotation = this.starSystemView.scene.getActiveController().getTransform().absoluteRotationQuaternion;
const nearestOrbitalObjectInverseRotation = nearestOrbitalObject.getTransform().absoluteRotationQuaternion.clone().invert();
const currentLocalRotation = currentWorldRotation.multiply(nearestOrbitalObjectInverseRotation);
return {
version: projectInfo.version,
- starSystem: {
- starSectorX: seed.starSectorX,
- starSectorY: seed.starSectorY,
- starSectorZ: seed.starSectorZ,
- starSectorIndex: seed.index
- },
- nearestOrbitalObjectIndex: nearestOrbitalObjectIndex,
- positionX: currentLocalPosition.x,
- positionY: currentLocalPosition.y,
- positionZ: currentLocalPosition.z,
- rotationQuaternionX: currentLocalRotation.x,
- rotationQuaternionY: currentLocalRotation.y,
- rotationQuaternionZ: currentLocalRotation.z,
- rotationQuaternionW: currentLocalRotation.w
+ universeCoordinates: {
+ starSystem: seed.serialize(),
+ nearestOrbitalObjectIndex: nearestOrbitalObjectIndex,
+ positionX: currentLocalPosition.x,
+ positionY: currentLocalPosition.y,
+ positionZ: currentLocalPosition.z,
+ rotationQuaternionX: currentLocalRotation.x,
+ rotationQuaternionY: currentLocalRotation.y,
+ rotationQuaternionZ: currentLocalRotation.z,
+ rotationQuaternionW: currentLocalRotation.w
+ }
};
}
@@ -358,45 +331,56 @@ export class CosmosJourneyer {
/**
* Loads a save file and apply it. This will generate the requested star system and position the player at the requested position around the requested orbital object.
+ * This will perform engine initialization if the engine is not initialized.
* @param saveData The save file data to load
*/
public loadSaveData(saveData: SaveFileData): void {
- const seed = new SystemSeed(saveData.starSystem.starSectorX, saveData.starSystem.starSectorY, saveData.starSystem.starSectorZ, saveData.starSystem.starSectorIndex);
+ this.loadUniverseCoordinates(saveData.universeCoordinates);
+ }
+
+ /**
+ * Loads universe coordinates and apply them. This will generate the requested star system and position the player at the requested position around the requested orbital object.
+ * This will perform engine initialization if the engine is not initialized.
+ * @param universeCoordinates The universe coordinates to load
+ */
+ public loadUniverseCoordinates(universeCoordinates: UniverseCoordinates): void {
+ const seed = SystemSeed.Deserialize(universeCoordinates.starSystem);
- this.getStarMap().setCurrentStarSystem(seed);
- this.getStarSystemView().setStarSystem(new StarSystemController(seed, this.getStarSystemView().scene), true);
+ this.starMap.setCurrentStarSystem(seed);
+ this.starSystemView.setStarSystem(new StarSystemController(seed, this.starSystemView.scene), true);
- this.getStarSystemView().onInitStarSystem.addOnce(() => {
- this.getStarSystemView().switchToSpaceshipControls();
+ this.starSystemView.onInitStarSystem.addOnce(() => {
+ this.starSystemView.switchToSpaceshipControls();
- this.getStarSystemView().ui.setEnabled(true);
- this.getStarSystemView().showUI();
+ this.starSystemView.ui.setEnabled(true);
+ this.starSystemView.showUI();
- const playerTransform = this.getStarSystemView().scene.getActiveController().getTransform();
+ const playerTransform = this.starSystemView.scene.getActiveController().getTransform();
- const nearestOrbitalObject = this.getStarSystemView().getStarSystem().getOrbitalObjects()[saveData.nearestOrbitalObjectIndex];
+ const nearestOrbitalObject = this.starSystemView.getStarSystem().getOrbitalObjects()[universeCoordinates.nearestOrbitalObjectIndex];
const nearestOrbitalObjectWorld = nearestOrbitalObject.getTransform().getWorldMatrix();
- const currentLocalPosition = new Vector3(saveData.positionX, saveData.positionY, saveData.positionZ);
+ const currentLocalPosition = new Vector3(universeCoordinates.positionX, universeCoordinates.positionY, universeCoordinates.positionZ);
const currentWorldPosition = Vector3.TransformCoordinates(currentLocalPosition, nearestOrbitalObjectWorld);
playerTransform.setAbsolutePosition(currentWorldPosition);
const nearestOrbitalObjectWorldRotation = nearestOrbitalObject.getTransform().absoluteRotationQuaternion;
const currentLocalRotationQuaternion = new Quaternion(
- saveData.rotationQuaternionX,
- saveData.rotationQuaternionY,
- saveData.rotationQuaternionZ,
- saveData.rotationQuaternionW
+ universeCoordinates.rotationQuaternionX,
+ universeCoordinates.rotationQuaternionY,
+ universeCoordinates.rotationQuaternionZ,
+ universeCoordinates.rotationQuaternionW
);
const currentWorldRotationQuaternion = currentLocalRotationQuaternion.multiply(nearestOrbitalObjectWorldRotation);
setRotationQuaternion(playerTransform, currentWorldRotationQuaternion);
// updates camera position
- this.getStarSystemView().getSpaceshipControls().getActiveCamera().getViewMatrix(true);
+ this.starSystemView.getSpaceshipControls().getActiveCamera().getViewMatrix(true);
// re-centers the star system
- this.getStarSystemView().getStarSystem().applyFloatingOrigin();
+ this.starSystemView.getStarSystem().applyFloatingOrigin();
});
- this.getStarSystemView().initStarSystem();
+ if (this.state === EngineState.UNINITIALIZED) this.init(true);
+ else this.starSystemView.initStarSystem();
}
}
diff --git a/src/ts/defaultController/defaultControls.ts b/src/ts/defaultController/defaultControls.ts
index 93edf92bb..73ce8ee89 100644
--- a/src/ts/defaultController/defaultControls.ts
+++ b/src/ts/defaultController/defaultControls.ts
@@ -19,7 +19,16 @@ import { Controls } from "../uberCore/controls";
import { Scene } from "@babylonjs/core/scene";
import { Vector3 } from "@babylonjs/core/Maths/math.vector";
import { TransformNode } from "@babylonjs/core/Meshes";
-import { getForwardDirection, getRightDirection, getUpwardDirection, pitch, roll, translate, yaw } from "../uberCore/transforms/basicTransform";
+import {
+ getForwardDirection,
+ getRightDirection,
+ getUpwardDirection,
+ pitch,
+ roll,
+ setRotationQuaternion,
+ translate,
+ yaw
+} from "../uberCore/transforms/basicTransform";
import { Input } from "../inputs/input";
import { Camera } from "@babylonjs/core/Cameras/camera";
import { FreeCamera } from "@babylonjs/core/Cameras/freeCamera";
@@ -38,6 +47,7 @@ export class DefaultControls implements Controls {
constructor(scene: Scene) {
this.transform = new TransformNode("playerController", scene);
+ setRotationQuaternion(this.getTransform(), Quaternion.Identity());
this.camera = new FreeCamera("firstPersonCamera", Vector3.Zero(), scene);
this.camera.parent = this.transform;
diff --git a/src/ts/index.ts b/src/ts/index.ts
index cb66f4439..4bccb6d95 100644
--- a/src/ts/index.ts
+++ b/src/ts/index.ts
@@ -19,17 +19,28 @@ import "../styles/index.scss";
import { CosmosJourneyer } from "./cosmosJourneyer";
import { getForwardDirection, getRotationQuaternion, setRotationQuaternion, translate } from "./uberCore/transforms/basicTransform";
+import { decodeBase64 } from "./utils/base64";
+import { isJsonStringValidUniverseCoordinates } from "./saveFile/universeCoordinates";
-const engine = new CosmosJourneyer();
+const engine = await CosmosJourneyer.CreateAsync();
-await engine.setup();
+const starSystemView = engine.starSystemView;
-const starSystemView = engine.getStarSystemView();
-engine.init();
+const urlParams = new URLSearchParams(window.location.search);
+const universeCoordinatesString = urlParams.get("universeCoordinates");
+
+if(universeCoordinatesString !== null) {
+ const jsonString = decodeBase64(universeCoordinatesString);
+ if(!isJsonStringValidUniverseCoordinates(jsonString)) {
+ alert("Invalid universe coordinates");
+ }
+ engine.loadUniverseCoordinates(JSON.parse(jsonString));
+} else {
+ engine.init(false);
+}
const shipControls = starSystemView.getSpaceshipControls();
const characterController = starSystemView.getCharacterControls();
-const defaultController = starSystemView.getDefaultControls();
document.addEventListener("keydown", (e) => {
if (engine.isPaused()) return;
diff --git a/src/ts/mainMenu/mainMenu.ts b/src/ts/mainMenu/mainMenu.ts
index de85dc922..4d1ebcd53 100644
--- a/src/ts/mainMenu/mainMenu.ts
+++ b/src/ts/mainMenu/mainMenu.ts
@@ -165,7 +165,7 @@ export class MainMenu {
this.startAnimation(() => this.onLoadSaveObservable.notifyObservers(saveFileData));
} catch (e) {
dropFileZone.classList.add("invalid");
- alert("Invalid save file");
+ alert("Invalid save file. Please check your save file against the current format at https://barthpaleologue.github.io/CosmosJourneyer/docs/types/saveFile_saveFileData.SaveFileData.html\nYou can open an issue here if the issue persists: https://github.com/BarthPaleologue/CosmosJourneyer");
}
};
reader.readAsText(file);
diff --git a/src/ts/planets/telluricPlanet/telluricPlanet.ts b/src/ts/planets/telluricPlanet/telluricPlanet.ts
index 552ec3e7e..6508a9cea 100644
--- a/src/ts/planets/telluricPlanet/telluricPlanet.ts
+++ b/src/ts/planets/telluricPlanet/telluricPlanet.ts
@@ -38,11 +38,11 @@ import { TransformNode } from "@babylonjs/core/Meshes";
import { OrbitProperties } from "../../orbit/orbitProperties";
import { PhysicsAggregate } from "@babylonjs/core/Physics/v2/physicsAggregate";
import { PhysicsShapeType } from "@babylonjs/core/Physics/v2/IPhysicsEnginePlugin";
-import { OrbitalObject } from "../../architecture/orbitalObject";
import { CelestialBody } from "../../architecture/celestialBody";
import { RingsUniforms } from "../../postProcesses/rings/ringsUniform";
import { OrbitalObjectPhysicalProperties } from "../../architecture/physicalProperties";
import { rotate } from "../../uberCore/transforms/basicTransform";
+import { BODY_TYPE } from "../../model/common";
export class TelluricPlanet implements Planet, Cullable {
readonly name: string;
@@ -60,7 +60,7 @@ export class TelluricPlanet implements Planet, Cullable {
readonly postProcesses: PostProcessType[] = [];
- readonly parent: OrbitalObject | null;
+ readonly parent: CelestialBody | null;
/**
* New Telluric Planet
@@ -149,6 +149,9 @@ export class TelluricPlanet implements Planet, Cullable {
}
getTypeName(): string {
+ if (this.parent?.model.bodyType === BODY_TYPE.TELLURIC_PLANET || this.parent?.model.bodyType === BODY_TYPE.GAS_PLANET) {
+ return "Telluric Moon";
+ }
return "Telluric Planet";
}
diff --git a/src/ts/planets/telluricPlanet/terrain/chunks/chunkTree.ts b/src/ts/planets/telluricPlanet/terrain/chunks/chunkTree.ts
index 4f8334338..bcc6264ac 100644
--- a/src/ts/planets/telluricPlanet/terrain/chunks/chunkTree.ts
+++ b/src/ts/planets/telluricPlanet/terrain/chunks/chunkTree.ts
@@ -32,6 +32,8 @@ import { DeleteSemaphore } from "./deleteSemaphore";
import { UberScene } from "../../../../uberCore/uberScene";
import { getRotationQuaternion } from "../../../../uberCore/transforms/basicTransform";
import { ChunkForge } from "./chunkForge";
+import { PhysicsRaycastResult } from "@babylonjs/core/Physics/physicsRaycastResult";
+import { PhysicsEngineV2 } from "@babylonjs/core/Physics/v2";
/**
* A quadTree is defined recursively
@@ -180,7 +182,7 @@ export class ChunkTree {
const distanceToNodeSquared = Vector3.DistanceSquared(chunkApproxPosition, observerPositionW);
const subdivisionDistanceThreshold = Settings.CHUNK_RENDER_DISTANCE_MULTIPLIER * (this.rootChunkLength / 2 ** walked.length);
- const deletionDistanceThreshold = 10e3 + Settings.CHUNK_RENDER_DISTANCE_MULTIPLIER * (this.rootChunkLength / 2 ** (walked.length - 1));
+ const deletionDistanceThreshold = 15e3 + 1.1 * Settings.CHUNK_RENDER_DISTANCE_MULTIPLIER * (this.rootChunkLength / 2 ** (walked.length - 1));
// the 1.5 is to avoid creation/deletion oscillations
if (distanceToNodeSquared > deletionDistanceThreshold ** 2 && walked.length >= this.minDepth && tree instanceof Array) {
diff --git a/src/ts/planets/telluricPlanet/terrain/chunks/planetChunk.ts b/src/ts/planets/telluricPlanet/terrain/chunks/planetChunk.ts
index 781b8497a..1d9b0e311 100644
--- a/src/ts/planets/telluricPlanet/terrain/chunks/planetChunk.ts
+++ b/src/ts/planets/telluricPlanet/terrain/chunks/planetChunk.ts
@@ -38,6 +38,7 @@ import { LockConstraint } from "@babylonjs/core/Physics/v2/physicsConstraint";
import { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh";
import { Transformable } from "../../../../architecture/transformable";
import { CollisionMask } from "../../../../settings";
+import { InstancePatch } from "../instancePatch/instancePatch";
export class PlanetChunk implements Transformable, BoundingSphere {
public readonly mesh: Mesh;
@@ -151,12 +152,12 @@ export class PlanetChunk implements Transformable, BoundingSphere {
if (instancesMatrixBuffer.length === 0) return;
- const rockPatch = new ThinInstancePatch(this.parent, randomDownSample(alignedInstancesMatrixBuffer, 3200));
+ const rockPatch = new InstancePatch(this.parent, randomDownSample(alignedInstancesMatrixBuffer, 3200));
rockPatch.createInstances(Assets.Rock);
this.instancePatches.push(rockPatch);
if (this.planetModel.physicalProperties.pressure > 0 && this.planetModel.physicalProperties.oceanLevel > 0) {
- const treePatch = new ThinInstancePatch(this.parent, randomDownSample(instancesMatrixBuffer, 4800));
+ const treePatch = new InstancePatch(this.parent, randomDownSample(instancesMatrixBuffer, 4800));
treePatch.createInstances(Assets.Tree);
this.instancePatches.push(treePatch);
diff --git a/src/ts/planets/telluricPlanet/terrain/instancePatch/instancePatch.ts b/src/ts/planets/telluricPlanet/terrain/instancePatch/instancePatch.ts
index 3f0157b0f..353492fc6 100644
--- a/src/ts/planets/telluricPlanet/terrain/instancePatch/instancePatch.ts
+++ b/src/ts/planets/telluricPlanet/terrain/instancePatch/instancePatch.ts
@@ -24,15 +24,16 @@ import { TransformNode } from "@babylonjs/core/Meshes/transformNode";
export class InstancePatch implements IPatch {
private baseMesh: Mesh | null = null;
- readonly position: Vector3;
+
+ readonly parent: TransformNode;
readonly instances: InstancedMesh[] = [];
private positions: Vector3[] = [];
private rotations: Quaternion[] = [];
private scalings: Vector3[] = [];
- constructor(position: Vector3, matrixBuffer: Float32Array) {
- this.position = position;
+ constructor(parent: TransformNode, matrixBuffer: Float32Array) {
+ this.parent = parent;
// decompose matrix buffer into position, rotation and scaling
for (let i = 0; i < matrixBuffer.length; i += 16) {
@@ -58,9 +59,9 @@ export class InstancePatch implements IPatch {
this.baseMesh = null;
}
- public static CreateSquare(position: Vector3, size: number, resolution: number) {
+ public static CreateSquare(parent: TransformNode, position: Vector3, size: number, resolution: number) {
const buffer = createSquareMatrixBuffer(position, size, resolution);
- return new InstancePatch(position, buffer);
+ return new InstancePatch(parent, buffer);
}
public createInstances(baseMesh: TransformNode): void {
@@ -79,6 +80,8 @@ export class InstancePatch implements IPatch {
instance.scaling.copyFrom(this.scalings[i]);
this.instances.push(instance);
+ instance.parent = this.parent;
+
instance.checkCollisions = baseMesh.checkCollisions;
}
}
@@ -93,10 +96,6 @@ export class InstancePatch implements IPatch {
return this.baseMesh.instances.length;
}
- public getPosition(): Vector3 {
- return this.position;
- }
-
public dispose() {
this.clearInstances();
if (this.baseMesh !== null) this.baseMesh.dispose();
diff --git a/src/ts/planets/telluricPlanet/terrain/instancePatch/thinInstancePatch.ts b/src/ts/planets/telluricPlanet/terrain/instancePatch/thinInstancePatch.ts
index f36258cae..891a06387 100644
--- a/src/ts/planets/telluricPlanet/terrain/instancePatch/thinInstancePatch.ts
+++ b/src/ts/planets/telluricPlanet/terrain/instancePatch/thinInstancePatch.ts
@@ -67,7 +67,7 @@ export class ThinInstancePatch implements IPatch {
});
this.baseMesh.isVisible = true;
- this.baseMesh.thinInstanceSetBuffer("matrix", this.matrixBuffer, 16);
+ this.baseMesh.thinInstanceSetBuffer("matrix", this.matrixBuffer, 16, false);
}
public syncWithParent(): void {
diff --git a/src/ts/postProcesses/postProcessManager.ts b/src/ts/postProcesses/postProcessManager.ts
index 436aeea78..e1e19860b 100644
--- a/src/ts/postProcesses/postProcessManager.ts
+++ b/src/ts/postProcesses/postProcessManager.ts
@@ -16,7 +16,6 @@
// along with this program. If not, see .
import { UberScene } from "../uberCore/uberScene";
-import { UberRenderingPipeline } from "../uberCore/uberRenderingPipeline";
import { OceanPostProcess } from "./oceanPostProcess";
import { TelluricPlanet } from "../planets/telluricPlanet/telluricPlanet";
import { FlatCloudsPostProcess } from "./clouds/flatCloudsPostProcess";
@@ -33,7 +32,6 @@ import { CloudsPostProcess } from "./volumetricCloudsPostProcess";
import { Engine } from "@babylonjs/core/Engines/engine";
import { FxaaPostProcess } from "@babylonjs/core/PostProcesses/fxaaPostProcess";
import { PostProcessRenderEffect } from "@babylonjs/core/PostProcesses/RenderPipeline/postProcessRenderEffect";
-import { BloomEffect } from "@babylonjs/core/PostProcesses/bloomEffect";
import { Texture } from "@babylonjs/core/Materials/Textures/texture";
import "@babylonjs/core/PostProcesses/RenderPipeline/postProcessRenderPipelineManagerSceneComponent";
import { PostProcessType } from "./postProcessTypes";
@@ -50,6 +48,8 @@ import { BlackHole } from "../stellarObjects/blackHole/blackHole";
import { NeutronStar } from "../stellarObjects/neutronStar/neutronStar";
import { CelestialBody } from "../architecture/celestialBody";
import { StellarObject } from "../architecture/stellarObject";
+import { PostProcessRenderPipelineManager } from "@babylonjs/core";
+import { PostProcessRenderPipeline } from "@babylonjs/core/PostProcesses/RenderPipeline/postProcessRenderPipeline";
/**
* The order in which the post processes are rendered when away from a planet
@@ -88,9 +88,11 @@ export class PostProcessManager {
private readonly engine: Engine;
private readonly scene: UberScene;
- private readonly spaceRenderingPipeline: UberRenderingPipeline;
- private readonly surfaceRenderingPipeline: UberRenderingPipeline;
- private currentRenderingPipeline: UberRenderingPipeline;
+ private readonly renderingPipelineManager: PostProcessRenderPipelineManager;
+
+ private readonly spaceRenderingPipeline: PostProcessRenderPipeline;
+ private readonly surfaceRenderingPipeline: PostProcessRenderPipeline;
+ private currentRenderingPipeline: PostProcessRenderPipeline;
private currentRenderingOrder: PostProcessType[] = spaceRenderingOrder;
@@ -142,6 +144,8 @@ export class PostProcessManager {
this.scene = scene;
this.engine = scene.getEngine();
+ this.renderingPipelineManager = scene.postProcessRenderPipelineManager;
+
this.colorCorrection = new ColorCorrection("colorCorrection", scene.getEngine());
this.colorCorrection.exposure = 1.5;
this.colorCorrection.gamma = 1.0;
@@ -156,11 +160,11 @@ export class PostProcessManager {
return [this.fxaa];
});
- this.spaceRenderingPipeline = new UberRenderingPipeline("space", scene.getEngine());
- scene.postProcessRenderPipelineManager.addPipeline(this.spaceRenderingPipeline);
+ this.spaceRenderingPipeline = new PostProcessRenderPipeline(scene.getEngine(), "spaceRenderingPipeline");
+ this.renderingPipelineManager.addPipeline(this.spaceRenderingPipeline);
- this.surfaceRenderingPipeline = new UberRenderingPipeline("surface", scene.getEngine());
- scene.postProcessRenderPipelineManager.addPipeline(this.surfaceRenderingPipeline);
+ this.surfaceRenderingPipeline = new PostProcessRenderPipeline(scene.getEngine(), "surfaceRenderingPipeline");
+ this.renderingPipelineManager.addPipeline(this.surfaceRenderingPipeline);
this.currentRenderingPipeline = this.spaceRenderingPipeline;
@@ -337,7 +341,7 @@ export class PostProcessManager {
public setSpaceOrder() {
if (this.currentRenderingPipeline === this.spaceRenderingPipeline) return;
- this.surfaceRenderingPipeline.detachCamera(this.scene.getActiveCamera());
+ this.renderingPipelineManager.detachCamerasFromRenderPipeline(this.surfaceRenderingPipeline.name, [this.scene.getActiveCamera()]);
this.currentRenderingPipeline = this.spaceRenderingPipeline;
this.currentRenderingOrder = spaceRenderingOrder;
this.init();
@@ -345,7 +349,7 @@ export class PostProcessManager {
public setSurfaceOrder() {
if (this.currentRenderingPipeline === this.surfaceRenderingPipeline) return;
- this.spaceRenderingPipeline.detachCamera(this.scene.getActiveCamera());
+ this.renderingPipelineManager.detachCamerasFromRenderPipeline(this.spaceRenderingPipeline.name, [this.scene.getActiveCamera()]);
this.currentRenderingPipeline = this.surfaceRenderingPipeline;
this.currentRenderingOrder = surfaceRenderingOrder;
this.init();
@@ -466,7 +470,7 @@ export class PostProcessManager {
//this.currentRenderingPipeline.addEffect(this.bloomRenderEffect);
this.currentRenderingPipeline.addEffect(this.colorCorrectionRenderEffect);
- this.currentRenderingPipeline.attachToCamera(this.scene.getActiveCamera());
+ this.renderingPipelineManager.attachCamerasToRenderPipeline(this.currentRenderingPipeline.name, [this.scene.getActiveCamera()]);
}
/**
@@ -486,6 +490,9 @@ export class PostProcessManager {
this.colorCorrection.dispose();
this.fxaa.dispose();
+ this.surfaceRenderingPipeline._detachCameras(this.surfaceRenderingPipeline.cameras);
+ this.spaceRenderingPipeline._detachCameras(this.spaceRenderingPipeline.cameras);
+
this.surfaceRenderingPipeline.dispose();
this.spaceRenderingPipeline.dispose();
}
diff --git a/src/ts/proceduralAssets/butterfly/butterfly.ts b/src/ts/proceduralAssets/butterfly/butterfly.ts
index ab2b63802..1ebfef3f9 100644
--- a/src/ts/proceduralAssets/butterfly/butterfly.ts
+++ b/src/ts/proceduralAssets/butterfly/butterfly.ts
@@ -18,7 +18,6 @@
import { VertexData } from "@babylonjs/core/Meshes/mesh.vertexData";
import { Mesh } from "@babylonjs/core/Meshes/mesh";
import { Scene } from "@babylonjs/core/scene";
-import { createButterflyMaterial } from "./butterflyMaterial";
export function createButterfly(scene: Scene) {
const positions = new Float32Array(6 * 3);
@@ -103,7 +102,5 @@ export function createButterfly(scene: Scene) {
mesh.scaling.scaleInPlace(0.2);
mesh.bakeCurrentTransformIntoVertices();
- mesh.material = createButterflyMaterial(scene);
-
return mesh;
}
diff --git a/src/ts/proceduralAssets/butterfly/butterflyMaterial.ts b/src/ts/proceduralAssets/butterfly/butterflyMaterial.ts
index cd3df67dc..6600b2adb 100644
--- a/src/ts/proceduralAssets/butterfly/butterflyMaterial.ts
+++ b/src/ts/proceduralAssets/butterfly/butterflyMaterial.ts
@@ -23,42 +23,38 @@ import butterflyVertex from "../../../shaders/butterflyMaterial/butterflyVertex.
import butterflyTexture from "../../../asset/butterfly.png";
import { Texture } from "@babylonjs/core/Materials/Textures/texture";
-import { TransformNode } from "@babylonjs/core/Meshes/transformNode";
import { Vector3 } from "@babylonjs/core/Maths/math.vector";
-import { PointLight } from "@babylonjs/core/Lights/pointLight";
-
-export function createButterflyMaterial(scene: Scene, player?: TransformNode) {
- const shaderName = "butterflyMaterial";
- Effect.ShadersStore[`${shaderName}FragmentShader`] = butterflyFragment;
- Effect.ShadersStore[`${shaderName}VertexShader`] = butterflyVertex;
-
- const butterflyMaterial = new ShaderMaterial(shaderName, scene, shaderName, {
- attributes: ["position", "normal", "uv"],
- uniforms: ["world", "worldView", "worldViewProjection", "view", "projection", "viewProjection", "time", "lightDirection", "playerPosition"],
- defines: ["#define INSTANCES"],
- samplers: ["butterflyTexture"]
- });
-
- butterflyMaterial.setTexture("butterflyTexture", new Texture(butterflyTexture, scene));
- butterflyMaterial.backFaceCulling = false;
-
- let elapsedSeconds = 0;
- scene.onBeforeRenderObservable.add(() => {
- elapsedSeconds += scene.getEngine().getDeltaTime() / 1000;
-
- if (scene.activeCamera === null) throw new Error("Active camera is null");
-
- const starIndex = scene.lights.findIndex((light) => light instanceof PointLight);
- if (starIndex === -1) throw new Error("Could not find star light");
- const star = scene.lights[starIndex] as PointLight;
-
- const lightDirection = star.position.subtract(scene.activeCamera.globalPosition).normalize();
- butterflyMaterial.setVector3("lightDirection", lightDirection);
-
- const playerPosition = player?.position ?? new Vector3(0, 0, 0);
- butterflyMaterial.setVector3("playerPosition", playerPosition);
- butterflyMaterial.setFloat("time", elapsedSeconds);
- });
-
- return butterflyMaterial;
-}
+import { Transformable } from "../../architecture/transformable";
+
+export class ButterflyMaterial extends ShaderMaterial {
+ private elapsedSeconds = 0;
+ constructor(scene: Scene) {
+ const shaderName = "butterflyMaterial";
+ Effect.ShadersStore[`${shaderName}FragmentShader`] = butterflyFragment;
+ Effect.ShadersStore[`${shaderName}VertexShader`] = butterflyVertex;
+
+ super(shaderName, scene, shaderName, {
+ attributes: ["position", "normal", "uv"],
+ uniforms: ["world", "worldView", "worldViewProjection", "view", "projection", "viewProjection", "time", "lightDirection", "playerPosition"],
+ defines: ["#define INSTANCES"],
+ samplers: ["butterflyTexture"]
+ });
+
+ this.setVector3("lightDirection", new Vector3(0, 0, 0));
+ this.setVector3("playerPosition", new Vector3(0, 0, 0));
+ this.setFloat("time", 0);
+ this.setTexture("butterflyTexture", new Texture(butterflyTexture, scene));
+ this.backFaceCulling = false;
+ }
+
+ update(stars: Transformable[], playerPosition: Vector3, deltaSeconds: number) {
+ this.elapsedSeconds += deltaSeconds;
+
+ const star = stars[0];
+ const lightDirection = star.getTransform().getAbsolutePosition().subtract(playerPosition).normalize();
+ this.setVector3("lightDirection", lightDirection);
+
+ this.setVector3("playerPosition", playerPosition);
+ this.setFloat("time", this.elapsedSeconds);
+ }
+}
\ No newline at end of file
diff --git a/src/ts/proceduralAssets/grass/grassBlade.ts b/src/ts/proceduralAssets/grass/grassBlade.ts
index 7fb9e2c3c..0c7dc34c3 100644
--- a/src/ts/proceduralAssets/grass/grassBlade.ts
+++ b/src/ts/proceduralAssets/grass/grassBlade.ts
@@ -19,7 +19,6 @@ import { Mesh } from "@babylonjs/core/Meshes/mesh";
import { VertexData } from "@babylonjs/core/Meshes/mesh.vertexData";
import { Scene } from "@babylonjs/core/scene";
import { Vector3 } from "@babylonjs/core/Maths/math.vector";
-import { createGrassMaterial } from "./grassMaterial";
// rotation using https://www.wikiwand.com/en/Rodrigues%27_rotation_formula
function rotateAround(vector: Vector3, axis: Vector3, theta: number) {
@@ -100,7 +99,5 @@ export function createGrassBlade(scene: Scene, nbStacks: number) {
const grassBlade = new Mesh("grassBlade", scene);
vertexData.applyToMesh(grassBlade);
- grassBlade.material = createGrassMaterial(scene);
-
return grassBlade;
}
diff --git a/src/ts/proceduralAssets/grass/grassMaterial.ts b/src/ts/proceduralAssets/grass/grassMaterial.ts
index fe9bcbc40..62c743583 100644
--- a/src/ts/proceduralAssets/grass/grassMaterial.ts
+++ b/src/ts/proceduralAssets/grass/grassMaterial.ts
@@ -21,49 +21,39 @@ import { Scene } from "@babylonjs/core/scene";
import grassFragment from "../../../shaders/grassMaterial/grassFragment.glsl";
import grassVertex from "../../../shaders/grassMaterial/grassVertex.glsl";
-import { TransformNode } from "@babylonjs/core/Meshes/transformNode";
import { Texture } from "@babylonjs/core/Materials/Textures/texture";
import perlinNoise from "../../../asset/perlin.png";
-import { PointLight } from "@babylonjs/core/Lights/pointLight";
-
-export function createGrassMaterial(scene: Scene) {
- const shaderName = "grassMaterial";
- Effect.ShadersStore[`${shaderName}FragmentShader`] = grassFragment;
- Effect.ShadersStore[`${shaderName}VertexShader`] = grassVertex;
-
- const grassMaterial = new ShaderMaterial(shaderName, scene, shaderName, {
- attributes: ["position", "normal"],
- uniforms: ["world", "worldView", "worldViewProjection", "view", "projection", "viewProjection", "time", "lightDirection", "cameraPosition", "playerPosition"],
- defines: ["#define INSTANCES"],
- samplers: ["perlinNoise"]
- });
-
- const perlinTexture = new Texture(perlinNoise, scene);
-
- grassMaterial.backFaceCulling = false;
- grassMaterial.setTexture("perlinNoise", perlinTexture);
-
- let elapsedSeconds = 0;
- scene.onBeforeRenderObservable.add(() => {
- elapsedSeconds += scene.getEngine().getDeltaTime() / 1000;
-
- if (scene.activeCamera === null) throw new Error("Active camera is null");
-
- const starIndex = scene.lights.findIndex((light) => light instanceof PointLight);
- if (starIndex === -1) throw new Error("Could not find star light");
- const star = scene.lights[starIndex] as PointLight;
-
- const lightDirection = star.position.subtract(scene.activeCamera.globalPosition).normalize();
- grassMaterial.setVector3("lightDirection", lightDirection);
-
- if (scene.activeCamera.parent !== null && !(scene.activeCamera.parent instanceof TransformNode)) throw new Error("Camera parent is not a TransformNode");
-
- const playerPosition = scene.activeCamera.parent !== null ? scene.activeCamera.parent.getAbsolutePosition() : scene.activeCamera.globalPosition; // high y to avoid interaction with grass
- const cameraPosition = scene.activeCamera.globalPosition;
- grassMaterial.setVector3("playerPosition", playerPosition);
- grassMaterial.setVector3("cameraPosition", cameraPosition);
- grassMaterial.setFloat("time", elapsedSeconds);
- });
-
- return grassMaterial;
+import { Transformable } from "../../architecture/transformable";
+import { Vector3 } from "@babylonjs/core/Maths/math.vector";
+
+export class GrassMaterial extends ShaderMaterial {
+ private elapsedSeconds = 0;
+ constructor(scene: Scene) {
+ const shaderName = "grassMaterial";
+ Effect.ShadersStore[`${shaderName}FragmentShader`] = grassFragment;
+ Effect.ShadersStore[`${shaderName}VertexShader`] = grassVertex;
+
+ super(shaderName, scene, shaderName, {
+ attributes: ["position", "normal"],
+ uniforms: ["world", "worldView", "worldViewProjection", "view", "projection", "viewProjection", "time", "lightDirection", "cameraPosition", "playerPosition"],
+ defines: ["#define INSTANCES"],
+ samplers: ["perlinNoise"]
+ });
+
+ const perlinTexture = new Texture(perlinNoise, scene);
+
+ this.backFaceCulling = false;
+ this.setTexture("perlinNoise", perlinTexture);
+ }
+
+ update(stars: Transformable[], playerPosition: Vector3, deltaSeconds: number) {
+ this.elapsedSeconds += deltaSeconds;
+
+ const star = stars[0];
+ const lightDirection = star.getTransform().getAbsolutePosition().subtract(playerPosition).normalize();
+ this.setVector3("lightDirection", lightDirection);
+
+ this.setVector3("playerPosition", playerPosition);
+ this.setFloat("time", this.elapsedSeconds);
+ }
}
diff --git a/src/ts/randomizer.ts b/src/ts/randomizer.ts
index aec492cd7..299c5421b 100644
--- a/src/ts/randomizer.ts
+++ b/src/ts/randomizer.ts
@@ -23,69 +23,30 @@ import { positionNearObjectBrightSide } from "./utils/positionNearObject";
import { CosmosJourneyer } from "./cosmosJourneyer";
import { BODY_TYPE } from "./model/common";
import { SystemSeed } from "./utils/systemSeed";
-import { Vector3 } from "@babylonjs/core/Maths/math.vector";
-import { Quaternion } from "@babylonjs/core/Maths/math";
-import { setRotationQuaternion } from "./uberCore/transforms/basicTransform";
-const engine = new CosmosJourneyer();
+const engine = await CosmosJourneyer.CreateAsync();
-await engine.setup();
-
-const starSystemView = engine.getStarSystemView();
+const starSystemView = engine.starSystemView;
const scene = starSystemView.scene;
-//check if url contains a seed
-const urlParams = new URLSearchParams(window.location.search);
-const urlStarMapX = urlParams.get("starMapX");
-const urlStarMapY = urlParams.get("starMapY");
-const urlStarMapZ = urlParams.get("starMapZ");
-const urlIndex = urlParams.get("index");
-const urlObjectIndex = urlParams.get("objectIndex");
-const urlPositionX = urlParams.get("positionX");
-const urlPositionY = urlParams.get("positionY");
-const urlPositionZ = urlParams.get("positionZ");
-const urlRotationX = urlParams.get("rotationQuaternionX");
-const urlRotationY = urlParams.get("rotationQuaternionY");
-const urlRotationZ = urlParams.get("rotationQuaternionZ");
-const urlRotationW = urlParams.get("rotationQuaternionW");
-
-const starMapX = urlStarMapX !== null ? Number(urlStarMapX) : Math.trunc((Math.random() * 2 - 1) * Number.MAX_SAFE_INTEGER * 0.1);
-const starMapY = urlStarMapY !== null ? Number(urlStarMapY) : Math.trunc((Math.random() * 2 - 1) * Number.MAX_SAFE_INTEGER * 0.1);
-const starMapZ = urlStarMapZ !== null ? Number(urlStarMapZ) : Math.trunc((Math.random() * 2 - 1) * Number.MAX_SAFE_INTEGER * 0.1);
-const index = urlIndex !== null ? Number(urlIndex) : 0;
-const objectIndex = urlObjectIndex !== null ? Number(urlObjectIndex) : 0;
-const positionX = urlPositionX !== null ? Number(urlPositionX) : 0;
-const positionY = urlPositionY !== null ? Number(urlPositionY) : 0;
-const positionZ = urlPositionZ !== null ? Number(urlPositionZ) : 0;
-const rotationX = urlRotationX !== null ? Number(urlRotationX) : 0;
-const rotationY = urlRotationY !== null ? Number(urlRotationY) : 0;
-const rotationZ = urlRotationZ !== null ? Number(urlRotationZ) : 0;
-const rotationW = urlRotationW !== null ? Number(urlRotationW) : 1;
+const starMapX = Math.trunc((Math.random() * 2 - 1) * Number.MAX_SAFE_INTEGER * 0.1);
+const starMapY = Math.trunc((Math.random() * 2 - 1) * Number.MAX_SAFE_INTEGER * 0.1);
+const starMapZ = Math.trunc((Math.random() * 2 - 1) * Number.MAX_SAFE_INTEGER * 0.1);
+const index = 0;
const seed = new SystemSeed(starMapX, starMapY, starMapZ, index);
const starSystem = new StarSystemController(seed, scene);
starSystemView.setStarSystem(starSystem, true);
-engine.getStarMap().setCurrentStarSystem(seed);
+engine.starMap.setCurrentStarSystem(seed);
engine.init(true);
-const position = new Vector3(positionX, positionY, positionZ);
-const rotation = new Quaternion(rotationX, rotationY, rotationZ, rotationW);
-
const nbRadius = starSystem.model.getBodyTypeOfStar(0) === BODY_TYPE.BLACK_HOLE ? 8 : 3;
-if (objectIndex >= starSystem.getOrbitalObjects().length) throw new Error(`Object index (${objectIndex}) out of bound (0 - ${starSystem.getOrbitalObjects().length - 1})!`);
-const object = starSystem.getOrbitalObjects().length > 0 ? starSystem.getOrbitalObjects()[objectIndex] : starSystem.stellarObjects[0];
-if(position.length() === 0) positionNearObjectBrightSide(scene.getActiveController(), object, starSystem, nbRadius);
-else {
- const absolutePosition = Vector3.TransformCoordinates(position, object.getTransform().computeWorldMatrix());
- scene.getActiveController().getTransform().setAbsolutePosition(absolutePosition);
-
- const absoluteRotationQuaternion = rotation.multiply(object.getTransform().absoluteRotationQuaternion);
- setRotationQuaternion(scene.getActiveController().getTransform(), absoluteRotationQuaternion);
-}
+const planet = starSystem.planets.length > 0 ? starSystem.planets[0] : starSystem.stellarObjects[0];
+positionNearObjectBrightSide(scene.getActiveController(), planet, starSystem, nbRadius);
starSystemView.ui.setEnabled(true);
starSystemView.showUI();
diff --git a/src/ts/saveFile/saveFileData.ts b/src/ts/saveFile/saveFileData.ts
index ccc4e31d3..1071079a0 100644
--- a/src/ts/saveFile/saveFileData.ts
+++ b/src/ts/saveFile/saveFileData.ts
@@ -1,3 +1,5 @@
+import { isJsonStringValidUniverseCoordinates, UniverseCoordinates } from "./universeCoordinates";
+
/**
* Data structure for the save file to allow restoring current star system and position.
*/
@@ -8,54 +10,9 @@ export type SaveFileData = {
version: string;
/**
- * The seed of the current star system.
- */
- starSystem: {
- starSectorX: number;
- starSectorY: number;
- starSectorZ: number;
- starSectorIndex: number;
- };
-
- /**
- * The index of the nearest orbital object.
- */
- nearestOrbitalObjectIndex: number;
-
- /**
- * The x coordinate of the player's position in the nearest orbital object's frame of reference.
- */
- positionX: number;
-
- /**
- * The y coordinate of the player's position in the nearest orbital object's frame of reference.
- */
- positionY: number;
-
- /**
- * The z coordinate of the player's position in the nearest orbital object's frame of reference.
- */
- positionZ: number;
-
- /**
- * The x component of the player's rotation quaternion in the nearest orbital object's frame of reference.
- */
- rotationQuaternionX: number;
-
- /**
- * The y component of the player's rotation quaternion in the nearest orbital object's frame of reference.
- */
- rotationQuaternionY: number;
-
- /**
- * The z component of the player's rotation quaternion in the nearest orbital object's frame of reference.
- */
- rotationQuaternionZ: number;
-
- /**
- * The w component of the player's rotation quaternion in the nearest orbital object's frame of reference.
+ * The coordinates of the current star system and the coordinates inside the star system.
*/
- rotationQuaternionW: number;
+ universeCoordinates: UniverseCoordinates;
};
/**
@@ -69,21 +26,9 @@ export function isJsonStringValidSaveFileData(jsonString: string): boolean {
if (typeof data.version !== "string") return false;
- if (typeof data.starSystem !== "object") return false;
- if (typeof data.starSystem.starSectorX !== "number") return false;
- if (typeof data.starSystem.starSectorY !== "number") return false;
- if (typeof data.starSystem.starSectorZ !== "number") return false;
- if (typeof data.starSystem.starSectorIndex !== "number") return false;
+ if (typeof data.universeCoordinates !== "object") return false;
- if (typeof data.nearestOrbitalObjectIndex !== "number") return false;
-
- if (typeof data.positionX !== "number") return false;
- if (typeof data.positionY !== "number") return false;
- if (typeof data.positionZ !== "number") return false;
-
- if (typeof data.rotationQuaternionX !== "number") return false;
- if (typeof data.rotationQuaternionY !== "number") return false;
- if (typeof data.rotationQuaternionZ !== "number") return false;
+ if (!isJsonStringValidUniverseCoordinates(JSON.stringify(data.universeCoordinates))) return false;
return true;
} catch (e) {
@@ -99,23 +44,5 @@ export function isJsonStringValidSaveFileData(jsonString: string): boolean {
export function parseSaveFileData(jsonString: string): SaveFileData {
if (!isJsonStringValidSaveFileData(jsonString)) throw new Error("Invalid save file data");
- const data = JSON.parse(jsonString);
-
- return {
- version: data.version,
- starSystem: {
- starSectorX: data.starSystem.starSectorX,
- starSectorY: data.starSystem.starSectorY,
- starSectorZ: data.starSystem.starSectorZ,
- starSectorIndex: data.starSystem.starSectorIndex
- },
- nearestOrbitalObjectIndex: data.nearestOrbitalObjectIndex,
- positionX: data.positionX,
- positionY: data.positionY,
- positionZ: data.positionZ,
- rotationQuaternionX: data.rotationQuaternionX,
- rotationQuaternionY: data.rotationQuaternionY,
- rotationQuaternionZ: data.rotationQuaternionZ,
- rotationQuaternionW: data.rotationQuaternionW
- };
+ return JSON.parse(jsonString);
}
diff --git a/src/ts/saveFile/universeCoordinates.ts b/src/ts/saveFile/universeCoordinates.ts
new file mode 100644
index 000000000..5d4c2dd89
--- /dev/null
+++ b/src/ts/saveFile/universeCoordinates.ts
@@ -0,0 +1,80 @@
+import { SystemSeedSerialized } from "../utils/systemSeed";
+
+export type UniverseCoordinates = {
+ /**
+ * The seed of the current star system.
+ */
+ starSystem: SystemSeedSerialized;
+
+ /**
+ * The index of the nearest orbital object.
+ */
+ nearestOrbitalObjectIndex: number;
+
+ /**
+ * The x coordinate of the player's position in the nearest orbital object's frame of reference.
+ */
+ positionX: number;
+
+ /**
+ * The y coordinate of the player's position in the nearest orbital object's frame of reference.
+ */
+ positionY: number;
+
+ /**
+ * The z coordinate of the player's position in the nearest orbital object's frame of reference.
+ */
+ positionZ: number;
+
+ /**
+ * The x component of the player's rotation quaternion in the nearest orbital object's frame of reference.
+ */
+ rotationQuaternionX: number;
+
+ /**
+ * The y component of the player's rotation quaternion in the nearest orbital object's frame of reference.
+ */
+ rotationQuaternionY: number;
+
+ /**
+ * The z component of the player's rotation quaternion in the nearest orbital object's frame of reference.
+ */
+ rotationQuaternionZ: number;
+
+ /**
+ * The w component of the player's rotation quaternion in the nearest orbital object's frame of reference.
+ */
+ rotationQuaternionW: number;
+};
+
+/**
+ * Checks if a string is a valid universe coordinates json data.
+ * @param jsonString The string to check.
+ */
+export function isJsonStringValidUniverseCoordinates(jsonString: string): boolean {
+ try {
+ const data = JSON.parse(jsonString);
+ if (typeof data !== "object") return false;
+
+ if (typeof data.starSystem !== "object") return false;
+ if (typeof data.starSystem.starSectorX !== "number") return false;
+ if (typeof data.starSystem.starSectorY !== "number") return false;
+ if (typeof data.starSystem.starSectorZ !== "number") return false;
+ if (typeof data.starSystem.index !== "number") return false;
+
+ if (typeof data.nearestOrbitalObjectIndex !== "number") return false;
+
+ if (typeof data.positionX !== "number") return false;
+ if (typeof data.positionY !== "number") return false;
+ if (typeof data.positionZ !== "number") return false;
+
+ if (typeof data.rotationQuaternionX !== "number") return false;
+ if (typeof data.rotationQuaternionY !== "number") return false;
+ if (typeof data.rotationQuaternionZ !== "number") return false;
+ if (typeof data.rotationQuaternionW !== "number") return false;
+
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/ts/spaceship/spaceship.ts b/src/ts/spaceship/spaceship.ts
index c52489ff8..89d256e99 100644
--- a/src/ts/spaceship/spaceship.ts
+++ b/src/ts/spaceship/spaceship.ts
@@ -29,7 +29,13 @@ import { Observable } from "@babylonjs/core/Misc/observable";
import { Axis } from "@babylonjs/core/Maths/math.axis";
import { HavokPlugin } from "@babylonjs/core/Physics/v2/Plugins/havokPlugin";
import { setEnabledBody } from "../utils/havok";
-import { getForwardDirection, getUpwardDirection, rotate, translate } from "../uberCore/transforms/basicTransform";
+import {
+ getForwardDirection,
+ getUpwardDirection,
+ rotate,
+ setRotationQuaternion,
+ translate
+} from "../uberCore/transforms/basicTransform";
import { TransformNode } from "@babylonjs/core/Meshes";
import { Assets } from "../assets";
import { PhysicsRaycastResult } from "@babylonjs/core/Physics/physicsRaycastResult";
@@ -37,6 +43,7 @@ import { PhysicsEngineV2 } from "@babylonjs/core/Physics/v2";
import { CollisionMask } from "../settings";
import { Transformable } from "../architecture/transformable";
import { WarpTunnel } from "../utils/warpTunnel";
+import { Quaternion } from "@babylonjs/core/Maths/math";
enum ShipState {
FLYING,
@@ -75,6 +82,7 @@ export class Spaceship implements Transformable {
constructor(scene: Scene) {
this.instanceRoot = Assets.CreateSpaceShipInstance();
+ setRotationQuaternion(this.instanceRoot, Quaternion.Identity());
this.aggregate = new PhysicsAggregate(
this.instanceRoot,
@@ -224,7 +232,7 @@ export class Spaceship implements Transformable {
this.warpDrive.update(currentForwardSpeed, this.closestObject.distance, this.closestObject.radius, deltaTime);
// the warp throttle goes from 0.1 to 1 smoothly using an inverse function
- if (this.warpDrive.isEnabled()) this.warpTunnel.setThrottle(1 - 1 / (1.1 * (1 + 1e-6 * this.warpDrive.getWarpSpeed())));
+ if (this.warpDrive.isEnabled()) this.warpTunnel.setThrottle(1 - 1 / (1.1 * (1 + 1e-7 * this.warpDrive.getWarpSpeed())));
else this.warpTunnel.setThrottle(0);
for (const thruster of this.mainThrusters) thruster.update();
diff --git a/src/ts/starSystem/StarSystemView.ts b/src/ts/starSystem/StarSystemView.ts
index 226f17d14..ec041eb74 100644
--- a/src/ts/starSystem/StarSystemView.ts
+++ b/src/ts/starSystem/StarSystemView.ts
@@ -150,7 +150,7 @@ export class StarSystemView {
this.scene.getEngine().loadingScreen.displayLoadingUI();
this.scene.getEngine().loadingScreen.loadingUIText = `Warping to ${this.getStarSystem().model.getName()}`;
- this.getStarSystem().initPositions(100, this.chunkForge);
+ this.getStarSystem().initPositions(10, this.chunkForge);
this.ui.createObjectOverlays(this.getStarSystem().getOrbitalObjects());
const firstBody = this.getStarSystem().getBodies()[0];
@@ -209,6 +209,9 @@ export class StarSystemView {
update(deltaTime: number) {
const starSystem = this.getStarSystem();
+ Assets.ButterflyMaterial.update(starSystem.stellarObjects, this.scene.getActiveController().getTransform().getAbsolutePosition(), deltaTime);
+ Assets.GrassMaterial.update(starSystem.stellarObjects, this.scene.getActiveController().getTransform().getAbsolutePosition(), deltaTime);
+
this.chunkForge.update();
starSystem.update(deltaTime * Settings.TIME_MULTIPLIER, this.chunkForge);
diff --git a/src/ts/uberCore/uberRenderingPipeline.ts b/src/ts/uberCore/uberRenderingPipeline.ts
deleted file mode 100644
index c278f97c4..000000000
--- a/src/ts/uberCore/uberRenderingPipeline.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-// This file is part of CosmosJourneyer
-//
-// 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 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 General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-import { Camera } from "@babylonjs/core/Cameras/camera";
-import { Engine } from "@babylonjs/core/Engines/engine";
-import { PostProcessRenderPipeline } from "@babylonjs/core/PostProcesses/RenderPipeline/postProcessRenderPipeline";
-
-export class UberRenderingPipeline extends PostProcessRenderPipeline {
- constructor(name: string, engine: Engine) {
- super(engine, name);
- }
-
- attachToCamera(camera: Camera) {
- this._attachCameras([camera], false);
- }
-
- detachCamera(camera: Camera) {
- this._detachCameras([camera]);
- }
-
- detachCameras() {
- this._detachCameras(this.cameras);
- }
-
- public override dispose() {
- this.detachCameras();
- super.dispose();
- }
-}
diff --git a/src/ts/utils/base64.ts b/src/ts/utils/base64.ts
new file mode 100644
index 000000000..361b789a5
--- /dev/null
+++ b/src/ts/utils/base64.ts
@@ -0,0 +1,7 @@
+export function encodeBase64(str: string): string {
+ return btoa(str);
+}
+
+export function decodeBase64(str: string): string {
+ return atob(str);
+}
\ No newline at end of file
diff --git a/src/ts/utils/systemSeed.ts b/src/ts/utils/systemSeed.ts
index 947168749..bc422c151 100644
--- a/src/ts/utils/systemSeed.ts
+++ b/src/ts/utils/systemSeed.ts
@@ -20,6 +20,13 @@ import { hashVec3 } from "./hashVec3";
import { centeredRand } from "extended-random";
import { Settings } from "../settings";
+export type SystemSeedSerialized = {
+ starSectorX: number;
+ starSectorY: number;
+ starSectorZ: number;
+ index: number;
+};
+
export class SystemSeed {
readonly starSectorX: number;
readonly starSectorY: number;
@@ -45,4 +52,17 @@ export class SystemSeed {
toString(): string {
return `${this.starSectorX},${this.starSectorY},${this.starSectorZ},${this.index}`;
}
+
+ serialize(): SystemSeedSerialized {
+ return {
+ starSectorX: this.starSectorX,
+ starSectorY: this.starSectorY,
+ starSectorZ: this.starSectorZ,
+ index: this.index
+ };
+ }
+
+ static Deserialize(data: SystemSeedSerialized): SystemSeed {
+ return new SystemSeed(data.starSectorX, data.starSectorY, data.starSectorZ, data.index);
+ }
}
diff --git a/src/ts/utils/warpTunnel.ts b/src/ts/utils/warpTunnel.ts
index ab6c9d497..26da4fb92 100644
--- a/src/ts/utils/warpTunnel.ts
+++ b/src/ts/utils/warpTunnel.ts
@@ -27,6 +27,7 @@ import { Quaternion } from "@babylonjs/core/Maths/math";
import { StandardMaterial } from "@babylonjs/core/Materials/standardMaterial";
import { Color3, Color4 } from "@babylonjs/core/Maths/math.color";
import { getForwardDirection } from "../uberCore/transforms/basicTransform";
+import { uniformRandBool } from "extended-random";
/**
* @see https://playground.babylonjs.com/#GLZ1PX#1241 (SPS)
@@ -101,7 +102,7 @@ export class WarpTunnel implements Transformable {
particle.position.addInPlace(direction.scale(Math.random() * 10));
particle.position.addInPlace(this.anchor.getAbsolutePosition());
- particle.velocity.copyFrom(direction.scale(200));
+ particle.velocity.copyFrom(direction.scale(300));
particle.rotationQuaternion = rotationQuaternion;
@@ -196,8 +197,10 @@ export class WarpTunnel implements Transformable {
updateGlobals();
if (this.nbParticlesAlive < this.targetNbParticles && this.recycledParticles.length > 0) {
- instanceFromStock();
- this.nbParticlesAlive++;
+ if(Math.random() < this.targetNbParticles / WarpTunnel.MAX_NB_PARTICLES) {
+ instanceFromStock();
+ this.nbParticlesAlive++;
+ }
}
if (this.nbParticlesAlive === 0 && SPS.mesh.isEnabled()) {