close
Skip to content

Commit c74f07e

Browse files
committed
feat: extend shelf cover atlases to both faces
1 parent 45537db commit c74f07e

1 file changed

Lines changed: 65 additions & 73 deletions

File tree

‎src/app/surf/DevWebSurf3D.tsx‎

Lines changed: 65 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ export default function DevWebSurf3D({
827827
>()
828828
const thumbnailPrefetchTimers = new Set<number>()
829829
const MAX_RESIDENT_COVERS = 32
830-
const SHELF_ATLAS_PANELS_PER_FLOOR = 6
830+
const SHELF_ATLAS_STRIPS_PER_SHELF = 2
831831
const COVERS_PER_SHELF_ATLAS = 3
832832
const MAX_ACTIVE_BOOK_DETAILS = 14
833833
const COVER_LOAD_DISTANCE = 10.5
@@ -3725,81 +3725,73 @@ export default function DevWebSurf3D({
37253725
)
37263726
if (!candidates.length) continue
37273727

3728-
const floorEntries: ShelfCoverAtlasLod[] = []
37293728
const floorBase = floor * LIBRARY_FLOOR_HEIGHT
3729+
// One small atlas is shared by every strip on the floor. This keeps
3730+
// remote image work bounded (three cached requests per floor) while
3731+
// letting every synthetic stack carry a cover-detail layer on both
3732+
// faces instead of a handful of floating cards.
3733+
const urls = candidates
3734+
.slice(0, COVERS_PER_SHELF_ATLAS)
3735+
.map(articleCoverUrl)
3736+
.filter((url): url is string => Boolean(url))
3737+
if (!urls.length) continue
3738+
3739+
const atlas = createShelfCoverAtlas(
3740+
urls,
3741+
floor,
3742+
(floor - 1) * 320,
3743+
)
3744+
const material = new THREE.MeshBasicMaterial({
3745+
map: atlas,
3746+
color: 0xffffff,
3747+
transparent: true,
3748+
opacity: .48,
3749+
toneMapped: false,
3750+
depthWrite: true,
3751+
polygonOffset: true,
3752+
polygonOffsetFactor: -1,
3753+
polygonOffsetUnits: -1,
3754+
})
3755+
architecturalMaterials.push(material)
37303756

3731-
for (
3732-
let panelIndex = 0;
3733-
panelIndex < SHELF_ATLAS_PANELS_PER_FLOOR;
3734-
panelIndex += 1
3735-
) {
3736-
const rowIndex = Math.round(
3737-
panelIndex *
3738-
((placeholderRows.length - 1) /
3739-
Math.max(1, SHELF_ATLAS_PANELS_PER_FLOOR - 1)),
3740-
)
3741-
const columnIndex =
3742-
(panelIndex * 3 + floor) % placeholderColumns.length
3743-
const rotationY = rowIndex % 2 === 0 ? 0 : Math.PI
3744-
const level = panelIndex % 3
3745-
const urls: string[] = []
3746-
3747-
for (
3748-
let coverIndex = 0;
3749-
coverIndex < COVERS_PER_SHELF_ATLAS;
3750-
coverIndex += 1
3751-
) {
3752-
const sampleIndex =
3753-
(panelIndex * COVERS_PER_SHELF_ATLAS + coverIndex) %
3754-
candidates.length
3755-
const url = articleCoverUrl(candidates[sampleIndex])
3756-
if (url) urls.push(url)
3757-
}
3758-
if (!urls.length) continue
3759-
3760-
const atlas = createShelfCoverAtlas(
3761-
urls,
3762-
floor,
3763-
(floor - 1) * 260 + panelIndex * 70,
3764-
)
3765-
const material = new THREE.MeshBasicMaterial({
3766-
map: atlas,
3767-
color: 0xffffff,
3768-
transparent: true,
3769-
opacity: .48,
3770-
toneMapped: false,
3771-
depthWrite: true,
3772-
side: THREE.DoubleSide,
3773-
polygonOffset: true,
3774-
polygonOffsetFactor: -1,
3775-
polygonOffsetUnits: -1,
3776-
})
3777-
architecturalMaterials.push(material)
3778-
3779-
const mesh = new THREE.Mesh(
3780-
shelfCoverAtlasGeometry,
3781-
material,
3782-
)
3783-
const x = placeholderColumns[columnIndex]
3784-
const z = placeholderRows[rowIndex]
3785-
const front = .095
3786-
mesh.position.set(
3787-
x + Math.sin(rotationY) * front,
3788-
floorBase + .64 + level * 1.08,
3789-
z + Math.cos(rotationY) * front,
3790-
)
3791-
mesh.rotation.y = rotationY
3792-
mesh.renderOrder = 2
3793-
scene.add(mesh)
3794-
3795-
floorEntries.push({
3796-
mesh,
3797-
material,
3798-
floorIndex: floor,
3757+
const stripCount =
3758+
placeholderRows.length *
3759+
placeholderColumns.length *
3760+
SHELF_ATLAS_STRIPS_PER_SHELF
3761+
const mesh = new THREE.InstancedMesh(
3762+
shelfCoverAtlasGeometry,
3763+
material,
3764+
stripCount,
3765+
)
3766+
const stripMatrix = new THREE.Matrix4()
3767+
const stripPosition = new THREE.Vector3()
3768+
const stripScale = new THREE.Vector3(1, 1, 1)
3769+
const stripQuaternion = new THREE.Quaternion()
3770+
let stripIndex = 0
3771+
placeholderRows.forEach((z, rowIndex) => {
3772+
placeholderColumns.forEach((x, columnIndex) => {
3773+
const baseRotation = rowIndex % 2 === 0 ? 0 : Math.PI
3774+
for (let face = -1; face <= 1; face += 2) {
3775+
const rotationY = baseRotation + (face < 0 ? Math.PI : 0)
3776+
const front = face * .692
3777+
const level =
3778+
(floor + rowIndex + columnIndex + (face < 0 ? 1 : 0)) % 3
3779+
stripPosition.set(
3780+
x + Math.sin(baseRotation) * front,
3781+
floorBase + .64 + level * 1.08,
3782+
z + Math.cos(baseRotation) * front,
3783+
)
3784+
stripQuaternion.setFromAxisAngle(placeholderUp, rotationY)
3785+
stripMatrix.compose(stripPosition, stripQuaternion, stripScale)
3786+
mesh.setMatrixAt(stripIndex, stripMatrix)
3787+
stripIndex += 1
3788+
}
37993789
})
3800-
}
3801-
3802-
shelfCoverAtlasesByFloor.set(floor, floorEntries)
3790+
})
3791+
mesh.instanceMatrix.needsUpdate = true
3792+
mesh.renderOrder = 2
3793+
scene.add(mesh)
3794+
shelfCoverAtlasesByFloor.set(floor, [{mesh, material, floorIndex: floor}])
38033795
}
38043796

38053797
// Article LOD: every real article has a tiny instanced stand-in. Distant

0 commit comments

Comments
 (0)