diff --git a/public/models/summit/summit-marker.glb b/public/models/summit/summit-marker.glb index b3978eb..5fc1039 100644 Binary files a/public/models/summit/summit-marker.glb and b/public/models/summit/summit-marker.glb differ diff --git a/scripts/export-summit-plateau.py b/scripts/export-summit-plateau.py index 4715356..26752ca 100644 --- a/scripts/export-summit-plateau.py +++ b/scripts/export-summit-plateau.py @@ -15,6 +15,16 @@ for obj in [marker,*marker.children_recursive]:obj.select_set(True) bpy.context.view_layer.objects.active=marker location=marker.location.copy();marker.location=(0,0,0) photo_body=bpy.data.objects.get('Photo matched summit boulder') +# Repacking an already-packed image after baking can retain its old PNG bytes. +# Refresh from the saved bake before glTF copies those bytes into the GLB. +if photo_body and photo_body.get('paintedInscription'): + images={n.image for mat in photo_body.data.materials for n in mat.node_tree.nodes + if n.type=='TEX_IMAGE' and n.image and n.image.filepath} + for image in images: + path=Path(bpy.path.abspath(image.filepath)) + data=path.read_bytes() + image.pack(data=data,data_len=len(data)) + image.reload() restore=None if photo_body and not photo_body.get('paintedInscription'): mat=photo_body.data.materials[0] diff --git a/src/constants/summitMarker.ts b/src/constants/summitMarker.ts index d3154aa..0b786c2 100644 --- a/src/constants/summitMarker.ts +++ b/src/constants/summitMarker.ts @@ -1,5 +1,5 @@ export const SUMMIT_MARKER = { - assetRevision: '8de117c42335', + assetRevision: 'e8ea25042407', buriedDepth: 0.12, footHeight: 0.18, } as const; diff --git a/tests/summit-marker.test.ts b/tests/summit-marker.test.ts index 214bff1..693d042 100644 --- a/tests/summit-marker.test.ts +++ b/tests/summit-marker.test.ts @@ -1,8 +1,24 @@ import assert from 'node:assert/strict'; import test from 'node:test'; +import { readFileSync } from 'node:fs'; import { BoxGeometry, Group, Mesh, MeshStandardMaterial, Vector3 } from 'three'; import { createSummitMarker } from '../src/scene/summitMarker.ts'; +test('exported marker embeds the current baked textures, not stale packed images', () => { + const glb = readFileSync(new URL('../public/models/summit/summit-marker.glb', import.meta.url)); + const jsonLength = glb.readUInt32LE(12); + const document = JSON.parse(glb.subarray(20, 20 + jsonLength).toString()); + const binaryStart = 28 + jsonLength; + assert.equal(document.images.length, 4); + for (const image of document.images) { + const view = document.bufferViews[image.bufferView]; + const start = binaryStart + (view.byteOffset ?? 0); + const embedded = glb.subarray(start, start + view.byteLength); + const source = readFileSync(new URL(`../public/terrain/materials/${image.name}.png`, import.meta.url)); + assert.ok(embedded.equals(source), `${image.name} must match the latest bake`); + } +}); + test('marker seats its foot on sloping bedrock without deforming the stone', () => { const asset = new Group(); const mesh = new Mesh(new BoxGeometry(4, 4, 2), new MeshStandardMaterial());