From d99a7026bd623f0817bde2e1aafc43ecd6fbc485 Mon Sep 17 00:00:00 2001 From: alowpoly Date: Mon, 5 Oct 2026 16:33:52 -0300 Subject: [PATCH 1/2] perf(objects): Haumea draws 452 faces instead of 1,444; a dataset switch took 177 to 225 ms on an iPad, now 47 to 106 --- packages/bake/src/presentation/leaf-box.ts | 3 +- src/objects/haumea/README.md | 2 ++ src/objects/haumea/inventory.json | 28 +++++++++---------- .../source/preparation/shape-model.json | 4 +-- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/packages/bake/src/presentation/leaf-box.ts b/packages/bake/src/presentation/leaf-box.ts index 0f8ec4de6ae..1f679bc2999 100644 --- a/packages/bake/src/presentation/leaf-box.ts +++ b/packages/bake/src/presentation/leaf-box.ts @@ -28,7 +28,8 @@ export { LEAF_BOX_FACTOR } from '@cssearth/objects'; export const LEAF_BOX_SCREEN_PIXELS = 2; /** Leaves per group: the smallest repaint the runtime can schedule in one frame (prepared-leaf-box-blocks.ts paces the * groups by the frames they cost). In the iOS simulator a Moon leaf repaints in about 0.7 ms and a Haumea leaf in about - * 2.5 ms, so a group of 8 stays near one frame on either. The Moon's 448 leaves make 56 blocks, Haumea's 1,444 make 180. */ + * 2.5 ms, so a group of 8 stays near one frame on either. The Moon's 448 leaves make 56 blocks; Haumea's 1,444 made 180 + * until its mesh went from 32 by 48 to 16 by 32 on 2026-10-05. */ export const LEAF_BOX_GROUP_LEAVES = 8; /** Leaf boxes never shrink below this many silhouette pixels' worth: a body smaller than this on screen keeps its first step. */ const FIRST_STEP = 16; diff --git a/src/objects/haumea/README.md b/src/objects/haumea/README.md index 35db912d7d2..81901ac9c7b 100644 --- a/src/objects/haumea/README.md +++ b/src/objects/haumea/README.md @@ -40,6 +40,8 @@ The shared `disc-integrated-color` method ([disc-integrated-color.ts](../../../p For the Illustration, each texel is found through the model's own texture coordinates on its ellipsoid and placed on the measured triaxial shape at the same normalized direction; the texture is not repainted. Its longitudes are arbitrary. Color stays the default dataset, and the illustration never counts as imagery: Haumea stays "Shape only". +The ellipsoid is drawn as 16 latitude bands of 32 faces and four polar caps (452 faces), as the other globes are. Its flat faces sit at most 2.19 px from the true ellipsoid at rest, against 2.20 px for a sphere on the same mesh. Until 5 October 2026 it had 32 bands of 48 (1,444 faces, 0.77 px): a dataset switch repaints every face and took 177 to 225 ms on an iPad, against 47 to 106 ms now. + ## Evidence Each published color uncertainty moves an sRGB channel by at most 2 of 255, and the albedo uncertainty moves every channel by 3. The [MBOSS](https://doi.org/10.26093/cds/vizier.35460115) three-epoch mean (B−V 0.631, V−R 0.370, V−I 0.687) gives 190, 189, 191. The Herschel and Spitzer albedo of 0.804 that Ortiz et al. (2017) replace would give 230, 232, 234. diff --git a/src/objects/haumea/inventory.json b/src/objects/haumea/inventory.json index 0f034f31b5b..a632a2f55d0 100644 --- a/src/objects/haumea/inventory.json +++ b/src/objects/haumea/inventory.json @@ -16,14 +16,14 @@ { "location": "public", "filename": "haumea-arrival.webp", - "bytes": 48986, - "sha256": "c99bfac0ee57cb418d7e58da4d5c476a218442905380d7b88ab6ecf7e190bef1" + "bytes": 46896, + "sha256": "933382630bab9142a36d0f8aea419058f2e4c3b22c793748a218349fc0a5d51c" }, { "location": "public", "filename": "haumea-billboard.webp", - "bytes": 5128, - "sha256": "f35b82ed761b5d6bf392d015da3ef13779cb51ac7803c6a74f6a1c8bfc038811" + "bytes": 5022, + "sha256": "99e55f73d95900a30b51e7a873b4fa96b2e7c168b8dd16eebfcd2e675e2b1e30" }, { "location": "public", @@ -46,8 +46,8 @@ { "location": "public", "filename": "poles-illustration.webp", - "bytes": 75844, - "sha256": "ceb4de7e2d997b2b0cda4ef9fc932e5bd8edd1cc0052dd85c3fc716c3ec9d8b1" + "bytes": 97670, + "sha256": "e2970904f89b619403cb947532ddb89437d12edc763d7de3c518c895904dc091" }, { "location": "public", @@ -58,14 +58,14 @@ { "location": "public", "filename": "surface-color.webp", - "bytes": 342, - "sha256": "ad3e5db9db6f594a967970ac8cde7bab9724f4d208310efe95f7ef7233fed0a5" + "bytes": 346, + "sha256": "0640ba905d3930a9be8ee6566d52351f14341c844b6ceb8adf2f6af4bfee91d6" }, { "location": "public", "filename": "surface-illustration.webp", - "bytes": 3525294, - "sha256": "c69a552407aa144d2c47741928cfac6bfdc798a25503c29941d2639b96f60742" + "bytes": 3552420, + "sha256": "d40d63f7f29680241858897fc7ca1065c2dd7f42d8f6ac40049217263506cb55" }, { "location": "prepared", @@ -118,14 +118,14 @@ { "location": "prepared", "filename": "runtime.json", - "bytes": 634110, - "sha256": "ef25172f86a3c5beb548dddc0f230408422d6ba311997fb890679e9696b298e2" + "bytes": 214899, + "sha256": "bf4fb310261159c590308bd370bd515da5b324d37545d7493804d8fa0f7a741b" }, { "location": "prepared", "filename": "scene.json", - "bytes": 955890, - "sha256": "0caac01892d1b06310db43a98074b12197adffe45c7aa3f7821e1455d2fd3908" + "bytes": 328087, + "sha256": "8fa1f4d37ab753d4d69b08309eb5a81c064a097bbe290c3829737955f58b5621" }, { "location": "prepared", diff --git a/src/objects/haumea/source/preparation/shape-model.json b/src/objects/haumea/source/preparation/shape-model.json index e175beae6e5..93e929cd0ae 100644 --- a/src/objects/haumea/source/preparation/shape-model.json +++ b/src/objects/haumea/source/preparation/shape-model.json @@ -4,8 +4,8 @@ "displayRadius": 230, "quadBudget": 2000, "mesh": { - "latitudeSegments": 32, - "longitudeSegments": 48, + "latitudeSegments": 16, + "longitudeSegments": 32, "width": 3072, "height": 1536, "poleSize": 256, From 805db69de52c5a7404497884f9af34acc8a70f24 Mon Sep 17 00:00:00 2001 From: alowpoly Date: Mon, 5 Oct 2026 16:48:47 -0300 Subject: [PATCH 2/2] perf(objects): Deimos, Phobos and Dimorphos hide their back faces and get depth groups; a Deimos drag had 23 frames over 33 ms, now none --- src/objects/deimos/README.md | 2 +- src/objects/deimos/inventory.json | 4 ++-- src/objects/dimorphos/README.md | 1 + src/objects/dimorphos/inventory.json | 4 ++-- src/objects/phobos/README.md | 1 + src/objects/phobos/inventory.json | 4 ++-- src/renderers/css/styles/deimos-surfaces.css | 2 +- src/renderers/css/styles/dimorphos-surfaces.css | 2 +- src/renderers/css/styles/phobos-surfaces.css | 2 +- 9 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/objects/deimos/README.md b/src/objects/deimos/README.md index fdf9226cc85..c1e0710a5d1 100644 --- a/src/objects/deimos/README.md +++ b/src/objects/deimos/README.md @@ -34,4 +34,4 @@ Four barycentric samples per retained face gave a maximum distance of 69.40 m; t - Only part of Deimos has detailed SPC support; the rest of the mesh is less constrained. The newer shape and older mosaic have separate control histories. - This is radial height, not elevation above a geoid. Facets whose released Albedo attribute is NaN are withheld from the scientific datasets. This support rule does not claim a complete image-coverage mask. - Feature outlines are not published nomenclature boundaries. -- Every display atlas is 2,509 × 2,611 pixels, 64 × 64 texels a face, which reduces display detail, not the source map. Until 5 October 2026 the layout was twice those dimensions, and picking a dataset froze an iPad's page for 5 to 13 seconds; it now takes 223 to 353 ms. The camera's turn toward a dataset's data still runs at 45 to 70 ms a frame over the 1,600 faces. +- Every display atlas is 2,509 × 2,611 pixels, 64 × 64 texels a face, which reduces display detail, not the source map. Until 5 October 2026 the layout was twice those dimensions, and picking a dataset froze an iPad's page for 5 to 13 seconds; it now takes 223 to 353 ms. Until the same day its faces were drawn from both sides, so the far half was drawn and sorted on every frame and the bake could build no depth groups: a drag had 23 of 390 frames over 33 ms, the longest 140 ms, against none over 25 ms now. diff --git a/src/objects/deimos/inventory.json b/src/objects/deimos/inventory.json index 4b4424343bb..898dbc35302 100644 --- a/src/objects/deimos/inventory.json +++ b/src/objects/deimos/inventory.json @@ -238,8 +238,8 @@ { "location": "prepared", "filename": "runtime.json", - "bytes": 989999, - "sha256": "096aff4535d6b5d3a9ef50a07c8c916d1db1cf1fabecb853fcf3d406c118ff2c" + "bytes": 1032135, + "sha256": "2233e7ab47d07e888217b5a40eb7b057d12f3b876d9016fcee8fa200ce4da44d" }, { "location": "prepared", diff --git a/src/objects/dimorphos/README.md b/src/objects/dimorphos/README.md index 71af1fd031d..56abf8d0dc4 100644 --- a/src/objects/dimorphos/README.md +++ b/src/objects/dimorphos/README.md @@ -79,4 +79,5 @@ Limb columns: the position-angle residual between the projected limb and the pho - Model precision varies with DRACO/LICIACube coverage and SPC constraints. A closed model does not mean every facet was photographed with the same precision. - **Relative albedo:** this is the SPC model's relative brightness field, not a photograph, absolute albedo, or a measurement of the post-impact surface. The accepted triangles cover 31.2138% of the mesh area; unqualified facets use the common neutral gray. - **Named features:** outlines are not published nomenclature boundaries. +- Until 5 October 2026 the faces were drawn from both sides; they now hide the far side, as on every other shape-model body, and the bake builds 7 depth groups. A drag on an iPad then had no frame over 33 ms of 390, the longest 30 ms; it was not timed before. - **Orientation and orbit:** the mesh uses the observed pre-impact pole (ICRF RA 69.70029°, declination −72.69527°) and an explicitly arbitrary display phase. The pre-impact 11.92177 h period is not a post-impact attitude prediction. The orbit is a compact display fit to the post-impact DART s547 trajectory, not a long-term binary dynamics solution. diff --git a/src/objects/dimorphos/inventory.json b/src/objects/dimorphos/inventory.json index 0b56d961f10..27963f1b300 100644 --- a/src/objects/dimorphos/inventory.json +++ b/src/objects/dimorphos/inventory.json @@ -268,8 +268,8 @@ { "location": "prepared", "filename": "runtime.json", - "bytes": 509423, - "sha256": "2c9ccf9df981603113ffc186da075a4617a5427e77c8c359411484f4be7fbeb2" + "bytes": 530769, + "sha256": "006ee14608c25af854fc23028e558a7dad014d17c724552037b5d1ef76876080" }, { "location": "prepared", diff --git a/src/objects/phobos/README.md b/src/objects/phobos/README.md index d0c532fe580..9b75f1dbcb4 100644 --- a/src/objects/phobos/README.md +++ b/src/objects/phobos/README.md @@ -48,4 +48,5 @@ We checked the Phobos layers that [NASA Phobos Trek](https://trek.nasa.gov/phobo - This is radial height, not elevation above a geoid. This presentation is a low-resolution approximation of the released model, not the original scientific mesh. - Shape and cartographic products have different source histories. A display mesh cannot remove the source mosaic's residual control errors. - Relative albedo and slope withhold any facet whose released Albedo field is non-finite; this is not a complete photographic coverage mask. +- Every display atlas is 3,756 × 3,922 pixels, 96 × 96 texels a face, which reduces display detail, not the source mosaic. Until 5 October 2026 the layout was 128 × 128 texels a face and a dataset switch took 312 to 552 ms on an iPad, against 166 to 187 ms on repeat visits now. Until the same day its faces were drawn from both sides, so the far half was drawn and sorted on every frame: a drag had 24 of 390 frames over 33 ms, the longest 160 ms, against 1 and 37 ms now. - Feature outlines are not published nomenclature boundaries. diff --git a/src/objects/phobos/inventory.json b/src/objects/phobos/inventory.json index 3eaf81037d8..1ae4edbcec6 100644 --- a/src/objects/phobos/inventory.json +++ b/src/objects/phobos/inventory.json @@ -274,8 +274,8 @@ { "location": "prepared", "filename": "runtime.json", - "bytes": 986781, - "sha256": "0927849f616741af8c3011c746fd4357292fa67a46c32525f574fc8b9567dfcc" + "bytes": 1004807, + "sha256": "314719a16527777c215f09fa18e5a0063a9cd5b6b63da9862291c9cbcbd14abc" }, { "location": "prepared", diff --git a/src/renderers/css/styles/deimos-surfaces.css b/src/renderers/css/styles/deimos-surfaces.css index a0352e6f95d..a48d643ca87 100644 --- a/src/renderers/css/styles/deimos-surfaces.css +++ b/src/renderers/css/styles/deimos-surfaces.css @@ -7,7 +7,7 @@ :where(.object-stage[data-object-id="deimos"]) .deimos-camera .polycss-mesh { position: absolute; transform-style: preserve-3d; transform-origin: 0 0 0; } :where(.object-stage[data-object-id="deimos"]) .deimos-body > u { position: absolute; display: block; width: 64px; height: 64px; - margin: 0; padding: 0; border: 0; transform-origin: 0 0; transform-style: flat; backface-visibility: visible; + margin: 0; padding: 0; border: 0; transform-origin: 0 0; transform-style: flat; backface-visibility: hidden; border-top-left-radius: 50% 100%; border-top-right-radius: 50% 100%; corner-top-left-shape: bevel; corner-top-right-shape: bevel; background-repeat: no-repeat; diff --git a/src/renderers/css/styles/dimorphos-surfaces.css b/src/renderers/css/styles/dimorphos-surfaces.css index 00e19b0bddf..631decb244c 100644 --- a/src/renderers/css/styles/dimorphos-surfaces.css +++ b/src/renderers/css/styles/dimorphos-surfaces.css @@ -7,7 +7,7 @@ :where(.object-stage[data-object-id="dimorphos"]) .dimorphos-camera .polycss-mesh { position: absolute; transform-style: preserve-3d; transform-origin: 0 0 0; } :where(.object-stage[data-object-id="dimorphos"]) .dimorphos-body > u { position: absolute; display: block; width: 64px; height: 64px; - margin: 0; padding: 0; border: 0; transform-origin: 0 0; transform-style: flat; backface-visibility: visible; + margin: 0; padding: 0; border: 0; transform-origin: 0 0; transform-style: flat; backface-visibility: hidden; border-top-left-radius: 50% 100%; border-top-right-radius: 50% 100%; corner-top-left-shape: bevel; corner-top-right-shape: bevel; background-repeat: no-repeat; diff --git a/src/renderers/css/styles/phobos-surfaces.css b/src/renderers/css/styles/phobos-surfaces.css index 86c77c7aec0..49e708687a6 100644 --- a/src/renderers/css/styles/phobos-surfaces.css +++ b/src/renderers/css/styles/phobos-surfaces.css @@ -7,7 +7,7 @@ :where(.object-stage[data-object-id="phobos"]) .phobos-camera .polycss-mesh { position: absolute; transform-style: preserve-3d; transform-origin: 0 0 0; } :where(.object-stage[data-object-id="phobos"]) .phobos-body > u { position: absolute; display: block; width: 64px; height: 64px; - margin: 0; padding: 0; border: 0; transform-origin: 0 0; transform-style: flat; backface-visibility: visible; + margin: 0; padding: 0; border: 0; transform-origin: 0 0; transform-style: flat; backface-visibility: hidden; border-top-left-radius: 50% 100%; border-top-right-radius: 50% 100%; corner-top-left-shape: bevel; corner-top-right-shape: bevel; background-repeat: no-repeat;