Lazy-load page textures with LRU cache and double-sided materials

Replace eager texture generation with a reference-counted pool
that loads only the visible window and evicts unused pages, and
swap front/back mesh pairs for single meshes using a two-sided
material to halve draw calls. The timeline now drives its texture
window from the camera's visible world range each frame, and the
binder tracks a current-page window. Flip animations also finalize
immediately so rapid flips chain smoothly.
This commit is contained in:
2026-09-19 02:44:15 +08:00
parent 2a173833d0
commit eb165d03c5
4 changed files with 303 additions and 61 deletions
+16 -1
View File
@@ -165,7 +165,7 @@ export class App {
this.interactives.binder.push(m);
});
});
this.timeline.cards.forEach((c) => this.interactives.timeline.push(c.front, c.back));
this.timeline.cards.forEach((c) => this.interactives.timeline.push(c.mesh));
// 地理视图由 Cesium 自行拾取,不参与 Three.js 射线检测
}
@@ -258,6 +258,18 @@ export class App {
return (2 * Math.tan(halfFov) * dist * aspect) / canvas.clientWidth;
}
// 时间轴:按当前相机可视区域刷新纹理窗口(拖拽/缩放/居中动画时连续跟随)
_updateTimelineTextures() {
if (this.view !== 'timeline') return;
const dist = this.camera.position.distanceTo(this.controls.target);
const halfFov = THREE.MathUtils.degToRad(this.camera.fov / 2);
const el = this.renderer.domElement;
const aspect = el.clientWidth / el.clientHeight;
const halfW = Math.tan(halfFov) * dist * aspect;
// 时间轴相机始终在 z 轴看向原点(旋转已锁定),可见世界 x ∈ [-halfW, halfW]
this.timeline.setVisibleWorldRange(-halfW, halfW);
}
_hitTest() {
const list = this.interactives[this.view];
if (!list || !list.length) return null;
@@ -388,6 +400,7 @@ export class App {
const limit = TIMELINE_SPREAD + 0.6;
this.timelineOffset = clamp(-this.timeline.getCardX(this.selected), -limit, limit);
this.timeline.group.position.x = this.timelineOffset;
this.timeline.refreshTextures();
}
if (!isGlobe) {
@@ -444,6 +457,8 @@ export class App {
this.binder.update(dt);
this.timeline.update(dt);
this.timeline.drainPending();
this._updateTimelineTextures();
if (this.cameraTween) {
const t = this.cameraTween;