@johnmorrisdotca/uchusen-rockets 0.19.1 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/LICENSES/Orbiter-MIT.txt +21 -0
- package/NOTICE.md +37 -1
- package/README.md +13 -6
- package/dist/assets/falcon-heavy-test-flight-apart.painted.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-apart.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-apart.thick.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-car.glb +0 -0
- package/dist/assets/falcon-heavy-test-flight-car.painted.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-car.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-car.thick.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-centre.glb +0 -0
- package/dist/assets/falcon-heavy-test-flight-centre.painted.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-centre.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-centre.thick.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-side-left.glb +0 -0
- package/dist/assets/falcon-heavy-test-flight-side-left.painted.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-side-left.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-side-left.thick.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-side-right.glb +0 -0
- package/dist/assets/falcon-heavy-test-flight-side-right.painted.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-side-right.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-side-right.thick.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-starman.glb +0 -0
- package/dist/assets/falcon-heavy-test-flight-starman.painted.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-starman.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight-starman.thick.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight.glb +0 -0
- package/dist/assets/falcon-heavy-test-flight.painted.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight.svg +1 -0
- package/dist/assets/falcon-heavy-test-flight.thick.svg +1 -0
- package/dist/assets/models/roadster-first-generation-car.glb +0 -0
- package/dist/assets/models/roadster-second-generation-2-car.glb +0 -0
- package/dist/assets/models/roadster-second-generation-car.glb +0 -0
- package/dist/assets/roadster-first-generation-apart.painted.svg +1 -0
- package/dist/assets/roadster-first-generation-apart.svg +1 -0
- package/dist/assets/roadster-first-generation-apart.thick.svg +1 -0
- package/dist/assets/roadster-first-generation-car.glb +0 -0
- package/dist/assets/roadster-first-generation-car.painted.svg +1 -0
- package/dist/assets/roadster-first-generation-car.svg +1 -0
- package/dist/assets/roadster-first-generation-car.thick.svg +1 -0
- package/dist/assets/roadster-first-generation-starman.glb +0 -0
- package/dist/assets/roadster-first-generation-starman.painted.svg +1 -0
- package/dist/assets/roadster-first-generation-starman.svg +1 -0
- package/dist/assets/roadster-first-generation-starman.thick.svg +1 -0
- package/dist/assets/roadster-first-generation.glb +0 -0
- package/dist/assets/roadster-first-generation.painted.svg +1 -0
- package/dist/assets/roadster-first-generation.svg +1 -0
- package/dist/assets/roadster-first-generation.thick.svg +1 -0
- package/dist/assets/roadster-second-generation-2-apart.painted.svg +1 -0
- package/dist/assets/roadster-second-generation-2-apart.svg +1 -0
- package/dist/assets/roadster-second-generation-2-apart.thick.svg +1 -0
- package/dist/assets/roadster-second-generation-2-car.glb +0 -0
- package/dist/assets/roadster-second-generation-2-car.painted.svg +1 -0
- package/dist/assets/roadster-second-generation-2-car.svg +1 -0
- package/dist/assets/roadster-second-generation-2-car.thick.svg +1 -0
- package/dist/assets/roadster-second-generation-2-starman.glb +0 -0
- package/dist/assets/roadster-second-generation-2-starman.painted.svg +1 -0
- package/dist/assets/roadster-second-generation-2-starman.svg +1 -0
- package/dist/assets/roadster-second-generation-2-starman.thick.svg +1 -0
- package/dist/assets/roadster-second-generation-2.glb +0 -0
- package/dist/assets/roadster-second-generation-2.painted.svg +1 -0
- package/dist/assets/roadster-second-generation-2.svg +1 -0
- package/dist/assets/roadster-second-generation-2.thick.svg +1 -0
- package/dist/assets/roadster-second-generation-apart.painted.svg +1 -0
- package/dist/assets/roadster-second-generation-apart.svg +1 -0
- package/dist/assets/roadster-second-generation-apart.thick.svg +1 -0
- package/dist/assets/roadster-second-generation-car.glb +0 -0
- package/dist/assets/roadster-second-generation-car.painted.svg +1 -0
- package/dist/assets/roadster-second-generation-car.svg +1 -0
- package/dist/assets/roadster-second-generation-car.thick.svg +1 -0
- package/dist/assets/roadster-second-generation-starman.glb +0 -0
- package/dist/assets/roadster-second-generation-starman.painted.svg +1 -0
- package/dist/assets/roadster-second-generation-starman.svg +1 -0
- package/dist/assets/roadster-second-generation-starman.thick.svg +1 -0
- package/dist/assets/roadster-second-generation.glb +0 -0
- package/dist/assets/roadster-second-generation.painted.svg +1 -0
- package/dist/assets/roadster-second-generation.svg +1 -0
- package/dist/assets/roadster-second-generation.thick.svg +1 -0
- package/dist/data/countries.d.ts +51 -0
- package/dist/data/countries.js +91 -0
- package/dist/data/credits.d.ts +36 -0
- package/dist/data/credits.js +36 -0
- package/dist/data/falcon.js +26 -14
- package/dist/data/makers.js +1 -0
- package/dist/data/roadster.d.ts +13 -0
- package/dist/data/roadster.js +73 -0
- package/dist/data/sources.d.ts +56 -0
- package/dist/data/sources.js +7 -0
- package/dist/element/flag.d.ts +30 -0
- package/dist/element/flag.js +23 -0
- package/dist/element/scene.d.ts +7 -0
- package/dist/element/scene.js +35 -1
- package/dist/element.d.ts +5 -0
- package/dist/element.js +58 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/inspace.js +1 -0
- package/dist/model/registry.js +6 -4
- package/dist/model/roadster.d.ts +31 -0
- package/dist/model/roadster.js +112 -0
- package/dist/parts.d.ts +1 -1
- package/dist/physics/atmosphere.d.ts +182 -0
- package/dist/physics/atmosphere.js +246 -0
- package/dist/physics/attitude.d.ts +342 -0
- package/dist/physics/attitude.js +351 -0
- package/dist/physics/burns.d.ts +194 -0
- package/dist/physics/burns.js +157 -0
- package/dist/physics/elements.d.ts +133 -0
- package/dist/physics/elements.js +239 -0
- package/dist/physics/gravity.d.ts +53 -0
- package/dist/physics/gravity.js +78 -0
- package/dist/physics/index.d.ts +17 -0
- package/dist/physics/index.js +8 -0
- package/dist/physics/propagate.d.ts +110 -0
- package/dist/physics/propagate.js +122 -0
- package/dist/physics/rocket.d.ts +105 -0
- package/dist/physics/rocket.js +102 -0
- package/dist/physics/transfers.d.ts +128 -0
- package/dist/physics/transfers.js +155 -0
- package/dist/physics/vector.d.ts +20 -0
- package/dist/physics/vector.js +9 -0
- package/dist/react.d.ts +1 -1
- package/dist/rockets.d.ts +5 -0
- package/dist/rockets.js +9 -4
- package/dist/sun.d.ts +13 -0
- package/dist/sun.js +25 -0
- package/package.json +11 -1
package/dist/element.d.ts
CHANGED
|
@@ -63,6 +63,8 @@ export declare class UchusenRocket extends HTMLBase {
|
|
|
63
63
|
private builtNow;
|
|
64
64
|
private queued;
|
|
65
65
|
private stateNow;
|
|
66
|
+
/** What the flag in the corner is for: a country's code, "" for none, "off", or "-" before the first look. */
|
|
67
|
+
private flagKey;
|
|
66
68
|
private shownAt;
|
|
67
69
|
private starting;
|
|
68
70
|
/** Whether this element has asked the page's WebGL answer since it started watching. */
|
|
@@ -201,6 +203,8 @@ export declare class UchusenRocket extends HTMLBase {
|
|
|
201
203
|
/** The drawing for what the attributes say now. It is made from code, so it needs no file. A zoom or a move only changes which part of it the box shows (its viewBox), so the drawing is as sharp as the box and never grows past it. */
|
|
202
204
|
private redraw;
|
|
203
205
|
private mark;
|
|
206
|
+
/** `flags`: the rocket's country's flag in the picture's corner, from hata (an optional peer) when the page has it. `data-flag` is the code shown, or empty once it is settled that none is; it is absent while one is loading or the attribute is off. */
|
|
207
|
+
private syncFlag;
|
|
204
208
|
private applyRocket;
|
|
205
209
|
/** A fleet ship is built coarse first (the first picture and the far view) and fine when the camera comes near, an inset opens or one part is shown alone: once per visit, never on a turn or a look change. */
|
|
206
210
|
private fine;
|
|
@@ -257,6 +261,7 @@ export declare class UchusenLineup extends HTMLBase {
|
|
|
257
261
|
*/
|
|
258
262
|
export declare function defineUchusenRocket(): void;
|
|
259
263
|
export { ROCKETS, UchusenFlight };
|
|
264
|
+
export { setFlagLoader, type FlagSource } from "./element/flag.ts";
|
|
260
265
|
export type { FlightWords } from "./flightbar.ts";
|
|
261
266
|
declare global {
|
|
262
267
|
interface HTMLElementTagNameMap {
|
package/dist/element.js
CHANGED
|
@@ -6,6 +6,7 @@ import { buildOf } from "./buildPlay.js";
|
|
|
6
6
|
import { bellsOf, enginesWanted, pickBells } from "./engines.js";
|
|
7
7
|
import { lightMode } from "./model/fleet/lights.js";
|
|
8
8
|
import { thrusterMode } from "./thrusters.js";
|
|
9
|
+
import { parseSun } from "./sun.js";
|
|
9
10
|
import { motionsOf, motionSpeed, motionWanted } from "./model/fleet/motion.js";
|
|
10
11
|
import { engineChart } from "./draw/plume.js";
|
|
11
12
|
import { burnsOf, FlightClock, flightOf, frameAt, phaseAt, phasePosition } from "./flight.js";
|
|
@@ -23,6 +24,7 @@ import { skyQuery } from "./element/solarGroups.js";
|
|
|
23
24
|
import { Panel } from "./element/panel.js";
|
|
24
25
|
import { glProbe } from "./element/probe.js";
|
|
25
26
|
import { spinOf } from "./spin.js";
|
|
27
|
+
import { flagSvg } from "./element/flag.js";
|
|
26
28
|
const HTMLBase = typeof HTMLElement === "undefined" ? class {
|
|
27
29
|
} : HTMLElement;
|
|
28
30
|
/** A view out of sight keeps its WebGL canvas this long before letting it go (a browser allows only a few at a time). */
|
|
@@ -47,6 +49,15 @@ export function setAssetBase(url) {
|
|
|
47
49
|
assetBase = url.endsWith("/") ? url : `${url}/`;
|
|
48
50
|
}
|
|
49
51
|
const defaultBase = () => assetBase ?? new URL("./assets/", import.meta.url).href;
|
|
52
|
+
/** A country's name in the page's language, or its code where the browser has no name for it. */
|
|
53
|
+
function regionName(code, lang) {
|
|
54
|
+
try {
|
|
55
|
+
return new Intl.DisplayNames([lang || "en"], { type: "region" }).of(code) ?? code;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return code;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
50
61
|
const CSS = `
|
|
51
62
|
:host { display: block; position: relative; color: inherit; }
|
|
52
63
|
:host([hidden]) { display: none; }
|
|
@@ -73,6 +84,8 @@ const CSS = `
|
|
|
73
84
|
.panel table { border-collapse: collapse; width: 100%; }
|
|
74
85
|
.panel th, .panel td { text-align: left; padding: 0.15rem 0.4rem; border-bottom: 1px solid color-mix(in srgb, currentColor 25%, transparent); vertical-align: top; }
|
|
75
86
|
.panel p { margin: 0 0 0.5rem; }
|
|
87
|
+
.flag { position: absolute; top: 0.5rem; left: 0.5rem; display: block; width: 1.5rem; aspect-ratio: 4 / 3; line-height: 0; pointer-events: none; box-shadow: 0 0 0 1px color-mix(in srgb, currentColor 35%, transparent); }
|
|
88
|
+
.flag svg { display: block; width: 100%; height: 100%; }
|
|
76
89
|
.tilt { position: absolute; right: 0.5rem; bottom: 0.5rem; min-height: 2rem; padding: 0.25rem 0.75rem; border: 1px solid currentColor; border-radius: 1rem; background: transparent; color: inherit; font: inherit; font-size: 0.8rem; cursor: pointer; }
|
|
77
90
|
@media (prefers-reduced-motion: reduce) {
|
|
78
91
|
.drawing, .canvas { filter: none !important; transition: opacity var(--uchusen-fade, 400ms) ease; }
|
|
@@ -119,7 +132,7 @@ function whyNot(mode) {
|
|
|
119
132
|
* ```
|
|
120
133
|
*/
|
|
121
134
|
export class UchusenRocket extends HTMLBase {
|
|
122
|
-
static observedAttributes = ["rocket", "variant", "show", "look", "view", "build", "mode", "assets", "spin", "way", "label", "engines", "lights", "thrusters", "phase", "motion", "labels", "inspector", "beside", "captions", "scale-note", "off-screen", "scale", "progress", "float", "names", "leave", "docked", "edges", "world", "world-turn", "form"];
|
|
135
|
+
static observedAttributes = ["rocket", "variant", "show", "look", "view", "build", "mode", "assets", "spin", "way", "label", "engines", "lights", "thrusters", "phase", "motion", "labels", "inspector", "beside", "captions", "scale-note", "off-screen", "scale", "progress", "float", "names", "leave", "docked", "edges", "world", "world-turn", "form", "sun", "flags"];
|
|
123
136
|
descriptionValue = null;
|
|
124
137
|
picture = null;
|
|
125
138
|
holder = null;
|
|
@@ -137,6 +150,8 @@ export class UchusenRocket extends HTMLBase {
|
|
|
137
150
|
builtNow = null;
|
|
138
151
|
queued = false;
|
|
139
152
|
stateNow = "picture";
|
|
153
|
+
/** What the flag in the corner is for: a country's code, "" for none, "off", or "-" before the first look. */
|
|
154
|
+
flagKey = "-";
|
|
140
155
|
shownAt = 0;
|
|
141
156
|
starting = false;
|
|
142
157
|
/** Whether this element has asked the page's WebGL answer since it started watching. */
|
|
@@ -321,7 +336,9 @@ export class UchusenRocket extends HTMLBase {
|
|
|
321
336
|
attributeChangedCallback(name, before, after) {
|
|
322
337
|
if (before === after)
|
|
323
338
|
return;
|
|
324
|
-
if (name === "
|
|
339
|
+
if (name === "flags")
|
|
340
|
+
this.syncFlag();
|
|
341
|
+
else if (name === "scale") {
|
|
325
342
|
this.viewer?.setScaleMode(after === "true");
|
|
326
343
|
// `scale="true"` is the true-scale view. A number is a Kaminari size, which rebuilds the craft.
|
|
327
344
|
if (after !== "true" && after !== "false")
|
|
@@ -346,6 +363,8 @@ export class UchusenRocket extends HTMLBase {
|
|
|
346
363
|
this.viewer?.setFloating(after !== null);
|
|
347
364
|
else if (name === "edges")
|
|
348
365
|
this.viewer?.setEdges(after === "open");
|
|
366
|
+
else if (name === "sun")
|
|
367
|
+
this.viewer?.setSun(parseSun(after));
|
|
349
368
|
else if (name === "world")
|
|
350
369
|
this.viewer?.setOrbit(after === "earth");
|
|
351
370
|
else if (name === "world-turn")
|
|
@@ -664,6 +683,7 @@ export class UchusenRocket extends HTMLBase {
|
|
|
664
683
|
holder.className = "stage";
|
|
665
684
|
picture.append(drawing, holder);
|
|
666
685
|
root.appendChild(picture);
|
|
686
|
+
this.flagKey = "-";
|
|
667
687
|
this.picture = picture;
|
|
668
688
|
this.drawing = drawing;
|
|
669
689
|
this.holder = holder;
|
|
@@ -734,6 +754,40 @@ export class UchusenRocket extends HTMLBase {
|
|
|
734
754
|
else
|
|
735
755
|
delete this.dataset.docked;
|
|
736
756
|
this.dataset.custom = String(this.builtNow.report.custom);
|
|
757
|
+
this.syncFlag();
|
|
758
|
+
}
|
|
759
|
+
/** `flags`: the rocket's country's flag in the picture's corner, from hata (an optional peer) when the page has it. `data-flag` is the code shown, or empty once it is settled that none is; it is absent while one is loading or the attribute is off. */
|
|
760
|
+
syncFlag() {
|
|
761
|
+
const picture = this.picture;
|
|
762
|
+
if (!picture)
|
|
763
|
+
return;
|
|
764
|
+
const on = this.hasAttribute("flags") && this.getAttribute("flags") !== "off";
|
|
765
|
+
const code = on && this.builtNow ? (ROCKETS[this.descriptionNow().rocket]?.country.value ?? "") : "";
|
|
766
|
+
const key = on ? code : "off";
|
|
767
|
+
if (key === this.flagKey)
|
|
768
|
+
return;
|
|
769
|
+
this.flagKey = key;
|
|
770
|
+
picture.querySelector(".flag")?.remove();
|
|
771
|
+
if (!on)
|
|
772
|
+
return void delete this.dataset.flag;
|
|
773
|
+
if (!code)
|
|
774
|
+
return void (this.dataset.flag = "");
|
|
775
|
+
delete this.dataset.flag;
|
|
776
|
+
void flagSvg(code).then((svg) => {
|
|
777
|
+
if (this.flagKey !== key || this.picture !== picture)
|
|
778
|
+
return;
|
|
779
|
+
if (svg) {
|
|
780
|
+
const badge = document.createElement("span");
|
|
781
|
+
badge.className = "flag";
|
|
782
|
+
badge.setAttribute("part", "flag");
|
|
783
|
+
badge.setAttribute("role", "img");
|
|
784
|
+
badge.setAttribute("aria-label", regionName(code, this.closest("[lang]")?.getAttribute("lang")));
|
|
785
|
+
badge.innerHTML = svg;
|
|
786
|
+
badge.firstElementChild?.setAttribute("aria-hidden", "true");
|
|
787
|
+
picture.append(badge);
|
|
788
|
+
}
|
|
789
|
+
this.dataset.flag = svg ? code : "";
|
|
790
|
+
});
|
|
737
791
|
}
|
|
738
792
|
async applyRocket() {
|
|
739
793
|
this.mark();
|
|
@@ -1001,6 +1055,7 @@ export class UchusenRocket extends HTMLBase {
|
|
|
1001
1055
|
made.drive(this.driven);
|
|
1002
1056
|
made.setFloating(this.hasAttribute("float"));
|
|
1003
1057
|
made.setEdges(this.getAttribute("edges") === "open");
|
|
1058
|
+
made.setSun(parseSun(this.getAttribute("sun")));
|
|
1004
1059
|
made.setNameLabels(this.getAttribute("names") !== "off");
|
|
1005
1060
|
made.setVisible(true);
|
|
1006
1061
|
const { look, show, viewName, angle } = this.settings(this.builtNow ?? built);
|
|
@@ -1193,3 +1248,4 @@ export function defineUchusenRocket() {
|
|
|
1193
1248
|
}
|
|
1194
1249
|
defineUchusenRocket();
|
|
1195
1250
|
export { ROCKETS, UchusenFlight };
|
|
1251
|
+
export { setFlagLoader } from "./element/flag.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export { blank, figureWords } from "./data/types.ts";
|
|
|
4
4
|
export type { Disagreement, Figure, Variant, VariantFacts, VariantStatus } from "./data/types.ts";
|
|
5
5
|
export { MAKERS } from "./data/makers.ts";
|
|
6
6
|
export type { MakerId } from "./data/makers.ts";
|
|
7
|
+
export { COUNTRY_CODES, countryOf, MAKER_COUNTRIES } from "./data/countries.ts";
|
|
8
|
+
export type { CountryCode } from "./data/countries.ts";
|
|
7
9
|
export { FLIGHT_LOG, flightLogOf } from "./data/flight-log.ts";
|
|
8
10
|
export type { LoggedFlight } from "./data/flight-log.ts";
|
|
9
11
|
export { moved, movingGroupsOf } from "./model/moves.ts";
|
|
@@ -57,6 +59,7 @@ export { beaconLamp, dutyOf, lampFactor, lightMode, lightPool, sternLamp, workLa
|
|
|
57
59
|
export type { Motion, MotionKind, MotionSpeed } from "./model/fleet/motion.ts";
|
|
58
60
|
export { bellsOf, enginesWanted, FLAME_SETTLE_MS, pickBells, plumeLength, ringsOf } from "./engines.ts";
|
|
59
61
|
export type { Bell } from "./engines.ts";
|
|
62
|
+
export { parseSun } from "./sun.ts";
|
|
60
63
|
export { OPTION_ATTRIBUTES, attributesFromOptions, optionsFromAttributes, rocketFromParams, rocketToParams } from "./attrs.ts";
|
|
61
64
|
export type { RocketOptions } from "./attrs.ts";
|
|
62
65
|
export { assetPathOf, CDN, EMBED_KINDS, SITE, THREE_VERSION, embedCode, embedNote, paintedCredit } from "./embed.ts";
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
export { PLANNED_ROCKETS, ROCKETS, partIdOf, SLOT_NAMES, variantOf } from "./rockets.js";
|
|
3
3
|
export { blank, figureWords } from "./data/types.js";
|
|
4
4
|
export { MAKERS } from "./data/makers.js";
|
|
5
|
+
export { COUNTRY_CODES, countryOf, MAKER_COUNTRIES } from "./data/countries.js";
|
|
5
6
|
export { FLIGHT_LOG, flightLogOf } from "./data/flight-log.js";
|
|
6
7
|
export { moved, movingGroupsOf } from "./model/moves.js";
|
|
7
8
|
export { PROPELLANTS, propellantOf } from "./data/propellants.js";
|
|
@@ -34,6 +35,7 @@ export { beamLight } from "./draw/beamLight.js";
|
|
|
34
35
|
export { angleAt, MOTIONS, motionNote, motionSpeed, motionsOf, motionWanted, slideAt } from "./model/fleet/motion.js";
|
|
35
36
|
export { beaconLamp, dutyOf, lampFactor, lightMode, lightPool, sternLamp, workLamp } from "./model/fleet/lights.js";
|
|
36
37
|
export { bellsOf, enginesWanted, FLAME_SETTLE_MS, pickBells, plumeLength, ringsOf } from "./engines.js";
|
|
38
|
+
export { parseSun } from "./sun.js";
|
|
37
39
|
export { OPTION_ATTRIBUTES, attributesFromOptions, optionsFromAttributes, rocketFromParams, rocketToParams } from "./attrs.js";
|
|
38
40
|
export { assetPathOf, CDN, EMBED_KINDS, SITE, THREE_VERSION, embedCode, embedNote, paintedCredit } from "./embed.js";
|
|
39
41
|
export { COMPANIES, COMPANY_KINDS, companyOf } from "./model/fleet/company.js";
|
package/dist/inspace.js
CHANGED
|
@@ -7,6 +7,7 @@ const SPACE = {
|
|
|
7
7
|
sls: ["upper-stage", "service-module", "capsule"],
|
|
8
8
|
"falcon-9": ["second-stage", "fairing", "trunk", "capsule"],
|
|
9
9
|
dragon: ["trunk", "capsule"],
|
|
10
|
+
"falcon-heavy": ["car", "starman"],
|
|
10
11
|
};
|
|
11
12
|
/**
|
|
12
13
|
* The slots to draw when the craft is in space, or null when the picture stays the whole variant.
|
package/dist/model/registry.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Every part there is, with its record and how to make its pieces. A new rocket adds its rows here and nothing else changes.
|
|
2
2
|
import { DRAGON_VARIANTS } from "../data/dragon.js";
|
|
3
|
-
import { FALCON_9_VARIANTS } from "../data/falcon.js";
|
|
3
|
+
import { FALCON_9_VARIANTS, FALCON_HEAVY_VARIANTS } from "../data/falcon.js";
|
|
4
4
|
import { STARSHIP_VARIANTS } from "../data/starship.js";
|
|
5
5
|
import { capsule, centreCore, DRAGON_DRAWS, falconFairing, falconFirstStage, FALCON_DRAWS, falconSecondStage, grasshopper, merlin, sideBooster, trunk } from "./falcon.js";
|
|
6
6
|
import { FALCON_1_VARIANTS } from "../data/falcon1.js";
|
|
@@ -37,6 +37,8 @@ import { HUBBLE_VARIANTS } from "../data/hubble.js";
|
|
|
37
37
|
import { HUBBLE_BUILDS } from "./hubble.js";
|
|
38
38
|
import { TIANGONG_VARIANTS } from "../data/tiangong.js";
|
|
39
39
|
import { TIANGONG_BUILDS } from "./tiangong.js";
|
|
40
|
+
import { ROADSTER_VARIANTS } from "../data/roadster.js";
|
|
41
|
+
import { ROADSTER_BUILDS } from "./roadster.js";
|
|
40
42
|
import { DRONE_VARIANTS } from "../data/drone.js";
|
|
41
43
|
import { DRONE_BUILDS } from "./drone.js";
|
|
42
44
|
import { DRAGON_INSIDE_BUILDS } from "./dragoninside.js";
|
|
@@ -145,11 +147,11 @@ const FH_FROM = "This package's code for the two line looks, proportions taken f
|
|
|
145
147
|
const FH_SIDE_HEIGHT = 45.6;
|
|
146
148
|
const FH_OFFSET = 4.25;
|
|
147
149
|
const figure = (value, source) => ({ value, source });
|
|
148
|
-
entries.push({ record: { id: "falcon-heavy-falcon-heavy-centre", kind: "first-stage", name: "Falcon Heavy centre core, with its upper stage and fairing", rocket: "falcon-heavy", trueTo: ["falcon-heavy"], height: 70, diameter: 5.2, sourced: { height: figure(70, "wikipedia-falcon-heavy"), diameter: { ...blankFigure, note: "3.7 m the core; 5.2 m the fairing." } }, joints: {}, painted: PAINTED["falcon-heavy-falcon-heavy-centre"], drawnFrom: FH_FROM }, pieces: () => centreCore(70, 1.85) }, { record: { id: "falcon-heavy-falcon-heavy-side-left", kind: "first-stage", name: "Falcon Heavy side booster, left", rocket: "falcon-heavy", trueTo: ["falcon-heavy"], height: FH_SIDE_HEIGHT, diameter: 3.7, strapOn: { x: -FH_OFFSET, z: 0 }, sourced: { height: blankFigure, diameter: figure(3.7, "wikipedia-falcon-heavy") }, joints: {}, painted: PAINTED["falcon-heavy-falcon-heavy-side-left"], drawnFrom: FH_FROM }, pieces: () => sideBooster(FH_SIDE_HEIGHT, 1.85, -1) }, { record: { id: "falcon-heavy-falcon-heavy-side-right", kind: "first-stage", name: "Falcon Heavy side booster, right", rocket: "falcon-heavy", trueTo: ["falcon-heavy"], height: FH_SIDE_HEIGHT, diameter: 3.7, strapOn: { x: FH_OFFSET, z: 0 }, sourced: { height: blankFigure, diameter: figure(3.7, "wikipedia-falcon-heavy") }, joints: {}, painted: PAINTED["falcon-heavy-falcon-heavy-side-right"], drawnFrom: FH_FROM }, pieces: () => sideBooster(FH_SIDE_HEIGHT, 1.85, 1) }, { record: { id: "grasshopper-grasshopper-vehicle", kind: "test-vehicle", name: "Grasshopper, test vehicle", rocket: "grasshopper", trueTo: ["grasshopper"], height: 32, diameter: 3.2, sourced: { height: figure(32, "wikipedia-grasshopper"), diameter: blankFigure }, joints: {}, painted: PAINTED["grasshopper-grasshopper-vehicle"], drawnFrom: "This package's code for the two line looks, proportions taken from Echo_3's low-poly model at the sourced height; that model for the painted look." }, pieces: () => grasshopper(32) });
|
|
150
|
+
entries.push({ record: { id: "falcon-heavy-falcon-heavy-centre", kind: "first-stage", name: "Falcon Heavy centre core, with its upper stage and fairing", rocket: "falcon-heavy", trueTo: ["falcon-heavy"], height: 70, diameter: 5.2, sourced: { height: figure(70, "wikipedia-falcon-heavy"), diameter: { ...blankFigure, note: "3.7 m the core; 5.2 m the fairing." } }, joints: {}, painted: PAINTED["falcon-heavy-falcon-heavy-centre"], drawnFrom: FH_FROM }, pieces: () => centreCore(70, 1.85) }, { record: { id: "falcon-heavy-falcon-heavy-side-left", kind: "first-stage", name: "Falcon Heavy side booster, left", rocket: "falcon-heavy", trueTo: ["falcon-heavy", "test-flight"], height: FH_SIDE_HEIGHT, diameter: 3.7, strapOn: { x: -FH_OFFSET, z: 0 }, sourced: { height: blankFigure, diameter: figure(3.7, "wikipedia-falcon-heavy") }, joints: {}, painted: PAINTED["falcon-heavy-falcon-heavy-side-left"], drawnFrom: FH_FROM }, pieces: () => sideBooster(FH_SIDE_HEIGHT, 1.85, -1) }, { record: { id: "falcon-heavy-falcon-heavy-side-right", kind: "first-stage", name: "Falcon Heavy side booster, right", rocket: "falcon-heavy", trueTo: ["falcon-heavy", "test-flight"], height: FH_SIDE_HEIGHT, diameter: 3.7, strapOn: { x: FH_OFFSET, z: 0 }, sourced: { height: blankFigure, diameter: figure(3.7, "wikipedia-falcon-heavy") }, joints: {}, painted: PAINTED["falcon-heavy-falcon-heavy-side-right"], drawnFrom: FH_FROM }, pieces: () => sideBooster(FH_SIDE_HEIGHT, 1.85, 1) }, { record: { id: "grasshopper-grasshopper-vehicle", kind: "test-vehicle", name: "Grasshopper, test vehicle", rocket: "grasshopper", trueTo: ["grasshopper"], height: 32, diameter: 3.2, sourced: { height: figure(32, "wikipedia-grasshopper"), diameter: blankFigure }, joints: {}, painted: PAINTED["grasshopper-grasshopper-vehicle"], drawnFrom: "This package's code for the two line looks, proportions taken from Echo_3's low-poly model at the sourced height; that model for the painted look." }, pieces: () => grasshopper(32) });
|
|
149
151
|
// ---------------------------------------------------------------------------------------------------------------------------------
|
|
150
152
|
// Rockets drawn wholly by this package's code, from their tables
|
|
151
|
-
const stackFacts = [...DRONE_VARIANTS, ...HUBBLE_VARIANTS, ...ISS_VARIANTS, ...TIANGONG_VARIANTS, ...JUPITER_C_VARIANTS, ...MERCURY_VARIANTS, ...GEMINI_VARIANTS, ...APOLLO_SOYUZ_VARIANTS, ...LUNAR_MODULE_VARIANTS, ...STARBASE_VARIANTS, ...DRAGON_VARIANTS, ...TOWER_VARIANTS, ...DRONESHIP_VARIANTS, ...LANDING_ZONE_VARIANTS, ...SOYUZ_VARIANTS, ...NEW_GLENN_VARIANTS, ...ELECTRON_VARIANTS, ...SLS_VARIANTS, ...FALCON_1_VARIANTS, ...SATURN_V_VARIANTS, ...SHUTTLE_VARIANTS, ...SHIP_02_VARIANTS];
|
|
152
|
-
const stacks = [...DRONE_BUILDS, ...HUBBLE_BUILDS, ...ISS_BUILDS, ...TIANGONG_BUILDS, ...JUPITER_C_BUILDS, ...MERCURY_BUILDS, ...GEMINI_BUILDS, ...APOLLO_SOYUZ_BUILDS, ...LUNAR_MODULE_BUILDS, ...STARBASE_BUILDS, ...DRAGON_INSIDE_BUILDS, ...TOWER_BUILDS, ...DRONESHIP_BUILDS, ...LANDING_ZONE_BUILDS, ...SOYUZ_BUILDS, ...NEW_GLENN_BUILDS, ...ELECTRON_BUILDS, ...SLS_BUILDS, ...FALCON_1_BUILDS, ...SATURN_V_BUILDS, ...SHUTTLE_BUILDS, ...SHIP_02_BUILDS];
|
|
153
|
+
const stackFacts = [...ROADSTER_VARIANTS, ...FALCON_HEAVY_VARIANTS, ...DRONE_VARIANTS, ...HUBBLE_VARIANTS, ...ISS_VARIANTS, ...TIANGONG_VARIANTS, ...JUPITER_C_VARIANTS, ...MERCURY_VARIANTS, ...GEMINI_VARIANTS, ...APOLLO_SOYUZ_VARIANTS, ...LUNAR_MODULE_VARIANTS, ...STARBASE_VARIANTS, ...DRAGON_VARIANTS, ...TOWER_VARIANTS, ...DRONESHIP_VARIANTS, ...LANDING_ZONE_VARIANTS, ...SOYUZ_VARIANTS, ...NEW_GLENN_VARIANTS, ...ELECTRON_VARIANTS, ...SLS_VARIANTS, ...FALCON_1_VARIANTS, ...SATURN_V_VARIANTS, ...SHUTTLE_VARIANTS, ...SHIP_02_VARIANTS];
|
|
154
|
+
const stacks = [...ROADSTER_BUILDS, ...DRONE_BUILDS, ...HUBBLE_BUILDS, ...ISS_BUILDS, ...TIANGONG_BUILDS, ...JUPITER_C_BUILDS, ...MERCURY_BUILDS, ...GEMINI_BUILDS, ...APOLLO_SOYUZ_BUILDS, ...LUNAR_MODULE_BUILDS, ...STARBASE_BUILDS, ...DRAGON_INSIDE_BUILDS, ...TOWER_BUILDS, ...DRONESHIP_BUILDS, ...LANDING_ZONE_BUILDS, ...SOYUZ_BUILDS, ...NEW_GLENN_BUILDS, ...ELECTRON_BUILDS, ...SLS_BUILDS, ...FALCON_1_BUILDS, ...SATURN_V_BUILDS, ...SHUTTLE_BUILDS, ...SHIP_02_BUILDS];
|
|
153
155
|
for (const build of stacks)
|
|
154
156
|
for (const part of build.parts) {
|
|
155
157
|
const { height, diameter } = facts(stackFacts, build.variant, part.slot);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Piece, Vec3 } from "./pieces.ts";
|
|
2
|
+
import type { StackBuild } from "./stacks.ts";
|
|
3
|
+
/** One car as measured from its model, in metres: nose towards +Z, on the ground at y = 0. */
|
|
4
|
+
export interface CarDraw {
|
|
5
|
+
/** Nose to tail, and across. */
|
|
6
|
+
length: number;
|
|
7
|
+
width: number;
|
|
8
|
+
/** The top of the windscreen. */
|
|
9
|
+
height: number;
|
|
10
|
+
/** The wheels: their middles along the car, their radius and how far each stands from the middle. */
|
|
11
|
+
front: number;
|
|
12
|
+
rear: number;
|
|
13
|
+
wheel: number;
|
|
14
|
+
track: number;
|
|
15
|
+
/** The top of the doors. */
|
|
16
|
+
belt: number;
|
|
17
|
+
/** Where the windscreen meets the body, along the car. */
|
|
18
|
+
screen: number;
|
|
19
|
+
/** The driver's hip, in the left seat: across, up and along. */
|
|
20
|
+
seat: Vec3;
|
|
21
|
+
/** The middle of the steering wheel. */
|
|
22
|
+
wheelAt: Vec3;
|
|
23
|
+
}
|
|
24
|
+
export declare const ROADSTER_DRAWS: Readonly<Record<string, CarDraw>>;
|
|
25
|
+
/** The car: its body seen from the side and pressed to its width, its cockpit open, the windscreen and the four wheels. */
|
|
26
|
+
export declare function carPieces(d: CarDraw): Piece[];
|
|
27
|
+
/** Starman in the driver's seat: legs forward to the pedals, his back against the seat, his right hand on the wheel, his left arm along the top of the door. */
|
|
28
|
+
export declare function starmanPieces(d: CarDraw): Piece[];
|
|
29
|
+
/** Where the payload stands in Falcon Heavy: 0.8 m above where its fairing begins (the fairing's sourced 13.1 m under the 70 m top), clear of the fairing's walls. The 0.8 m is a placing, not a figure. */
|
|
30
|
+
export declare const FALCON_HEAVY_PAYLOAD_Y: number;
|
|
31
|
+
export declare const ROADSTER_BUILDS: readonly StackBuild[];
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// The Roadster in plain shapes for the line looks, and Starman in every look. The car's length, wheelbase, wheels and seat are measured from each licensed model at its sourced scale; the painted look is the
|
|
2
|
+
// model. Starman is this package's own: a seated figure in a white suit with dark trim, a white helmet with a dark visor, his right hand on the wheel and his left arm on the door. He shares the car's origin
|
|
3
|
+
// (the middle of the car on the ground), so he sits in its seat in any build that places the two together.
|
|
4
|
+
import { ROADSTER_FLIGHT } from "../data/roadster.js";
|
|
5
|
+
import { blank } from "../data/types.js";
|
|
6
|
+
import { centreCore } from "./falcon.js";
|
|
7
|
+
import { strut } from "./pieces.js";
|
|
8
|
+
export const ROADSTER_DRAWS = {
|
|
9
|
+
"first-generation": { length: 3.946, width: 1.85, height: 1.03, front: 1.114, rear: -1.258, wheel: 0.3, track: 1.46, belt: 0.8, screen: 0.95, seat: [0.29, 0.34, -0.22], wheelAt: [0.29, 0.62, 0.37] },
|
|
10
|
+
"second-generation": { length: 4.47, width: 1.83, height: 1.14, front: 1.417, rear: -1.408, wheel: 0.31, track: 1.52, belt: 0.84, screen: 0.75, seat: [0.32, 0.22, -0.18], wheelAt: [0.32, 0.58, 0.3] },
|
|
11
|
+
"second-generation-2": { length: 4.28, width: 1.86, height: 1.07, front: 1.398, rear: -1.429, wheel: 0.31, track: 1.58, belt: 0.8, screen: 0.7, seat: [0.32, 0.17, -0.2], wheelAt: [0.32, 0.55, 0.28] },
|
|
12
|
+
};
|
|
13
|
+
const side = (d) => {
|
|
14
|
+
const nose = d.length / 2;
|
|
15
|
+
return [
|
|
16
|
+
[-nose, 0.22],
|
|
17
|
+
[-d.length * 0.16, 0.14],
|
|
18
|
+
[nose * 0.8, 0.14],
|
|
19
|
+
[nose, 0.32],
|
|
20
|
+
[nose * 0.92, 0.6],
|
|
21
|
+
[d.screen, d.belt - 0.02],
|
|
22
|
+
[-nose * 0.9, d.belt + 0.04],
|
|
23
|
+
[-nose, 0.62],
|
|
24
|
+
];
|
|
25
|
+
};
|
|
26
|
+
const octagon = (r) => Array.from({ length: 12 }, (_, i) => [Math.cos((i * Math.PI) / 6) * r, Math.sin((i * Math.PI) / 6) * r]);
|
|
27
|
+
/** The car: its body seen from the side and pressed to its width, its cockpit open, the windscreen and the four wheels. */
|
|
28
|
+
export function carPieces(d) {
|
|
29
|
+
const half = d.width / 2;
|
|
30
|
+
const pieces = [{ kind: "plate", material: "red", frame: { o: [0, 0, 0], u: [0, 0, 1], v: [0, 1, 0], w: [1, 0, 0] }, outline: side(d), thickness: d.width - 0.06 }];
|
|
31
|
+
// the open cockpit, dark, sunk into the top of the body
|
|
32
|
+
pieces.push({ kind: "plate", material: "dark", frame: { o: [0, d.belt + 0.005, 0], u: [1, 0, 0], v: [0, 0, 1], w: [0, 1, 0] }, outline: [[-half + 0.2, -0.75], [half - 0.2, -0.75], [half - 0.2, d.screen - 0.05], [-half + 0.2, d.screen - 0.05]], thickness: 0.01, plain: true });
|
|
33
|
+
// the windscreen, leaning back from the scuttle
|
|
34
|
+
const lean = 0.55;
|
|
35
|
+
const rise = d.height - d.belt;
|
|
36
|
+
const up = [0, Math.cos(lean), -Math.sin(lean)];
|
|
37
|
+
pieces.push({ kind: "plate", material: "glass", frame: { o: [0, d.belt, d.screen], u: [1, 0, 0], v: up, w: [0, Math.sin(lean), Math.cos(lean)] }, outline: [[-half + 0.18, 0], [half - 0.18, 0], [half - 0.26, rise / Math.cos(lean)], [-half + 0.26, rise / Math.cos(lean)]], thickness: 0.012 });
|
|
38
|
+
for (const z of [d.front, d.rear])
|
|
39
|
+
for (const s of [1, -1]) {
|
|
40
|
+
const x = (s * d.track) / 2;
|
|
41
|
+
pieces.push({ kind: "plate", material: "black", frame: { o: [x, d.wheel, z], u: [0, 0, 1], v: [0, 1, 0], w: [1, 0, 0] }, outline: octagon(d.wheel), thickness: 0.24 });
|
|
42
|
+
pieces.push({ kind: "plate", material: "fin-dark", frame: { o: [x + s * 0.121, d.wheel, z], u: [0, 0, 1], v: [0, 1, 0], w: [1, 0, 0] }, outline: octagon(d.wheel * 0.62), thickness: 0.01, plain: true });
|
|
43
|
+
}
|
|
44
|
+
return pieces;
|
|
45
|
+
}
|
|
46
|
+
const at = (p, dx, dy, dz) => [p[0] + dx, p[1] + dy, p[2] + dz];
|
|
47
|
+
/** Starman in the driver's seat: legs forward to the pedals, his back against the seat, his right hand on the wheel, his left arm along the top of the door. */
|
|
48
|
+
export function starmanPieces(d) {
|
|
49
|
+
const hip = d.seat;
|
|
50
|
+
const shoulder = at(hip, 0, 0.52, -0.1);
|
|
51
|
+
const knee = at(hip, 0, 0.12, 0.44);
|
|
52
|
+
// the feet on the floor, which is never under the ground
|
|
53
|
+
const foot = [hip[0], Math.max(0.12, hip[1] - 0.18), hip[2] + 0.86];
|
|
54
|
+
const right = at(shoulder, -0.19, 0, 0);
|
|
55
|
+
const left = at(shoulder, 0.19, 0, 0);
|
|
56
|
+
const door = [Math.min(d.width / 2 - 0.08, hip[0] + 0.42), d.belt + 0.05, hip[2] + 0.12];
|
|
57
|
+
const pieces = [
|
|
58
|
+
// the torso, leaning back with the seat
|
|
59
|
+
{ kind: "lathe", material: "white", segs: 16, at: [hip[0], hip[2]], lean: [0, -0.19], profile: [[0.14, hip[1]], [0.18, hip[1] + 0.22], [0.19, shoulder[1] - 0.06], [0.1, shoulder[1] + 0.04]] },
|
|
60
|
+
// the helmet, white, round, with its dark visor facing the road
|
|
61
|
+
{ kind: "lathe", material: "white", segs: 20, at: [shoulder[0], shoulder[2] - 0.02], profile: [[0.07, shoulder[1] + 0.04], [0.15, shoulder[1] + 0.13], [0.155, shoulder[1] + 0.22], [0.12, shoulder[1] + 0.31], [0.001, shoulder[1] + 0.35]] },
|
|
62
|
+
{ kind: "plate", material: "glass", frame: { o: [shoulder[0], shoulder[1] + 0.2, shoulder[2] + 0.12], u: [1, 0, 0], v: [0, 1, 0], w: [0, 0, 1] }, outline: [[-0.1, -0.06], [0.1, -0.06], [0.11, 0.05], [-0.11, 0.05]], thickness: 0.04, plain: true },
|
|
63
|
+
// a dark ring where the helmet meets the suit
|
|
64
|
+
{ kind: "lathe", material: "black", segs: 16, at: [shoulder[0], shoulder[2] - 0.02], profile: [[0.12, shoulder[1] + 0.01], [0.12, shoulder[1] + 0.06]], only: "mesh" },
|
|
65
|
+
];
|
|
66
|
+
for (const s of [-1, 1]) {
|
|
67
|
+
const h = at(hip, s * 0.1, 0, 0);
|
|
68
|
+
const k = at(knee, s * 0.1, 0, 0);
|
|
69
|
+
const f = at(foot, s * 0.1, 0, 0);
|
|
70
|
+
pieces.push(strut("white", h, k, 0.15, 0.15), strut("white", k, f, 0.13, 0.13), strut("black", f, at(f, 0, 0.02, 0.1), 0.12, 0.14));
|
|
71
|
+
}
|
|
72
|
+
// his right hand on the wheel's rim, his left arm on the door top
|
|
73
|
+
const hand = at(d.wheelAt, -0.12, 0.04, -0.03);
|
|
74
|
+
const elbowR = at(right, -0.02, -0.22, 0.2);
|
|
75
|
+
const elbowL = at(left, 0.12, -0.2, 0.05);
|
|
76
|
+
pieces.push(strut("white", right, elbowR, 0.11, 0.11), strut("white", elbowR, hand, 0.1, 0.1), strut("black", hand, at(hand, 0, 0, 0.06), 0.09, 0.09));
|
|
77
|
+
pieces.push(strut("white", left, elbowL, 0.11, 0.11), strut("white", elbowL, door, 0.1, 0.1), strut("black", door, at(door, 0, 0, 0.07), 0.09, 0.09));
|
|
78
|
+
return pieces;
|
|
79
|
+
}
|
|
80
|
+
const FILES = {
|
|
81
|
+
"first-generation": { file: "roadster-first-generation-car.glb", credit: "the86guy-roadster" },
|
|
82
|
+
"second-generation": { file: "roadster-second-generation-car.glb", credit: "metarex4d-roadster" },
|
|
83
|
+
"second-generation-2": { file: "roadster-second-generation-2-car.glb", credit: "gmmichaelonearth-roadster", also: ["minchou19-wheels"] },
|
|
84
|
+
};
|
|
85
|
+
const STARMAN_NAME = "Starman, a mannequin in a pressure suit";
|
|
86
|
+
const carPart = (variant, place) => {
|
|
87
|
+
const d = ROADSTER_DRAWS[variant];
|
|
88
|
+
return { slot: "car", kind: "payload", name: variant === "first-generation" ? "The Roadster, first generation" : "The Roadster, second generation", height: d.height, diameter: d.width, sourcedDiameter: blank(`Its width as drawn: the model at its sourced scale is ${d.width} m across.`), painted: FILES[variant], ...(place ? { place } : {}), pieces: () => carPieces(d) };
|
|
89
|
+
};
|
|
90
|
+
const starmanPart = (variant, place) => {
|
|
91
|
+
const d = ROADSTER_DRAWS[variant];
|
|
92
|
+
return { slot: "starman", kind: "payload", name: STARMAN_NAME, height: d.seat[1] + 0.87, diameter: 0.6, sourcedDiameter: blank("No source read here gives Starman's size."), place, pieces: () => starmanPieces(d) };
|
|
93
|
+
};
|
|
94
|
+
const FROM = (variant) => variant === "first-generation"
|
|
95
|
+
? "The 86 guy's model for the painted look, with its badges and roof left off and its bonnet made bare carbon; this package's plain shapes for the line looks, measured from it at the sourced length. Starman is this package's own in every look."
|
|
96
|
+
: "Its author's model for the painted look, with its badges left off, painted the first generation's red; this package's plain shapes for the line looks, measured from it at the sourced wheelbase. Starman is this package's own in every look.";
|
|
97
|
+
/** Where the payload stands in Falcon Heavy: 0.8 m above where its fairing begins (the fairing's sourced 13.1 m under the 70 m top), clear of the fairing's walls. The 0.8 m is a placing, not a figure. */
|
|
98
|
+
export const FALCON_HEAVY_PAYLOAD_Y = 70 - 13.1 + 0.8;
|
|
99
|
+
export const ROADSTER_BUILDS = [
|
|
100
|
+
...Object.keys(ROADSTER_DRAWS).map((variant) => ({ rocket: "roadster", variant, drawnFrom: FROM(variant), parts: [carPart(variant), starmanPart(variant, { x: 0, z: 0 })] })),
|
|
101
|
+
{
|
|
102
|
+
rocket: "falcon-heavy",
|
|
103
|
+
variant: ROADSTER_FLIGHT.id,
|
|
104
|
+
drawnFrom: "Antonio_Adams's low-poly Falcon Heavy and the 86 guy's Roadster for the painted look, this package's plain shapes for the line looks. Starman is this package's own in every look.",
|
|
105
|
+
parts: [
|
|
106
|
+
// the same vehicle as Falcon Heavy's own, on its first flight: its centre core is its own part here, so the test flight is reached from its own foot
|
|
107
|
+
{ slot: "centre", kind: "first-stage", name: "Falcon Heavy centre core, with its upper stage and fairing", height: 70, diameter: 5.2, sourcedDiameter: blank("3.7 m the core; 5.2 m the fairing."), painted: { file: "falcon-heavy-falcon-heavy-centre.glb", credit: "antonio-falcon-heavy" }, pieces: () => centreCore(70, 1.85) },
|
|
108
|
+
carPart("first-generation", { x: 0, z: 0, y: FALCON_HEAVY_PAYLOAD_Y }),
|
|
109
|
+
starmanPart("first-generation", { x: 0, z: 0, y: FALCON_HEAVY_PAYLOAD_Y }),
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
];
|
package/dist/parts.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type { Figure } from "./data/types.ts";
|
|
|
11
11
|
* console.log(kind);
|
|
12
12
|
* ```
|
|
13
13
|
*/
|
|
14
|
-
export type PartKind = "booster" | "first-stage" | "ship" | "second-stage" | "fairing" | "capsule" | "trunk" | "engine" | "fin" | "flap" | "ring" | "test-vehicle" | "third-stage" | "fourth-stage" | "tail" | "adapter" | "service-module" | "tower" | "tank" | "solid-booster" | "liquid-booster" | "orbiter" | "deck" | "mount" | "arms" | "site" | "spacecraft" | "module" | "array" | "antenna";
|
|
14
|
+
export type PartKind = "booster" | "first-stage" | "ship" | "second-stage" | "fairing" | "capsule" | "trunk" | "engine" | "fin" | "flap" | "ring" | "test-vehicle" | "third-stage" | "fourth-stage" | "tail" | "adapter" | "service-module" | "tower" | "tank" | "solid-booster" | "liquid-booster" | "orbiter" | "deck" | "mount" | "arms" | "site" | "spacecraft" | "module" | "array" | "antenna" | "payload";
|
|
15
15
|
/**
|
|
16
16
|
* Where a part mates. Every part's origin is the middle of its base on its axis, at its lowest point; Y is up and the windward side faces +Z, in metres.
|
|
17
17
|
*
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { type Vec3 } from "./vector.ts";
|
|
2
|
+
/**
|
|
3
|
+
* One layer of a layered atmosphere: from its base up, the temperature changes at a fixed rate with geopotential height (or stays the same), and the pressure and density follow.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { EARTH_ATMOSPHERE, type AtmosphereLayer } from "@johnmorrisdotca/uchusen-rockets/physics";
|
|
8
|
+
*
|
|
9
|
+
* const ground: AtmosphereLayer = EARTH_ATMOSPHERE.layers[0]!;
|
|
10
|
+
* console.log(ground.temperature, ground.lapse);
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export interface AtmosphereLayer {
|
|
14
|
+
/** The layer's base, geopotential metres. */
|
|
15
|
+
base: number;
|
|
16
|
+
/** Temperature at the base, kelvin. */
|
|
17
|
+
temperature: number;
|
|
18
|
+
/** How the temperature changes going up, kelvin a geopotential metre (0 for a layer of one temperature). */
|
|
19
|
+
lapse: number;
|
|
20
|
+
/** Pressure at the base, pascals. */
|
|
21
|
+
pressure: number;
|
|
22
|
+
/** Density at the base, kg/m^3. */
|
|
23
|
+
density: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* A layered model of a planet's air, as Orbiter's 2006 models are.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* import { MARS_ATMOSPHERE, type AtmosphereModel } from "@johnmorrisdotca/uchusen-rockets/physics";
|
|
31
|
+
*
|
|
32
|
+
* const mars: AtmosphereModel = MARS_ATMOSPHERE;
|
|
33
|
+
* console.log(mars.name, mars.limit);
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export interface AtmosphereModel {
|
|
37
|
+
name: string;
|
|
38
|
+
/** The radius the geopotential height is worked from, metres. */
|
|
39
|
+
radius: number;
|
|
40
|
+
/** Standard gravity over the gas constant, g0 / R, kelvin a metre. */
|
|
41
|
+
g0R: number;
|
|
42
|
+
/** The specific gas constant, J/(kg K). */
|
|
43
|
+
gasConstant: number;
|
|
44
|
+
/** The ratio of specific heats. */
|
|
45
|
+
gamma: number;
|
|
46
|
+
/** Above this height (geometric metres) the model has no air. */
|
|
47
|
+
limit: number;
|
|
48
|
+
/** The layers, lowest first. */
|
|
49
|
+
layers: readonly AtmosphereLayer[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The air at a height: temperature (K), pressure (Pa), density (kg/m^3) and the speed of sound (m/s). All zero where there is no air.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* import { atmosphereAt, EARTH_ATMOSPHERE, type Air } from "@johnmorrisdotca/uchusen-rockets/physics";
|
|
57
|
+
*
|
|
58
|
+
* const air: Air = atmosphereAt(EARTH_ATMOSPHERE, 10_000);
|
|
59
|
+
* console.log(air.density.toFixed(3));
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export interface Air {
|
|
63
|
+
temperature: number;
|
|
64
|
+
pressure: number;
|
|
65
|
+
density: number;
|
|
66
|
+
speedOfSound: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The Earth's air as Orbiter 2006 models it (Orbiter's EarthAtm2006: "a simple static atmosphere model", its own description, ending at 200 km).
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* import { atmosphereAt, EARTH_ATMOSPHERE } from "@johnmorrisdotca/uchusen-rockets/physics";
|
|
74
|
+
*
|
|
75
|
+
* console.log(atmosphereAt(EARTH_ATMOSPHERE, 0).pressure);
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export declare const EARTH_ATMOSPHERE: AtmosphereModel;
|
|
79
|
+
/**
|
|
80
|
+
* Mars's air as Orbiter 2006 models it (Orbiter's MarsAtm2006), ending at 100 km.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* import { atmosphereAt, MARS_ATMOSPHERE } from "@johnmorrisdotca/uchusen-rockets/physics";
|
|
85
|
+
*
|
|
86
|
+
* console.log(atmosphereAt(MARS_ATMOSPHERE, 0).pressure);
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare const MARS_ATMOSPHERE: AtmosphereModel;
|
|
90
|
+
/**
|
|
91
|
+
* Venus's air as Orbiter 2006 models it (Orbiter's VenusAtm2006), ending at 200 km.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* import { atmosphereAt, VENUS_ATMOSPHERE } from "@johnmorrisdotca/uchusen-rockets/physics";
|
|
96
|
+
*
|
|
97
|
+
* console.log(atmosphereAt(VENUS_ATMOSPHERE, 0).temperature);
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export declare const VENUS_ATMOSPHERE: AtmosphereModel;
|
|
101
|
+
/**
|
|
102
|
+
* The air of a layered model at a height above the surface (Orbiter's `clbkParams`): the geometric height is turned into geopotential height, the layer below it is found, and the temperature, pressure and density follow from that layer.
|
|
103
|
+
* @param model The model.
|
|
104
|
+
* @param altitude The geometric height above the reference radius, metres (below 0 the lowest layer goes on down).
|
|
105
|
+
* @returns The air there; all zero above the model's limit, as Orbiter has no air there.
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* import { atmosphereAt, EARTH_ATMOSPHERE } from "@johnmorrisdotca/uchusen-rockets/physics";
|
|
109
|
+
*
|
|
110
|
+
* const air = atmosphereAt(EARTH_ATMOSPHERE, 30_000);
|
|
111
|
+
* console.log(air.temperature.toFixed(1), "K,", air.pressure.toFixed(0), "Pa,", air.density.toFixed(4), "kg/m^3");
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export declare function atmosphereAt(model: AtmosphereModel, altitude: number): Air;
|
|
115
|
+
/**
|
|
116
|
+
* The 1976 U.S. Standard Atmosphere from 5 km below sea level to 86 km, worked from its defining constants and equations (its tables 2, 3 and 4): seven layers of fixed temperature gradient in geopotential height, the sea-level air's mean molecular weight from its table 3, the hydrostatic equation and the gas law.
|
|
117
|
+
* @param altitude The geometric height above sea level, metres, from -5,000 to 86,000.
|
|
118
|
+
* @returns The air there (the temperature is the molecular-scale temperature, the same as the kinetic temperature below 80 km), or null outside those heights.
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* import { standardAtmosphere } from "@johnmorrisdotca/uchusen-rockets/physics";
|
|
122
|
+
*
|
|
123
|
+
* const air = standardAtmosphere(11_000);
|
|
124
|
+
* console.log(air?.temperature.toFixed(3), "K,", air?.pressure.toFixed(0), "Pa");
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export declare function standardAtmosphere(altitude: number): Air | null;
|
|
128
|
+
/**
|
|
129
|
+
* A craft's speed through the air, for air that turns with its planet and no wind (Orbiter's airspeed): its speed relative to the planet less the speed of the air where it is, `v - w x r`.
|
|
130
|
+
* @param position The craft's position from the planet's centre, metres.
|
|
131
|
+
* @param velocity Its speed relative to the planet's centre, metres a second.
|
|
132
|
+
* @param spin The planet's turn rate as a vector along its pole, radians a second (`[0, 0, 7.292115e-5]` for the Earth in an equatorial frame).
|
|
133
|
+
* @returns The velocity through the air, metres a second.
|
|
134
|
+
* @example
|
|
135
|
+
* ```ts
|
|
136
|
+
* import { airVelocity } from "@johnmorrisdotca/uchusen-rockets/physics";
|
|
137
|
+
*
|
|
138
|
+
* console.log(airVelocity([6_778_000, 0, 0], [0, 7_669, 0], [0, 0, 7.292115e-5]));
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
export declare const airVelocity: (position: Vec3, velocity: Vec3, spin: Vec3) => Vec3;
|
|
142
|
+
/**
|
|
143
|
+
* The dynamic pressure of the air on a craft, `rho v^2 / 2` (Orbiter's `dynp`).
|
|
144
|
+
* @param density The air's density, kg/m^3.
|
|
145
|
+
* @param airspeed The speed through the air, metres a second.
|
|
146
|
+
* @returns The dynamic pressure, pascals.
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* import { dynamicPressure } from "@johnmorrisdotca/uchusen-rockets/physics";
|
|
150
|
+
*
|
|
151
|
+
* console.log(dynamicPressure(0.4, 400));
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
export declare const dynamicPressure: (density: number, airspeed: number) => number;
|
|
155
|
+
/**
|
|
156
|
+
* The Mach number: the speed through the air over the speed of sound there (Orbiter's `atmM`).
|
|
157
|
+
* @param airspeed The speed through the air, metres a second.
|
|
158
|
+
* @param air The air, from {@link atmosphereAt} or {@link standardAtmosphere}.
|
|
159
|
+
* @returns The Mach number; 0 where there is no air.
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* import { atmosphereAt, EARTH_ATMOSPHERE, machNumber } from "@johnmorrisdotca/uchusen-rockets/physics";
|
|
163
|
+
*
|
|
164
|
+
* console.log(machNumber(600, atmosphereAt(EARTH_ATMOSPHERE, 11_000)).toFixed(2));
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
export declare const machNumber: (airspeed: number, air: Air) => number;
|
|
168
|
+
/**
|
|
169
|
+
* The drag on a craft as an acceleration: `-(rho |v| v / 2) Cd A / m`, against its velocity through the air (Orbiter's drag element: its drag coefficient times the dynamic pressure, along the airflow).
|
|
170
|
+
* @param density The air's density, kg/m^3.
|
|
171
|
+
* @param air The velocity through the air, from {@link airVelocity}, metres a second.
|
|
172
|
+
* @param dragArea The drag coefficient times the reference area, `Cd A`, m^2.
|
|
173
|
+
* @param mass The craft's mass, kilograms.
|
|
174
|
+
* @returns The acceleration, metres a second squared.
|
|
175
|
+
* @example
|
|
176
|
+
* ```ts
|
|
177
|
+
* import { atmosphereAt, dragAcceleration, EARTH_ATMOSPHERE } from "@johnmorrisdotca/uchusen-rockets/physics";
|
|
178
|
+
*
|
|
179
|
+
* console.log(dragAcceleration(atmosphereAt(EARTH_ATMOSPHERE, 60_000).density, [0, 7_000, 0], 1.3 * 12, 9_000));
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
export declare function dragAcceleration(density: number, air: Vec3, dragArea: number, mass: number): Vec3;
|