mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
Away from live, a launch shows from its lift-off on: its marker, label, paths and orbit stay hidden while the world time is before it, so scrubbing or playing brings the launches up in the order they flew. The selected mission stays whenever it flies, and live shows every launch as before. Play on the timeline runs the whole track in about a minute, from its start when at live, and runs the clock itself past weather's own replay. It goes live when it reaches now, or holds at an end that lies ahead of now. Going live puts the rate back to 1.
187 lines
5.9 KiB
JavaScript
187 lines
5.9 KiB
JavaScript
import * as Cesium from 'cesium';
|
|
import {
|
|
MISSION_ORBIT_PATTERN_GROUPS,
|
|
MISSION_ORBIT_DASHES_PER_GROUP,
|
|
} from './policy.js';
|
|
|
|
export function createOrbitRendering({
|
|
state: layerState,
|
|
services,
|
|
parts,
|
|
source,
|
|
}) {
|
|
const { orbitFrameModelMatrix } = services.satellites;
|
|
|
|
/**
|
|
* Register the selected-orbit tactical material once. Each group begins with
|
|
* one compact round dot followed by one hundred short dashes.
|
|
*/
|
|
|
|
function ensureMissionOrbitPatternRegistered() {
|
|
if (layerState._missionOrbitPatternRegistered) return;
|
|
new Cesium.Material({
|
|
fabric: {
|
|
type: 'GevMissionOrbitTactical',
|
|
uniforms: {
|
|
color: Cesium.Color.CYAN,
|
|
groupCount: MISSION_ORBIT_PATTERN_GROUPS,
|
|
dashCount: MISSION_ORBIT_DASHES_PER_GROUP,
|
|
},
|
|
source: `
|
|
czm_material czm_getMaterial(czm_materialInput materialInput) {
|
|
czm_material material = czm_getDefaultMaterial(materialInput);
|
|
float groupPosition = fract(materialInput.st.s * groupCount);
|
|
float markPosition = groupPosition * (dashCount + 1.0);
|
|
float markIndex = floor(markPosition);
|
|
float localPosition = fract(markPosition);
|
|
float centerDistance = abs(localPosition - 0.5);
|
|
float edge = max(fwidth(localPosition) * 1.35, 0.012);
|
|
float dashAlong = 1.0 - smoothstep(0.27 - edge, 0.27 + edge, centerDistance);
|
|
float dashAcross = 1.0 - smoothstep(0.12, 0.24, abs(materialInput.st.t - 0.5));
|
|
float dash = dashAlong * dashAcross;
|
|
float dotAlong = (localPosition - 0.5) / 0.32;
|
|
float dotAcross = (materialInput.st.t - 0.5) / 0.5;
|
|
float dot = 1.0 - smoothstep(0.78, 1.0, length(vec2(dotAlong, dotAcross)));
|
|
float isDot = 1.0 - step(0.5, markIndex);
|
|
float visible = mix(dash, dot, isDot);
|
|
material.diffuse = color.rgb;
|
|
material.emission = color.rgb * mix(0.07, 0.65, isDot);
|
|
material.alpha = color.a * visible * mix(0.58, 1.0, isDot);
|
|
return material;
|
|
}`,
|
|
},
|
|
});
|
|
layerState._missionOrbitPatternRegistered = true;
|
|
}
|
|
|
|
function createMissionOrbitPatternMaterial(color) {
|
|
ensureMissionOrbitPatternRegistered();
|
|
return Cesium.Material.fromType('GevMissionOrbitTactical', {
|
|
color,
|
|
groupCount: MISSION_ORBIT_PATTERN_GROUPS,
|
|
dashCount: MISSION_ORBIT_DASHES_PER_GROUP,
|
|
});
|
|
}
|
|
|
|
function missionOrbitPrimitiveVisible(launchId) {
|
|
return Boolean(
|
|
layerState._enabled &&
|
|
layerState._dataSource?.show &&
|
|
!layerState.launchHidden(
|
|
layerState._missionOverlayRecords.get(launchId)?.launch,
|
|
) &&
|
|
(!layerState._selectedLaunchId ||
|
|
layerState._selectedLaunchId === launchId),
|
|
);
|
|
}
|
|
|
|
function syncMissionOrbitPrimitiveVisibility() {
|
|
for (const [launchId, path] of layerState._missionOrbitPrimitives) {
|
|
if (path.primitive)
|
|
path.primitive.show = missionOrbitPrimitiveVisible(launchId);
|
|
}
|
|
}
|
|
|
|
function removeMissionOrbitPrimitives() {
|
|
for (const path of layerState._missionOrbitPrimitives.values()) {
|
|
if (path.primitive && layerState._viewer?.scene?.primitives) {
|
|
layerState._viewer.scene.primitives.remove(path.primitive);
|
|
}
|
|
}
|
|
layerState._missionOrbitPrimitives.clear();
|
|
}
|
|
|
|
function updateMissionOrbitPrimitiveFrames(nowDate) {
|
|
for (const [launchId, path] of layerState._missionOrbitPrimitives) {
|
|
if (!path.primitive || !missionOrbitPrimitiveVisible(launchId)) continue;
|
|
orbitFrameModelMatrix(
|
|
path.gmstAtBake,
|
|
nowDate,
|
|
path.primitive.modelMatrix,
|
|
);
|
|
if (path.labelBakePosition && path.labelPosition) {
|
|
Cesium.Matrix4.multiplyByPoint(
|
|
path.primitive.modelMatrix,
|
|
path.labelBakePosition,
|
|
path.labelPosition,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function addMissionOrbitPrimitive(launch, orbitPath, satelliteTrack) {
|
|
if (
|
|
!layerState._viewer ||
|
|
!satelliteTrack ||
|
|
!Number.isFinite(satelliteTrack.gmstAtBake)
|
|
)
|
|
return false;
|
|
const collection = new Cesium.PolylineCollection();
|
|
collection.add({
|
|
positions: orbitPath,
|
|
width: 3,
|
|
material: createMissionOrbitPatternMaterial(
|
|
Cesium.Color.fromCssColorString('#22e6e6').withAlpha(0.95),
|
|
),
|
|
});
|
|
collection.show = missionOrbitPrimitiveVisible(launch.id);
|
|
orbitFrameModelMatrix(
|
|
satelliteTrack.gmstAtBake,
|
|
new Date(layerState.orbitNow()),
|
|
collection.modelMatrix,
|
|
);
|
|
layerState._viewer.scene.primitives.add(collection);
|
|
layerState._missionOrbitPrimitives.set(launch.id, {
|
|
primitive: collection,
|
|
gmstAtBake: satelliteTrack.gmstAtBake,
|
|
});
|
|
return true;
|
|
}
|
|
|
|
function MissionOrbitPatternMaterialProperty(color) {
|
|
ensureMissionOrbitPatternRegistered();
|
|
this._color = color;
|
|
this._definitionChanged = new Cesium.Event();
|
|
}
|
|
Object.defineProperties(MissionOrbitPatternMaterialProperty.prototype, {
|
|
isConstant: {
|
|
get() {
|
|
return true;
|
|
},
|
|
},
|
|
definitionChanged: {
|
|
get() {
|
|
return this._definitionChanged;
|
|
},
|
|
},
|
|
});
|
|
MissionOrbitPatternMaterialProperty.prototype.getType = function getType() {
|
|
return 'GevMissionOrbitTactical';
|
|
};
|
|
MissionOrbitPatternMaterialProperty.prototype.getValue = function getValue(
|
|
time,
|
|
result,
|
|
) {
|
|
if (!Cesium.defined(result)) result = {};
|
|
result.color = this._color;
|
|
result.groupCount = MISSION_ORBIT_PATTERN_GROUPS;
|
|
result.dashCount = MISSION_ORBIT_DASHES_PER_GROUP;
|
|
return result;
|
|
};
|
|
MissionOrbitPatternMaterialProperty.prototype.equals = function equals(
|
|
other,
|
|
) {
|
|
return this === other;
|
|
};
|
|
return {
|
|
ensureMissionOrbitPatternRegistered,
|
|
createMissionOrbitPatternMaterial,
|
|
missionOrbitPrimitiveVisible,
|
|
syncMissionOrbitPrimitiveVisibility,
|
|
removeMissionOrbitPrimitives,
|
|
updateMissionOrbitPrimitiveFrames,
|
|
addMissionOrbitPrimitive,
|
|
MissionOrbitPatternMaterialProperty,
|
|
};
|
|
}
|