three-base 2.0.190 → 2.0.193

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.
@@ -220,7 +220,7 @@ export class PanoTileStitcher {
220
220
  * ⚠️ 唯一按张数**能混进来**的是 10-06 那版同为 32 片的老档(切片顺序与槽分组两版一致 ⇒ 不会错位),
221
221
  * 但它的瓦片是 1024²、被画进 1536² 的格子 = 1.5× 放大 ⇒ 发虚,那类老点仍要重传一次。
222
222
  * ⚠️ 每槽数组长度由 `RT_STITCH_SLOT_COUNT` 派生(⛔ 不许手写 `[null,null]` —— 槽数再变会漏改)。 */
223
- ensure(urls, layout) {
223
+ ensure(urls, layout, front = false) {
224
224
  const L = layout ?? PANO_TILE_LAYOUT;
225
225
  const maxTiles = tilesPerBatchOf(L);
226
226
  if (!urls || urls.length === 0 || urls.length > maxTiles)
@@ -229,8 +229,11 @@ export class PanoTileStitcher {
229
229
  while (u.length < maxTiles)
230
230
  u.push("");
231
231
  const batch = rtStitchBatchOf(u);
232
- if (this._groups.has(batch))
232
+ if (this._groups.has(batch)) {
233
+ if (front)
234
+ this._toFront(batch);
233
235
  return;
236
+ }
234
237
  const slotCount = L.slotCount;
235
238
  const cellsPerSlot = cellsPerSlotOf(L);
236
239
  this._groups.set(batch, {
@@ -244,8 +247,26 @@ export class PanoTileStitcher {
244
247
  drawnCount: Array.from({ length: slotCount }, () => 0),
245
248
  pending: slotCount,
246
249
  });
250
+ if (front)
251
+ this._toFront(batch);
247
252
  this._stamp++;
248
253
  }
254
+ /** 把一批挪到在册顺序的**最前**(只动 Map 的顺序,⛔ 不动组里任何东西:RT、已画格子、瓦片账本原样)。
255
+ * 已在最前 ⇒ 一次 `keys().next()` 就返回(每帧点名走的就是这条零成本支路)。 */
256
+ _toFront(batch) {
257
+ const g = this._groups.get(batch);
258
+ if (!g)
259
+ return;
260
+ const head = this._groups.keys().next();
261
+ if (!head.done && head.value === batch)
262
+ return;
263
+ const rest = [...this._groups.entries()];
264
+ this._groups.clear();
265
+ this._groups.set(batch, g);
266
+ for (const [k, v] of rest)
267
+ if (k !== batch)
268
+ this._groups.set(k, v);
269
+ }
249
270
  /** 取某一拼合槽的纹理:**画过 ≥1 格就交出去**(同日旨「需要先喂给 shader」⇒ 不再等 `cellsPerSlot` 格画满)。
250
271
  * RT 建好时整张涂过缺失灰 ⇒ 交出去的那张里**没有未定义像素**,观感 = 该象限逐格显影。 */
251
272
  peek(batch, slot, renderer) {
@@ -238,8 +238,11 @@ interface StitchGroup {
238
238
  export interface PanoStitcher {
239
239
  /** 确保批次已在册并发起瓦片加载(幂等;同批已在册 ⇒ 什么都不做)。
240
240
  * 新增可选 `layout` 参数:缺省 = PANO_TILE_LAYOUT(全景 8×4 / 2 槽 / 6144×6144,2026-10-27 需求);
241
- * 图片平面传 `imageTileLayout(natW, natH)`(2×2 / 1 槽 / RT 宽高比=原图)。 */
242
- ensure(urls: string[], layout?: TileLayout): void;
241
+ * 图片平面传 `imageTileLayout(natW, natH)`(2×2 / 1 槽 / RT 宽高比=原图)。
242
+ * 新增可选 `front` 参数(2026-10-29 需求):`true` ⇒ 这一批**挪到在册顺序最前** = 每帧那三道工序
243
+ * 先取它的料(下载额度「每帧 2 张」先归它)。消费方每帧点一次 ⇒ 换渲染器那次整份作废后,
244
+ * 下一帧又把头名抢回来(⛔ 光靠「先入册」做不到,见 `MktMesh.prefetchHeadPanoramas` 的说明)。 */
245
+ ensure(urls: string[], layout?: TileLayout, front?: boolean): void;
243
246
  /**
244
247
  * 取某一拼合槽的纹理。**画过 ≥1 格就返回**(同日旨「需要先喂给 shader」)。
245
248
  * ⭐ 2026-10-09 皇上旨「切换全景时上一个全景的内容要渲染成深灰」:**传了 `renderer` 且该槽一格都还没画时,
@@ -326,14 +329,17 @@ private _uploadQueued: Set<TileRec> = new Set();
326
329
  * ⚠️ 唯一按张数**能混进来**的是 10-06 那版同为 32 片的老档(切片顺序与槽分组两版一致 ⇒ 不会错位),
327
330
  * 但它的瓦片是 1024²、被画进 1536² 的格子 = 1.5× 放大 ⇒ 发虚,那类老点仍要重传一次。
328
331
  * ⚠️ 每槽数组长度由 `RT_STITCH_SLOT_COUNT` 派生(⛔ 不许手写 `[null,null]` —— 槽数再变会漏改)。 */
329
- ensure(urls: string[], layout?: TileLayout): void {
332
+ ensure(urls: string[], layout?: TileLayout, front = false): void {
330
333
  const L = layout ?? PANO_TILE_LAYOUT;
331
334
  const maxTiles = tilesPerBatchOf(L);
332
335
  if (!urls || urls.length === 0 || urls.length > maxTiles) return;
333
336
  const u = urls.slice();
334
337
  while (u.length < maxTiles) u.push("");
335
338
  const batch = rtStitchBatchOf(u);
336
- if (this._groups.has(batch)) return;
339
+ if (this._groups.has(batch)) {
340
+ if (front) this._toFront(batch);
341
+ return;
342
+ }
337
343
  const slotCount = L.slotCount;
338
344
  const cellsPerSlot = cellsPerSlotOf(L);
339
345
  this._groups.set(batch, {
@@ -347,9 +353,23 @@ private _uploadQueued: Set<TileRec> = new Set();
347
353
  drawnCount: Array.from({ length: slotCount }, () => 0),
348
354
  pending: slotCount,
349
355
  });
356
+ if (front) this._toFront(batch);
350
357
  this._stamp++;
351
358
  }
352
359
 
360
+ /** 把一批挪到在册顺序的**最前**(只动 Map 的顺序,⛔ 不动组里任何东西:RT、已画格子、瓦片账本原样)。
361
+ * 已在最前 ⇒ 一次 `keys().next()` 就返回(每帧点名走的就是这条零成本支路)。 */
362
+ private _toFront(batch: string): void {
363
+ const g = this._groups.get(batch);
364
+ if (!g) return;
365
+ const head = this._groups.keys().next();
366
+ if (!head.done && head.value === batch) return;
367
+ const rest = [...this._groups.entries()];
368
+ this._groups.clear();
369
+ this._groups.set(batch, g);
370
+ for (const [k, v] of rest) if (k !== batch) this._groups.set(k, v);
371
+ }
372
+
353
373
  /** 取某一拼合槽的纹理:**画过 ≥1 格就交出去**(同日旨「需要先喂给 shader」⇒ 不再等 `cellsPerSlot` 格画满)。
354
374
  * RT 建好时整张涂过缺失灰 ⇒ 交出去的那张里**没有未定义像素**,观感 = 该象限逐格显影。 */
355
375
  peek(batch: string, slot: number, renderer?: WebGLRenderer | null): Texture | null {
@@ -1,6 +1,7 @@
1
1
  import type { Matrix4 } from "three";
2
2
  import type { ImagePlaneData } from "./imagePlane";
3
3
  import type { ModelSlotData } from "./modelSlot";
4
+ import type { GlassPaneData } from "./glassPane";
4
5
  /**
5
6
  * 单个纹理的运行时信息:url + 矩阵(位置 + 旋转,缩放忽略)。
6
7
  * ⚠️ 这个矩阵记在 MktMesh **自身局部(制图)空间**,与 `wallPoints` 同一空间 —— 不是世界矩阵:
@@ -87,4 +88,9 @@ export interface MktMeshData {
87
88
  images?: ImagePlaneData[];
88
89
  /** 模型槽层(同一道旨):`url` 是 .glb 的相对地址;空串 = 还没上传 ⇒ 显示占位小立方体 */
89
90
  models?: ModelSlotData[];
91
+ /**
92
+ * 玻璃面层(2026-10-28 需求「正方的面」):正方形、双面、transmission 折射,反射环境取运行时第一个全景。
93
+ * ⛔ 这一层不落任何素材地址 ⇒ 既不过 `stripAssetHost` 也不过 `absAssetUrl`,只有位置/旋转/边长。
94
+ */
95
+ glass?: GlassPaneData[];
90
96
  }
package/MktMesh/types.ts CHANGED
@@ -8,6 +8,7 @@
8
8
  import type { Matrix4 } from "three";
9
9
  import type { ImagePlaneData } from "./imagePlane";
10
10
  import type { ModelSlotData } from "./modelSlot";
11
+ import type { GlassPaneData } from "./glassPane";
11
12
 
12
13
  /**
13
14
  * 单个纹理的运行时信息:url + 矩阵(位置 + 旋转,缩放忽略)。
@@ -99,4 +100,9 @@ export interface MktMeshData {
99
100
  images?: ImagePlaneData[];
100
101
  /** 模型槽层(同一道旨):`url` 是 .glb 的相对地址;空串 = 还没上传 ⇒ 显示占位小立方体 */
101
102
  models?: ModelSlotData[];
103
+ /**
104
+ * 玻璃面层(2026-10-28 需求「正方的面」):正方形、双面、transmission 折射,反射环境取运行时第一个全景。
105
+ * ⛔ 这一层不落任何素材地址 ⇒ 既不过 `stripAssetHost` 也不过 `absAssetUrl`,只有位置/旋转/边长。
106
+ */
107
+ glass?: GlassPaneData[];
102
108
  }
@@ -122,6 +122,9 @@ export default class InstancedMeshBase extends MeshBase {
122
122
  instanceCollect[uuid] = instancedMesh;
123
123
  this.add(instancedMesh);
124
124
  });
125
+ // ⭐ 2026-10-28「每个模型对象逐帧显示出来」:这一组 InstancedMesh 是**一个对象**的内容 ⇒ 一次放行
126
+ // (一帧一个对象,⛔ 不是一个对象里的几十块零件排几十帧,那会变成零件逐块拼装)
127
+ this.revealSoon(this.children.slice());
125
128
  // 加载完成事件
126
129
  await new Promise((resolve) => setTimeout(resolve, 30));
127
130
  this.loaded = true;
@@ -124,6 +124,9 @@ export default class InstancedMeshBase extends MeshBase {
124
124
  instanceCollect[uuid] = instancedMesh;
125
125
  this.add(instancedMesh);
126
126
  });
127
+ // ⭐ 2026-10-28「每个模型对象逐帧显示出来」:这一组 InstancedMesh 是**一个对象**的内容 ⇒ 一次放行
128
+ // (一帧一个对象,⛔ 不是一个对象里的几十块零件排几十帧,那会变成零件逐块拼装)
129
+ this.revealSoon(this.children.slice());
127
130
  // 加载完成事件
128
131
  await new Promise((resolve) => setTimeout(resolve, 30));
129
132
  this.loaded = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "three-base",
3
- "version": "2.0.190",
3
+ "version": "2.0.193",
4
4
  "description": "A Three.js extension library providing common 3D components, animations, materials, and utilities",
5
5
  "author": "xiaosihan",
6
6
  "publishConfig": {
@@ -47,6 +47,11 @@
47
47
  "import": "./MktMesh/modelSlot.js",
48
48
  "require": "./MktMesh/modelSlot.js"
49
49
  },
50
+ "./MktMesh/glassPane": {
51
+ "types": "./MktMesh/glassPane.d.ts",
52
+ "import": "./MktMesh/glassPane.js",
53
+ "require": "./MktMesh/glassPane.js"
54
+ },
50
55
  "./MktMesh/boxLine2": {
51
56
  "types": "./MktMesh/boxLine2.d.ts",
52
57
  "import": "./MktMesh/boxLine2.js",
package/threeLoader.js CHANGED
@@ -28,6 +28,8 @@ class ThreeLoader extends EventDispatcher {
28
28
  };
29
29
  // 资源加载进度
30
30
  DefaultLoadingManager.onProgress = (url, loaded, total) => {
31
+ // 三个数一并转发:首页只认「还在不在加载」,弹窗一类要看进度
32
+ this.dispatchEvent({ type: "progress", url, loaded, total });
31
33
  if (loaded < total) {
32
34
  this.dispatchEvent({ type: "loadding" });
33
35
  }
package/threeLoader.ts CHANGED
@@ -32,6 +32,8 @@ class ThreeLoader extends EventDispatcher<ThreeLoaderEventMap> {
32
32
  };
33
33
  // 资源加载进度
34
34
  DefaultLoadingManager.onProgress = (url: string, loaded: number, total: number) => {
35
+ // 三个数一并转发:首页只认「还在不在加载」,弹窗一类要看进度
36
+ this.dispatchEvent({ type: "progress", url, loaded, total });
35
37
  if (loaded < total) {
36
38
  this.dispatchEvent({ type: "loadding" });
37
39
  }