three-base 2.0.190 → 2.0.192
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.
- package/MeshBase.d.ts +23 -0
- package/MeshBase.js +47 -1
- package/MeshBase.ts +301 -257
- package/MktMesh/MktMesh.d.ts +34 -1
- package/MktMesh/MktMesh.js +70 -3
- package/MktMesh/MktMesh.ts +1437 -1368
- package/MktMesh/imagePlane.d.ts +4 -0
- package/MktMesh/imagePlane.js +8 -0
- package/MktMesh/imagePlane.ts +7 -0
- package/MktMesh/modelSlot.d.ts +8 -0
- package/MktMesh/modelSlot.js +26 -2
- package/MktMesh/modelSlot.ts +26 -2
- package/instanced/InstancedMeshBase.js +3 -0
- package/instanced/InstancedMeshBase.ts +3 -0
- package/package.json +1 -1
package/MktMesh/imagePlane.d.ts
CHANGED
|
@@ -37,9 +37,13 @@ export declare class ImagePlane extends Mesh<PlaneGeometry, MeshBasicMaterial> {
|
|
|
37
37
|
private _uInset;
|
|
38
38
|
private _uValid;
|
|
39
39
|
private _data;
|
|
40
|
+
/** 内容是否已落定:4 格里至少有一格真的绑上了纹理。**只朝 true 翻一次**(之后逐张显影继续,但不再回退成「没内容」)。 */
|
|
41
|
+
private _loaded;
|
|
40
42
|
constructor(name?: string);
|
|
41
43
|
get imageWidth(): number;
|
|
42
44
|
get imageHeight(): number;
|
|
45
|
+
/** 这一颗的内容落定没有 —— 库的逐帧点亮闸只认这一条(`MktMesh.tickProgressiveReveal`)。 */
|
|
46
|
+
get loaded(): boolean;
|
|
43
47
|
setPlaneSize(w: number, h: number): void;
|
|
44
48
|
setPlaneData(d: Pick<ImagePlaneData, "url" | "tiles" | "naturalW" | "naturalH">): void;
|
|
45
49
|
get tiles(): string[];
|
package/MktMesh/imagePlane.js
CHANGED
|
@@ -70,6 +70,8 @@ export class ImagePlane extends Mesh {
|
|
|
70
70
|
url: "",
|
|
71
71
|
tiles: [],
|
|
72
72
|
};
|
|
73
|
+
/** 内容是否已落定:4 格里至少有一格真的绑上了纹理。**只朝 true 翻一次**(之后逐张显影继续,但不再回退成「没内容」)。 */
|
|
74
|
+
_loaded = false;
|
|
73
75
|
constructor(name) {
|
|
74
76
|
const geo = new PlaneGeometry(DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
|
75
77
|
const mat = new MeshBasicMaterial({
|
|
@@ -108,6 +110,8 @@ export class ImagePlane extends Mesh {
|
|
|
108
110
|
}
|
|
109
111
|
get imageWidth() { return this.geometry.parameters.width; }
|
|
110
112
|
get imageHeight() { return this.geometry.parameters.height; }
|
|
113
|
+
/** 这一颗的内容落定没有 —— 库的逐帧点亮闸只认这一条(`MktMesh.tickProgressiveReveal`)。 */
|
|
114
|
+
get loaded() { return this._loaded; }
|
|
111
115
|
setPlaneSize(w, h) {
|
|
112
116
|
this.geometry.dispose();
|
|
113
117
|
this.geometry = new PlaneGeometry(w, h);
|
|
@@ -127,6 +131,10 @@ export class ImagePlane extends Mesh {
|
|
|
127
131
|
if (insets[i])
|
|
128
132
|
this._uInset.value[i].copy(insets[i]);
|
|
129
133
|
this._uValid.value[i] = t ? 1 : 0;
|
|
134
|
+
// 第一格就绪 = 这一颗有东西可画了 ⇒ 落定(点亮闸认的就是这一条,⛔ 不是「4 格全到齐」:
|
|
135
|
+
// 「逐张就绪逐张显影」是本文件 10-22 晚定下的口径,等到全到齐会让先到的那几格白等几帧)。
|
|
136
|
+
if (t)
|
|
137
|
+
this._loaded = true;
|
|
130
138
|
}
|
|
131
139
|
}
|
|
132
140
|
/** 只读「此刻材质里绑了什么」的戳记:4 格就绪位 + 已绑纹理的版本号。
|
package/MktMesh/imagePlane.ts
CHANGED
|
@@ -102,6 +102,8 @@ export class ImagePlane extends Mesh<PlaneGeometry, MeshBasicMaterial> {
|
|
|
102
102
|
url: "",
|
|
103
103
|
tiles: [],
|
|
104
104
|
};
|
|
105
|
+
/** 内容是否已落定:4 格里至少有一格真的绑上了纹理。**只朝 true 翻一次**(之后逐张显影继续,但不再回退成「没内容」)。 */
|
|
106
|
+
private _loaded = false;
|
|
105
107
|
|
|
106
108
|
constructor(name?: string) {
|
|
107
109
|
const geo = new PlaneGeometry(DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
|
@@ -145,6 +147,8 @@ export class ImagePlane extends Mesh<PlaneGeometry, MeshBasicMaterial> {
|
|
|
145
147
|
|
|
146
148
|
get imageWidth(): number { return (this.geometry as PlaneGeometry).parameters.width; }
|
|
147
149
|
get imageHeight(): number { return (this.geometry as PlaneGeometry).parameters.height; }
|
|
150
|
+
/** 这一颗的内容落定没有 —— 库的逐帧点亮闸只认这一条(`MktMesh.tickProgressiveReveal`)。 */
|
|
151
|
+
get loaded(): boolean { return this._loaded; }
|
|
148
152
|
|
|
149
153
|
setPlaneSize(w: number, h: number): void {
|
|
150
154
|
this.geometry.dispose();
|
|
@@ -167,6 +171,9 @@ export class ImagePlane extends Mesh<PlaneGeometry, MeshBasicMaterial> {
|
|
|
167
171
|
this._uTiles.value[i] = t || PLACEHOLDER_TEX;
|
|
168
172
|
if (insets[i]) this._uInset.value[i].copy(insets[i]);
|
|
169
173
|
this._uValid.value[i] = t ? 1 : 0;
|
|
174
|
+
// 第一格就绪 = 这一颗有东西可画了 ⇒ 落定(点亮闸认的就是这一条,⛔ 不是「4 格全到齐」:
|
|
175
|
+
// 「逐张就绪逐张显影」是本文件 10-22 晚定下的口径,等到全到齐会让先到的那几格白等几帧)。
|
|
176
|
+
if (t) this._loaded = true;
|
|
170
177
|
}
|
|
171
178
|
}
|
|
172
179
|
|
package/MktMesh/modelSlot.d.ts
CHANGED
|
@@ -66,6 +66,12 @@ export declare class ModelSlot extends Group {
|
|
|
66
66
|
private _staged;
|
|
67
67
|
/** 载入令牌:换地址/删除后迟到的回调靠它作废(否则旧模型会挂进新槽) */
|
|
68
68
|
private _loadToken;
|
|
69
|
+
/**
|
|
70
|
+
* 内容是否已落定:真模型挂进了 `_contentRoot`,或这一颗压根没在等什么(空地址 / 取回失败 ⇒ 停在占位小立方体)。
|
|
71
|
+
* ⚠️ 落定**不等于**已经画进 GPU —— 顶点缓冲与首次 program 编译发生在「亮出来的那一帧」,
|
|
72
|
+
* 所以逐帧限流必须闸在点亮这一下(`MktMesh.tickProgressiveReveal`),闸在挂载那一下拦不住 GPU 侧的账。
|
|
73
|
+
*/
|
|
74
|
+
private _loaded;
|
|
69
75
|
private _disposed;
|
|
70
76
|
constructor(name?: string);
|
|
71
77
|
get size(): number;
|
|
@@ -78,6 +84,8 @@ export declare class ModelSlot extends Group {
|
|
|
78
84
|
} | undefined;
|
|
79
85
|
/** 是否已经挂上真模型(false = 仍是占位小立方体) */
|
|
80
86
|
get hasModel(): boolean;
|
|
87
|
+
/** 这一颗的内容落定没有 —— 库的逐帧点亮闸只认这一条(`MktMesh.tickProgressiveReveal`)。 */
|
|
88
|
+
get loaded(): boolean;
|
|
81
89
|
/** 改尺寸档(米,最长边):立刻重缩内容 */
|
|
82
90
|
setSize(size: number): void;
|
|
83
91
|
/**
|
package/MktMesh/modelSlot.js
CHANGED
|
@@ -107,6 +107,12 @@ export class ModelSlot extends Group {
|
|
|
107
107
|
_staged = null;
|
|
108
108
|
/** 载入令牌:换地址/删除后迟到的回调靠它作废(否则旧模型会挂进新槽) */
|
|
109
109
|
_loadToken = 0;
|
|
110
|
+
/**
|
|
111
|
+
* 内容是否已落定:真模型挂进了 `_contentRoot`,或这一颗压根没在等什么(空地址 / 取回失败 ⇒ 停在占位小立方体)。
|
|
112
|
+
* ⚠️ 落定**不等于**已经画进 GPU —— 顶点缓冲与首次 program 编译发生在「亮出来的那一帧」,
|
|
113
|
+
* 所以逐帧限流必须闸在点亮这一下(`MktMesh.tickProgressiveReveal`),闸在挂载那一下拦不住 GPU 侧的账。
|
|
114
|
+
*/
|
|
115
|
+
_loaded = false;
|
|
110
116
|
_disposed = false;
|
|
111
117
|
constructor(name) {
|
|
112
118
|
super();
|
|
@@ -126,6 +132,8 @@ export class ModelSlot extends Group {
|
|
|
126
132
|
get naturalSize() { return this._naturalSize; }
|
|
127
133
|
/** 是否已经挂上真模型(false = 仍是占位小立方体) */
|
|
128
134
|
get hasModel() { return this._model !== null; }
|
|
135
|
+
/** 这一颗的内容落定没有 —— 库的逐帧点亮闸只认这一条(`MktMesh.tickProgressiveReveal`)。 */
|
|
136
|
+
get loaded() { return this._loaded; }
|
|
129
137
|
/** 改尺寸档(米,最长边):立刻重缩内容 */
|
|
130
138
|
setSize(size) {
|
|
131
139
|
this._size = size > 0 ? size : this._size;
|
|
@@ -161,13 +169,25 @@ export class ModelSlot extends Group {
|
|
|
161
169
|
async loadModel(url) {
|
|
162
170
|
this._url = url;
|
|
163
171
|
const token = ++this._loadToken;
|
|
172
|
+
this._loaded = false;
|
|
164
173
|
this._detachModel();
|
|
165
174
|
// 先立刻退回占位小立方体:GLB 在路上那段窗口(慢网/大模型)⛔ 不许让这一槽凭空消失
|
|
166
175
|
// (取回失败那条支路本来也是停在占位上,两段时间里画面一致)
|
|
167
176
|
this._layout();
|
|
168
|
-
if (!url)
|
|
177
|
+
if (!url) {
|
|
178
|
+
// 空地址 = 这一颗压根没在等什么 ⇒ 当场落定(占位小立方体就是它的最终内容)
|
|
179
|
+
this._loaded = true;
|
|
169
180
|
return true;
|
|
170
|
-
|
|
181
|
+
}
|
|
182
|
+
// 取回失败(404 / 解析报错都从这一档走):`threeLoader.loadModel` 是会 reject 的,⚠️ 必须当「落定在占位方块」处理
|
|
183
|
+
// —— 整层重建时这一颗是压着不亮的,不落定就永远隐形(旧写法里它至少还露得出占位方块)。
|
|
184
|
+
let obj;
|
|
185
|
+
try {
|
|
186
|
+
obj = await threeLoader.loadModel(url);
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
obj = undefined;
|
|
190
|
+
}
|
|
171
191
|
// 迟到回调:这一槽已经改指向别的地址、或已经删除 ⇒ 当场释放,别留一份没人认领的显存
|
|
172
192
|
if (this._disposed || token !== this._loadToken) {
|
|
173
193
|
if (obj)
|
|
@@ -175,6 +195,7 @@ export class ModelSlot extends Group {
|
|
|
175
195
|
return false;
|
|
176
196
|
}
|
|
177
197
|
if (!obj) {
|
|
198
|
+
this._loaded = true;
|
|
178
199
|
this._layout();
|
|
179
200
|
return false;
|
|
180
201
|
}
|
|
@@ -189,6 +210,7 @@ export class ModelSlot extends Group {
|
|
|
189
210
|
this._staged = null;
|
|
190
211
|
this._model = obj;
|
|
191
212
|
this._contentRoot.add(obj);
|
|
213
|
+
this._loaded = true;
|
|
192
214
|
this._layout();
|
|
193
215
|
return true;
|
|
194
216
|
}
|
|
@@ -220,6 +242,8 @@ export class ModelSlot extends Group {
|
|
|
220
242
|
this._size = d.size > 0 ? d.size : MODEL_SLOT_DEFAULT_SIZE;
|
|
221
243
|
this._naturalSize = d.naturalSize;
|
|
222
244
|
this._url = d.url || "";
|
|
245
|
+
// 落定判据跟着地址走:空地址 = 没在等什么(占位方块就是最终内容);有地址 = 等 GLB 那一拍
|
|
246
|
+
this._loaded = !this._url;
|
|
223
247
|
if (!this._url)
|
|
224
248
|
this._detachModel();
|
|
225
249
|
this._layout();
|
package/MktMesh/modelSlot.ts
CHANGED
|
@@ -137,6 +137,12 @@ export class ModelSlot extends Group {
|
|
|
137
137
|
private _staged: Object3D | null = null;
|
|
138
138
|
/** 载入令牌:换地址/删除后迟到的回调靠它作废(否则旧模型会挂进新槽) */
|
|
139
139
|
private _loadToken = 0;
|
|
140
|
+
/**
|
|
141
|
+
* 内容是否已落定:真模型挂进了 `_contentRoot`,或这一颗压根没在等什么(空地址 / 取回失败 ⇒ 停在占位小立方体)。
|
|
142
|
+
* ⚠️ 落定**不等于**已经画进 GPU —— 顶点缓冲与首次 program 编译发生在「亮出来的那一帧」,
|
|
143
|
+
* 所以逐帧限流必须闸在点亮这一下(`MktMesh.tickProgressiveReveal`),闸在挂载那一下拦不住 GPU 侧的账。
|
|
144
|
+
*/
|
|
145
|
+
private _loaded = false;
|
|
140
146
|
private _disposed = false;
|
|
141
147
|
|
|
142
148
|
constructor(name?: string) {
|
|
@@ -164,6 +170,8 @@ export class ModelSlot extends Group {
|
|
|
164
170
|
get naturalSize(): { x: number; y: number; z: number } | undefined { return this._naturalSize; }
|
|
165
171
|
/** 是否已经挂上真模型(false = 仍是占位小立方体) */
|
|
166
172
|
get hasModel(): boolean { return this._model !== null; }
|
|
173
|
+
/** 这一颗的内容落定没有 —— 库的逐帧点亮闸只认这一条(`MktMesh.tickProgressiveReveal`)。 */
|
|
174
|
+
get loaded(): boolean { return this._loaded; }
|
|
167
175
|
|
|
168
176
|
/** 改尺寸档(米,最长边):立刻重缩内容 */
|
|
169
177
|
setSize(size: number): void {
|
|
@@ -201,18 +209,31 @@ export class ModelSlot extends Group {
|
|
|
201
209
|
async loadModel(url: string): Promise<boolean> {
|
|
202
210
|
this._url = url;
|
|
203
211
|
const token = ++this._loadToken;
|
|
212
|
+
this._loaded = false;
|
|
204
213
|
this._detachModel();
|
|
205
214
|
// 先立刻退回占位小立方体:GLB 在路上那段窗口(慢网/大模型)⛔ 不许让这一槽凭空消失
|
|
206
215
|
// (取回失败那条支路本来也是停在占位上,两段时间里画面一致)
|
|
207
216
|
this._layout();
|
|
208
|
-
if (!url)
|
|
209
|
-
|
|
217
|
+
if (!url) {
|
|
218
|
+
// 空地址 = 这一颗压根没在等什么 ⇒ 当场落定(占位小立方体就是它的最终内容)
|
|
219
|
+
this._loaded = true;
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
// 取回失败(404 / 解析报错都从这一档走):`threeLoader.loadModel` 是会 reject 的,⚠️ 必须当「落定在占位方块」处理
|
|
223
|
+
// —— 整层重建时这一颗是压着不亮的,不落定就永远隐形(旧写法里它至少还露得出占位方块)。
|
|
224
|
+
let obj: Object3D | undefined;
|
|
225
|
+
try {
|
|
226
|
+
obj = await threeLoader.loadModel(url);
|
|
227
|
+
} catch {
|
|
228
|
+
obj = undefined;
|
|
229
|
+
}
|
|
210
230
|
// 迟到回调:这一槽已经改指向别的地址、或已经删除 ⇒ 当场释放,别留一份没人认领的显存
|
|
211
231
|
if (this._disposed || token !== this._loadToken) {
|
|
212
232
|
if (obj) disposeSubtree(obj);
|
|
213
233
|
return false;
|
|
214
234
|
}
|
|
215
235
|
if (!obj) {
|
|
236
|
+
this._loaded = true;
|
|
216
237
|
this._layout();
|
|
217
238
|
return false;
|
|
218
239
|
}
|
|
@@ -227,6 +248,7 @@ export class ModelSlot extends Group {
|
|
|
227
248
|
this._staged = null;
|
|
228
249
|
this._model = obj;
|
|
229
250
|
this._contentRoot.add(obj);
|
|
251
|
+
this._loaded = true;
|
|
230
252
|
this._layout();
|
|
231
253
|
return true;
|
|
232
254
|
}
|
|
@@ -257,6 +279,8 @@ export class ModelSlot extends Group {
|
|
|
257
279
|
this._size = d.size > 0 ? d.size : MODEL_SLOT_DEFAULT_SIZE;
|
|
258
280
|
this._naturalSize = d.naturalSize;
|
|
259
281
|
this._url = d.url || "";
|
|
282
|
+
// 落定判据跟着地址走:空地址 = 没在等什么(占位方块就是最终内容);有地址 = 等 GLB 那一拍
|
|
283
|
+
this._loaded = !this._url;
|
|
260
284
|
if (!this._url) this._detachModel();
|
|
261
285
|
this._layout();
|
|
262
286
|
}
|
|
@@ -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;
|