From e791889971900ab87eb977e1ed1ea94d8ba53b44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Mon, 8 Jan 2024 10:19:41 +0100 Subject: [PATCH 01/14] added landing pad --- src/asset/landingpad.glb | Bin 0 -> 15148 bytes src/ts/assets.ts | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/asset/landingpad.glb diff --git a/src/asset/landingpad.glb b/src/asset/landingpad.glb new file mode 100644 index 0000000000000000000000000000000000000000..eb8ad5e7d728b3142044f56d07230b569af0ab3a GIT binary patch literal 15148 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 S^?VZ3qtvnKV_r>~v*aI7P_N$r literal 0 HcmV?d00001 diff --git a/src/ts/assets.ts b/src/ts/assets.ts index c0ad04c03..e6c6d8c3a 100644 --- a/src/ts/assets.ts +++ b/src/ts/assets.ts @@ -25,6 +25,7 @@ import banana from "../asset/banana/banana.glb"; import endeavorSpaceship from "../asset/spaceship/endeavour.glb"; import character from "../asset/character.glb"; import rock from "../asset/rock.glb"; +import landingPad from "../asset/landingpad.glb"; import ouchSound from "../asset/sound/ouch.mp3"; import engineRunningSound from "../asset/sound/engineRunning.mp3"; @@ -71,6 +72,7 @@ export class Assets { private static Banana: Mesh; private static Character: Mesh; static Rock: Mesh; + private static LandingPad: Mesh; public static ScatterCube: Mesh; @@ -174,6 +176,18 @@ export class Assets { console.log("Rock loaded"); }; + const landingPadTask = Assets.manager.addMeshTask("landingPadTask", "", "", landingPad); + landingPadTask.onSuccess = function (task: MeshAssetTask) { + Assets.LandingPad = task.loadedMeshes[0] as Mesh; + Assets.LandingPad.isVisible = false; + + for (const mesh of Assets.LandingPad.getChildMeshes()) { + mesh.isVisible = false; + } + + console.log("LandingPad loaded"); + }; + const ouchSoundTask = Assets.manager.addBinaryFileTask("ouchSoundTask", ouchSound); ouchSoundTask.onSuccess = function (task) { Assets.OuchSound = new Sound("OuchSound", task.data, scene); @@ -242,6 +256,10 @@ export class Assets { return Assets.Rock.instantiateHierarchy(null, { doNotInstantiate: false }) as InstancedMesh; } + static CreateLandingPadInstance(): InstancedMesh { + return Assets.LandingPad.instantiateHierarchy(null, { doNotInstantiate: false }) as InstancedMesh; + } + static DebugMaterial(name: string, diffuse = false, wireframe = false) { const mat = new StandardMaterial(`${name}DebugMaterial`); if (!diffuse) { From 3daf9f64c7ef53e471b01d962af034031423adf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Mon, 8 Jan 2024 10:32:10 +0100 Subject: [PATCH 02/14] added basic landing playground --- src/ts/landingSimulator.ts | 65 ++++++++++++++++++++++++++++++++++++++ webpack.config.js | 9 +++++- 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/ts/landingSimulator.ts diff --git a/src/ts/landingSimulator.ts b/src/ts/landingSimulator.ts new file mode 100644 index 000000000..703a61252 --- /dev/null +++ b/src/ts/landingSimulator.ts @@ -0,0 +1,65 @@ +import "../styles/index.scss"; + +import { Engine } from "@babylonjs/core/Engines/engine"; +import HavokPhysics from "@babylonjs/havok"; +import { HavokPlugin } from "@babylonjs/core/Physics/v2/Plugins/havokPlugin"; +import { setMaxLinVel } from "./utils/havok"; +import { UberScene } from "./uberCore/uberScene"; +import { ScenePerformancePriority } from "@babylonjs/core"; +import { Vector3 } from "@babylonjs/core/Maths/math.vector"; +import { Assets } from "./assets"; +import { ShipControls } from "./spaceship/shipControls"; +import { translate } from "./uberCore/transforms/basicTransform"; +import { DirectionalLight } from "@babylonjs/core/Lights/directionalLight"; +import { Color4 } from "@babylonjs/core/Maths/math.color"; +import "@babylonjs/core/Physics/physicsEngineComponent"; +import { Keyboard } from "./inputs/keyboard"; +import { Mouse } from "./inputs/mouse"; + +const canvas = document.getElementById("renderer") as HTMLCanvasElement; +canvas.width = window.innerWidth; +canvas.height = window.innerHeight; + +const engine = new Engine(canvas, true); +engine.useReverseDepthBuffer = true; + +// Init Havok physics engine +const havokInstance = await HavokPhysics(); +const havokPlugin = new HavokPlugin(true, havokInstance); +setMaxLinVel(havokPlugin, 10000, 10000); +console.log(`Havok initialized`); + +const scene = new UberScene(engine); +scene.useRightHandedSystem = true; +scene.enablePhysics(Vector3.Zero(), havokPlugin); +scene.clearColor = new Color4(0.2, 0.2, 0.6, 1); + +const light = new DirectionalLight("light", new Vector3(0, -1, 1).normalize(), scene); + +await Assets.Init(scene); + +const spaceship = new ShipControls(scene); +spaceship.addInput(new Keyboard()); +spaceship.addInput(new Mouse(canvas)); +scene.setActiveController(spaceship); + +const landingPad = Assets.CreateLandingPadInstance(); +landingPad.position = new Vector3(0, -20, 50); + +scene.onBeforeRenderObservable.add(() => { + const deltaTime = scene.deltaTime / 1000; + scene.getActiveController().update(deltaTime); +}); + + +scene.executeWhenReady(() => { + engine.runRenderLoop(() => { + scene.render(); + }); +}); + +window.addEventListener("resize", () => { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + engine.resize(true); +}); diff --git a/webpack.config.js b/webpack.config.js index dfc8c9fba..9ea1c3a20 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -13,6 +13,7 @@ const config = { random: "./src/ts/randomizer.ts", blackHole: "./src/ts/blackHoleDemo.ts", physicSpaceship: "./src/ts/physicSpaceship.ts", + landingSimulator: "./src/ts/landingSimulator.ts", characterDemo: "./src/ts/characterDemo.ts", playground: "./src/ts/playground.ts", xr: "./src/ts/xr.ts", @@ -51,11 +52,17 @@ const config = { chunks: ["blackHole"] }), new HtmlWebpackPlugin({ - title: "Playground", + title: "Physics Spaceship", filename: "physicSpaceship.html", template: path.join(htmlPath, "index.html"), chunks: ["physicSpaceship"] }), + new HtmlWebpackPlugin({ + title: "Landing Simulator", + filename: "landingSimulator.html", + template: path.join(htmlPath, "index.html"), + chunks: ["landingSimulator"] + }), new HtmlWebpackPlugin({ title: "Character demo", filename: "characterdemo.html", From 76555ae8e961d3e955a13c4c6cb4ffd97d33c032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:11:33 +0100 Subject: [PATCH 03/14] separated spaceship from ship controls --- src/ts/blackHoleDemo.ts | 36 ++--- src/ts/index.ts | 61 ++++--- src/ts/randomizer.ts | 40 ++--- src/ts/spaceship/shipControls.ts | 241 +++------------------------- src/ts/spaceship/spaceship.ts | 235 +++++++++++++++++++++++++++ src/ts/starSystem/StarSystemView.ts | 2 +- 6 files changed, 325 insertions(+), 290 deletions(-) create mode 100644 src/ts/spaceship/spaceship.ts diff --git a/src/ts/blackHoleDemo.ts b/src/ts/blackHoleDemo.ts index 88a444618..36a1c0317 100644 --- a/src/ts/blackHoleDemo.ts +++ b/src/ts/blackHoleDemo.ts @@ -34,32 +34,32 @@ player.addInput(keyboard); player.addInput(mouse); player.addInput(gamepad); -const spaceshipController = new ShipControls(scene); -spaceshipController.getActiveCamera().maxZ = Settings.EARTH_RADIUS * 100000; -spaceshipController.addInput(keyboard); -spaceshipController.addInput(mouse); -spaceshipController.addInput(gamepad); +const shipControls = new ShipControls(scene); +shipControls.getActiveCamera().maxZ = Settings.EARTH_RADIUS * 100000; +shipControls.addInput(keyboard); +shipControls.addInput(mouse); +shipControls.addInput(gamepad); -scene.setActiveController(spaceshipController); +scene.setActiveController(shipControls); engine.registerStarSystemUpdateCallback(() => { - if (scene.getActiveController() != spaceshipController) return; + if (scene.getActiveController() != shipControls) return; - const shipPosition = spaceshipController.getTransform().getAbsolutePosition(); + const shipPosition = shipControls.getTransform().getAbsolutePosition(); const nearestBody = starSystemView.getStarSystem().getNearestOrbitalObject(); const distance = nearestBody.getTransform().getAbsolutePosition().subtract(shipPosition).length(); const radius = nearestBody.getBoundingRadius(); - spaceshipController.registerClosestObject(distance, radius); + shipControls.spaceship.registerClosestObject(distance, radius); - const warpDrive = spaceshipController.getWarpDrive(); + const warpDrive = shipControls.spaceship.getWarpDrive(); const shipInternalThrottle = warpDrive.getInternalThrottle(); const shipTargetThrottle = warpDrive.getTargetThrottle(); const throttleString = warpDrive.isEnabled() ? `${parsePercentageFrom01(shipInternalThrottle)}/${parsePercentageFrom01(shipTargetThrottle)}` - : `${parsePercentageFrom01(spaceshipController.getThrottle())}/100%`; + : `${parsePercentageFrom01(shipControls.spaceship.getThrottle())}/100%`; - (document.querySelector("#speedometer") as HTMLElement).innerHTML = `${throttleString} | ${parseSpeed(spaceshipController.getSpeed())}`; + (document.querySelector("#speedometer") as HTMLElement).innerHTML = `${throttleString} | ${parseSpeed(shipControls.spaceship.getSpeed())}`; }); const starSystemSeed = randRange(-1, 1, (step: number) => Math.random(), 0); @@ -75,18 +75,18 @@ planet.model.orbit.radius = 45 * planet.getRadius(); document.addEventListener("keydown", (e) => { if (engine.isPaused()) return; if (e.key === "g") { - if (scene.getActiveController() === spaceshipController) { + if (scene.getActiveController() === shipControls) { scene.setActiveController(player); - setRotationQuaternion(player.getTransform(), getRotationQuaternion(spaceshipController.getTransform()).clone()); + setRotationQuaternion(player.getTransform(), getRotationQuaternion(shipControls.getTransform()).clone()); starSystemView.getStarSystem().postProcessManager.rebuild(); - spaceshipController.setEnabled(false, engine.getHavokPlugin()); + shipControls.spaceship.setEnabled(false, engine.getHavokPlugin()); } else { - scene.setActiveController(spaceshipController); - setRotationQuaternion(spaceshipController.getTransform(), getRotationQuaternion(player.getTransform()).clone()); + scene.setActiveController(shipControls); + setRotationQuaternion(shipControls.getTransform(), getRotationQuaternion(player.getTransform()).clone()); starSystemView.getStarSystem().postProcessManager.rebuild(); - spaceshipController.setEnabled(true, engine.getHavokPlugin()); + shipControls.spaceship.setEnabled(true, engine.getHavokPlugin()); } } }); diff --git a/src/ts/index.ts b/src/ts/index.ts index ab1fbcafa..7992f38a2 100644 --- a/src/ts/index.ts +++ b/src/ts/index.ts @@ -26,7 +26,6 @@ import { Mouse } from "./inputs/mouse"; import { Keyboard } from "./inputs/keyboard"; import { StarModel } from "./stellarObjects/star/starModel"; import { RingsUniforms } from "./postProcesses/rings/ringsUniform"; -import { SpaceStation } from "./spacestation/spaceStation"; import { getMoonSeed } from "./planemos/common"; import { Gamepad } from "./inputs/gamepad"; @@ -50,11 +49,11 @@ defaultController.getActiveCamera().maxZ = maxZ; defaultController.addInput(keyboard); defaultController.addInput(gamepad); -const spaceshipController = new ShipControls(starSystemView.scene); -spaceshipController.getActiveCamera().maxZ = maxZ; -spaceshipController.addInput(keyboard); -spaceshipController.addInput(gamepad); -spaceshipController.addInput(mouse); +const shipControls = new ShipControls(starSystemView.scene); +shipControls.getActiveCamera().maxZ = maxZ; +shipControls.addInput(keyboard); +shipControls.addInput(gamepad); +shipControls.addInput(mouse); const characterController = new CharacterControls(starSystemView.scene); characterController.getTransform().setEnabled(false); @@ -63,43 +62,43 @@ characterController.addInput(keyboard); characterController.addInput(gamepad); // const physicsViewer = new PhysicsViewer(); -// physicsViewer.showBody(spaceshipController.aggregate.body); +// physicsViewer.showBody(shipControls.aggregate.body); mouse.onMouseLeaveObservable.add(() => { - if (starSystemView.scene.getActiveController() === spaceshipController) engine.pause(); + if (starSystemView.scene.getActiveController() === shipControls) engine.pause(); }); -starSystemView.scene.setActiveController(spaceshipController); +starSystemView.scene.setActiveController(shipControls); engine.registerStarSystemUpdateCallback(() => { - if (starSystemView.scene.getActiveController() != spaceshipController) return; + if (starSystemView.scene.getActiveController() != shipControls) return; - const shipPosition = spaceshipController.getTransform().getAbsolutePosition(); + const shipPosition = shipControls.getTransform().getAbsolutePosition(); const nearestBody = starSystemView.getStarSystem().getNearestOrbitalObject(); const distance = nearestBody.getTransform().getAbsolutePosition().subtract(shipPosition).length(); const radius = nearestBody.getBoundingRadius(); - spaceshipController.registerClosestObject(distance, radius); + shipControls.spaceship.registerClosestObject(distance, radius); - const warpDrive = spaceshipController.getWarpDrive(); + const warpDrive = shipControls.spaceship.getWarpDrive(); const shipInternalThrottle = warpDrive.getInternalThrottle(); const shipTargetThrottle = warpDrive.getTargetThrottle(); const throttleString = warpDrive.isEnabled() ? `${parsePercentageFrom01(shipInternalThrottle)}/${parsePercentageFrom01(shipTargetThrottle)}` - : `${parsePercentageFrom01(spaceshipController.getThrottle())}/100%`; + : `${parsePercentageFrom01(shipControls.spaceship.getThrottle())}/100%`; - (document.querySelector("#speedometer") as HTMLElement).innerHTML = `${throttleString} | ${parseSpeed(spaceshipController.getSpeed())}`; + (document.querySelector("#speedometer") as HTMLElement).innerHTML = `${throttleString} | ${parseSpeed(shipControls.spaceship.getSpeed())}`; characterController.setClosestWalkableObject(nearestBody); - spaceshipController.setClosestWalkableObject(nearestBody); + shipControls.spaceship.setClosestWalkableObject(nearestBody); }); engine.getStarMap().onWarpObservable.add(() => { - spaceshipController.thirdPersonCamera.radius = 30; + shipControls.thirdPersonCamera.radius = 30; }); engine.onToggleStarMapObservable.add((isStarMapOpen) => { - if (!isStarMapOpen) spaceshipController.thirdPersonCamera.radius = 30; + if (!isStarMapOpen) shipControls.thirdPersonCamera.radius = 30; }); console.log(`Time is going ${Settings.TIME_MULTIPLIER} time${Settings.TIME_MULTIPLIER > 1 ? "s" : ""} faster than in reality`); @@ -204,7 +203,7 @@ engine.init(); positionNearObject(starSystemView.scene.getActiveController(), planet, starSystem, 2); -spaceshipController.toggleWarpDrive(); +shipControls.spaceship.toggleWarpDrive(); const aresAtmosphere = starSystem.postProcessManager.getAtmosphere(ares); if (aresAtmosphere) { @@ -219,14 +218,14 @@ document.addEventListener("keydown", (e) => { if (engine.isPaused()) return; if(e.key === "y") { - if(starSystemView.scene.getActiveController() === spaceshipController) { + if(starSystemView.scene.getActiveController() === shipControls) { console.log("disembark"); characterController.getTransform().setEnabled(true); - characterController.getTransform().setAbsolutePosition(spaceshipController.getTransform().absolutePosition); - translate(characterController.getTransform(), getForwardDirection(spaceshipController.getTransform()).scale(10)); + characterController.getTransform().setAbsolutePosition(shipControls.getTransform().absolutePosition); + translate(characterController.getTransform(), getForwardDirection(shipControls.getTransform()).scale(10)); - setRotationQuaternion(characterController.getTransform(), getRotationQuaternion(spaceshipController.getTransform()).clone()); + setRotationQuaternion(characterController.getTransform(), getRotationQuaternion(shipControls.getTransform()).clone()); starSystemView.scene.setActiveController(characterController); starSystemView.getStarSystem().postProcessManager.rebuild(); @@ -234,18 +233,18 @@ document.addEventListener("keydown", (e) => { console.log("embark"); characterController.getTransform().setEnabled(false); - starSystemView.scene.setActiveController(spaceshipController); + starSystemView.scene.setActiveController(shipControls); starSystemView.getStarSystem().postProcessManager.rebuild(); } } if (e.key === "g") { - if (starSystemView.scene.getActiveController() === spaceshipController) { + if (starSystemView.scene.getActiveController() === shipControls) { starSystemView.scene.setActiveController(defaultController); - setRotationQuaternion(defaultController.getTransform(), getRotationQuaternion(spaceshipController.getTransform()).clone()); + setRotationQuaternion(defaultController.getTransform(), getRotationQuaternion(shipControls.getTransform()).clone()); starSystemView.getStarSystem().postProcessManager.rebuild(); - spaceshipController.setEnabled(false, engine.getHavokPlugin()); + shipControls.spaceship.setEnabled(false, engine.getHavokPlugin()); } else if (starSystemView.scene.getActiveController() === defaultController) { characterController.getTransform().setEnabled(true); characterController.getTransform().setAbsolutePosition(defaultController.getTransform().absolutePosition); @@ -253,14 +252,14 @@ document.addEventListener("keydown", (e) => { setRotationQuaternion(characterController.getTransform(), getRotationQuaternion(defaultController.getTransform()).clone()); starSystemView.getStarSystem().postProcessManager.rebuild(); - spaceshipController.setEnabled(false, engine.getHavokPlugin()); + shipControls.spaceship.setEnabled(false, engine.getHavokPlugin()); } else if (starSystemView.scene.getActiveController() === characterController) { characterController.getTransform().setEnabled(false); - starSystemView.scene.setActiveController(spaceshipController); - setRotationQuaternion(spaceshipController.getTransform(), getRotationQuaternion(defaultController.getTransform()).clone()); + starSystemView.scene.setActiveController(shipControls); + setRotationQuaternion(shipControls.getTransform(), getRotationQuaternion(defaultController.getTransform()).clone()); starSystemView.getStarSystem().postProcessManager.rebuild(); - spaceshipController.setEnabled(true, engine.getHavokPlugin()); + shipControls.spaceship.setEnabled(true, engine.getHavokPlugin()); } } }); diff --git a/src/ts/randomizer.ts b/src/ts/randomizer.ts index f02eeddcc..5afcbcef5 100644 --- a/src/ts/randomizer.ts +++ b/src/ts/randomizer.ts @@ -34,40 +34,40 @@ player.getActiveCamera().maxZ = Settings.EARTH_RADIUS * 100000; player.addInput(keyboard); player.addInput(gamepad); -const spaceshipController = new ShipControls(scene); -spaceshipController.getActiveCamera().maxZ = Settings.EARTH_RADIUS * 100000; -spaceshipController.addInput(keyboard); -spaceshipController.addInput(mouse); -spaceshipController.addInput(gamepad); +const shipControls = new ShipControls(scene); +shipControls.getActiveCamera().maxZ = Settings.EARTH_RADIUS * 100000; +shipControls.addInput(keyboard); +shipControls.addInput(mouse); +shipControls.addInput(gamepad); -scene.setActiveController(spaceshipController); +scene.setActiveController(shipControls); engine.registerStarSystemUpdateCallback(() => { - if (scene.getActiveController() != spaceshipController) return; + if (scene.getActiveController() != shipControls) return; - const shipPosition = spaceshipController.getTransform().getAbsolutePosition(); + const shipPosition = shipControls.getTransform().getAbsolutePosition(); const nearestBody = starSystemView.getStarSystem().getNearestOrbitalObject(); const distance = nearestBody.getTransform().getAbsolutePosition().subtract(shipPosition).length(); const radius = nearestBody.getBoundingRadius(); - spaceshipController.registerClosestObject(distance, radius); + shipControls.spaceship.registerClosestObject(distance, radius); - const warpDrive = spaceshipController.getWarpDrive(); + const warpDrive = shipControls.spaceship.getWarpDrive(); const shipInternalThrottle = warpDrive.getInternalThrottle(); const shipTargetThrottle = warpDrive.getTargetThrottle(); const throttleString = warpDrive.isEnabled() ? `${parsePercentageFrom01(shipInternalThrottle)}/${parsePercentageFrom01(shipTargetThrottle)}` - : `${parsePercentageFrom01(spaceshipController.getThrottle())}/100%`; + : `${parsePercentageFrom01(shipControls.spaceship.getThrottle())}/100%`; - (document.querySelector("#speedometer") as HTMLElement).innerHTML = `${throttleString} | ${parseSpeed(spaceshipController.getSpeed())}`; + (document.querySelector("#speedometer") as HTMLElement).innerHTML = `${throttleString} | ${parseSpeed(shipControls.spaceship.getSpeed())}`; }); engine.getStarMap().onWarpObservable.add(() => { - spaceshipController.thirdPersonCamera.radius = 30; + shipControls.thirdPersonCamera.radius = 30; }); engine.onToggleStarMapObservable.add((isStarMapOpen) => { - if (!isStarMapOpen) spaceshipController.thirdPersonCamera.radius = 30; + if (!isStarMapOpen) shipControls.thirdPersonCamera.radius = 30; }); //check if url contains a seed @@ -80,18 +80,18 @@ starSystemView.setStarSystem(starSystem, true); document.addEventListener("keydown", (e) => { if (engine.isPaused()) return; if (e.key === "g") { - if (scene.getActiveController() === spaceshipController) { + if (scene.getActiveController() === shipControls) { scene.setActiveController(player); - setRotationQuaternion(player.getTransform(), getRotationQuaternion(spaceshipController.getTransform()).clone()); + setRotationQuaternion(player.getTransform(), getRotationQuaternion(shipControls.getTransform()).clone()); starSystemView.getStarSystem().postProcessManager.rebuild(); - spaceshipController.setEnabled(false, engine.getHavokPlugin()); + shipControls.spaceship.setEnabled(false, engine.getHavokPlugin()); } else { - scene.setActiveController(spaceshipController); - setRotationQuaternion(spaceshipController.getTransform(), getRotationQuaternion(player.getTransform()).clone()); + scene.setActiveController(shipControls); + setRotationQuaternion(shipControls.getTransform(), getRotationQuaternion(player.getTransform()).clone()); starSystemView.getStarSystem().postProcessManager.rebuild(); - spaceshipController.setEnabled(true, engine.getHavokPlugin()); + shipControls.spaceship.setEnabled(true, engine.getHavokPlugin()); } } }); diff --git a/src/ts/spaceship/shipControls.ts b/src/ts/spaceship/shipControls.ts index 6dbeba0a3..094183c7e 100644 --- a/src/ts/spaceship/shipControls.ts +++ b/src/ts/spaceship/shipControls.ts @@ -1,124 +1,45 @@ import { Scene } from "@babylonjs/core/scene"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; -import { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh"; -import { MainThruster } from "./mainThruster"; -import { ReadonlyWarpDrive, WarpDrive } from "./warpDrive"; import { LOCAL_DIRECTION } from "../uberCore/localDirections"; -import { RCSThruster } from "./rcsThruster"; -import { PhysicsAggregate } from "@babylonjs/core/Physics/v2/physicsAggregate"; -import { IPhysicsCollisionEvent, PhysicsMotionType, PhysicsShapeType } from "@babylonjs/core/Physics/v2/IPhysicsEnginePlugin"; -import { PhysicsShapeMesh } from "@babylonjs/core/Physics/v2/physicsShape"; -import { Mesh } from "@babylonjs/core/Meshes/mesh"; -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, pitch, roll, - rotate, - Transformable, translate } from "../uberCore/transforms/basicTransform"; import { TransformNode } from "@babylonjs/core/Meshes"; import { Controls } from "../uberCore/controls"; -import { Assets } from "../assets"; import { Input, InputType } from "../inputs/input"; import { Keyboard } from "../inputs/keyboard"; import { Mouse } from "../inputs/mouse"; import { Camera } from "@babylonjs/core/Cameras/camera"; import { FreeCamera } from "@babylonjs/core/Cameras/freeCamera"; import { ArcRotateCamera } from "@babylonjs/core/Cameras/arcRotateCamera"; -import { PhysicsRaycastResult } from "@babylonjs/core/Physics/physicsRaycastResult"; -import { PhysicsEngineV2 } from "@babylonjs/core/Physics/v2"; -import { CollisionMask } from "../settings"; - -enum ShipState { - FLYING, - LANDING, - LANDED -} +import { Spaceship } from "./spaceship"; export class ShipControls implements Controls { - readonly instanceRoot: AbstractMesh; + readonly spaceship: Spaceship; readonly thirdPersonCamera: ArcRotateCamera; readonly firstPersonCamera: FreeCamera; - readonly aggregate: PhysicsAggregate; - private readonly collisionObservable: Observable; - - private flightAssistEnabled = true; - - private readonly mainThrusters: MainThruster[] = []; - private readonly rcsThrusters: RCSThruster[] = []; - - private readonly warpDrive = new WarpDrive(false); - - private closestWalkableObject: Transformable | null = null; - private readonly raycastResult = new PhysicsRaycastResult(); - - private state = ShipState.FLYING; - - private closestObject = { - distance: Infinity, - radius: 1 - }; - private inputs: Input[] = []; private readonly scene: Scene; constructor(scene: Scene) { - this.instanceRoot = Assets.CreateSpaceShipInstance(); + this.spaceship = new Spaceship(scene); this.firstPersonCamera = new FreeCamera("firstPersonCamera", Vector3.Zero(), scene); - this.firstPersonCamera.parent = this.instanceRoot; + this.firstPersonCamera.parent = this.getTransform(); this.firstPersonCamera.position = new Vector3(0, 1, 0); this.thirdPersonCamera = new ArcRotateCamera("thirdPersonCamera", -3.14 / 2, 3.14 / 2, 30, Vector3.Zero(), scene); - this.thirdPersonCamera.parent = this.instanceRoot; + this.thirdPersonCamera.parent = this.getTransform(); this.thirdPersonCamera.lowerRadiusLimit = 10; this.thirdPersonCamera.upperRadiusLimit = 500; - this.aggregate = new PhysicsAggregate( - this.instanceRoot, - PhysicsShapeType.CONTAINER, - { - mass: 10, - restitution: 0.2 - }, - scene - ); - for (const child of this.instanceRoot.getChildMeshes()) { - const childShape = new PhysicsShapeMesh(child as Mesh, scene); - childShape.filterMembershipMask = CollisionMask.SPACESHIP; - this.aggregate.shape.addChildFromParent(this.instanceRoot, childShape, child); - } - this.aggregate.body.disablePreStep = false; - - this.aggregate.body.setCollisionCallbackEnabled(true); - - this.collisionObservable = this.aggregate.body.getCollisionObservable(); - this.collisionObservable.add((collisionEvent: IPhysicsCollisionEvent) => { - console.log("Collision"); - if (collisionEvent.impulse < 0.8) return; - console.log(collisionEvent); - //Assets.OuchSound.play(); - }); - - for (const child of this.instanceRoot.getChildMeshes()) { - if (child.name.includes("mainThruster")) { - console.log("Found main thruster"); - this.addMainThruster(child); - } else if (child.name.includes("rcsThruster")) { - console.log("Found rcs thruster"); - this.addRCSThruster(child); - } - } - this.scene = scene; } @@ -127,71 +48,24 @@ export class ShipControls implements Controls { if (input.type === InputType.KEYBOARD) { const keyboard = input as Keyboard; keyboard.addPressedOnceListener("f", () => { - this.flightAssistEnabled = !this.flightAssistEnabled; + this.spaceship.setFlightAssistEnabled(!this.spaceship.getFlightAssistEnabled()); }); keyboard.addPressedOnceListener("h", () => { - this.toggleWarpDrive(); + this.spaceship.toggleWarpDrive(); }); } } - - public setClosestWalkableObject(object: Transformable) { - this.closestWalkableObject = object; - } - public getTransform(): TransformNode { - return this.aggregate.transformNode; - } - - private addMainThruster(mesh: AbstractMesh) { - const direction = mesh.getDirection(new Vector3(0, 1, 0)); - this.mainThrusters.push(new MainThruster(mesh, direction, this.aggregate)); - } - - private addRCSThruster(mesh: AbstractMesh) { - const direction = mesh.getDirection(new Vector3(0, 1, 0)); - const thruster = new RCSThruster(mesh, direction, this.aggregate); - this.rcsThrusters.push(thruster); - - //FIXME: this is temporary to balance rc thrust - thruster.setMaxAuthority(thruster.getMaxAuthority() / thruster.leverage); + return this.spaceship.getTransform(); } public getActiveCamera(): Camera { return this.thirdPersonCamera; } - public setEnabled(enabled: boolean, havokPlugin: HavokPlugin) { - this.instanceRoot.setEnabled(enabled); - setEnabledBody(this.aggregate.body, enabled, havokPlugin); - } - - public registerClosestObject(distance: number, radius: number) { - this.closestObject = { distance, radius }; - } - - public enableWarpDrive() { - for (const thruster of this.mainThrusters) thruster.setThrottle(0); - for (const thruster of this.rcsThrusters) thruster.deactivate(); - this.warpDrive.enable(); - } - - public toggleWarpDrive() { - if (!this.warpDrive.isEnabled()) this.enableWarpDrive(); - else this.warpDrive.desengage(); - } - - /** - * Returns a readonly interface to the warp drive of the ship. - * @returns A readonly interface to the warp drive of the ship. - */ - public getWarpDrive(): ReadonlyWarpDrive { - return this.warpDrive; - } - private listenTo(input: Input, deltaTime: number) { - if (this.warpDrive.isDisabled()) { - for (const thruster of this.mainThrusters) { + if (this.spaceship.getWarpDrive().isDisabled()) { + for (const thruster of this.spaceship.mainThrusters) { thruster.updateThrottle(2 * deltaTime * input.getZAxis() * thruster.getAuthority01(LOCAL_DIRECTION.FORWARD)); thruster.updateThrottle(2 * deltaTime * -input.getZAxis() * thruster.getAuthority01(LOCAL_DIRECTION.BACKWARD)); @@ -205,16 +79,12 @@ export class ShipControls implements Controls { if (input.type === InputType.KEYBOARD) { const keyboard = input as Keyboard; if (keyboard.isPressed("r")) { - this.aggregate.body.applyForce(getUpwardDirection(this.getTransform()).scale(9.8 * 10), this.aggregate.body.getObjectCenterWorld()); + this.spaceship.aggregate.body.applyForce(getUpwardDirection(this.getTransform()).scale(9.8 * 10), this.spaceship.aggregate.body.getObjectCenterWorld()); } if (keyboard.isPressed("l")) { - if (this.closestWalkableObject === null) return; - - console.log("Landing sequence engaged"); - this.aggregate.body.setMotionType(PhysicsMotionType.ANIMATED); - - this.state = ShipState.LANDING; + if (this.spaceship.getClosestWalkableObject() === null) return; + this.spaceship.engageLanding(); } } @@ -223,7 +93,7 @@ export class ShipControls implements Controls { const roll = mouse.getRoll(); const pitch = mouse.getPitch(); - for (const rcsThruster of this.rcsThrusters) { + for (const rcsThruster of this.spaceship.rcsThrusters) { let throttle = 0; // rcs rotation contribution @@ -238,19 +108,14 @@ export class ShipControls implements Controls { mouse.reset(); } - - if (this.closestWalkableObject) { - const gravityDir = this.closestWalkableObject.getTransform().getAbsolutePosition().subtract(this.getTransform().getAbsolutePosition()).normalize(); - this.aggregate.body.applyForce(gravityDir.scale(9.8), this.aggregate.body.getObjectCenterWorld()); - } } else { if (input.type === InputType.MOUSE) { const mouse = input as Mouse; const rollContribution = mouse.getRoll(); const pitchContribution = mouse.getPitch(); - roll(this.aggregate.transformNode, rollContribution * deltaTime); - pitch(this.aggregate.transformNode, pitchContribution * deltaTime); + roll(this.getTransform(), rollContribution * deltaTime); + pitch(this.getTransform(), pitchContribution * deltaTime); mouse.reset(); } @@ -258,83 +123,19 @@ export class ShipControls implements Controls { if (input.type === InputType.KEYBOARD) { const keyboard = input as Keyboard; const deltaThrottle = keyboard.getZAxis() * deltaTime; - this.warpDrive.increaseTargetThrottle(deltaThrottle); + this.spaceship.getWarpDrive().increaseTargetThrottle(deltaThrottle); } - const warpSpeed = getForwardDirection(this.aggregate.transformNode).scale(this.warpDrive.getWarpSpeed()); + const warpSpeed = getForwardDirection(this.getTransform()).scale(this.spaceship.getWarpDrive().getWarpSpeed()); //this.aggregate.body.setLinearVelocity(warpSpeed); - translate(this.aggregate.transformNode, warpSpeed.scale(deltaTime)); + translate(this.getTransform(), warpSpeed.scale(deltaTime)); } } - /** - * Returns the speed of the ship in m/s - * If warp drive is enabled, returns the warp speed - * If warp drive is disabled, returns the linear velocity of the ship - * @returns The speed of the ship in m/s - */ - public getSpeed(): number { - return this.warpDrive.isEnabled() ? this.warpDrive.getWarpSpeed() : this.aggregate.body.getLinearVelocity().length(); - } - - public getThrottle(): number { - return this.warpDrive.isEnabled() ? this.warpDrive.getTargetThrottle() : this.mainThrusters[0].getThrottle(); - } - public update(deltaTime: number): Vector3 { - for (const input of this.inputs) this.listenTo(input, deltaTime); - //const displacement = this.transform.update(deltaTime).negate(); + this.spaceship.update(deltaTime); - const warpSpeed = getForwardDirection(this.aggregate.transformNode).scale(this.warpDrive.getWarpSpeed()); //Vector3.Zero(); - - const currentForwardSpeed = Vector3.Dot(warpSpeed, this.aggregate.transformNode.getDirection(Axis.Z)); - this.warpDrive.update(currentForwardSpeed, this.closestObject.distance, this.closestObject.radius, deltaTime); - - for (const thruster of this.mainThrusters) thruster.update(); - for (const thruster of this.rcsThrusters) thruster.update(); - - if (this.warpDrive.isDisabled()) { - for (const thruster of this.mainThrusters) thruster.applyForce(); - for (const thruster of this.rcsThrusters) thruster.applyForce(); - } - - if (this.flightAssistEnabled) { - this.aggregate.body.setAngularDamping(0.9); - } else { - this.aggregate.body.setAngularDamping(1); - } - - if (this.state == ShipState.LANDING) { - if (this.closestWalkableObject === null) { - throw new Error("Closest walkable object is null"); - } - - const gravityDir = this.closestWalkableObject.getTransform().getAbsolutePosition().subtract(this.getTransform().getAbsolutePosition()).normalize(); - const start = this.getTransform().getAbsolutePosition().add(gravityDir.scale(-50e3)); - const end = this.getTransform().getAbsolutePosition().add(gravityDir.scale(50e3)); - - (this.scene.getPhysicsEngine() as PhysicsEngineV2).raycastToRef(start, end, this.raycastResult, { collideWith: CollisionMask.GROUND }); - if (this.raycastResult.hasHit) { - const landingSpotNormal = this.raycastResult.hitNormalWorld; - const landingSpot = this.raycastResult.hitPointWorld.add(this.raycastResult.hitNormalWorld.scale(2)); - - const distance = landingSpot.subtract(this.getTransform().getAbsolutePosition()).dot(gravityDir); - console.log(500 * deltaTime * Math.sign(distance), distance); - translate(this.getTransform(), gravityDir.scale(Math.min(500 * deltaTime * Math.sign(distance), distance))); - - - const currentUp = getUpwardDirection(this.getTransform()); - const targetUp = landingSpotNormal; - const axis = Vector3.Cross(currentUp, targetUp); - const theta = Math.acos(Vector3.Dot(currentUp, targetUp)); - rotate(this.getTransform(), axis, Math.min(0.1 * deltaTime, theta)); - - if(Math.abs(distance) < 0.3 && Math.abs(theta) < 0.01) { - this.state = ShipState.LANDED; - this.aggregate.body.setMotionType(PhysicsMotionType.STATIC); - } - } - } + for (const input of this.inputs) this.listenTo(input, deltaTime); this.getActiveCamera().getViewMatrix(); return this.getTransform().getAbsolutePosition(); diff --git a/src/ts/spaceship/spaceship.ts b/src/ts/spaceship/spaceship.ts new file mode 100644 index 000000000..52fc1ce2c --- /dev/null +++ b/src/ts/spaceship/spaceship.ts @@ -0,0 +1,235 @@ +import { Scene } from "@babylonjs/core/scene"; +import { Vector3 } from "@babylonjs/core/Maths/math.vector"; +import { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh"; +import { MainThruster } from "./mainThruster"; +import { ReadonlyWarpDrive, WarpDrive } from "./warpDrive"; +import { RCSThruster } from "./rcsThruster"; +import { PhysicsAggregate } from "@babylonjs/core/Physics/v2/physicsAggregate"; +import { IPhysicsCollisionEvent, PhysicsMotionType, PhysicsShapeType } from "@babylonjs/core/Physics/v2/IPhysicsEnginePlugin"; +import { PhysicsShapeMesh } from "@babylonjs/core/Physics/v2/physicsShape"; +import { Mesh } from "@babylonjs/core/Meshes/mesh"; +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, Transformable, translate } from "../uberCore/transforms/basicTransform"; +import { TransformNode } from "@babylonjs/core/Meshes"; +import { Assets } from "../assets"; +import { PhysicsRaycastResult } from "@babylonjs/core/Physics/physicsRaycastResult"; +import { PhysicsEngineV2 } from "@babylonjs/core/Physics/v2"; +import { CollisionMask } from "../settings"; + +enum ShipState { + FLYING, + LANDING, + LANDED +} + +export class Spaceship { + readonly instanceRoot: AbstractMesh; + + readonly aggregate: PhysicsAggregate; + private readonly collisionObservable: Observable; + + private flightAssistEnabled = true; + + readonly mainThrusters: MainThruster[] = []; + readonly rcsThrusters: RCSThruster[] = []; + + private readonly warpDrive = new WarpDrive(false); + + private closestWalkableObject: Transformable | null = null; + private readonly raycastResult = new PhysicsRaycastResult(); + + private state = ShipState.FLYING; + + private closestObject = { + distance: Infinity, + radius: 1 + }; + + private readonly scene: Scene; + + constructor(scene: Scene) { + this.instanceRoot = Assets.CreateSpaceShipInstance(); + + this.aggregate = new PhysicsAggregate( + this.instanceRoot, + PhysicsShapeType.CONTAINER, + { + mass: 10, + restitution: 0.2 + }, + scene + ); + for (const child of this.instanceRoot.getChildMeshes()) { + const childShape = new PhysicsShapeMesh(child as Mesh, scene); + childShape.filterMembershipMask = CollisionMask.SPACESHIP; + this.aggregate.shape.addChildFromParent(this.instanceRoot, childShape, child); + } + this.aggregate.body.disablePreStep = false; + + this.aggregate.body.setCollisionCallbackEnabled(true); + + this.collisionObservable = this.aggregate.body.getCollisionObservable(); + this.collisionObservable.add((collisionEvent: IPhysicsCollisionEvent) => { + console.log("Collision"); + if (collisionEvent.impulse < 0.8) return; + console.log(collisionEvent); + //Assets.OuchSound.play(); + }); + + for (const child of this.instanceRoot.getChildMeshes()) { + if (child.name.includes("mainThruster")) { + console.log("Found main thruster"); + this.addMainThruster(child); + } else if (child.name.includes("rcsThruster")) { + console.log("Found rcs thruster"); + this.addRCSThruster(child); + } + } + + this.scene = scene; + } + + public setClosestWalkableObject(object: Transformable) { + this.closestWalkableObject = object; + } + + public getTransform(): TransformNode { + return this.aggregate.transformNode; + } + + private addMainThruster(mesh: AbstractMesh) { + const direction = mesh.getDirection(new Vector3(0, 1, 0)); + this.mainThrusters.push(new MainThruster(mesh, direction, this.aggregate)); + } + + private addRCSThruster(mesh: AbstractMesh) { + const direction = mesh.getDirection(new Vector3(0, 1, 0)); + const thruster = new RCSThruster(mesh, direction, this.aggregate); + this.rcsThrusters.push(thruster); + + //FIXME: this is temporary to balance rc thrust + thruster.setMaxAuthority(thruster.getMaxAuthority() / thruster.leverage); + } + + public setEnabled(enabled: boolean, havokPlugin: HavokPlugin) { + this.instanceRoot.setEnabled(enabled); + setEnabledBody(this.aggregate.body, enabled, havokPlugin); + } + + public registerClosestObject(distance: number, radius: number) { + this.closestObject = { distance, radius }; + } + + public enableWarpDrive() { + for (const thruster of this.mainThrusters) thruster.setThrottle(0); + for (const thruster of this.rcsThrusters) thruster.deactivate(); + this.warpDrive.enable(); + } + + public toggleWarpDrive() { + if (!this.warpDrive.isEnabled()) this.enableWarpDrive(); + else this.warpDrive.desengage(); + } + + /** + * Returns a readonly interface to the warp drive of the ship. + * @returns A readonly interface to the warp drive of the ship. + */ + public getWarpDrive(): WarpDrive { + return this.warpDrive; + } + + public setFlightAssistEnabled(enabled: boolean) { + this.flightAssistEnabled = enabled; + } + + public getFlightAssistEnabled(): boolean { + return this.flightAssistEnabled; + } + + /** + * Returns the speed of the ship in m/s + * If warp drive is enabled, returns the warp speed + * If warp drive is disabled, returns the linear velocity of the ship + * @returns The speed of the ship in m/s + */ + public getSpeed(): number { + return this.warpDrive.isEnabled() ? this.warpDrive.getWarpSpeed() : this.aggregate.body.getLinearVelocity().length(); + } + + public getThrottle(): number { + return this.warpDrive.isEnabled() ? this.warpDrive.getTargetThrottle() : this.mainThrusters[0].getThrottle(); + } + + public getClosestWalkableObject(): Transformable | null { + return this.closestWalkableObject; + } + + public engageLanding() { + console.log("Landing sequence engaged"); + this.aggregate.body.setMotionType(PhysicsMotionType.ANIMATED); + this.state = ShipState.LANDING; + } + + public update(deltaTime: number): Vector3 { + const warpSpeed = getForwardDirection(this.aggregate.transformNode).scale(this.warpDrive.getWarpSpeed()); + + const currentForwardSpeed = Vector3.Dot(warpSpeed, this.aggregate.transformNode.getDirection(Axis.Z)); + this.warpDrive.update(currentForwardSpeed, this.closestObject.distance, this.closestObject.radius, deltaTime); + + for (const thruster of this.mainThrusters) thruster.update(); + for (const thruster of this.rcsThrusters) thruster.update(); + + if (this.warpDrive.isDisabled()) { + for (const thruster of this.mainThrusters) thruster.applyForce(); + for (const thruster of this.rcsThrusters) thruster.applyForce(); + + if (this.closestWalkableObject !== null) { + const gravityDir = this.closestWalkableObject.getTransform().getAbsolutePosition().subtract(this.getTransform().getAbsolutePosition()).normalize(); + this.aggregate.body.applyForce(gravityDir.scale(9.8), this.aggregate.body.getObjectCenterWorld()); + } + } + + if (this.flightAssistEnabled) { + this.aggregate.body.setAngularDamping(0.9); + } else { + this.aggregate.body.setAngularDamping(1); + } + + if (this.state == ShipState.LANDING) { + if (this.closestWalkableObject === null) { + throw new Error("Closest walkable object is null"); + } + + const gravityDir = this.closestWalkableObject.getTransform().getAbsolutePosition().subtract(this.getTransform().getAbsolutePosition()).normalize(); + const start = this.getTransform().getAbsolutePosition().add(gravityDir.scale(-50e3)); + const end = this.getTransform().getAbsolutePosition().add(gravityDir.scale(50e3)); + + (this.scene.getPhysicsEngine() as PhysicsEngineV2).raycastToRef(start, end, this.raycastResult, { collideWith: CollisionMask.GROUND }); + if (this.raycastResult.hasHit) { + const landingSpotNormal = this.raycastResult.hitNormalWorld; + const landingSpot = this.raycastResult.hitPointWorld.add(this.raycastResult.hitNormalWorld.scale(2)); + + const distance = landingSpot.subtract(this.getTransform().getAbsolutePosition()).dot(gravityDir); + console.log(500 * deltaTime * Math.sign(distance), distance); + translate(this.getTransform(), gravityDir.scale(Math.min(500 * deltaTime * Math.sign(distance), distance))); + + const currentUp = getUpwardDirection(this.getTransform()); + const targetUp = landingSpotNormal; + const axis = Vector3.Cross(currentUp, targetUp); + const theta = Math.acos(Vector3.Dot(currentUp, targetUp)); + rotate(this.getTransform(), axis, Math.min(0.1 * deltaTime, theta)); + + if (Math.abs(distance) < 0.3 && Math.abs(theta) < 0.01) { + this.state = ShipState.LANDED; + this.aggregate.body.setMotionType(PhysicsMotionType.STATIC); + } + } + } + + return this.getTransform().getAbsolutePosition(); + } +} diff --git a/src/ts/starSystem/StarSystemView.ts b/src/ts/starSystem/StarSystemView.ts index dc8190eaf..cf38cfa70 100644 --- a/src/ts/starSystem/StarSystemView.ts +++ b/src/ts/starSystem/StarSystemView.ts @@ -149,7 +149,7 @@ export class StarSystemView { const activeController = this.scene.getActiveController(); positionNearObject(activeController, firstBody, this.getStarSystem(), firstBody instanceof BlackHole ? 7 : 5); - if (activeController instanceof ShipControls) activeController.enableWarpDrive(); + if (activeController instanceof ShipControls) activeController.spaceship.enableWarpDrive(); this.getStarSystem() .initPostProcesses() From 70251eb8bdc613d4a8d355401eb9e484144c2f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:32:27 +0100 Subject: [PATCH 04/14] landing target can be different from closest walkable object --- src/ts/spaceship/spaceship.ts | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/ts/spaceship/spaceship.ts b/src/ts/spaceship/spaceship.ts index 52fc1ce2c..b28c319fb 100644 --- a/src/ts/spaceship/spaceship.ts +++ b/src/ts/spaceship/spaceship.ts @@ -2,7 +2,7 @@ import { Scene } from "@babylonjs/core/scene"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; import { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh"; import { MainThruster } from "./mainThruster"; -import { ReadonlyWarpDrive, WarpDrive } from "./warpDrive"; +import { WarpDrive } from "./warpDrive"; import { RCSThruster } from "./rcsThruster"; import { PhysicsAggregate } from "@babylonjs/core/Physics/v2/physicsAggregate"; import { IPhysicsCollisionEvent, PhysicsMotionType, PhysicsShapeType } from "@babylonjs/core/Physics/v2/IPhysicsEnginePlugin"; @@ -39,6 +39,8 @@ export class Spaceship { private readonly warpDrive = new WarpDrive(false); private closestWalkableObject: Transformable | null = null; + + private landingTarget: Transformable | null = null; private readonly raycastResult = new PhysicsRaycastResult(); private state = ShipState.FLYING; @@ -127,11 +129,17 @@ export class Spaceship { for (const thruster of this.mainThrusters) thruster.setThrottle(0); for (const thruster of this.rcsThrusters) thruster.deactivate(); this.warpDrive.enable(); + this.aggregate.body.setMotionType(PhysicsMotionType.ANIMATED); + } + + public disableWarpDrive() { + this.warpDrive.desengage(); + this.aggregate.body.setMotionType(PhysicsMotionType.DYNAMIC); } public toggleWarpDrive() { if (!this.warpDrive.isEnabled()) this.enableWarpDrive(); - else this.warpDrive.desengage(); + else this.disableWarpDrive(); } /** @@ -172,6 +180,14 @@ export class Spaceship { console.log("Landing sequence engaged"); this.aggregate.body.setMotionType(PhysicsMotionType.ANIMATED); this.state = ShipState.LANDING; + this.landingTarget = this.closestWalkableObject; + } + + private completeLanding() { + console.log("Landing sequence complete"); + this.state = ShipState.LANDED; + this.aggregate.body.setMotionType(PhysicsMotionType.STATIC); + this.landingTarget = null; } public update(deltaTime: number): Vector3 { @@ -200,18 +216,18 @@ export class Spaceship { } if (this.state == ShipState.LANDING) { - if (this.closestWalkableObject === null) { - throw new Error("Closest walkable object is null"); + if (this.landingTarget === null) { + throw new Error("Closest walkable object is null while landing"); } - const gravityDir = this.closestWalkableObject.getTransform().getAbsolutePosition().subtract(this.getTransform().getAbsolutePosition()).normalize(); + const gravityDir = this.landingTarget.getTransform().getAbsolutePosition().subtract(this.getTransform().getAbsolutePosition()).normalize(); const start = this.getTransform().getAbsolutePosition().add(gravityDir.scale(-50e3)); const end = this.getTransform().getAbsolutePosition().add(gravityDir.scale(50e3)); (this.scene.getPhysicsEngine() as PhysicsEngineV2).raycastToRef(start, end, this.raycastResult, { collideWith: CollisionMask.GROUND }); if (this.raycastResult.hasHit) { const landingSpotNormal = this.raycastResult.hitNormalWorld; - const landingSpot = this.raycastResult.hitPointWorld.add(this.raycastResult.hitNormalWorld.scale(2)); + const landingSpot = this.raycastResult.hitPointWorld.add(this.raycastResult.hitNormalWorld.scale(0)); const distance = landingSpot.subtract(this.getTransform().getAbsolutePosition()).dot(gravityDir); console.log(500 * deltaTime * Math.sign(distance), distance); @@ -224,8 +240,7 @@ export class Spaceship { rotate(this.getTransform(), axis, Math.min(0.1 * deltaTime, theta)); if (Math.abs(distance) < 0.3 && Math.abs(theta) < 0.01) { - this.state = ShipState.LANDED; - this.aggregate.body.setMotionType(PhysicsMotionType.STATIC); + this.completeLanding(); } } } From 57b8b063c8bd385a5b210ed69c8931dce40b6a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:32:46 +0100 Subject: [PATCH 05/14] added new landing pad class --- src/ts/landingPad/landingPad.ts | 15 +++++++++++++++ src/ts/landingSimulator.ts | 5 +++-- 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/ts/landingPad/landingPad.ts diff --git a/src/ts/landingPad/landingPad.ts b/src/ts/landingPad/landingPad.ts new file mode 100644 index 000000000..25dbc4efc --- /dev/null +++ b/src/ts/landingPad/landingPad.ts @@ -0,0 +1,15 @@ +import { TransformNode } from "@babylonjs/core/Meshes"; +import { Transformable } from "../uberCore/transforms/basicTransform"; +import { Assets } from "../assets"; + +export class LandingPad implements Transformable { + private readonly instanceRoot: TransformNode; + + constructor() { + this.instanceRoot = Assets.CreateLandingPadInstance(); + } + + getTransform(): TransformNode { + return this.instanceRoot; + } +} diff --git a/src/ts/landingSimulator.ts b/src/ts/landingSimulator.ts index 703a61252..13fa104c7 100644 --- a/src/ts/landingSimulator.ts +++ b/src/ts/landingSimulator.ts @@ -15,6 +15,7 @@ import { Color4 } from "@babylonjs/core/Maths/math.color"; import "@babylonjs/core/Physics/physicsEngineComponent"; import { Keyboard } from "./inputs/keyboard"; import { Mouse } from "./inputs/mouse"; +import { LandingPad } from "./landingPad/landingPad"; const canvas = document.getElementById("renderer") as HTMLCanvasElement; canvas.width = window.innerWidth; @@ -43,8 +44,8 @@ spaceship.addInput(new Keyboard()); spaceship.addInput(new Mouse(canvas)); scene.setActiveController(spaceship); -const landingPad = Assets.CreateLandingPadInstance(); -landingPad.position = new Vector3(0, -20, 50); +const landingPad = new LandingPad(); +landingPad.getTransform().position = new Vector3(0, -20, 50); scene.onBeforeRenderObservable.add(() => { const deltaTime = scene.deltaTime / 1000; From feb2f2e13211d897b3d8fa46b4fa0410be337f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:36:44 +0100 Subject: [PATCH 06/14] added collider to landing pad + fixed all transforms not being applied to 3d landing pad model --- src/asset/landingpad.glb | Bin 15148 -> 15064 bytes src/ts/landingPad/landingPad.ts | 27 +++++++++++++++++++++++++-- src/ts/landingSimulator.ts | 17 ++++++++++++----- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/asset/landingpad.glb b/src/asset/landingpad.glb index eb8ad5e7d728b3142044f56d07230b569af0ab3a..a90e29d9181b1586f847b6ef83ac33a9331d2917 100644 GIT binary patch literal 15064 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 S>tk3Rr4CCQ`qGelmi#Xf!ThrT literal 15148 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 S^?VZ3qtvnKV_r>~v*aI7P_N$r diff --git a/src/ts/landingPad/landingPad.ts b/src/ts/landingPad/landingPad.ts index 25dbc4efc..5049c11cd 100644 --- a/src/ts/landingPad/landingPad.ts +++ b/src/ts/landingPad/landingPad.ts @@ -1,15 +1,38 @@ import { TransformNode } from "@babylonjs/core/Meshes"; import { Transformable } from "../uberCore/transforms/basicTransform"; import { Assets } from "../assets"; +import { PhysicsAggregate } from "@babylonjs/core/Physics/v2/physicsAggregate"; +import { PhysicsShapeType } from "@babylonjs/core/Physics/v2/IPhysicsEnginePlugin"; +import { PhysicsShapeConvexHull, PhysicsShapeMesh } from "@babylonjs/core/Physics/v2/physicsShape"; +import { Mesh } from "@babylonjs/core/Meshes/mesh"; +import { CollisionMask } from "../settings"; +import { Scene } from "@babylonjs/core/scene"; export class LandingPad implements Transformable { private readonly instanceRoot: TransformNode; + readonly aggregate: PhysicsAggregate; - constructor() { + constructor(scene: Scene) { this.instanceRoot = Assets.CreateLandingPadInstance(); + + this.aggregate = new PhysicsAggregate( + this.instanceRoot, + PhysicsShapeType.CONTAINER, + { + mass: 10, + restitution: 0.2 + }, + scene + ); + for (const child of this.instanceRoot.getChildMeshes()) { + const childShape = new PhysicsShapeConvexHull(child as Mesh, scene); + childShape.filterMembershipMask = CollisionMask.SPACESHIP; + this.aggregate.shape.addChildFromParent(this.instanceRoot, childShape, child); + } + this.aggregate.body.disablePreStep = false; } getTransform(): TransformNode { - return this.instanceRoot; + return this.aggregate.transformNode; } } diff --git a/src/ts/landingSimulator.ts b/src/ts/landingSimulator.ts index 13fa104c7..2d634dcfb 100644 --- a/src/ts/landingSimulator.ts +++ b/src/ts/landingSimulator.ts @@ -16,6 +16,7 @@ import "@babylonjs/core/Physics/physicsEngineComponent"; import { Keyboard } from "./inputs/keyboard"; import { Mouse } from "./inputs/mouse"; import { LandingPad } from "./landingPad/landingPad"; +import { PhysicsViewer } from "@babylonjs/core/Debug/physicsViewer"; const canvas = document.getElementById("renderer") as HTMLCanvasElement; canvas.width = window.innerWidth; @@ -39,14 +40,20 @@ const light = new DirectionalLight("light", new Vector3(0, -1, 1).normalize(), s await Assets.Init(scene); -const spaceship = new ShipControls(scene); -spaceship.addInput(new Keyboard()); -spaceship.addInput(new Mouse(canvas)); -scene.setActiveController(spaceship); +const physicsViewer = new PhysicsViewer(); -const landingPad = new LandingPad(); +const shipControls = new ShipControls(scene); +shipControls.addInput(new Keyboard()); +shipControls.addInput(new Mouse(canvas)); +scene.setActiveController(shipControls); + +physicsViewer.showBody(shipControls.spaceship.aggregate.body) + +const landingPad = new LandingPad(scene); landingPad.getTransform().position = new Vector3(0, -20, 50); +physicsViewer.showBody(landingPad.aggregate.body); + scene.onBeforeRenderObservable.add(() => { const deltaTime = scene.deltaTime / 1000; scene.getActiveController().update(deltaTime); From 9503495584c0082cef007ad0648288e4cbee79b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:47:58 +0100 Subject: [PATCH 07/14] complete basic setup --- src/ts/landingPad/landingPad.ts | 2 +- src/ts/landingSimulator.ts | 43 +++++++++++++++++++++----------- src/ts/spaceship/shipControls.ts | 2 +- src/ts/spaceship/spaceship.ts | 8 ++++-- 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/ts/landingPad/landingPad.ts b/src/ts/landingPad/landingPad.ts index 5049c11cd..5169a6f2d 100644 --- a/src/ts/landingPad/landingPad.ts +++ b/src/ts/landingPad/landingPad.ts @@ -3,7 +3,7 @@ import { Transformable } from "../uberCore/transforms/basicTransform"; import { Assets } from "../assets"; import { PhysicsAggregate } from "@babylonjs/core/Physics/v2/physicsAggregate"; import { PhysicsShapeType } from "@babylonjs/core/Physics/v2/IPhysicsEnginePlugin"; -import { PhysicsShapeConvexHull, PhysicsShapeMesh } from "@babylonjs/core/Physics/v2/physicsShape"; +import { PhysicsShapeConvexHull } from "@babylonjs/core/Physics/v2/physicsShape"; import { Mesh } from "@babylonjs/core/Meshes/mesh"; import { CollisionMask } from "../settings"; import { Scene } from "@babylonjs/core/scene"; diff --git a/src/ts/landingSimulator.ts b/src/ts/landingSimulator.ts index 2d634dcfb..8d4e8ece0 100644 --- a/src/ts/landingSimulator.ts +++ b/src/ts/landingSimulator.ts @@ -17,6 +17,8 @@ import { Keyboard } from "./inputs/keyboard"; import { Mouse } from "./inputs/mouse"; import { LandingPad } from "./landingPad/landingPad"; import { PhysicsViewer } from "@babylonjs/core/Debug/physicsViewer"; +import { DefaultControls } from "./defaultController/defaultControls"; +import { Spaceship } from "./spaceship/spaceship"; const canvas = document.getElementById("renderer") as HTMLCanvasElement; canvas.width = window.innerWidth; @@ -42,32 +44,45 @@ await Assets.Init(scene); const physicsViewer = new PhysicsViewer(); -const shipControls = new ShipControls(scene); -shipControls.addInput(new Keyboard()); -shipControls.addInput(new Mouse(canvas)); -scene.setActiveController(shipControls); +const spaceship = new Spaceship(scene); -physicsViewer.showBody(shipControls.spaceship.aggregate.body) +physicsViewer.showBody(spaceship.aggregate.body); const landingPad = new LandingPad(scene); landingPad.getTransform().position = new Vector3(0, -20, 50); physicsViewer.showBody(landingPad.aggregate.body); +const defaultControls = new DefaultControls(scene); +defaultControls.speed *= 15; +defaultControls.addInput(new Keyboard()); +scene.setActiveController(defaultControls); + +translate(defaultControls.getTransform(), new Vector3(50, 0, 0)); + +defaultControls.getTransform().lookAt(Vector3.Lerp(spaceship.getTransform().position, landingPad.getTransform().position, 0.5)); + + scene.onBeforeRenderObservable.add(() => { - const deltaTime = scene.deltaTime / 1000; - scene.getActiveController().update(deltaTime); + const deltaTime = scene.deltaTime / 1000; + scene.getActiveController().update(deltaTime); + spaceship.update(deltaTime); }); - scene.executeWhenReady(() => { - engine.runRenderLoop(() => { - scene.render(); - }); + engine.runRenderLoop(() => { + scene.render(); + }); +}); + +document.addEventListener("keydown", (event) => { + if (event.key === "o") { + spaceship.engageLanding(landingPad); + } }); window.addEventListener("resize", () => { - canvas.width = window.innerWidth; - canvas.height = window.innerHeight; - engine.resize(true); + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + engine.resize(true); }); diff --git a/src/ts/spaceship/shipControls.ts b/src/ts/spaceship/shipControls.ts index 094183c7e..83746cf0c 100644 --- a/src/ts/spaceship/shipControls.ts +++ b/src/ts/spaceship/shipControls.ts @@ -84,7 +84,7 @@ export class ShipControls implements Controls { if (keyboard.isPressed("l")) { if (this.spaceship.getClosestWalkableObject() === null) return; - this.spaceship.engageLanding(); + this.spaceship.engageLanding(null); } } diff --git a/src/ts/spaceship/spaceship.ts b/src/ts/spaceship/spaceship.ts index b28c319fb..d2ecfc885 100644 --- a/src/ts/spaceship/spaceship.ts +++ b/src/ts/spaceship/spaceship.ts @@ -176,11 +176,15 @@ export class Spaceship { return this.closestWalkableObject; } - public engageLanding() { + public engageLanding(landingTarget: Transformable | null) { console.log("Landing sequence engaged"); this.aggregate.body.setMotionType(PhysicsMotionType.ANIMATED); this.state = ShipState.LANDING; - this.landingTarget = this.closestWalkableObject; + this.landingTarget = landingTarget !== null ? landingTarget : this.closestWalkableObject; + if(this.landingTarget === null) { + throw new Error("Landing target is null"); + } + console.log("landing on", this.landingTarget.getTransform().name); } private completeLanding() { From f8d03de15f090217acc7e8b6261b6a83304df55a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Mon, 8 Jan 2024 14:05:21 +0100 Subject: [PATCH 08/14] basic linear landing (without physics) --- src/ts/landingPad/landingPad.ts | 10 +++++++--- src/ts/landingSimulator.ts | 32 ++++++++++++++++++++------------ src/ts/settings.ts | 1 + src/ts/spaceship/spaceship.ts | 18 ++++++++++++------ 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/ts/landingPad/landingPad.ts b/src/ts/landingPad/landingPad.ts index 5169a6f2d..fc1effb41 100644 --- a/src/ts/landingPad/landingPad.ts +++ b/src/ts/landingPad/landingPad.ts @@ -7,9 +7,10 @@ import { PhysicsShapeConvexHull } from "@babylonjs/core/Physics/v2/physicsShape" import { Mesh } from "@babylonjs/core/Meshes/mesh"; import { CollisionMask } from "../settings"; import { Scene } from "@babylonjs/core/scene"; +import { Vector3 } from "@babylonjs/core/Maths/math"; export class LandingPad implements Transformable { - private readonly instanceRoot: TransformNode; + readonly instanceRoot: TransformNode; readonly aggregate: PhysicsAggregate; constructor(scene: Scene) { @@ -19,14 +20,17 @@ export class LandingPad implements Transformable { this.instanceRoot, PhysicsShapeType.CONTAINER, { - mass: 10, + mass: 0, restitution: 0.2 }, scene ); + + this.aggregate.body.setMassProperties({ inertia: Vector3.Zero(), mass: 0 }); + for (const child of this.instanceRoot.getChildMeshes()) { const childShape = new PhysicsShapeConvexHull(child as Mesh, scene); - childShape.filterMembershipMask = CollisionMask.SPACESHIP; + childShape.filterMembershipMask = CollisionMask.LANDING_PADS; this.aggregate.shape.addChildFromParent(this.instanceRoot, childShape, child); } this.aggregate.body.disablePreStep = false; diff --git a/src/ts/landingSimulator.ts b/src/ts/landingSimulator.ts index 8d4e8ece0..0c340dd00 100644 --- a/src/ts/landingSimulator.ts +++ b/src/ts/landingSimulator.ts @@ -5,20 +5,20 @@ import HavokPhysics from "@babylonjs/havok"; import { HavokPlugin } from "@babylonjs/core/Physics/v2/Plugins/havokPlugin"; import { setMaxLinVel } from "./utils/havok"; import { UberScene } from "./uberCore/uberScene"; -import { ScenePerformancePriority } from "@babylonjs/core"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; import { Assets } from "./assets"; -import { ShipControls } from "./spaceship/shipControls"; -import { translate } from "./uberCore/transforms/basicTransform"; +import { roll, translate } from "./uberCore/transforms/basicTransform"; import { DirectionalLight } from "@babylonjs/core/Lights/directionalLight"; import { Color4 } from "@babylonjs/core/Maths/math.color"; import "@babylonjs/core/Physics/physicsEngineComponent"; import { Keyboard } from "./inputs/keyboard"; -import { Mouse } from "./inputs/mouse"; import { LandingPad } from "./landingPad/landingPad"; import { PhysicsViewer } from "@babylonjs/core/Debug/physicsViewer"; import { DefaultControls } from "./defaultController/defaultControls"; import { Spaceship } from "./spaceship/spaceship"; +import "@babylonjs/core/Lights/Shadows/shadowGeneratorSceneComponent"; +import { ShadowGenerator } from "@babylonjs/core/Lights/Shadows/shadowGenerator"; +import { MeshBuilder } from "@babylonjs/core/Meshes/meshBuilder"; const canvas = document.getElementById("renderer") as HTMLCanvasElement; canvas.width = window.innerWidth; @@ -38,20 +38,29 @@ scene.useRightHandedSystem = true; scene.enablePhysics(Vector3.Zero(), havokPlugin); scene.clearColor = new Color4(0.2, 0.2, 0.6, 1); -const light = new DirectionalLight("light", new Vector3(0, -1, 1).normalize(), scene); +const light = new DirectionalLight("light", new Vector3(-2, -5, 1).normalize(), scene); +const shadowGenerator = new ShadowGenerator(2048, light); await Assets.Init(scene); -const physicsViewer = new PhysicsViewer(); - const spaceship = new Spaceship(scene); - -physicsViewer.showBody(spaceship.aggregate.body); +shadowGenerator.addShadowCaster(spaceship.instanceRoot, true); +spaceship.getTransform().position = new Vector3(0, 0, -10); +roll(spaceship.getTransform(), Math.random() * 6.28); const landingPad = new LandingPad(scene); -landingPad.getTransform().position = new Vector3(0, -20, 50); +landingPad.getTransform().position = new Vector3(0, -20, 0); +landingPad.instanceRoot.getChildMeshes().forEach((mesh) => { + mesh.receiveShadows = true; +}); -physicsViewer.showBody(landingPad.aggregate.body); +/*const ground = MeshBuilder.CreateGround("ground", { width: 50, height: 50 }); +ground.position.y = -40; +ground.receiveShadows = true;*/ + +/*const physicsViewer = new PhysicsViewer(); +physicsViewer.showBody(spaceship.aggregate.body); +physicsViewer.showBody(landingPad.aggregate.body);*/ const defaultControls = new DefaultControls(scene); defaultControls.speed *= 15; @@ -62,7 +71,6 @@ translate(defaultControls.getTransform(), new Vector3(50, 0, 0)); defaultControls.getTransform().lookAt(Vector3.Lerp(spaceship.getTransform().position, landingPad.getTransform().position, 0.5)); - scene.onBeforeRenderObservable.add(() => { const deltaTime = scene.deltaTime / 1000; scene.getActiveController().update(deltaTime); diff --git a/src/ts/settings.ts b/src/ts/settings.ts index c9a47f3f9..e6f04bf4f 100644 --- a/src/ts/settings.ts +++ b/src/ts/settings.ts @@ -21,4 +21,5 @@ export const Settings = { export const CollisionMask = { GROUND: 0b00000001, SPACESHIP: 0b00000010, + LANDING_PADS: 0b00000100, } \ No newline at end of file diff --git a/src/ts/spaceship/spaceship.ts b/src/ts/spaceship/spaceship.ts index d2ecfc885..24ece9ad4 100644 --- a/src/ts/spaceship/spaceship.ts +++ b/src/ts/spaceship/spaceship.ts @@ -228,20 +228,26 @@ export class Spaceship { const start = this.getTransform().getAbsolutePosition().add(gravityDir.scale(-50e3)); const end = this.getTransform().getAbsolutePosition().add(gravityDir.scale(50e3)); - (this.scene.getPhysicsEngine() as PhysicsEngineV2).raycastToRef(start, end, this.raycastResult, { collideWith: CollisionMask.GROUND }); + (this.scene.getPhysicsEngine() as PhysicsEngineV2).raycastToRef(start, end, this.raycastResult, { collideWith: CollisionMask.GROUND | CollisionMask.LANDING_PADS }); if (this.raycastResult.hasHit) { const landingSpotNormal = this.raycastResult.hitNormalWorld; - const landingSpot = this.raycastResult.hitPointWorld.add(this.raycastResult.hitNormalWorld.scale(0)); + const extent = this.instanceRoot.getHierarchyBoundingVectors(); + const shipYExtend = extent.max.y - extent.min.y; + + const landingSpot = this.raycastResult.hitPointWorld.add(this.raycastResult.hitNormalWorld.scale(shipYExtend / 2)); const distance = landingSpot.subtract(this.getTransform().getAbsolutePosition()).dot(gravityDir); console.log(500 * deltaTime * Math.sign(distance), distance); - translate(this.getTransform(), gravityDir.scale(Math.min(500 * deltaTime * Math.sign(distance), distance))); + translate(this.getTransform(), gravityDir.scale(Math.min(10 * deltaTime * Math.sign(distance), distance))); const currentUp = getUpwardDirection(this.getTransform()); const targetUp = landingSpotNormal; - const axis = Vector3.Cross(currentUp, targetUp); - const theta = Math.acos(Vector3.Dot(currentUp, targetUp)); - rotate(this.getTransform(), axis, Math.min(0.1 * deltaTime, theta)); + let theta = 0.0; + if(Vector3.Distance(currentUp, targetUp) > 0.01) { + const axis = Vector3.Cross(currentUp, targetUp); + theta = Math.acos(Vector3.Dot(currentUp, targetUp)); + rotate(this.getTransform(), axis, Math.min(0.4 * deltaTime, theta)); + } if (Math.abs(distance) < 0.3 && Math.abs(theta) < 0.01) { this.completeLanding(); From fb5d3ce82bc4d8cd29da872424c108c11349a261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Mon, 8 Jan 2024 14:22:11 +0100 Subject: [PATCH 09/14] the spaceship doesn't need to return its position --- src/ts/spaceship/spaceship.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ts/spaceship/spaceship.ts b/src/ts/spaceship/spaceship.ts index 24ece9ad4..5fb468294 100644 --- a/src/ts/spaceship/spaceship.ts +++ b/src/ts/spaceship/spaceship.ts @@ -194,7 +194,7 @@ export class Spaceship { this.landingTarget = null; } - public update(deltaTime: number): Vector3 { + public update(deltaTime: number) { const warpSpeed = getForwardDirection(this.aggregate.transformNode).scale(this.warpDrive.getWarpSpeed()); const currentForwardSpeed = Vector3.Dot(warpSpeed, this.aggregate.transformNode.getDirection(Axis.Z)); @@ -254,7 +254,5 @@ export class Spaceship { } } } - - return this.getTransform().getAbsolutePosition(); } } From fabd18d18fe4e610de627c6c0bd4ffa9ca3cd4f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Mon, 22 Jan 2024 11:51:47 +0100 Subject: [PATCH 10/14] fixed html parse crash --- src/html/mainMenu.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/html/mainMenu.html b/src/html/mainMenu.html index 7935243a1..2c8a452f1 100644 --- a/src/html/mainMenu.html +++ b/src/html/mainMenu.html @@ -22,7 +22,7 @@

Contribute

Bug reports

If you experience any bug during your exploration, please add it to the issue tracker. You can also send an email at + href="https://github.com/BarthPaleologue/CosmosJourneyer/issues">issue tracker. You can also send an email at barth.paleologue@cosmosjourneyer.com. Sending screenshots and save files can help enormously with the debugging process.

From d1a1a66fe49d0b81e2614be3f6edc77d8cbaf74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Mon, 22 Jan 2024 12:09:58 +0100 Subject: [PATCH 11/14] removed buggy systems from main menu --- src/ts/mainMenu/mainMenu.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ts/mainMenu/mainMenu.ts b/src/ts/mainMenu/mainMenu.ts index 1ef4eb21a..ae8d33e4f 100644 --- a/src/ts/mainMenu/mainMenu.ts +++ b/src/ts/mainMenu/mainMenu.ts @@ -48,7 +48,6 @@ export class MainMenu { new SystemSeed(-760, -856, 60, 0), new SystemSeed(-238, 254, -675, 0), new SystemSeed(-312, 314, 736, 0), - new SystemSeed(43 - 503, -427, 532, 0), new SystemSeed(-866, 71, -294, 0), new SystemSeed(-249, 706, 631, 0), new SystemSeed(-433, 945, -693, 0), @@ -58,9 +57,7 @@ export class MainMenu { new SystemSeed(-596, 339, -571, 0), new SystemSeed(-319, 253, 30, 0), new SystemSeed(709, 570, 285, 0), - new SystemSeed(-939, -753, -401, 0), new SystemSeed(-516, -140, -2, 0), - new SystemSeed(984, -155, 179, 0), new SystemSeed(728, 691, -883, 0), new SystemSeed(-673, -545, 753, 0), new SystemSeed(-218, 213, 765, 0), From 8672fd77dd07b9d2b78c1df26f17d92f3ab58154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Mon, 22 Jan 2024 14:02:34 +0100 Subject: [PATCH 12/14] merge fixes --- src/ts/alphaTestis.ts | 4 +--- src/ts/cosmosJourneyer.ts | 5 ++--- src/ts/landingPad/landingPad.ts | 7 ++++++- src/ts/spaceship/spaceship.ts | 14 ++++++++++---- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/ts/alphaTestis.ts b/src/ts/alphaTestis.ts index 1dffabd99..03b5c84a3 100644 --- a/src/ts/alphaTestis.ts +++ b/src/ts/alphaTestis.ts @@ -150,8 +150,6 @@ engine.init(true); positionNearObjectBrightSide(starSystemView.scene.getActiveController(), planet, starSystem, 2); -spaceshipController.toggleWarpDrive(); - const aresAtmosphere = starSystem.postProcessManager.getAtmosphere(ares); if (aresAtmosphere) { aresAtmosphere.atmosphereUniforms.redWaveLength = 500; @@ -202,4 +200,4 @@ document.addEventListener("keydown", (e) => { starSystemView.ui.setEnabled(true); starSystemView.showUI(); -starSystemView.getSpaceshipControls().enableWarpDrive(); +starSystemView.getSpaceshipControls().spaceship.enableWarpDrive(); diff --git a/src/ts/cosmosJourneyer.ts b/src/ts/cosmosJourneyer.ts index 6fcd2feac..e3dc4d512 100644 --- a/src/ts/cosmosJourneyer.ts +++ b/src/ts/cosmosJourneyer.ts @@ -39,7 +39,6 @@ import { SaveFileData } from "./saveFile/saveFileData"; import { Vector3 } from "@babylonjs/core/Maths/math.vector"; import { Quaternion } from "@babylonjs/core/Maths/math"; import { setRotationQuaternion } from "./uberCore/transforms/basicTransform"; -import { positionNearObjectBrightSide } from "./utils/positionNearObject"; import { ShipControls } from "./spaceship/shipControls"; enum EngineState { @@ -146,7 +145,7 @@ export class CosmosJourneyer { const activeControls = this.getStarSystemView().scene.getActiveController(); if (activeControls instanceof ShipControls) { - activeControls.enableWarpDrive(); + activeControls.spaceship.enableWarpDrive(); activeControls.thirdPersonCamera.radius = 30; } }); @@ -159,7 +158,7 @@ export class CosmosJourneyer { this.mainMenu.onStartObservable.add(() => { this.getStarMap().setCurrentStarSystem(this.getStarSystemView().getStarSystem().model.seed); this.getStarSystemView().switchToSpaceshipControls(); - this.getStarSystemView().getSpaceshipControls().enableWarpDrive(); + this.getStarSystemView().getSpaceshipControls().spaceship.enableWarpDrive(); this.getStarSystemView().showUI(); this.getStarSystemView().ui.setEnabled(true); }); diff --git a/src/ts/landingPad/landingPad.ts b/src/ts/landingPad/landingPad.ts index fc1effb41..0a134071d 100644 --- a/src/ts/landingPad/landingPad.ts +++ b/src/ts/landingPad/landingPad.ts @@ -1,5 +1,4 @@ import { TransformNode } from "@babylonjs/core/Meshes"; -import { Transformable } from "../uberCore/transforms/basicTransform"; import { Assets } from "../assets"; import { PhysicsAggregate } from "@babylonjs/core/Physics/v2/physicsAggregate"; import { PhysicsShapeType } from "@babylonjs/core/Physics/v2/IPhysicsEnginePlugin"; @@ -8,6 +7,7 @@ import { Mesh } from "@babylonjs/core/Meshes/mesh"; import { CollisionMask } from "../settings"; import { Scene } from "@babylonjs/core/scene"; import { Vector3 } from "@babylonjs/core/Maths/math"; +import { Transformable } from "../architecture/transformable"; export class LandingPad implements Transformable { readonly instanceRoot: TransformNode; @@ -39,4 +39,9 @@ export class LandingPad implements Transformable { getTransform(): TransformNode { return this.aggregate.transformNode; } + + dispose() { + this.aggregate.dispose(); + this.instanceRoot.dispose(); + } } diff --git a/src/ts/spaceship/spaceship.ts b/src/ts/spaceship/spaceship.ts index 5fb468294..310f82bdc 100644 --- a/src/ts/spaceship/spaceship.ts +++ b/src/ts/spaceship/spaceship.ts @@ -12,12 +12,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, Transformable, translate } from "../uberCore/transforms/basicTransform"; +import { getForwardDirection, getUpwardDirection, rotate, translate } from "../uberCore/transforms/basicTransform"; import { TransformNode } from "@babylonjs/core/Meshes"; import { Assets } from "../assets"; import { PhysicsRaycastResult } from "@babylonjs/core/Physics/physicsRaycastResult"; import { PhysicsEngineV2 } from "@babylonjs/core/Physics/v2"; import { CollisionMask } from "../settings"; +import { Transformable } from "../architecture/transformable"; enum ShipState { FLYING, @@ -25,7 +26,7 @@ enum ShipState { LANDED } -export class Spaceship { +export class Spaceship implements Transformable { readonly instanceRoot: AbstractMesh; readonly aggregate: PhysicsAggregate; @@ -181,7 +182,7 @@ export class Spaceship { this.aggregate.body.setMotionType(PhysicsMotionType.ANIMATED); this.state = ShipState.LANDING; this.landingTarget = landingTarget !== null ? landingTarget : this.closestWalkableObject; - if(this.landingTarget === null) { + if (this.landingTarget === null) { throw new Error("Landing target is null"); } console.log("landing on", this.landingTarget.getTransform().name); @@ -243,7 +244,7 @@ export class Spaceship { const currentUp = getUpwardDirection(this.getTransform()); const targetUp = landingSpotNormal; let theta = 0.0; - if(Vector3.Distance(currentUp, targetUp) > 0.01) { + if (Vector3.Distance(currentUp, targetUp) > 0.01) { const axis = Vector3.Cross(currentUp, targetUp); theta = Math.acos(Vector3.Dot(currentUp, targetUp)); rotate(this.getTransform(), axis, Math.min(0.4 * deltaTime, theta)); @@ -255,4 +256,9 @@ export class Spaceship { } } } + + public dispose() { + this.aggregate.dispose(); + this.instanceRoot.dispose(); + } } From ad2434cb0b200112c40add49af43d54ff9bc4a6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Mon, 22 Jan 2024 14:09:23 +0100 Subject: [PATCH 13/14] temporary fixed for grass and butterfly materials --- src/ts/landingSimulator.ts | 5 +++++ src/ts/proceduralAssets/butterfly/butterflyMaterial.ts | 5 +++-- src/ts/proceduralAssets/grass/grassMaterial.ts | 5 +++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/ts/landingSimulator.ts b/src/ts/landingSimulator.ts index 0c340dd00..ad1f43a40 100644 --- a/src/ts/landingSimulator.ts +++ b/src/ts/landingSimulator.ts @@ -19,6 +19,8 @@ import { Spaceship } from "./spaceship/spaceship"; import "@babylonjs/core/Lights/Shadows/shadowGeneratorSceneComponent"; import { ShadowGenerator } from "@babylonjs/core/Lights/Shadows/shadowGenerator"; import { MeshBuilder } from "@babylonjs/core/Meshes/meshBuilder"; +import { HemisphericLight } from "@babylonjs/core/Lights/hemisphericLight"; +import { PointLight } from "@babylonjs/core/Lights/pointLight"; const canvas = document.getElementById("renderer") as HTMLCanvasElement; canvas.width = window.innerWidth; @@ -38,7 +40,10 @@ scene.useRightHandedSystem = true; scene.enablePhysics(Vector3.Zero(), havokPlugin); scene.clearColor = new Color4(0.2, 0.2, 0.6, 1); +const hemi = new HemisphericLight("hemi", new Vector3(0, 1, 0), scene); const light = new DirectionalLight("light", new Vector3(-2, -5, 1).normalize(), scene); +const pointLight = new PointLight("pointLight", new Vector3(0, 0, 0), scene); +pointLight.intensity = 0; const shadowGenerator = new ShadowGenerator(2048, light); await Assets.Init(scene); diff --git a/src/ts/proceduralAssets/butterfly/butterflyMaterial.ts b/src/ts/proceduralAssets/butterfly/butterflyMaterial.ts index ff8a5126f..cd3df67dc 100644 --- a/src/ts/proceduralAssets/butterfly/butterflyMaterial.ts +++ b/src/ts/proceduralAssets/butterfly/butterflyMaterial.ts @@ -48,8 +48,9 @@ export function createButterflyMaterial(scene: Scene, player?: TransformNode) { if (scene.activeCamera === null) throw new Error("Active camera is null"); - const star = scene.lights[1]; - if (!(star instanceof PointLight)) throw new Error("Could not find star light"); + 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); diff --git a/src/ts/proceduralAssets/grass/grassMaterial.ts b/src/ts/proceduralAssets/grass/grassMaterial.ts index 2a4c85120..fe9bcbc40 100644 --- a/src/ts/proceduralAssets/grass/grassMaterial.ts +++ b/src/ts/proceduralAssets/grass/grassMaterial.ts @@ -49,8 +49,9 @@ export function createGrassMaterial(scene: Scene) { if (scene.activeCamera === null) throw new Error("Active camera is null"); - const star = scene.lights[1]; - if (!(star instanceof PointLight)) throw new Error("Could not find star light"); + 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); From f48a71bace520fc2c749051cdff4cd88c3e0421f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Mon, 22 Jan 2024 15:01:20 +0100 Subject: [PATCH 14/14] bug fix The ship would spin very fast when loading a save. This was likely due to float imprecision as the scene was not re centered on the camera after loading the save --- src/ts/cosmosJourneyer.ts | 8 ++++++++ src/ts/spaceship/shipControls.ts | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ts/cosmosJourneyer.ts b/src/ts/cosmosJourneyer.ts index e3dc4d512..2a5c6d6ca 100644 --- a/src/ts/cosmosJourneyer.ts +++ b/src/ts/cosmosJourneyer.ts @@ -40,6 +40,8 @@ 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"; enum EngineState { RUNNING, @@ -382,6 +384,12 @@ export class CosmosJourneyer { ); const currentWorldRotationQuaternion = currentLocalRotationQuaternion.multiply(nearestOrbitalObjectWorldRotation); setRotationQuaternion(playerTransform, currentWorldRotationQuaternion); + + // updates camera position + this.getStarSystemView().getSpaceshipControls().getActiveCamera().getViewMatrix(true); + + // re-centers the star system + this.getStarSystemView().getStarSystem().applyFloatingOrigin(); }); this.getStarSystemView().initStarSystem(); diff --git a/src/ts/spaceship/shipControls.ts b/src/ts/spaceship/shipControls.ts index 5d45d0c3a..ad542fd09 100644 --- a/src/ts/spaceship/shipControls.ts +++ b/src/ts/spaceship/shipControls.ts @@ -160,7 +160,7 @@ export class ShipControls implements Controls { for (const input of this.inputs) this.listenTo(input, deltaTime); - this.getActiveCamera().getViewMatrix(); + this.getActiveCamera().getViewMatrix(true); return this.getTransform().getAbsolutePosition(); }