mirror of
https://github.com/Krafpy/KSP-MGA-Planner.git
synced 2025-12-12 07:40:41 -08:00
Added SOI display
- Added SOI checkbox in the editor - Added management of SOI displays during rendering in `system.ts` - Replaced body sprites with spheres
This commit is contained in:
@@ -11,6 +11,7 @@ solarSystem:
|
||||
satFarSize: 0.04 # size of satellites sprites
|
||||
satDispRadii: 10 # minimum display distance of satellites (in radii of the scaled semi major axis)
|
||||
mouseFocusDst: 25 # minimum distance to between body on screen and mouse to set focus (in pixels)
|
||||
soiOpacity: 0.3 # the opacity of SOI spheres
|
||||
|
||||
orbit:
|
||||
satSampPoints: 1000 # sample points for satellites' orbits
|
||||
|
||||
3
dist/main/editor/editor.js
vendored
3
dist/main/editor/editor.js
vendored
@@ -21,6 +21,9 @@ export function initEditor(controls, system, config, canvas) {
|
||||
};
|
||||
systemTime.input(updateSystemTime);
|
||||
updateSystemTime();
|
||||
const soiCheckbox = document.getElementById("soi-checkbox");
|
||||
soiCheckbox.onchange = () => system.showSOIs = soiCheckbox.checked;
|
||||
soiCheckbox.checked = false;
|
||||
const sequenceSelector = new SequenceSelector("sequence-selector");
|
||||
sequenceSelector.disable();
|
||||
const originSelector = new BodySelector("origin-selector", system);
|
||||
|
||||
1
dist/main/main.js
vendored
1
dist/main/main.js
vendored
@@ -25,6 +25,7 @@ async function main() {
|
||||
requestAnimationFrame(loop);
|
||||
controls.update();
|
||||
system.updateSatellitesDisplay(controls);
|
||||
system.updateSOIsDisplay(controls);
|
||||
renderer.render(scene, camera);
|
||||
};
|
||||
requestAnimationFrame(loop);
|
||||
|
||||
59
dist/main/objects/system.js
vendored
59
dist/main/objects/system.js
vendored
@@ -1,11 +1,13 @@
|
||||
import { OrbitingBody, CelestialBody } from "./body.js";
|
||||
import { createLine, createOrbitPoints, createSprite } from "../utilities/geometry.js";
|
||||
import * as Geometry from "../utilities/geometry.js";
|
||||
export class SolarSystem {
|
||||
constructor(sun, bodies, config) {
|
||||
this.config = config;
|
||||
this._orbiting = new Map();
|
||||
this._objects = new Map();
|
||||
this._orbits = new Map();
|
||||
this._sois = new Map();
|
||||
this.showSOIs = false;
|
||||
this.sun = new CelestialBody(sun);
|
||||
for (const data of bodies) {
|
||||
const { orbiting } = data;
|
||||
@@ -56,31 +58,43 @@ export class SolarSystem {
|
||||
const textureLoader = new THREE.TextureLoader();
|
||||
return new Promise((resolve, _) => {
|
||||
const loaded = (texture) => {
|
||||
const material = new THREE.SpriteMaterial({
|
||||
const spriteMaterial = new THREE.SpriteMaterial({
|
||||
map: texture
|
||||
});
|
||||
const { scale } = this.config.rendering;
|
||||
const { satSampPoints, planetSampPoints, orbitLineWidth } = this.config.orbit;
|
||||
const { planetFarSize, satFarSize } = this.config.solarSystem;
|
||||
const sunSprite = createSprite(material, this.sun.color, true, scale * this.sun.radius * 2);
|
||||
const { soiOpacity } = this.config.solarSystem;
|
||||
const sunSprite = Geometry.createSprite(spriteMaterial, this.sun.color, true, scale * this.sun.radius * 2);
|
||||
const sunGroup = new THREE.Group();
|
||||
sunGroup.add(sunSprite);
|
||||
this._objects.set(0, sunGroup);
|
||||
for (const body of this.orbiting) {
|
||||
const { radius, orbit, color, attractor } = body;
|
||||
const { radius, soi, orbit, color, attractor } = body;
|
||||
const parentGroup = this._objects.get(attractor.id);
|
||||
const bodyGroup = new THREE.Group();
|
||||
const samplePts = attractor.id == 0 ? planetSampPoints : satSampPoints;
|
||||
const spriteSize = attractor.id == 0 ? planetFarSize : satFarSize;
|
||||
const orbitPoints = createOrbitPoints(orbit, samplePts, scale);
|
||||
const ellipse = createLine(orbitPoints, canvas, {
|
||||
const orbitPoints = Geometry.createOrbitPoints(orbit, samplePts, scale);
|
||||
const ellipse = Geometry.createLine(orbitPoints, canvas, {
|
||||
color: color,
|
||||
linewidth: orbitLineWidth,
|
||||
});
|
||||
parentGroup.add(ellipse);
|
||||
this._orbits.set(body.id, ellipse);
|
||||
bodyGroup.add(createSprite(material, color, true, scale * radius * 2));
|
||||
bodyGroup.add(createSprite(material, color, false, spriteSize));
|
||||
const soiMaterial = new THREE.MeshBasicMaterial({
|
||||
color: color,
|
||||
transparent: true,
|
||||
opacity: soiOpacity
|
||||
});
|
||||
const soiLines = Geometry.createWireframeSphere(soi, scale, soiMaterial);
|
||||
bodyGroup.add(soiLines);
|
||||
this._sois.set(body.id, soiLines);
|
||||
const bodyMaterial = new THREE.MeshBasicMaterial({
|
||||
color: color
|
||||
});
|
||||
bodyGroup.add(Geometry.createSphere(radius, scale, bodyMaterial));
|
||||
bodyGroup.add(Geometry.createSprite(spriteMaterial, color, false, spriteSize));
|
||||
parentGroup.add(bodyGroup);
|
||||
this._objects.set(body.id, bodyGroup);
|
||||
}
|
||||
@@ -115,4 +129,33 @@ export class SolarSystem {
|
||||
}
|
||||
}
|
||||
}
|
||||
updateSOIsDisplay(camController) {
|
||||
if (!this.showSOIs) {
|
||||
for (const sphere of this._sois.values()) {
|
||||
sphere.visible = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const camPos = camController.camera.position;
|
||||
const { scale } = this.config.rendering;
|
||||
for (const body of this.orbiting) {
|
||||
const group = this._objects.get(body.id);
|
||||
const objPos = new THREE.Vector3();
|
||||
group.getWorldPosition(objPos);
|
||||
const dstToCam = camPos.distanceTo(objPos);
|
||||
const sphere = this._sois.get(body.id);
|
||||
sphere.visible = dstToCam > body.soi * scale;
|
||||
}
|
||||
for (const body of this.orbiting) {
|
||||
const soi = this._sois.get(body.id);
|
||||
const attrSoi = this._sois.get(body.attractor.id);
|
||||
if (attrSoi === null || attrSoi === void 0 ? void 0 : attrSoi.visible) {
|
||||
soi.visible = false;
|
||||
}
|
||||
else {
|
||||
soi.visible && (soi.visible = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
11
dist/main/utilities/geometry.js
vendored
11
dist/main/utilities/geometry.js
vendored
@@ -1,9 +1,14 @@
|
||||
export function createSphere(radius, scale, color) {
|
||||
export function createSphere(radius, scale, material) {
|
||||
const geometry = new THREE.SphereGeometry(radius * scale, 50, 50);
|
||||
const material = new THREE.MeshBasicMaterial({ color: color });
|
||||
const mesh = new THREE.Mesh(geometry, material);
|
||||
const mesh = new THREE.Mesh(geometry, material.clone());
|
||||
return mesh;
|
||||
}
|
||||
export function createWireframeSphere(radius, scale, material) {
|
||||
const geometry = new THREE.SphereGeometry(radius * scale, 15, 15);
|
||||
const wireframe = new THREE.WireframeGeometry(geometry);
|
||||
const lines = new THREE.LineSegments(wireframe, material.clone());
|
||||
return lines;
|
||||
}
|
||||
export function createSprite(material, color, sizeAttenuation, scale) {
|
||||
const sprite = new THREE.Sprite(material.clone());
|
||||
sprite.center.set(0.5, 0.5);
|
||||
|
||||
@@ -217,6 +217,10 @@
|
||||
<strong>Double click:</strong> focus on body -
|
||||
<strong>Mouse wheel:</strong> zoom
|
||||
</p>
|
||||
<div id="soi-toggle-box">
|
||||
<input type="checkbox" id="soi-checkbox" name="soi-checkbox">
|
||||
<label for="soi-checkbox">Show SOIs</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End of the 3D display panel -->
|
||||
|
||||
@@ -25,7 +25,13 @@ export function initEditor(controls: CameraController, system: SolarSystem, conf
|
||||
};
|
||||
systemTime.input(updateSystemTime);
|
||||
updateSystemTime();
|
||||
|
||||
// SOI toggle
|
||||
const soiCheckbox = document.getElementById("soi-checkbox") as HTMLInputElement;
|
||||
soiCheckbox.onchange = () => system.showSOIs = soiCheckbox.checked;
|
||||
soiCheckbox.checked = false; // default
|
||||
|
||||
// Sequence generation panel
|
||||
const sequenceSelector = new SequenceSelector("sequence-selector");
|
||||
sequenceSelector.disable();
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ async function main(){
|
||||
requestAnimationFrame(loop);
|
||||
controls.update();
|
||||
system.updateSatellitesDisplay(controls);
|
||||
system.updateSOIsDisplay(controls);
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
requestAnimationFrame(loop);
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { OrbitingBody, CelestialBody } from "./body.js";
|
||||
import { CameraController } from "./camera.js";
|
||||
import { /*createSphere,*/ createLine, createOrbitPoints, createSprite } from "../utilities/geometry.js";
|
||||
import * as Geometry from "../utilities/geometry.js";
|
||||
|
||||
export class SolarSystem {
|
||||
readonly sun!: CelestialBody;
|
||||
private readonly _orbiting: Map<number, OrbitingBody> = new Map();
|
||||
private readonly _objects: Map<number, THREE.Group> = new Map();
|
||||
private readonly _orbits: Map<number, THREE.Object3D> = new Map();
|
||||
private readonly _sois: Map<number, THREE.Object3D> = new Map();
|
||||
public showSOIs: boolean = false;
|
||||
|
||||
constructor(sun: ICelestialBody, bodies: IOrbitingBody[], public readonly config: Config) {
|
||||
this.sun = new CelestialBody(sun);
|
||||
@@ -68,36 +70,37 @@ export class SolarSystem {
|
||||
* Creates the 3D objects of all the celestial bodies.
|
||||
* @returns The promise to wait for the loading to complete.
|
||||
*/
|
||||
public fillSceneObjects(scene: THREE.Scene, canvas: HTMLCanvasElement) {
|
||||
public fillSceneObjects(scene: THREE.Scene, canvas: HTMLCanvasElement) {
|
||||
const textureLoader = new THREE.TextureLoader();
|
||||
|
||||
return new Promise(
|
||||
(resolve, _) => {
|
||||
const loaded = (texture: THREE.Texture) => {
|
||||
const material = new THREE.SpriteMaterial({
|
||||
const spriteMaterial = new THREE.SpriteMaterial({
|
||||
map: texture
|
||||
});
|
||||
|
||||
const {scale} = this.config.rendering;
|
||||
const {satSampPoints, planetSampPoints, orbitLineWidth} = this.config.orbit;
|
||||
const {planetFarSize, satFarSize} = this.config.solarSystem;
|
||||
const {soiOpacity} = this.config.solarSystem;
|
||||
|
||||
const sunSprite = createSprite(material, this.sun.color, true, scale * this.sun.radius * 2);
|
||||
const sunSprite = Geometry.createSprite(spriteMaterial, this.sun.color, true, scale * this.sun.radius * 2);
|
||||
const sunGroup = new THREE.Group();
|
||||
sunGroup.add(sunSprite);
|
||||
|
||||
this._objects.set(0, sunGroup);
|
||||
|
||||
for(const body of this.orbiting){
|
||||
const {radius, orbit, color, attractor} = body;
|
||||
const {radius, soi, orbit, color, attractor} = body;
|
||||
const parentGroup = <THREE.Group>this._objects.get(attractor.id);
|
||||
const bodyGroup = new THREE.Group();
|
||||
|
||||
const samplePts = attractor.id == 0 ? planetSampPoints : satSampPoints;
|
||||
const spriteSize = attractor.id == 0 ? planetFarSize : satFarSize;
|
||||
|
||||
const orbitPoints = createOrbitPoints(orbit, samplePts, scale);
|
||||
const ellipse = createLine(orbitPoints, canvas, {
|
||||
const orbitPoints = Geometry.createOrbitPoints(orbit, samplePts, scale);
|
||||
const ellipse = Geometry.createLine(orbitPoints, canvas, {
|
||||
color: color,
|
||||
linewidth: orbitLineWidth,
|
||||
});
|
||||
@@ -105,9 +108,23 @@ export class SolarSystem {
|
||||
|
||||
this._orbits.set(body.id, ellipse);
|
||||
|
||||
//bodyGroup.add(createSphere(radius, scale, color));
|
||||
bodyGroup.add(createSprite(material, color, true, scale * radius * 2));
|
||||
bodyGroup.add(createSprite(material, color, false, spriteSize));
|
||||
// Create the SOI sphere
|
||||
const soiMaterial = new THREE.MeshBasicMaterial({
|
||||
color: color,
|
||||
transparent: true,
|
||||
opacity: soiOpacity
|
||||
});
|
||||
const soiLines = Geometry.createWireframeSphere(soi, scale, soiMaterial)
|
||||
bodyGroup.add(soiLines);
|
||||
|
||||
this._sois.set(body.id, soiLines);
|
||||
|
||||
// Create body sphere and sprites
|
||||
const bodyMaterial = new THREE.MeshBasicMaterial({
|
||||
color: color
|
||||
});
|
||||
bodyGroup.add(Geometry.createSphere(radius, scale, bodyMaterial));
|
||||
bodyGroup.add(Geometry.createSprite(spriteMaterial, color, false, spriteSize));
|
||||
parentGroup.add(bodyGroup);
|
||||
|
||||
this._objects.set(body.id, bodyGroup);
|
||||
@@ -158,4 +175,39 @@ export class SolarSystem {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates how SOIs are displayed based on camera position.
|
||||
*/
|
||||
public updateSOIsDisplay(camController: CameraController){
|
||||
if(!this.showSOIs){
|
||||
for(const sphere of this._sois.values()){
|
||||
sphere.visible = false;
|
||||
}
|
||||
} else {
|
||||
const camPos = camController.camera.position;
|
||||
const {scale} = this.config.rendering;
|
||||
|
||||
for(const body of this.orbiting){
|
||||
const group = <THREE.Group>this._objects.get(body.id);
|
||||
const objPos = new THREE.Vector3();
|
||||
group.getWorldPosition(objPos);
|
||||
|
||||
const dstToCam = camPos.distanceTo(objPos);
|
||||
|
||||
const sphere = <THREE.Object3D>this._sois.get(body.id);
|
||||
sphere.visible = dstToCam > body.soi * scale;
|
||||
}
|
||||
|
||||
for(const body of this.orbiting){
|
||||
const soi = <THREE.Object3D>this._sois.get(body.id);
|
||||
const attrSoi = this._sois.get(body.attractor.id);
|
||||
if(attrSoi?.visible){
|
||||
soi.visible = false;
|
||||
} else {
|
||||
soi.visible &&= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,18 @@
|
||||
import { Orbit } from "../objects/orbit";
|
||||
|
||||
export function createSphere(radius: number, scale: number, color: number) {
|
||||
export function createSphere(radius: number, scale: number, material: THREE.MeshBasicMaterial) {
|
||||
const geometry = new THREE.SphereGeometry(radius * scale, 50, 50);
|
||||
const material = new THREE.MeshBasicMaterial({color: color});
|
||||
const mesh = new THREE.Mesh(geometry, material);
|
||||
const mesh = new THREE.Mesh(geometry, material.clone());
|
||||
return mesh;
|
||||
}
|
||||
|
||||
export function createWireframeSphere(radius: number, scale: number, material: THREE.Material){
|
||||
const geometry = new THREE.SphereGeometry(radius * scale, 15, 15);
|
||||
const wireframe = new THREE.WireframeGeometry(geometry);
|
||||
const lines = new THREE.LineSegments(wireframe, material.clone());
|
||||
return lines;
|
||||
}
|
||||
|
||||
export function createSprite(material: THREE.SpriteMaterial, color: number, sizeAttenuation: boolean, scale: number){
|
||||
const sprite = new THREE.Sprite(material.clone());
|
||||
sprite.center.set(0.5, 0.5);
|
||||
|
||||
2
src/types.d.ts
vendored
2
src/types.d.ts
vendored
@@ -40,6 +40,7 @@ interface SystemDrawSettings {
|
||||
readonly satFarSize: number;
|
||||
readonly satDispRadii: number;
|
||||
readonly mouseFocusDst: number;
|
||||
readonly soiOpacity: number;
|
||||
}
|
||||
|
||||
interface OrbitSettings {
|
||||
@@ -89,7 +90,6 @@ interface WorkersSettings {
|
||||
|
||||
interface TrajectorySearchSettings {
|
||||
readonly splitLimit: number;
|
||||
//readonly crossoverProba: number;
|
||||
readonly minCrossProba: number;
|
||||
readonly maxCrossProba: number;
|
||||
readonly crossProbaIncr: number;
|
||||
|
||||
Reference in New Issue
Block a user