@threepipe/plugin-blend-importer 0.1.0 → 0.3.1
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/CHANGELOG.md +53 -3
- package/README.md +25 -1
- package/dist/BlendLoadPlugin.d.ts +63 -3
- package/dist/BlendLoadPlugin.d.ts.map +1 -1
- package/dist/decompress.d.ts +10 -0
- package/dist/decompress.d.ts.map +1 -0
- package/dist/dependencies.txt +31 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1354 -89
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1352 -87
- package/dist/index.mjs.map +1 -1
- package/dist/loader/camera.d.ts +1 -1
- package/dist/loader/ctx.d.ts +9 -1
- package/dist/loader/ctx.d.ts.map +1 -1
- package/dist/loader/geometry.d.ts +2 -2
- package/dist/loader/geometry.d.ts.map +1 -1
- package/dist/loader/index.d.ts +1 -1
- package/dist/loader/light.d.ts +1 -1
- package/dist/loader/material.d.ts +4 -1
- package/dist/loader/material.d.ts.map +1 -1
- package/dist/loader/mesh.d.ts +1 -1
- package/dist/loader/mesh.d.ts.map +1 -1
- package/docs/assets/highlight.css +49 -0
- package/docs/assets/icons.js +1 -1
- package/docs/assets/icons.svg +1 -1
- package/docs/assets/main.js +2 -2
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/assets/style.css +3 -3
- package/docs/classes/BlendLoadPlugin.html +6 -3
- package/docs/index.html +1 -1
- package/docs/interfaces/BlendFile.html +18 -0
- package/docs/interfaces/BlendLoadOptions.html +12 -0
- package/package.json +1 -1
- package/src/BlendLoadPlugin.ts +204 -13
- package/src/decompress.ts +59 -0
- package/src/index.ts +1 -0
- package/src/js-blend/main.js +4 -1
- package/src/js-blend/parser/parser.js +192 -52
- package/src/loader/ctx.ts +9 -0
- package/src/loader/geometry.ts +270 -13
- package/src/loader/material.ts +326 -8
- package/src/loader/mesh.ts +34 -8
- package/tsconfig.json +1 -0
- package/docs/.nojekyll +0 -1
package/dist/index.js
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
(function(global, factory) {
|
|
2
2
|
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("threepipe")) : typeof define === "function" && define.amd ? define(["exports", "threepipe"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global["@threepipe/plugin-blend-importer"] = {}, global.threepipe));
|
|
3
|
-
})(this, function(exports2, threepipe) {
|
|
4
|
-
"use strict"
|
|
5
|
-
* @license
|
|
6
|
-
* @threepipe/plugin-blend-importer v0.1.0
|
|
7
|
-
* Copyright 2022-2025 repalash <palash@shaders.app>
|
|
8
|
-
* Apache-2.0 License
|
|
9
|
-
* See ./dependencies.txt for any bundled third-party dependencies and licenses.
|
|
10
|
-
*/
|
|
11
|
-
|
|
3
|
+
})(this, (function(exports2, threepipe) {
|
|
4
|
+
"use strict";
|
|
12
5
|
let worker = null;
|
|
13
6
|
const return_object = {
|
|
14
7
|
loadBlendFromArrayBuffer: function(array_buffer) {
|
|
@@ -41,6 +34,7 @@
|
|
|
41
34
|
struct_names = [];
|
|
42
35
|
offset = 0;
|
|
43
36
|
current_SDNA_template = null;
|
|
37
|
+
ERROR = null;
|
|
44
38
|
_data = msg.data;
|
|
45
39
|
AB = _data.slice();
|
|
46
40
|
data = new DataView(_data);
|
|
@@ -75,13 +69,30 @@
|
|
|
75
69
|
} else {
|
|
76
70
|
return pointerLow;
|
|
77
71
|
}
|
|
72
|
+
},
|
|
73
|
+
// Alignment-safe TypedArray read over the file buffer. Consumers (e.g. loader/geometry.ts)
|
|
74
|
+
// that reach into `__blender_file__.AB` at a datablock's `__data_address__` MUST use this
|
|
75
|
+
// instead of `new Ctor(AB, byteOffset, n)` — Blender packs blocks with no padding, so on
|
|
76
|
+
// v1 (17-byte header) and some v0 files the payload lands at an offset that isn't a multiple
|
|
77
|
+
// of the element size, where a direct view throws RangeError. All supported files are
|
|
78
|
+
// little-endian (big-endian is rejected at header parse), so a raw byte copy is correct.
|
|
79
|
+
readTypedArray: function(Ctor, byteOffset, length) {
|
|
80
|
+
return alignedTypedArray(Ctor, this.AB, byteOffset, length);
|
|
78
81
|
}
|
|
79
82
|
};
|
|
80
83
|
self2.onmessage = parseFile;
|
|
84
|
+
function alignedTypedArray(Ctor, buffer, byteOffset, length) {
|
|
85
|
+
if (byteOffset % Ctor.BYTES_PER_ELEMENT === 0) {
|
|
86
|
+
return new Ctor(buffer, byteOffset, length);
|
|
87
|
+
}
|
|
88
|
+
const out = new Ctor(length);
|
|
89
|
+
new Uint8Array(out.buffer).set(new Uint8Array(buffer, byteOffset, length * Ctor.BYTES_PER_ELEMENT));
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
81
92
|
function float64Prop(offset2, Blender_Array_Length, length) {
|
|
82
93
|
return {
|
|
83
94
|
get: function() {
|
|
84
|
-
return Blender_Array_Length > 1 ?
|
|
95
|
+
return Blender_Array_Length > 1 ? alignedTypedArray(Float64Array, this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getFloat64(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
85
96
|
},
|
|
86
97
|
set: function(float) {
|
|
87
98
|
if (Blender_Array_Length > 1) ;
|
|
@@ -96,7 +107,7 @@
|
|
|
96
107
|
function floatProp(offset2, Blender_Array_Length, length) {
|
|
97
108
|
return {
|
|
98
109
|
get: function() {
|
|
99
|
-
return Blender_Array_Length > 1 ?
|
|
110
|
+
return Blender_Array_Length > 1 ? alignedTypedArray(Float32Array, this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getFloat32(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
100
111
|
},
|
|
101
112
|
set: function(float) {
|
|
102
113
|
if (Blender_Array_Length > 1) ;
|
|
@@ -111,7 +122,7 @@
|
|
|
111
122
|
function intProp(offset2, Blender_Array_Length, length) {
|
|
112
123
|
return {
|
|
113
124
|
get: function() {
|
|
114
|
-
return Blender_Array_Length > 1 ?
|
|
125
|
+
return Blender_Array_Length > 1 ? alignedTypedArray(Int32Array, this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getInt32(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
115
126
|
},
|
|
116
127
|
set: function(float) {
|
|
117
128
|
if (Blender_Array_Length > 1) ;
|
|
@@ -123,10 +134,25 @@
|
|
|
123
134
|
configurable: true
|
|
124
135
|
};
|
|
125
136
|
}
|
|
137
|
+
function uIntProp(offset2, Blender_Array_Length, length) {
|
|
138
|
+
return {
|
|
139
|
+
get: function() {
|
|
140
|
+
return Blender_Array_Length > 1 ? alignedTypedArray(Uint32Array, this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getUint32(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
141
|
+
},
|
|
142
|
+
set: function(float) {
|
|
143
|
+
if (Blender_Array_Length > 1) ;
|
|
144
|
+
else {
|
|
145
|
+
this.__blender_file__.dv.setUint32(this.__data_address__ + offset2, float, this.__blender_file__.template.endianess);
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
enumerable: true,
|
|
149
|
+
configurable: true
|
|
150
|
+
};
|
|
151
|
+
}
|
|
126
152
|
function shortProp(offset2, Blender_Array_Length, length) {
|
|
127
153
|
return {
|
|
128
154
|
get: function() {
|
|
129
|
-
return Blender_Array_Length > 1 ?
|
|
155
|
+
return Blender_Array_Length > 1 ? alignedTypedArray(Int16Array, this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getInt16(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
130
156
|
},
|
|
131
157
|
set: function(float) {
|
|
132
158
|
if (Blender_Array_Length > 1) ;
|
|
@@ -141,7 +167,7 @@
|
|
|
141
167
|
const uShortProp = (offset2, Blender_Array_Length, length) => {
|
|
142
168
|
return {
|
|
143
169
|
get: function() {
|
|
144
|
-
return Blender_Array_Length > 1 ?
|
|
170
|
+
return Blender_Array_Length > 1 ? alignedTypedArray(Uint16Array, this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getUint16(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
145
171
|
},
|
|
146
172
|
set: function(float) {
|
|
147
173
|
if (Blender_Array_Length > 1) ;
|
|
@@ -189,18 +215,28 @@
|
|
|
189
215
|
function pointerProp2(offset2) {
|
|
190
216
|
return {
|
|
191
217
|
get: function() {
|
|
192
|
-
|
|
193
|
-
|
|
218
|
+
const bf = this.__blender_file__;
|
|
219
|
+
let pointer = bf.getPointer(this.__data_address__ + offset2, bf);
|
|
220
|
+
const link = bf.memory_lookup[pointer];
|
|
194
221
|
const results = [];
|
|
195
222
|
if (link) {
|
|
196
223
|
const address = link.__data_address__;
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
let
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
224
|
+
const ps = bf.template && bf.template.pointer_size || 8;
|
|
225
|
+
const count = typeof link.__byte_length__ === "number" && link.__byte_length__ > 0 ? Math.floor(link.__byte_length__ / ps) : 0;
|
|
226
|
+
if (count > 0) {
|
|
227
|
+
for (let j = 0; j < count; j++) {
|
|
228
|
+
pointer = bf.getPointer(address + j * ps, bf);
|
|
229
|
+
results.push(bf.memory_lookup[pointer] || null);
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
let j = 0;
|
|
233
|
+
while (true) {
|
|
234
|
+
pointer = bf.getPointer(address + j * ps, bf);
|
|
235
|
+
const obj = bf.memory_lookup[pointer];
|
|
236
|
+
if (!obj) break;
|
|
237
|
+
results.push(obj);
|
|
238
|
+
j++;
|
|
239
|
+
}
|
|
204
240
|
}
|
|
205
241
|
}
|
|
206
242
|
return results;
|
|
@@ -236,6 +272,33 @@
|
|
|
236
272
|
configurable: true
|
|
237
273
|
};
|
|
238
274
|
}
|
|
275
|
+
function int8Prop(offset2, Blender_Array_Length, length) {
|
|
276
|
+
return {
|
|
277
|
+
get: function() {
|
|
278
|
+
return Blender_Array_Length > 1 ? alignedTypedArray(Int8Array, this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getInt8(this.__data_address__ + offset2);
|
|
279
|
+
},
|
|
280
|
+
set: function(v) {
|
|
281
|
+
if (Blender_Array_Length <= 1) this.__blender_file__.dv.setInt8(this.__data_address__ + offset2, v);
|
|
282
|
+
},
|
|
283
|
+
enumerable: true,
|
|
284
|
+
configurable: true
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function int64Prop(offset2, Blender_Array_Length, length, unsigned) {
|
|
288
|
+
return {
|
|
289
|
+
get: function() {
|
|
290
|
+
if (Blender_Array_Length > 1) {
|
|
291
|
+
return alignedTypedArray(unsigned ? BigUint64Array : BigInt64Array, this.__blender_file__.AB, this.__data_address__ + offset2, length);
|
|
292
|
+
}
|
|
293
|
+
const dv = this.__blender_file__.dv, le = this.__blender_file__.template.endianess;
|
|
294
|
+
return Number(unsigned ? dv.getBigUint64(this.__data_address__ + offset2, le) : dv.getBigInt64(this.__data_address__ + offset2, le));
|
|
295
|
+
},
|
|
296
|
+
set: function() {
|
|
297
|
+
},
|
|
298
|
+
enumerable: true,
|
|
299
|
+
configurable: true
|
|
300
|
+
};
|
|
301
|
+
}
|
|
239
302
|
function compileProp(obj, name, type, offset2, array_size, IS_POINTER, pointer_size2, length) {
|
|
240
303
|
if (!IS_POINTER) {
|
|
241
304
|
switch (type) {
|
|
@@ -246,18 +309,34 @@
|
|
|
246
309
|
Object.defineProperty(obj, name, floatProp(offset2, array_size, length >> 2));
|
|
247
310
|
break;
|
|
248
311
|
case "int":
|
|
312
|
+
case "int32_t":
|
|
249
313
|
Object.defineProperty(obj, name, intProp(offset2, array_size, length >> 2));
|
|
250
314
|
break;
|
|
315
|
+
case "uint32_t":
|
|
316
|
+
Object.defineProperty(obj, name, uIntProp(offset2, array_size, length >> 2));
|
|
317
|
+
break;
|
|
251
318
|
case "short":
|
|
319
|
+
case "int16_t":
|
|
252
320
|
Object.defineProperty(obj, name, shortProp(offset2, array_size, length >> 1));
|
|
253
321
|
break;
|
|
254
322
|
case "ushort":
|
|
323
|
+
case "uint16_t":
|
|
255
324
|
Object.defineProperty(obj, name, uShortProp(offset2, array_size, length >> 1));
|
|
256
325
|
break;
|
|
326
|
+
case "int8_t":
|
|
327
|
+
Object.defineProperty(obj, name, int8Prop(offset2, array_size, length));
|
|
328
|
+
break;
|
|
257
329
|
case "char":
|
|
258
330
|
case "uchar":
|
|
331
|
+
case "uint8_t":
|
|
259
332
|
Object.defineProperty(obj, name, charProp(offset2, array_size, length));
|
|
260
333
|
break;
|
|
334
|
+
case "int64_t":
|
|
335
|
+
Object.defineProperty(obj, name, int64Prop(offset2, array_size, length >> 3, false));
|
|
336
|
+
break;
|
|
337
|
+
case "uint64_t":
|
|
338
|
+
Object.defineProperty(obj, name, int64Prop(offset2, array_size, length >> 3, true));
|
|
339
|
+
break;
|
|
261
340
|
default:
|
|
262
341
|
obj[name] = {};
|
|
263
342
|
obj.__list__.push(name, type, length, offset2, array_size, IS_POINTER);
|
|
@@ -333,7 +412,7 @@
|
|
|
333
412
|
offset2 = compileProp(blen_struct.prototype, array_name_, type, offset2, Blender_Array_Length, Pointer_Match, pointer_size, array_length);
|
|
334
413
|
}
|
|
335
414
|
Object.defineProperty(blen_struct.prototype, _name, {
|
|
336
|
-
get: /* @__PURE__ */ function(array_names2) {
|
|
415
|
+
get: /* @__PURE__ */ (function(array_names2) {
|
|
337
416
|
return function() {
|
|
338
417
|
const array = [];
|
|
339
418
|
for (let i2 = 0; i2 < array_names2.length; i2++) {
|
|
@@ -341,7 +420,7 @@
|
|
|
341
420
|
}
|
|
342
421
|
return array;
|
|
343
422
|
};
|
|
344
|
-
}(array_names),
|
|
423
|
+
})(array_names),
|
|
345
424
|
enumerable: true,
|
|
346
425
|
configurable: true
|
|
347
426
|
});
|
|
@@ -375,6 +454,7 @@
|
|
|
375
454
|
if (this.__list__ === null) return this;
|
|
376
455
|
BLENDER_FILE2.addObject(this);
|
|
377
456
|
this.__blender_file__ = BLENDER_FILE2;
|
|
457
|
+
this.__byte_length__ = data_block_length - _data_offset;
|
|
378
458
|
const struct = this.__list__;
|
|
379
459
|
let j = 0, i = 0, name = "", type, length, Blender_Array_Length, offset2, constructor;
|
|
380
460
|
this.__data_address__ = _data_offset;
|
|
@@ -437,25 +517,53 @@
|
|
|
437
517
|
offset = 0;
|
|
438
518
|
const magic = toString(_data, offset, 7);
|
|
439
519
|
if (magic !== "BLENDER") return ERROR = "File supplied is not a .blend compatible Blender file.";
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
520
|
+
let version, large_bhead = false;
|
|
521
|
+
const fmtByte = toString(_data, 7, 8);
|
|
522
|
+
if (fmtByte === "_" || fmtByte === "-") {
|
|
523
|
+
pointer_size = fmtByte === "_" ? 4 : 8;
|
|
524
|
+
BIG_ENDIAN = toString(_data, 8, 9) !== "V";
|
|
525
|
+
version = toString(_data, 9, 12);
|
|
526
|
+
offset = 12;
|
|
527
|
+
} else {
|
|
528
|
+
const headerSize = parseInt(toString(_data, 7, 9), 10);
|
|
529
|
+
if (headerSize !== 17) return ERROR = "Unsupported new-style blend header size: " + headerSize;
|
|
530
|
+
pointer_size = 8;
|
|
531
|
+
BIG_ENDIAN = true;
|
|
532
|
+
large_bhead = true;
|
|
533
|
+
version = toString(_data, 13, 17);
|
|
534
|
+
offset = headerSize;
|
|
535
|
+
}
|
|
536
|
+
if (!BIG_ENDIAN) {
|
|
537
|
+
return ERROR = "Big-endian .blend files are not supported";
|
|
538
|
+
}
|
|
539
|
+
const BLOCK_HDR = large_bhead ? 32 : 16 + pointer_size;
|
|
540
|
+
const SDNA_OFF = large_bhead ? 4 : 8 + pointer_size;
|
|
541
|
+
const LEN_OFF = large_bhead ? 16 : 4;
|
|
542
|
+
const NR_OFF = large_bhead ? 24 : 12 + pointer_size;
|
|
543
|
+
const LEN_I64 = large_bhead;
|
|
544
|
+
const NR_I64 = large_bhead;
|
|
545
|
+
const readLen = (o) => LEN_I64 ? Number(data.getBigInt64(o + LEN_OFF, true)) : data.getInt32(o + LEN_OFF, true);
|
|
546
|
+
const readSdna = (o) => data.getInt32(o + SDNA_OFF, BIG_ENDIAN);
|
|
547
|
+
const readNr = (o) => NR_I64 ? Number(data.getBigInt64(o + NR_OFF, true)) : data.getInt32(o + NR_OFF, BIG_ENDIAN);
|
|
548
|
+
const templateKey = (large_bhead ? "v1:" : "v0:") + version;
|
|
549
|
+
if (!templates[templateKey]) {
|
|
550
|
+
templates[templateKey] = new MASTER_SDNA_SCHEMA(version);
|
|
446
551
|
}
|
|
447
|
-
current_SDNA_template = templates[
|
|
552
|
+
current_SDNA_template = templates[templateKey];
|
|
448
553
|
FILE.template = current_SDNA_template;
|
|
449
|
-
offset += 3;
|
|
450
554
|
if (!current_SDNA_template.SDNA_SET) {
|
|
451
555
|
current_SDNA_template.endianess = BIG_ENDIAN;
|
|
452
556
|
current_SDNA_template.pointer_size = pointer_size;
|
|
453
557
|
offset2 = offset;
|
|
454
558
|
while (true) {
|
|
455
|
-
|
|
559
|
+
if (offset2 + BLOCK_HDR > data.byteLength) {
|
|
560
|
+
ERROR = "Unexpected end of file while searching for DNA1";
|
|
561
|
+
break;
|
|
562
|
+
}
|
|
563
|
+
sdna_index = readSdna(offset2);
|
|
456
564
|
code = toString(_data, offset2, offset2 + 4).replace(/\u0000/g, "");
|
|
457
|
-
block_length =
|
|
458
|
-
offset2 +=
|
|
565
|
+
block_length = readLen(offset2);
|
|
566
|
+
offset2 += BLOCK_HDR;
|
|
459
567
|
if (code === "DNA1") {
|
|
460
568
|
count = 0;
|
|
461
569
|
let types = [], names = [], lengths = [], curr_name = "";
|
|
@@ -553,27 +661,24 @@
|
|
|
553
661
|
}
|
|
554
662
|
break;
|
|
555
663
|
}
|
|
556
|
-
if (data.getInt8(offset) === 0) {
|
|
557
|
-
debugger;
|
|
558
|
-
}
|
|
559
664
|
data_offset = offset;
|
|
560
|
-
if (offset +
|
|
665
|
+
if (offset + BLOCK_HDR > data.byteLength) {
|
|
561
666
|
ERROR = "Unexpected end of file while parsing";
|
|
562
667
|
break;
|
|
563
668
|
}
|
|
564
|
-
sdna_index =
|
|
669
|
+
sdna_index = readSdna(offset);
|
|
565
670
|
const code_str = toString(_data, offset, offset + 4);
|
|
566
|
-
offset2 = offset +
|
|
567
|
-
const blockLength =
|
|
568
|
-
if (blockLength < 0 || offset + blockLength +
|
|
671
|
+
offset2 = offset + BLOCK_HDR;
|
|
672
|
+
const blockLength = readLen(offset);
|
|
673
|
+
if (blockLength < 0 || offset + blockLength + BLOCK_HDR > data.byteLength) {
|
|
569
674
|
ERROR = "Invalid block length detected";
|
|
570
675
|
break;
|
|
571
676
|
}
|
|
572
|
-
offset += blockLength +
|
|
677
|
+
offset += blockLength + BLOCK_HDR;
|
|
573
678
|
if (code_str === "DNA1") ;
|
|
574
679
|
else if (code_str === "ENDB") break;
|
|
575
680
|
else if (code_str === "TEST") {
|
|
576
|
-
const data_start = data_offset +
|
|
681
|
+
const data_start = data_offset + BLOCK_HDR;
|
|
577
682
|
const width = data.getInt32(data_start, BIG_ENDIAN);
|
|
578
683
|
const height = data.getInt32(data_start + 4, BIG_ENDIAN);
|
|
579
684
|
if (width * height > 0) {
|
|
@@ -582,7 +687,7 @@
|
|
|
582
687
|
ERROR = "Invalid TEST block length detected";
|
|
583
688
|
break;
|
|
584
689
|
}
|
|
585
|
-
const image_data =
|
|
690
|
+
const image_data = alignedTypedArray(Uint32Array, _data, data_start + 8, data_len >> 2);
|
|
586
691
|
const image = {
|
|
587
692
|
width,
|
|
588
693
|
height,
|
|
@@ -591,10 +696,10 @@
|
|
|
591
696
|
FILE.thumbnail = image;
|
|
592
697
|
}
|
|
593
698
|
} else {
|
|
594
|
-
const data_start = data_offset +
|
|
699
|
+
const data_start = data_offset + BLOCK_HDR;
|
|
595
700
|
const constructor = current_SDNA_template.getSDNAStructureConstructor(current_SDNA_template.SDNA_NAMES[sdna_index]);
|
|
596
|
-
const size =
|
|
597
|
-
count =
|
|
701
|
+
const size = readLen(data_offset);
|
|
702
|
+
count = readNr(data_offset);
|
|
598
703
|
if (count > 0 && constructor) {
|
|
599
704
|
let obj = new constructor();
|
|
600
705
|
const length = constructor.prototype._length;
|
|
@@ -619,18 +724,9 @@
|
|
|
619
724
|
}
|
|
620
725
|
}
|
|
621
726
|
worker = new worker_code();
|
|
622
|
-
worker.postMessage = function(message,
|
|
623
|
-
return_object.onParseReady(message,
|
|
727
|
+
worker.postMessage = function(message, err2) {
|
|
728
|
+
return_object.onParseReady(message, err2);
|
|
624
729
|
};
|
|
625
|
-
/**
|
|
626
|
-
* JS.Blend
|
|
627
|
-
* Original Repo: https://github.com/acweathersby/js.blend
|
|
628
|
-
* Slightly modified for three.js and js updates, minor refactor.
|
|
629
|
-
* Object-creation part re-written for latest three.js and typescript
|
|
630
|
-
* MIT License
|
|
631
|
-
* Copyright (c) 2020 Anthony C, Weathersby
|
|
632
|
-
* @license
|
|
633
|
-
*/
|
|
634
730
|
async function parseBlend(buffer, name = "") {
|
|
635
731
|
return new Promise((res, rej) => {
|
|
636
732
|
return_object.onParseReady = (file, error) => {
|
|
@@ -719,14 +815,147 @@
|
|
|
719
815
|
if (!Array.isArray(layers)) return layers;
|
|
720
816
|
return layers[i];
|
|
721
817
|
}
|
|
818
|
+
function readCString(block) {
|
|
819
|
+
if (!block || block.__data_address__ === void 0 || !block.__blender_file__) return null;
|
|
820
|
+
const u82 = block.__blender_file__.byte;
|
|
821
|
+
let s = "", o = block.__data_address__;
|
|
822
|
+
while (o < u82.length && u82[o] !== 0 && s.length < 256) s += String.fromCharCode(u82[o++]);
|
|
823
|
+
return s;
|
|
824
|
+
}
|
|
825
|
+
const ATTR_TYPE_INT32 = 3, ATTR_TYPE_FLOAT2 = 6, ATTR_TYPE_FLOAT3 = 7;
|
|
826
|
+
const ATTR_DOMAIN_CORNER = 3;
|
|
827
|
+
function getAttributes(meshData) {
|
|
828
|
+
const as = meshData.attribute_storage;
|
|
829
|
+
if (!as) return [];
|
|
830
|
+
let attrs = as.dna_attributes;
|
|
831
|
+
if (!attrs) return [];
|
|
832
|
+
attrs = Array.isArray(attrs) || attrs.length !== void 0 ? Array.from(attrs) : [attrs];
|
|
833
|
+
return attrs;
|
|
834
|
+
}
|
|
835
|
+
function findAttribute(attrs, name, type) {
|
|
836
|
+
for (const a of attrs) {
|
|
837
|
+
if (readCString(a.name) === name && (type === void 0 || a.data_type === type)) return a;
|
|
838
|
+
}
|
|
839
|
+
return null;
|
|
840
|
+
}
|
|
841
|
+
function attrSize(attr) {
|
|
842
|
+
const arr = attr && attr.data;
|
|
843
|
+
const n = arr && arr.size !== void 0 ? Number(arr.size) : 0;
|
|
844
|
+
return Number.isFinite(n) && n >= 0 ? n : 0;
|
|
845
|
+
}
|
|
846
|
+
function readAttrArray(attr, Ctor, count) {
|
|
847
|
+
const arr = attr && attr.data;
|
|
848
|
+
const block = arr && arr.data;
|
|
849
|
+
if (!block || block.__data_address__ === void 0 || !block.__blender_file__) return null;
|
|
850
|
+
return block.__blender_file__.readTypedArray(Ctor, block.__data_address__, count);
|
|
851
|
+
}
|
|
852
|
+
function mergeGroupRun(runs, start, count, mat) {
|
|
853
|
+
if (count <= 0) return;
|
|
854
|
+
const last = runs[runs.length - 1];
|
|
855
|
+
if (last && last.mat === mat && last.start + last.count === start) last.count += count;
|
|
856
|
+
else runs.push({ start, count, mat });
|
|
857
|
+
}
|
|
858
|
+
function readFaceMaterialIndex(meshData, faceCount) {
|
|
859
|
+
const pd = meshData.pdata;
|
|
860
|
+
if (!pd || !pd.layers || !pd.totlayer) return null;
|
|
861
|
+
for (let i = 0; i < pd.totlayer; i++) {
|
|
862
|
+
const l = getLayer(pd.layers, i);
|
|
863
|
+
if (l && l.name === "material_index" && l.data) {
|
|
864
|
+
const data = Array.isArray(l.data) ? l.data : l.data.length !== void 0 ? Array.from(l.data) : null;
|
|
865
|
+
if (!data) return null;
|
|
866
|
+
const out = new Array(faceCount);
|
|
867
|
+
for (let f = 0; f < faceCount; f++) {
|
|
868
|
+
const e = data[f];
|
|
869
|
+
out[f] = e && typeof e === "object" ? e.i ?? e.value ?? 0 : e || 0;
|
|
870
|
+
}
|
|
871
|
+
return out;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
return null;
|
|
875
|
+
}
|
|
876
|
+
function createBufferGeometryFromAttributes(meshData, ctx) {
|
|
877
|
+
const attrs = getAttributes(meshData);
|
|
878
|
+
if (!attrs.length) return null;
|
|
879
|
+
const posAttr = findAttribute(attrs, "position", ATTR_TYPE_FLOAT3);
|
|
880
|
+
const vertCount = attrSize(posAttr);
|
|
881
|
+
const posRaw = vertCount > 0 && readAttrArray(posAttr, Float32Array, vertCount * 3);
|
|
882
|
+
if (!posRaw) return null;
|
|
883
|
+
const geometry = new ctx.BufferGeometry();
|
|
884
|
+
geometry.name = meshData.aname || "";
|
|
885
|
+
const positions = new Float32Array(vertCount * 3);
|
|
886
|
+
for (let j = 0; j < vertCount; j++) {
|
|
887
|
+
const x = posRaw[j * 3], y = posRaw[j * 3 + 1], z = posRaw[j * 3 + 2];
|
|
888
|
+
positions[j * 3] = Number.isFinite(x) ? x : 0;
|
|
889
|
+
positions[j * 3 + 1] = Number.isFinite(z) ? z : 0;
|
|
890
|
+
positions[j * 3 + 2] = Number.isFinite(y) ? -y : 0;
|
|
891
|
+
}
|
|
892
|
+
geometry.setAttribute("position", new ctx.BufferAttribute(positions, 3));
|
|
893
|
+
const cvAttr = findAttribute(attrs, ".corner_vert", ATTR_TYPE_INT32);
|
|
894
|
+
const loopCount = attrSize(cvAttr);
|
|
895
|
+
const cornerVerts = loopCount > 0 && readAttrArray(cvAttr, Int32Array, loopCount);
|
|
896
|
+
const poi = meshData.poly_offset_indices;
|
|
897
|
+
const faceOffsetCount = poi && poi.__byte_length__ ? poi.__byte_length__ >> 2 : 0;
|
|
898
|
+
if (cornerVerts && faceOffsetCount > 1 && poi) {
|
|
899
|
+
const faceIndices = poi.__blender_file__.readTypedArray(Int32Array, poi.__data_address__, faceOffsetCount);
|
|
900
|
+
const faceCount = faceIndices.length - 1;
|
|
901
|
+
let totalTriangles = 0;
|
|
902
|
+
for (let i = 0; i < faceCount; i++) totalTriangles += Math.max(0, faceIndices[i + 1] - faceIndices[i] - 2);
|
|
903
|
+
const indexes = new Uint32Array(totalTriangles * 3);
|
|
904
|
+
const inRange = (v) => v >= 0 && v < vertCount;
|
|
905
|
+
const matAttr = (meshData.totcol || 0) > 1 ? findAttribute(attrs, "material_index", ATTR_TYPE_INT32) : null;
|
|
906
|
+
const faceMat = matAttr && attrSize(matAttr) >= faceCount ? readAttrArray(matAttr, Int32Array, faceCount) : null;
|
|
907
|
+
const groupRuns = [];
|
|
908
|
+
let t = 0;
|
|
909
|
+
for (let i = 0; i < faceCount; i++) {
|
|
910
|
+
const faceStart = faceIndices[i], faceVertCount = faceIndices[i + 1] - faceStart;
|
|
911
|
+
const triStart = t;
|
|
912
|
+
if (faceVertCount >= 3 && faceStart >= 0 && faceStart + faceVertCount <= loopCount) {
|
|
913
|
+
const firstVert = cornerVerts[faceStart];
|
|
914
|
+
for (let k = 1; k < faceVertCount - 1; k++) {
|
|
915
|
+
const b = cornerVerts[faceStart + k], c = cornerVerts[faceStart + k + 1];
|
|
916
|
+
if (inRange(firstVert) && inRange(b) && inRange(c)) {
|
|
917
|
+
indexes[t++] = firstVert;
|
|
918
|
+
indexes[t++] = b;
|
|
919
|
+
indexes[t++] = c;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
if (faceMat) mergeGroupRun(groupRuns, triStart, t - triStart, faceMat[i] || 0);
|
|
924
|
+
}
|
|
925
|
+
geometry.setIndex(new ctx.BufferAttribute(t === indexes.length ? indexes : indexes.slice(0, t), 1));
|
|
926
|
+
if (faceMat) for (const g of groupRuns) geometry.addGroup(g.start, g.count, g.mat);
|
|
927
|
+
const uvAttr = attrs.find((a) => a.data_type === ATTR_TYPE_FLOAT2 && a.domain === ATTR_DOMAIN_CORNER && !(readCString(a.name) || ".").startsWith("."));
|
|
928
|
+
const uvRaw = uvAttr && attrSize(uvAttr) >= loopCount && readAttrArray(uvAttr, Float32Array, loopCount * 2);
|
|
929
|
+
if (uvRaw) {
|
|
930
|
+
const uvs = new Float32Array(vertCount * 2);
|
|
931
|
+
for (let i = 0; i < loopCount; i++) {
|
|
932
|
+
const v = cornerVerts[i];
|
|
933
|
+
if (v >= 0 && v < vertCount) {
|
|
934
|
+
const u = uvRaw[i * 2], vv = uvRaw[i * 2 + 1];
|
|
935
|
+
uvs[v * 2] = Number.isFinite(u) ? u : 0;
|
|
936
|
+
uvs[v * 2 + 1] = Number.isFinite(vv) ? vv : 0;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
geometry.setAttribute("uv", new ctx.BufferAttribute(uvs, 2));
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
if (geometry.attributes.position && !geometry.attributes.normal)
|
|
943
|
+
geometry.computeVertexNormals();
|
|
944
|
+
return geometry;
|
|
945
|
+
}
|
|
722
946
|
function createBufferGeometry(meshData, ctx) {
|
|
723
947
|
if (meshData.mpoly) return createBufferGeometryOld(meshData, ctx);
|
|
948
|
+
if (meshData.attribute_storage) {
|
|
949
|
+
const g = createBufferGeometryFromAttributes(meshData, ctx);
|
|
950
|
+
if (g) return g;
|
|
951
|
+
}
|
|
724
952
|
const geometry = new ctx.BufferGeometry();
|
|
725
953
|
geometry.name = meshData.aname || "";
|
|
726
954
|
let vertices;
|
|
727
955
|
let verticesData;
|
|
728
956
|
let indices;
|
|
729
957
|
let indicesData;
|
|
958
|
+
let uvLayerData = null;
|
|
730
959
|
if (meshData.vdata && meshData.vdata.layers && meshData.vdata.totlayer > 0) {
|
|
731
960
|
for (let i = 0; i < meshData.vdata.totlayer; i++) {
|
|
732
961
|
const layer = getLayer(meshData.vdata.layers, i);
|
|
@@ -745,7 +974,12 @@
|
|
|
745
974
|
const layer = getLayer(meshData.ldata.layers, i);
|
|
746
975
|
const data = layer.data || [];
|
|
747
976
|
if (data.length === meshData.totloop) {
|
|
748
|
-
|
|
977
|
+
const lname = layer.name || "";
|
|
978
|
+
if (!uvLayerData && (layer.type === 49 || lname[0] !== "." && /uv/i.test(lname))) {
|
|
979
|
+
uvLayerData = data;
|
|
980
|
+
continue;
|
|
981
|
+
}
|
|
982
|
+
if (indices && (lname !== ".corner_vert" || indices.name === ".corner_vert")) {
|
|
749
983
|
continue;
|
|
750
984
|
}
|
|
751
985
|
indices = layer;
|
|
@@ -755,9 +989,44 @@
|
|
|
755
989
|
}
|
|
756
990
|
let faceIndices = [];
|
|
757
991
|
if (meshData.poly_offset_indices && meshData.totpoly > 0) {
|
|
758
|
-
faceIndices = [...
|
|
992
|
+
faceIndices = [...meshData.poly_offset_indices.__blender_file__.readTypedArray(Int32Array, meshData.poly_offset_indices.__data_address__, meshData.totpoly + 1)];
|
|
993
|
+
}
|
|
994
|
+
const vco = (vd) => vd?.x !== void 0 ? [vd.x, vd.y, vd.z] : vd?.co ? [vd.co[0], vd.co[1], vd.co[2]] : [0, 0, 0];
|
|
995
|
+
let cornerToVert = null;
|
|
996
|
+
let expandedPos = null;
|
|
997
|
+
let expandedUv = null;
|
|
998
|
+
if (uvLayerData && indicesData && verticesData && verticesData.length) {
|
|
999
|
+
cornerToVert = new Int32Array(indicesData.length);
|
|
1000
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1001
|
+
const ps = [], us = [];
|
|
1002
|
+
const uvN = uvLayerData.length;
|
|
1003
|
+
for (let i = 0; i < indicesData.length; i++) {
|
|
1004
|
+
const bv = indicesData[i]?.i;
|
|
1005
|
+
if (!(bv >= 0 && bv < verticesData.length)) {
|
|
1006
|
+
cornerToVert[i] = 0;
|
|
1007
|
+
continue;
|
|
1008
|
+
}
|
|
1009
|
+
const e = i < uvN ? uvLayerData[i] : null;
|
|
1010
|
+
const u = e && Number.isFinite(e.x) ? e.x : 0;
|
|
1011
|
+
const w = e && Number.isFinite(e.y) ? e.y : 0;
|
|
1012
|
+
const key = bv + "|" + Math.round(u * 4096) + "|" + Math.round(w * 4096);
|
|
1013
|
+
let ev = seen.get(key);
|
|
1014
|
+
if (ev === void 0) {
|
|
1015
|
+
ev = us.length / 2;
|
|
1016
|
+
seen.set(key, ev);
|
|
1017
|
+
const [x, y, z] = vco(verticesData[bv]);
|
|
1018
|
+
ps.push(x, z, -y);
|
|
1019
|
+
us.push(u, w);
|
|
1020
|
+
}
|
|
1021
|
+
cornerToVert[i] = ev;
|
|
1022
|
+
}
|
|
1023
|
+
expandedPos = new Float32Array(ps);
|
|
1024
|
+
expandedUv = new Float32Array(us);
|
|
759
1025
|
}
|
|
760
|
-
|
|
1026
|
+
const vAt = (corner) => cornerToVert ? cornerToVert[corner] : indicesData[corner].i;
|
|
1027
|
+
if (expandedPos) {
|
|
1028
|
+
geometry.setAttribute("position", new ctx.BufferAttribute(expandedPos, 3));
|
|
1029
|
+
} else if (verticesData && verticesData.length > 0) {
|
|
761
1030
|
const positions = new Float32Array(verticesData.length * 3);
|
|
762
1031
|
for (let j = 0; j < verticesData.length; j++) {
|
|
763
1032
|
const { x, y, z, co } = verticesData[j] || {};
|
|
@@ -776,44 +1045,50 @@
|
|
|
776
1045
|
}
|
|
777
1046
|
geometry.setAttribute("position", new ctx.BufferAttribute(positions, 3));
|
|
778
1047
|
}
|
|
779
|
-
if (indicesData && indicesData.length > 0 &&
|
|
1048
|
+
if (indicesData && indicesData.length > 0 && verticesData?.length) {
|
|
780
1049
|
const faceSize = meshData.totloop / meshData.totpoly;
|
|
781
1050
|
if (faceIndices.length > 0) {
|
|
1051
|
+
const faceCount = faceIndices.length - 1;
|
|
782
1052
|
let totalTriangles = 0;
|
|
783
|
-
for (let i = 0; i <
|
|
1053
|
+
for (let i = 0; i < faceCount; i++) {
|
|
784
1054
|
const faceVertCount = faceIndices[i + 1] - faceIndices[i];
|
|
785
1055
|
totalTriangles += Math.max(0, faceVertCount - 2);
|
|
786
1056
|
}
|
|
787
1057
|
const indexes = new Uint32Array(totalTriangles * 3);
|
|
788
1058
|
let t = 0;
|
|
789
|
-
|
|
1059
|
+
const faceMat = (meshData.totcol || 0) > 1 ? readFaceMaterialIndex(meshData, faceCount) : null;
|
|
1060
|
+
const groupRuns = [];
|
|
1061
|
+
for (let i = 0; i < faceCount; i++) {
|
|
790
1062
|
const faceStart = faceIndices[i];
|
|
791
1063
|
const faceEnd = faceIndices[i + 1];
|
|
792
1064
|
const faceVertCount = faceEnd - faceStart;
|
|
1065
|
+
const triStart = t;
|
|
793
1066
|
if (faceVertCount >= 3) {
|
|
794
|
-
const firstVert =
|
|
1067
|
+
const firstVert = vAt(faceStart);
|
|
795
1068
|
for (let k = 1; k < faceVertCount - 1; k++) {
|
|
796
1069
|
indexes[t++] = firstVert;
|
|
797
|
-
indexes[t++] =
|
|
798
|
-
indexes[t++] =
|
|
1070
|
+
indexes[t++] = vAt(faceStart + k);
|
|
1071
|
+
indexes[t++] = vAt(faceStart + k + 1);
|
|
799
1072
|
}
|
|
800
1073
|
}
|
|
1074
|
+
if (faceMat) mergeGroupRun(groupRuns, triStart, t - triStart, faceMat[i] || 0);
|
|
801
1075
|
}
|
|
802
1076
|
geometry.setIndex(new ctx.BufferAttribute(indexes, 1));
|
|
1077
|
+
if (faceMat) for (const g of groupRuns) geometry.addGroup(g.start, g.count, g.mat);
|
|
803
1078
|
} else if (faceSize === 3 || faceSize === 4) {
|
|
804
1079
|
const isQuad = faceSize === 4;
|
|
805
1080
|
const faceCount = indices.length / faceSize;
|
|
806
1081
|
const indexes = new Uint32Array(faceCount * 3 * (isQuad ? 2 : 1));
|
|
807
1082
|
if (faceSize !== 3 && faceSize !== 4) return geometry;
|
|
808
1083
|
for (let j = 0, t = 0; j < indices.length; j += faceSize) {
|
|
809
|
-
const a =
|
|
810
|
-
const b =
|
|
811
|
-
const c =
|
|
1084
|
+
const a = vAt(j);
|
|
1085
|
+
const b = vAt(j + 1);
|
|
1086
|
+
const c = vAt(j + 2);
|
|
812
1087
|
indexes[t++] = a;
|
|
813
1088
|
indexes[t++] = b;
|
|
814
1089
|
indexes[t++] = c;
|
|
815
1090
|
if (isQuad) {
|
|
816
|
-
const d =
|
|
1091
|
+
const d = vAt(j + 3);
|
|
817
1092
|
indexes[t++] = a;
|
|
818
1093
|
indexes[t++] = c;
|
|
819
1094
|
indexes[t++] = d;
|
|
@@ -824,6 +1099,9 @@
|
|
|
824
1099
|
} else if (faceIndices) {
|
|
825
1100
|
console.error("BlendLoader - no indices data found, but face indices are present", faceIndices);
|
|
826
1101
|
}
|
|
1102
|
+
if (expandedUv && !geometry.attributes.uv) {
|
|
1103
|
+
geometry.setAttribute("uv", new ctx.BufferAttribute(expandedUv, 2));
|
|
1104
|
+
}
|
|
827
1105
|
if (geometry.attributes.position && !geometry.attributes.normal)
|
|
828
1106
|
geometry.computeVertexNormals();
|
|
829
1107
|
return geometry;
|
|
@@ -839,9 +1117,12 @@
|
|
|
839
1117
|
const positions = new Float32Array(size * 3);
|
|
840
1118
|
let currentIndex = 0;
|
|
841
1119
|
let computeNormals = false;
|
|
1120
|
+
const useGroups = (mesh.totcol || 0) > 1;
|
|
1121
|
+
const groupRuns = [];
|
|
842
1122
|
for (const face of faces) {
|
|
843
1123
|
const len = face.totloop;
|
|
844
1124
|
const start = face.loopstart;
|
|
1125
|
+
const faceStartIndex = currentIndex;
|
|
845
1126
|
let indexi = 1;
|
|
846
1127
|
while (indexi < len) {
|
|
847
1128
|
let index = 0;
|
|
@@ -873,34 +1154,297 @@
|
|
|
873
1154
|
}
|
|
874
1155
|
indexi += 2;
|
|
875
1156
|
}
|
|
1157
|
+
if (useGroups) mergeGroupRun(groupRuns, faceStartIndex, currentIndex - faceStartIndex, face.mat_nr || 0);
|
|
876
1158
|
}
|
|
877
1159
|
geometry.setAttribute("position", new ctx.BufferAttribute(positions, 3));
|
|
878
1160
|
geometry.setIndex(new ctx.BufferAttribute(indices, 1));
|
|
879
1161
|
geometry.setAttribute("normal", new ctx.BufferAttribute(normals, 3));
|
|
880
1162
|
geometry.setAttribute("uv", new ctx.BufferAttribute(uvs, 2));
|
|
1163
|
+
if (useGroups && groupRuns.length)
|
|
1164
|
+
for (const g of groupRuns) geometry.addGroup(g.start, g.count, g.mat);
|
|
881
1165
|
if (computeNormals) {
|
|
882
1166
|
geometry.computeVertexNormals();
|
|
883
1167
|
}
|
|
884
1168
|
return geometry;
|
|
885
1169
|
}
|
|
1170
|
+
const MA_BL_CULL_BACKFACE = 1 << 2;
|
|
1171
|
+
const MA_BM_CLIP = 3;
|
|
1172
|
+
function listBaseToArray(lb) {
|
|
1173
|
+
const out = [];
|
|
1174
|
+
if (!lb) return out;
|
|
1175
|
+
let n = lb.first, guard = 0;
|
|
1176
|
+
while (n && guard++ < 8192) {
|
|
1177
|
+
out.push(n);
|
|
1178
|
+
n = n.next;
|
|
1179
|
+
}
|
|
1180
|
+
return out;
|
|
1181
|
+
}
|
|
1182
|
+
const idnameOf = (n) => n && typeof n.idname === "string" ? n.idname : "";
|
|
1183
|
+
const nameOf = (s) => s && typeof s.name === "string" ? s.name : "";
|
|
1184
|
+
function socketByName(sockets, ...names) {
|
|
1185
|
+
for (const name of names) {
|
|
1186
|
+
const s = sockets.find((x) => nameOf(x) === name);
|
|
1187
|
+
if (s) return s;
|
|
1188
|
+
}
|
|
1189
|
+
return null;
|
|
1190
|
+
}
|
|
1191
|
+
function inputsOf(node) {
|
|
1192
|
+
return node ? listBaseToArray(node.inputs) : [];
|
|
1193
|
+
}
|
|
1194
|
+
function socketConst(sock) {
|
|
1195
|
+
const dv = sock && sock.default_value;
|
|
1196
|
+
return dv ? dv.value : void 0;
|
|
1197
|
+
}
|
|
1198
|
+
const num = (v) => typeof v === "number" ? v : void 0;
|
|
1199
|
+
const clamp01 = (c) => Math.max(0, Math.min(1, c));
|
|
1200
|
+
function nodeFeeding(links, socket) {
|
|
1201
|
+
if (!socket) return null;
|
|
1202
|
+
let link = links.find((l) => l.tosock === socket);
|
|
1203
|
+
let guard = 0;
|
|
1204
|
+
while (link && idnameOf(link.fromnode).includes("Reroute") && guard++ < 32) {
|
|
1205
|
+
const re = inputsOf(link.fromnode)[0];
|
|
1206
|
+
link = links.find((l) => l.tosock === re);
|
|
1207
|
+
}
|
|
1208
|
+
return link ? link.fromnode : null;
|
|
1209
|
+
}
|
|
1210
|
+
function imageMime(b) {
|
|
1211
|
+
if (b[0] === 137 && b[1] === 80 && b[2] === 78 && b[3] === 71) return "image/png";
|
|
1212
|
+
if (b[0] === 255 && b[1] === 216 && b[2] === 255) return "image/jpeg";
|
|
1213
|
+
if (b[0] === 66 && b[1] === 77) return "image/bmp";
|
|
1214
|
+
if (b[0] === 82 && b[1] === 73 && b[2] === 70 && b[3] === 70 && b[8] === 87 && b[9] === 69) return "image/webp";
|
|
1215
|
+
return null;
|
|
1216
|
+
}
|
|
1217
|
+
function packedTexture(imageNode, srgb) {
|
|
1218
|
+
const img = imageNode && imageNode.id;
|
|
1219
|
+
if (!img) return null;
|
|
1220
|
+
const pf = img.packedfile || img.packedfiles && img.packedfiles.first && img.packedfiles.first.packedfile;
|
|
1221
|
+
const block = pf && pf.data;
|
|
1222
|
+
const size = pf && typeof pf.size === "number" ? pf.size : 0;
|
|
1223
|
+
if (!block || block.__data_address__ === void 0 || size <= 0) return null;
|
|
1224
|
+
const buf = block.__blender_file__.byte.buffer;
|
|
1225
|
+
if (block.__data_address__ + size > buf.byteLength) return null;
|
|
1226
|
+
const bytes = new Uint8Array(buf, block.__data_address__, size).slice();
|
|
1227
|
+
const mime = imageMime(bytes);
|
|
1228
|
+
if (!mime || typeof Blob === "undefined" || typeof URL === "undefined" || typeof Image === "undefined") return null;
|
|
1229
|
+
const url = URL.createObjectURL(new Blob([bytes], { type: mime }));
|
|
1230
|
+
const el = new Image();
|
|
1231
|
+
const texture = new threepipe.Texture(el);
|
|
1232
|
+
if (srgb) texture.colorSpace = threepipe.SRGBColorSpace;
|
|
1233
|
+
texture.name = (typeof img.aname === "string" ? img.aname : "") || "blendTexture";
|
|
1234
|
+
el.onload = () => {
|
|
1235
|
+
texture.needsUpdate = true;
|
|
1236
|
+
URL.revokeObjectURL(url);
|
|
1237
|
+
};
|
|
1238
|
+
el.onerror = () => {
|
|
1239
|
+
URL.revokeObjectURL(url);
|
|
1240
|
+
};
|
|
1241
|
+
el.src = url;
|
|
1242
|
+
return texture;
|
|
1243
|
+
}
|
|
1244
|
+
const IMA_SRC_GENERATED = 4, IMA_SRC_VIEWER = 5;
|
|
1245
|
+
function applyWrap(tex, imageNode) {
|
|
1246
|
+
if (!tex) return tex;
|
|
1247
|
+
const ext = imageNode?.storage?.extension;
|
|
1248
|
+
tex.wrapS = tex.wrapT = ext === 1 || ext === 2 ? threepipe.ClampToEdgeWrapping : ext === 3 ? threepipe.MirroredRepeatWrapping : threepipe.RepeatWrapping;
|
|
1249
|
+
tex.needsUpdate = true;
|
|
1250
|
+
return tex;
|
|
1251
|
+
}
|
|
1252
|
+
function imageNodeTexture(imageNode, srgb, ctx) {
|
|
1253
|
+
const packed = packedTexture(imageNode, srgb);
|
|
1254
|
+
if (packed) return applyWrap(packed, imageNode);
|
|
1255
|
+
const img = imageNode && imageNode.id;
|
|
1256
|
+
if (img && img.source !== IMA_SRC_GENERATED && img.source !== IMA_SRC_VIEWER && typeof img.name === "string" && img.name && ctx.loadExternalTexture) {
|
|
1257
|
+
return applyWrap(ctx.loadExternalTexture(img.name, srgb), imageNode);
|
|
1258
|
+
}
|
|
1259
|
+
return null;
|
|
1260
|
+
}
|
|
1261
|
+
function imageNodeFeeding(links, socket) {
|
|
1262
|
+
let src = nodeFeeding(links, socket);
|
|
1263
|
+
if (src && idnameOf(src).includes("NormalMap")) src = nodeFeeding(links, socketByName(inputsOf(src), "Color"));
|
|
1264
|
+
return src && idnameOf(src).includes("TexImage") ? src : null;
|
|
1265
|
+
}
|
|
1266
|
+
function textureFromSocket(links, socket, srgb, ctx) {
|
|
1267
|
+
const src = imageNodeFeeding(links, socket);
|
|
1268
|
+
return src ? imageNodeTexture(src, srgb, ctx) : null;
|
|
1269
|
+
}
|
|
1270
|
+
function resolveShaders(nodes, links) {
|
|
1271
|
+
const outputs = nodes.filter((n) => idnameOf(n).includes("OutputMaterial"));
|
|
1272
|
+
const activeOut = outputs.find((n) => n.is_active_output) || outputs[0];
|
|
1273
|
+
let principled = null, emission = null;
|
|
1274
|
+
if (activeOut) {
|
|
1275
|
+
let surf = nodeFeeding(links, socketByName(inputsOf(activeOut), "Surface"));
|
|
1276
|
+
let guard = 0;
|
|
1277
|
+
while (surf && !idnameOf(surf).includes("BsdfPrincipled") && guard++ < 4) {
|
|
1278
|
+
if (idnameOf(surf).includes("Emission") && !emission) emission = surf;
|
|
1279
|
+
const next = inputsOf(surf).map((s) => nodeFeeding(links, s)).find((n) => n && idnameOf(n).includes("BsdfPrincipled"));
|
|
1280
|
+
if (!next) break;
|
|
1281
|
+
surf = next;
|
|
1282
|
+
}
|
|
1283
|
+
if (surf && idnameOf(surf).includes("BsdfPrincipled")) principled = surf;
|
|
1284
|
+
}
|
|
1285
|
+
if (!principled) principled = nodes.find((n) => idnameOf(n).includes("BsdfPrincipled"));
|
|
1286
|
+
if (!emission) emission = nodes.find((n) => idnameOf(n) === "ShaderNodeEmission");
|
|
1287
|
+
return { principled, emission };
|
|
1288
|
+
}
|
|
886
1289
|
function createMaterial(mat, ctx) {
|
|
887
1290
|
const material = new ctx.MeshPhysicalMaterial();
|
|
888
|
-
material.
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
1291
|
+
material.side = typeof mat.blend_flag === "number" && mat.blend_flag & MA_BL_CULL_BACKFACE ? threepipe.FrontSide : threepipe.DoubleSide;
|
|
1292
|
+
const nodes = mat.nodetree ? listBaseToArray(mat.nodetree.nodes) : [];
|
|
1293
|
+
const links = mat.nodetree ? listBaseToArray(mat.nodetree.links) : [];
|
|
1294
|
+
const { principled, emission } = resolveShaders(nodes, links);
|
|
1295
|
+
let applied = false;
|
|
1296
|
+
if (principled) {
|
|
1297
|
+
const inp = inputsOf(principled);
|
|
1298
|
+
applied = true;
|
|
1299
|
+
const baseSock = socketByName(inp, "Base Color", "BaseColor");
|
|
1300
|
+
const baseImgNode = imageNodeFeeding(links, baseSock);
|
|
1301
|
+
const baseTex = baseImgNode ? imageNodeTexture(baseImgNode, true, ctx) : null;
|
|
1302
|
+
if (baseTex) {
|
|
1303
|
+
material.map = baseTex;
|
|
1304
|
+
material.color.setRGB(1, 1, 1);
|
|
1305
|
+
} else {
|
|
1306
|
+
const base = socketConst(baseSock);
|
|
1307
|
+
if (base && base.length >= 3) material.color.setRGB(clamp01(base[0]), clamp01(base[1]), clamp01(base[2]));
|
|
1308
|
+
}
|
|
1309
|
+
const roughSock = socketByName(inp, "Roughness");
|
|
1310
|
+
const roughTex = textureFromSocket(links, roughSock, false, ctx);
|
|
1311
|
+
if (roughTex) material.roughnessMap = roughTex;
|
|
1312
|
+
else {
|
|
1313
|
+
const r = num(socketConst(roughSock));
|
|
1314
|
+
if (r !== void 0) material.roughness = r;
|
|
1315
|
+
}
|
|
1316
|
+
const metalSock = socketByName(inp, "Metallic");
|
|
1317
|
+
const metalTex = textureFromSocket(links, metalSock, false, ctx);
|
|
1318
|
+
if (metalTex) {
|
|
1319
|
+
material.metalnessMap = metalTex;
|
|
1320
|
+
material.metalness = 1;
|
|
1321
|
+
} else {
|
|
1322
|
+
const m = num(socketConst(metalSock));
|
|
1323
|
+
if (m !== void 0) material.metalness = m;
|
|
1324
|
+
}
|
|
1325
|
+
const normSrc = nodeFeeding(links, socketByName(inp, "Normal"));
|
|
1326
|
+
if (normSrc) {
|
|
1327
|
+
const normTex = textureFromSocket(links, socketByName(inp, "Normal"), false, ctx);
|
|
1328
|
+
if (normTex) {
|
|
1329
|
+
material.normalMap = normTex;
|
|
1330
|
+
const strength = num(socketConst(socketByName(inputsOf(normSrc), "Strength")));
|
|
1331
|
+
if (strength !== void 0 && material.normalScale) material.normalScale.set(strength, strength);
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
const alphaSock = socketByName(inp, "Alpha");
|
|
1335
|
+
const alphaImgNode = imageNodeFeeding(links, alphaSock);
|
|
1336
|
+
const alphaFromBase = !!(alphaImgNode && baseImgNode && alphaImgNode === baseImgNode);
|
|
1337
|
+
const alphaTex = alphaImgNode && !alphaFromBase ? imageNodeTexture(alphaImgNode, false, ctx) : null;
|
|
1338
|
+
const alphaC = num(socketConst(alphaSock));
|
|
1339
|
+
const hasAlpha = !!alphaTex || alphaFromBase || alphaC !== void 0 && alphaC < 1;
|
|
1340
|
+
if (alphaTex) material.alphaMap = alphaTex;
|
|
1341
|
+
else if (!alphaFromBase && alphaC !== void 0 && alphaC < 1) material.opacity = alphaC;
|
|
1342
|
+
if (hasAlpha) {
|
|
1343
|
+
if (mat.blend_method === MA_BM_CLIP) {
|
|
1344
|
+
const thr = num(mat.alpha_threshold);
|
|
1345
|
+
material.alphaTest = thr !== void 0 && thr > 0 ? thr : 0.5;
|
|
1346
|
+
} else material.transparent = true;
|
|
1347
|
+
}
|
|
1348
|
+
const ior = num(socketConst(socketByName(inp, "IOR")));
|
|
1349
|
+
if (ior !== void 0 && material.ior !== void 0) material.ior = ior;
|
|
1350
|
+
const trans = num(socketConst(socketByName(inp, "Transmission Weight", "Transmission")));
|
|
1351
|
+
if (trans !== void 0 && trans > 0 && material.transmission !== void 0) {
|
|
1352
|
+
material.transmission = trans;
|
|
1353
|
+
}
|
|
1354
|
+
const coat = num(socketConst(socketByName(inp, "Coat Weight", "Clearcoat")));
|
|
1355
|
+
if (coat !== void 0 && coat > 0 && material.clearcoat !== void 0) {
|
|
1356
|
+
material.clearcoat = coat;
|
|
1357
|
+
const cr = num(socketConst(socketByName(inp, "Coat Roughness", "Clearcoat Roughness")));
|
|
1358
|
+
if (cr !== void 0) material.clearcoatRoughness = cr;
|
|
1359
|
+
}
|
|
1360
|
+
const sheen = num(socketConst(socketByName(inp, "Sheen Weight", "Sheen")));
|
|
1361
|
+
if (sheen !== void 0 && sheen > 0 && material.sheen !== void 0) {
|
|
1362
|
+
material.sheen = sheen;
|
|
1363
|
+
const stint = socketConst(socketByName(inp, "Sheen Tint"));
|
|
1364
|
+
if (stint && stint.length >= 3 && material.sheenColor) material.sheenColor.setRGB(stint[0], stint[1], stint[2]);
|
|
1365
|
+
const sr = num(socketConst(socketByName(inp, "Sheen Roughness")));
|
|
1366
|
+
if (sr !== void 0) material.sheenRoughness = sr;
|
|
1367
|
+
}
|
|
1368
|
+
const spec = num(socketConst(socketByName(inp, "Specular IOR Level", "Specular")));
|
|
1369
|
+
if (spec !== void 0 && material.specularIntensity !== void 0) {
|
|
1370
|
+
material.specularIntensity = Math.min(1, spec * 2);
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
const matOutput = nodes.find((n) => idnameOf(n).includes("OutputMaterial") && n.is_active_output) || nodes.find((n) => idnameOf(n).includes("OutputMaterial"));
|
|
1374
|
+
const dispNode = matOutput ? nodeFeeding(links, socketByName(inputsOf(matOutput), "Displacement")) : null;
|
|
1375
|
+
if (dispNode && idnameOf(dispNode).includes("Displacement")) {
|
|
1376
|
+
const heightTex = textureFromSocket(links, socketByName(inputsOf(dispNode), "Height"), false, ctx);
|
|
1377
|
+
if (heightTex) {
|
|
1378
|
+
const scale = num(socketConst(socketByName(inputsOf(dispNode), "Scale")));
|
|
1379
|
+
const s = scale !== void 0 && scale > 0 ? scale : 1;
|
|
1380
|
+
const mid = num(socketConst(socketByName(inputsOf(dispNode), "Midlevel")));
|
|
1381
|
+
if (material.displacementMap !== void 0) {
|
|
1382
|
+
material.displacementMap = heightTex;
|
|
1383
|
+
material.displacementScale = s;
|
|
1384
|
+
material.displacementBias = -(mid ?? 0.5) * s;
|
|
1385
|
+
}
|
|
1386
|
+
if (!material.normalMap && material.bumpMap !== void 0) {
|
|
1387
|
+
material.bumpMap = heightTex;
|
|
1388
|
+
material.bumpScale = s;
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
const emSock = emission ? socketByName(inputsOf(emission), "Color") : principled ? socketByName(inputsOf(principled), "Emission Color", "Emission") : null;
|
|
1393
|
+
const emStrSock = emission ? socketByName(inputsOf(emission), "Strength") : principled ? socketByName(inputsOf(principled), "Emission Strength") : null;
|
|
1394
|
+
const emTex = textureFromSocket(links, emSock, true, ctx);
|
|
1395
|
+
if (emTex) material.emissiveMap = emTex;
|
|
1396
|
+
let emCol = socketConst(emSock);
|
|
1397
|
+
if (emTex && (!emCol || emCol.length < 3 || !emCol[0] && !emCol[1] && !emCol[2])) emCol = [1, 1, 1];
|
|
1398
|
+
if (emCol && emCol.length >= 3 && (emCol[0] || emCol[1] || emCol[2] || emTex)) {
|
|
1399
|
+
const f = [emCol[0], emCol[1], emCol[2]];
|
|
1400
|
+
const strength = num(socketConst(emStrSock));
|
|
1401
|
+
if (typeof strength === "number") for (let i = 0; i < 3; i++) f[i] *= strength;
|
|
1402
|
+
const peak = Math.max(f[0], f[1], f[2]);
|
|
1403
|
+
if (peak > 1) {
|
|
1404
|
+
material.emissiveIntensity = peak;
|
|
1405
|
+
material.emissive.setRGB(f[0] / peak, f[1] / peak, f[2] / peak);
|
|
1406
|
+
} else material.emissive.setRGB(f[0], f[1], f[2]);
|
|
1407
|
+
}
|
|
1408
|
+
if (!applied) {
|
|
1409
|
+
if (mat.r !== void 0) material.color.setRGB(mat.r, mat.g, mat.b);
|
|
1410
|
+
material.roughness = mat.roughness !== void 0 ? mat.roughness : 0.4;
|
|
1411
|
+
material.metalness = mat.metallic !== void 0 ? mat.metallic : 0;
|
|
1412
|
+
}
|
|
893
1413
|
return material;
|
|
894
1414
|
}
|
|
895
1415
|
function createMesh(object, loaded, ctx) {
|
|
896
1416
|
if (!object.data) {
|
|
897
1417
|
return void 0;
|
|
898
1418
|
}
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
1419
|
+
let geometry = loaded.get(object.data);
|
|
1420
|
+
if (!geometry) {
|
|
1421
|
+
geometry = createBufferGeometry(object.data, ctx);
|
|
1422
|
+
loaded.set(object.data, geometry);
|
|
1423
|
+
}
|
|
1424
|
+
const matData = object.data.mat;
|
|
1425
|
+
const slots = Array.isArray(matData) ? matData : matData ? [matData] : [];
|
|
1426
|
+
const buildMaterial = (m) => {
|
|
1427
|
+
if (!m) {
|
|
1428
|
+
const d = new ctx.MeshPhysicalMaterial();
|
|
1429
|
+
d.side = threepipe.DoubleSide;
|
|
1430
|
+
return d;
|
|
1431
|
+
}
|
|
1432
|
+
const cached = loaded.get(m);
|
|
1433
|
+
if (cached) return cached;
|
|
1434
|
+
const created = createMaterial(m, ctx);
|
|
1435
|
+
loaded.set(m, created);
|
|
1436
|
+
return created;
|
|
1437
|
+
};
|
|
1438
|
+
const hasGroups = !!(geometry.groups && geometry.groups.length);
|
|
1439
|
+
let material;
|
|
1440
|
+
if (hasGroups) {
|
|
1441
|
+
material = slots.map(buildMaterial);
|
|
1442
|
+
let maxIdx = 0;
|
|
1443
|
+
for (const g of geometry.groups) if (g.materialIndex > maxIdx) maxIdx = g.materialIndex;
|
|
1444
|
+
while (material.length <= maxIdx) material.push(buildMaterial(null));
|
|
1445
|
+
} else {
|
|
1446
|
+
material = buildMaterial(slots[0]);
|
|
1447
|
+
}
|
|
904
1448
|
const mesh = new ctx.Mesh(geometry, material);
|
|
905
1449
|
mesh.castShadow = true;
|
|
906
1450
|
mesh.receiveShadow = true;
|
|
@@ -1000,25 +1544,743 @@
|
|
|
1000
1544
|
obj.updateMatrix();
|
|
1001
1545
|
if (obj.setDirty) obj.setDirty();
|
|
1002
1546
|
}
|
|
1547
|
+
var ab = ArrayBuffer, u8 = Uint8Array, u16 = Uint16Array, i16 = Int16Array, i32 = Int32Array;
|
|
1548
|
+
var slc = function(v, s, e) {
|
|
1549
|
+
if (u8.prototype.slice)
|
|
1550
|
+
return u8.prototype.slice.call(v, s, e);
|
|
1551
|
+
if (s == null || s < 0)
|
|
1552
|
+
s = 0;
|
|
1553
|
+
if (e == null || e > v.length)
|
|
1554
|
+
e = v.length;
|
|
1555
|
+
var n = new u8(e - s);
|
|
1556
|
+
n.set(v.subarray(s, e));
|
|
1557
|
+
return n;
|
|
1558
|
+
};
|
|
1559
|
+
var fill = function(v, n, s, e) {
|
|
1560
|
+
if (u8.prototype.fill)
|
|
1561
|
+
return u8.prototype.fill.call(v, n, s, e);
|
|
1562
|
+
if (s == null || s < 0)
|
|
1563
|
+
s = 0;
|
|
1564
|
+
if (e == null || e > v.length)
|
|
1565
|
+
e = v.length;
|
|
1566
|
+
for (; s < e; ++s)
|
|
1567
|
+
v[s] = n;
|
|
1568
|
+
return v;
|
|
1569
|
+
};
|
|
1570
|
+
var cpw = function(v, t, s, e) {
|
|
1571
|
+
if (u8.prototype.copyWithin)
|
|
1572
|
+
return u8.prototype.copyWithin.call(v, t, s, e);
|
|
1573
|
+
if (s == null || s < 0)
|
|
1574
|
+
s = 0;
|
|
1575
|
+
if (e == null || e > v.length)
|
|
1576
|
+
e = v.length;
|
|
1577
|
+
while (s < e) {
|
|
1578
|
+
v[t++] = v[s++];
|
|
1579
|
+
}
|
|
1580
|
+
};
|
|
1581
|
+
var ec = [
|
|
1582
|
+
"invalid zstd data",
|
|
1583
|
+
"window size too large (>2046MB)",
|
|
1584
|
+
"invalid block type",
|
|
1585
|
+
"FSE accuracy too high",
|
|
1586
|
+
"match distance too far back",
|
|
1587
|
+
"unexpected EOF"
|
|
1588
|
+
];
|
|
1589
|
+
var err = function(ind, msg, nt) {
|
|
1590
|
+
var e = new Error(msg || ec[ind]);
|
|
1591
|
+
e.code = ind;
|
|
1592
|
+
if (Error.captureStackTrace)
|
|
1593
|
+
Error.captureStackTrace(e, err);
|
|
1594
|
+
if (!nt)
|
|
1595
|
+
throw e;
|
|
1596
|
+
return e;
|
|
1597
|
+
};
|
|
1598
|
+
var rb = function(d, b, n) {
|
|
1599
|
+
var i = 0, o = 0;
|
|
1600
|
+
for (; i < n; ++i)
|
|
1601
|
+
o |= d[b++] << (i << 3);
|
|
1602
|
+
return o;
|
|
1603
|
+
};
|
|
1604
|
+
var b4 = function(d, b) {
|
|
1605
|
+
return (d[b] | d[b + 1] << 8 | d[b + 2] << 16 | d[b + 3] << 24) >>> 0;
|
|
1606
|
+
};
|
|
1607
|
+
var rzfh = function(dat, w) {
|
|
1608
|
+
var n3 = dat[0] | dat[1] << 8 | dat[2] << 16;
|
|
1609
|
+
if (n3 == 3126568 && dat[3] == 253) {
|
|
1610
|
+
var flg = dat[4];
|
|
1611
|
+
var ss = flg >> 5 & 1, cc = flg >> 2 & 1, df = flg & 3, fcf = flg >> 6;
|
|
1612
|
+
if (flg & 8)
|
|
1613
|
+
err(0);
|
|
1614
|
+
var bt = 6 - ss;
|
|
1615
|
+
var db = df == 3 ? 4 : df;
|
|
1616
|
+
var di = rb(dat, bt, db);
|
|
1617
|
+
bt += db;
|
|
1618
|
+
var fsb = fcf ? 1 << fcf : ss;
|
|
1619
|
+
var fss = rb(dat, bt, fsb) + (fcf == 1 && 256);
|
|
1620
|
+
var ws = fss;
|
|
1621
|
+
if (!ss) {
|
|
1622
|
+
var wb = 1 << 10 + (dat[5] >> 3);
|
|
1623
|
+
ws = wb + (wb >> 3) * (dat[5] & 7);
|
|
1624
|
+
}
|
|
1625
|
+
if (ws > 2145386496)
|
|
1626
|
+
err(1);
|
|
1627
|
+
var buf = new u8((w == 1 ? fss || ws : w ? 0 : ws) + 12);
|
|
1628
|
+
buf[0] = 1, buf[4] = 4, buf[8] = 8;
|
|
1629
|
+
return {
|
|
1630
|
+
b: bt + fsb,
|
|
1631
|
+
y: 0,
|
|
1632
|
+
l: 0,
|
|
1633
|
+
d: di,
|
|
1634
|
+
w: w && w != 1 ? w : buf.subarray(12),
|
|
1635
|
+
e: ws,
|
|
1636
|
+
o: new i32(buf.buffer, 0, 3),
|
|
1637
|
+
u: fss,
|
|
1638
|
+
c: cc,
|
|
1639
|
+
m: Math.min(131072, ws)
|
|
1640
|
+
};
|
|
1641
|
+
} else if ((n3 >> 4 | dat[3] << 20) == 25481893) {
|
|
1642
|
+
return b4(dat, 4) + 8;
|
|
1643
|
+
}
|
|
1644
|
+
err(0);
|
|
1645
|
+
};
|
|
1646
|
+
var msb = function(val) {
|
|
1647
|
+
var bits = 0;
|
|
1648
|
+
for (; 1 << bits <= val; ++bits)
|
|
1649
|
+
;
|
|
1650
|
+
return bits - 1;
|
|
1651
|
+
};
|
|
1652
|
+
var rfse = function(dat, bt, mal) {
|
|
1653
|
+
var tpos = (bt << 3) + 4;
|
|
1654
|
+
var al = (dat[bt] & 15) + 5;
|
|
1655
|
+
if (al > mal)
|
|
1656
|
+
err(3);
|
|
1657
|
+
var sz = 1 << al;
|
|
1658
|
+
var probs = sz, sym = -1, re = -1, i = -1, ht = sz;
|
|
1659
|
+
var buf = new ab(512 + (sz << 2));
|
|
1660
|
+
var freq = new i16(buf, 0, 256);
|
|
1661
|
+
var dstate = new u16(buf, 0, 256);
|
|
1662
|
+
var nstate = new u16(buf, 512, sz);
|
|
1663
|
+
var bb1 = 512 + (sz << 1);
|
|
1664
|
+
var syms = new u8(buf, bb1, sz);
|
|
1665
|
+
var nbits = new u8(buf, bb1 + sz);
|
|
1666
|
+
while (sym < 255 && probs > 0) {
|
|
1667
|
+
var bits = msb(probs + 1);
|
|
1668
|
+
var cbt = tpos >> 3;
|
|
1669
|
+
var msk = (1 << bits + 1) - 1;
|
|
1670
|
+
var val = (dat[cbt] | dat[cbt + 1] << 8 | dat[cbt + 2] << 16) >> (tpos & 7) & msk;
|
|
1671
|
+
var msk1fb = (1 << bits) - 1;
|
|
1672
|
+
var msv = msk - probs - 1;
|
|
1673
|
+
var sval = val & msk1fb;
|
|
1674
|
+
if (sval < msv)
|
|
1675
|
+
tpos += bits, val = sval;
|
|
1676
|
+
else {
|
|
1677
|
+
tpos += bits + 1;
|
|
1678
|
+
if (val > msk1fb)
|
|
1679
|
+
val -= msv;
|
|
1680
|
+
}
|
|
1681
|
+
freq[++sym] = --val;
|
|
1682
|
+
if (val == -1) {
|
|
1683
|
+
probs += val;
|
|
1684
|
+
syms[--ht] = sym;
|
|
1685
|
+
} else
|
|
1686
|
+
probs -= val;
|
|
1687
|
+
if (!val) {
|
|
1688
|
+
do {
|
|
1689
|
+
var rbt = tpos >> 3;
|
|
1690
|
+
re = (dat[rbt] | dat[rbt + 1] << 8) >> (tpos & 7) & 3;
|
|
1691
|
+
tpos += 2;
|
|
1692
|
+
sym += re;
|
|
1693
|
+
} while (re == 3);
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
if (sym > 255 || probs)
|
|
1697
|
+
err(0);
|
|
1698
|
+
var sympos = 0;
|
|
1699
|
+
var sstep = (sz >> 1) + (sz >> 3) + 3;
|
|
1700
|
+
var smask = sz - 1;
|
|
1701
|
+
for (var s = 0; s <= sym; ++s) {
|
|
1702
|
+
var sf = freq[s];
|
|
1703
|
+
if (sf < 1) {
|
|
1704
|
+
dstate[s] = -sf;
|
|
1705
|
+
continue;
|
|
1706
|
+
}
|
|
1707
|
+
for (i = 0; i < sf; ++i) {
|
|
1708
|
+
syms[sympos] = s;
|
|
1709
|
+
do {
|
|
1710
|
+
sympos = sympos + sstep & smask;
|
|
1711
|
+
} while (sympos >= ht);
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
if (sympos)
|
|
1715
|
+
err(0);
|
|
1716
|
+
for (i = 0; i < sz; ++i) {
|
|
1717
|
+
var ns = dstate[syms[i]]++;
|
|
1718
|
+
var nb = nbits[i] = al - msb(ns);
|
|
1719
|
+
nstate[i] = (ns << nb) - sz;
|
|
1720
|
+
}
|
|
1721
|
+
return [tpos + 7 >> 3, {
|
|
1722
|
+
b: al,
|
|
1723
|
+
s: syms,
|
|
1724
|
+
n: nbits,
|
|
1725
|
+
t: nstate
|
|
1726
|
+
}];
|
|
1727
|
+
};
|
|
1728
|
+
var rhu = function(dat, bt) {
|
|
1729
|
+
var i = 0, wc = -1;
|
|
1730
|
+
var buf = new u8(292), hb = dat[bt];
|
|
1731
|
+
var hw = buf.subarray(0, 256);
|
|
1732
|
+
var rc = buf.subarray(256, 268);
|
|
1733
|
+
var ri = new u16(buf.buffer, 268);
|
|
1734
|
+
if (hb < 128) {
|
|
1735
|
+
var _a = rfse(dat, bt + 1, 6), ebt = _a[0], fdt = _a[1];
|
|
1736
|
+
bt += hb;
|
|
1737
|
+
var epos = ebt << 3;
|
|
1738
|
+
var lb = dat[bt];
|
|
1739
|
+
if (!lb)
|
|
1740
|
+
err(0);
|
|
1741
|
+
var st1 = 0, st2 = 0, btr1 = fdt.b, btr2 = btr1;
|
|
1742
|
+
var fpos = (++bt << 3) - 8 + msb(lb);
|
|
1743
|
+
for (; ; ) {
|
|
1744
|
+
fpos -= btr1;
|
|
1745
|
+
if (fpos < epos)
|
|
1746
|
+
break;
|
|
1747
|
+
var cbt = fpos >> 3;
|
|
1748
|
+
st1 += (dat[cbt] | dat[cbt + 1] << 8) >> (fpos & 7) & (1 << btr1) - 1;
|
|
1749
|
+
hw[++wc] = fdt.s[st1];
|
|
1750
|
+
fpos -= btr2;
|
|
1751
|
+
if (fpos < epos)
|
|
1752
|
+
break;
|
|
1753
|
+
cbt = fpos >> 3;
|
|
1754
|
+
st2 += (dat[cbt] | dat[cbt + 1] << 8) >> (fpos & 7) & (1 << btr2) - 1;
|
|
1755
|
+
hw[++wc] = fdt.s[st2];
|
|
1756
|
+
btr1 = fdt.n[st1];
|
|
1757
|
+
st1 = fdt.t[st1];
|
|
1758
|
+
btr2 = fdt.n[st2];
|
|
1759
|
+
st2 = fdt.t[st2];
|
|
1760
|
+
}
|
|
1761
|
+
if (++wc > 255)
|
|
1762
|
+
err(0);
|
|
1763
|
+
} else {
|
|
1764
|
+
wc = hb - 127;
|
|
1765
|
+
for (; i < wc; i += 2) {
|
|
1766
|
+
var byte = dat[++bt];
|
|
1767
|
+
hw[i] = byte >> 4;
|
|
1768
|
+
hw[i + 1] = byte & 15;
|
|
1769
|
+
}
|
|
1770
|
+
++bt;
|
|
1771
|
+
}
|
|
1772
|
+
var wes = 0;
|
|
1773
|
+
for (i = 0; i < wc; ++i) {
|
|
1774
|
+
var wt = hw[i];
|
|
1775
|
+
if (wt > 11)
|
|
1776
|
+
err(0);
|
|
1777
|
+
wes += wt && 1 << wt - 1;
|
|
1778
|
+
}
|
|
1779
|
+
var mb = msb(wes) + 1;
|
|
1780
|
+
var ts = 1 << mb;
|
|
1781
|
+
var rem = ts - wes;
|
|
1782
|
+
if (rem & rem - 1)
|
|
1783
|
+
err(0);
|
|
1784
|
+
hw[wc++] = msb(rem) + 1;
|
|
1785
|
+
for (i = 0; i < wc; ++i) {
|
|
1786
|
+
var wt = hw[i];
|
|
1787
|
+
++rc[hw[i] = wt && mb + 1 - wt];
|
|
1788
|
+
}
|
|
1789
|
+
var hbuf = new u8(ts << 1);
|
|
1790
|
+
var syms = hbuf.subarray(0, ts), nb = hbuf.subarray(ts);
|
|
1791
|
+
ri[mb] = 0;
|
|
1792
|
+
for (i = mb; i > 0; --i) {
|
|
1793
|
+
var pv = ri[i];
|
|
1794
|
+
fill(nb, i, pv, ri[i - 1] = pv + rc[i] * (1 << mb - i));
|
|
1795
|
+
}
|
|
1796
|
+
if (ri[0] != ts)
|
|
1797
|
+
err(0);
|
|
1798
|
+
for (i = 0; i < wc; ++i) {
|
|
1799
|
+
var bits = hw[i];
|
|
1800
|
+
if (bits) {
|
|
1801
|
+
var code = ri[bits];
|
|
1802
|
+
fill(syms, i, code, ri[bits] = code + (1 << mb - bits));
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
return [bt, {
|
|
1806
|
+
n: nb,
|
|
1807
|
+
b: mb,
|
|
1808
|
+
s: syms
|
|
1809
|
+
}];
|
|
1810
|
+
};
|
|
1811
|
+
var dllt = rfse(/* @__PURE__ */ new u8([
|
|
1812
|
+
81,
|
|
1813
|
+
16,
|
|
1814
|
+
99,
|
|
1815
|
+
140,
|
|
1816
|
+
49,
|
|
1817
|
+
198,
|
|
1818
|
+
24,
|
|
1819
|
+
99,
|
|
1820
|
+
12,
|
|
1821
|
+
33,
|
|
1822
|
+
196,
|
|
1823
|
+
24,
|
|
1824
|
+
99,
|
|
1825
|
+
102,
|
|
1826
|
+
102,
|
|
1827
|
+
134,
|
|
1828
|
+
70,
|
|
1829
|
+
146,
|
|
1830
|
+
4
|
|
1831
|
+
]), 0, 6)[1];
|
|
1832
|
+
var dmlt = rfse(/* @__PURE__ */ new u8([
|
|
1833
|
+
33,
|
|
1834
|
+
20,
|
|
1835
|
+
196,
|
|
1836
|
+
24,
|
|
1837
|
+
99,
|
|
1838
|
+
140,
|
|
1839
|
+
33,
|
|
1840
|
+
132,
|
|
1841
|
+
16,
|
|
1842
|
+
66,
|
|
1843
|
+
8,
|
|
1844
|
+
33,
|
|
1845
|
+
132,
|
|
1846
|
+
16,
|
|
1847
|
+
66,
|
|
1848
|
+
8,
|
|
1849
|
+
33,
|
|
1850
|
+
68,
|
|
1851
|
+
68,
|
|
1852
|
+
68,
|
|
1853
|
+
68,
|
|
1854
|
+
68,
|
|
1855
|
+
68,
|
|
1856
|
+
68,
|
|
1857
|
+
68,
|
|
1858
|
+
36,
|
|
1859
|
+
9
|
|
1860
|
+
]), 0, 6)[1];
|
|
1861
|
+
var doct = rfse(/* @__PURE__ */ new u8([
|
|
1862
|
+
32,
|
|
1863
|
+
132,
|
|
1864
|
+
16,
|
|
1865
|
+
66,
|
|
1866
|
+
102,
|
|
1867
|
+
70,
|
|
1868
|
+
68,
|
|
1869
|
+
68,
|
|
1870
|
+
68,
|
|
1871
|
+
68,
|
|
1872
|
+
36,
|
|
1873
|
+
73,
|
|
1874
|
+
2
|
|
1875
|
+
]), 0, 5)[1];
|
|
1876
|
+
var b2bl = function(b, s) {
|
|
1877
|
+
var len = b.length, bl = new i32(len);
|
|
1878
|
+
for (var i = 0; i < len; ++i) {
|
|
1879
|
+
bl[i] = s;
|
|
1880
|
+
s += 1 << b[i];
|
|
1881
|
+
}
|
|
1882
|
+
return bl;
|
|
1883
|
+
};
|
|
1884
|
+
var llb = /* @__PURE__ */ new u8((/* @__PURE__ */ new i32([
|
|
1885
|
+
0,
|
|
1886
|
+
0,
|
|
1887
|
+
0,
|
|
1888
|
+
0,
|
|
1889
|
+
16843009,
|
|
1890
|
+
50528770,
|
|
1891
|
+
134678020,
|
|
1892
|
+
202050057,
|
|
1893
|
+
269422093
|
|
1894
|
+
])).buffer, 0, 36);
|
|
1895
|
+
var llbl = /* @__PURE__ */ b2bl(llb, 0);
|
|
1896
|
+
var mlb = /* @__PURE__ */ new u8((/* @__PURE__ */ new i32([
|
|
1897
|
+
0,
|
|
1898
|
+
0,
|
|
1899
|
+
0,
|
|
1900
|
+
0,
|
|
1901
|
+
0,
|
|
1902
|
+
0,
|
|
1903
|
+
0,
|
|
1904
|
+
0,
|
|
1905
|
+
16843009,
|
|
1906
|
+
50528770,
|
|
1907
|
+
117769220,
|
|
1908
|
+
185207048,
|
|
1909
|
+
252579084,
|
|
1910
|
+
16
|
|
1911
|
+
])).buffer, 0, 53);
|
|
1912
|
+
var mlbl = /* @__PURE__ */ b2bl(mlb, 3);
|
|
1913
|
+
var dhu = function(dat, out, hu) {
|
|
1914
|
+
var len = dat.length, ss = out.length, lb = dat[len - 1], msk = (1 << hu.b) - 1, eb = -hu.b;
|
|
1915
|
+
if (!lb)
|
|
1916
|
+
err(0);
|
|
1917
|
+
var st = 0, btr = hu.b, pos = (len << 3) - 8 + msb(lb) - btr, i = -1;
|
|
1918
|
+
for (; pos > eb && i < ss; ) {
|
|
1919
|
+
var cbt = pos >> 3;
|
|
1920
|
+
var val = (dat[cbt] | dat[cbt + 1] << 8 | dat[cbt + 2] << 16) >> (pos & 7);
|
|
1921
|
+
st = (st << btr | val) & msk;
|
|
1922
|
+
out[++i] = hu.s[st];
|
|
1923
|
+
pos -= btr = hu.n[st];
|
|
1924
|
+
}
|
|
1925
|
+
if (pos != eb || i + 1 != ss)
|
|
1926
|
+
err(0);
|
|
1927
|
+
};
|
|
1928
|
+
var dhu4 = function(dat, out, hu) {
|
|
1929
|
+
var bt = 6;
|
|
1930
|
+
var ss = out.length, sz1 = ss + 3 >> 2, sz2 = sz1 << 1, sz3 = sz1 + sz2;
|
|
1931
|
+
dhu(dat.subarray(bt, bt += dat[0] | dat[1] << 8), out.subarray(0, sz1), hu);
|
|
1932
|
+
dhu(dat.subarray(bt, bt += dat[2] | dat[3] << 8), out.subarray(sz1, sz2), hu);
|
|
1933
|
+
dhu(dat.subarray(bt, bt += dat[4] | dat[5] << 8), out.subarray(sz2, sz3), hu);
|
|
1934
|
+
dhu(dat.subarray(bt), out.subarray(sz3), hu);
|
|
1935
|
+
};
|
|
1936
|
+
var rzb = function(dat, st, out) {
|
|
1937
|
+
var _a;
|
|
1938
|
+
var bt = st.b;
|
|
1939
|
+
var b0 = dat[bt], btype = b0 >> 1 & 3;
|
|
1940
|
+
st.l = b0 & 1;
|
|
1941
|
+
var sz = b0 >> 3 | dat[bt + 1] << 5 | dat[bt + 2] << 13;
|
|
1942
|
+
var ebt = (bt += 3) + sz;
|
|
1943
|
+
if (btype == 1) {
|
|
1944
|
+
if (bt >= dat.length)
|
|
1945
|
+
return;
|
|
1946
|
+
st.b = bt + 1;
|
|
1947
|
+
if (out) {
|
|
1948
|
+
fill(out, dat[bt], st.y, st.y += sz);
|
|
1949
|
+
return out;
|
|
1950
|
+
}
|
|
1951
|
+
return fill(new u8(sz), dat[bt]);
|
|
1952
|
+
}
|
|
1953
|
+
if (ebt > dat.length)
|
|
1954
|
+
return;
|
|
1955
|
+
if (btype == 0) {
|
|
1956
|
+
st.b = ebt;
|
|
1957
|
+
if (out) {
|
|
1958
|
+
out.set(dat.subarray(bt, ebt), st.y);
|
|
1959
|
+
st.y += sz;
|
|
1960
|
+
return out;
|
|
1961
|
+
}
|
|
1962
|
+
return slc(dat, bt, ebt);
|
|
1963
|
+
}
|
|
1964
|
+
if (btype == 2) {
|
|
1965
|
+
var b3 = dat[bt], lbt = b3 & 3, sf = b3 >> 2 & 3;
|
|
1966
|
+
var lss = b3 >> 4, lcs = 0, s4 = 0;
|
|
1967
|
+
if (lbt < 2) {
|
|
1968
|
+
if (sf & 1)
|
|
1969
|
+
lss |= dat[++bt] << 4 | (sf & 2 && dat[++bt] << 12);
|
|
1970
|
+
else
|
|
1971
|
+
lss = b3 >> 3;
|
|
1972
|
+
} else {
|
|
1973
|
+
s4 = sf;
|
|
1974
|
+
if (sf < 2)
|
|
1975
|
+
lss |= (dat[++bt] & 63) << 4, lcs = dat[bt] >> 6 | dat[++bt] << 2;
|
|
1976
|
+
else if (sf == 2)
|
|
1977
|
+
lss |= dat[++bt] << 4 | (dat[++bt] & 3) << 12, lcs = dat[bt] >> 2 | dat[++bt] << 6;
|
|
1978
|
+
else
|
|
1979
|
+
lss |= dat[++bt] << 4 | (dat[++bt] & 63) << 12, lcs = dat[bt] >> 6 | dat[++bt] << 2 | dat[++bt] << 10;
|
|
1980
|
+
}
|
|
1981
|
+
++bt;
|
|
1982
|
+
var buf = out ? out.subarray(st.y, st.y + st.m) : new u8(st.m);
|
|
1983
|
+
var spl = buf.length - lss;
|
|
1984
|
+
if (lbt == 0)
|
|
1985
|
+
buf.set(dat.subarray(bt, bt += lss), spl);
|
|
1986
|
+
else if (lbt == 1)
|
|
1987
|
+
fill(buf, dat[bt++], spl);
|
|
1988
|
+
else {
|
|
1989
|
+
var hu = st.h;
|
|
1990
|
+
if (lbt == 2) {
|
|
1991
|
+
var hud = rhu(dat, bt);
|
|
1992
|
+
lcs += bt - (bt = hud[0]);
|
|
1993
|
+
st.h = hu = hud[1];
|
|
1994
|
+
} else if (!hu)
|
|
1995
|
+
err(0);
|
|
1996
|
+
(s4 ? dhu4 : dhu)(dat.subarray(bt, bt += lcs), buf.subarray(spl), hu);
|
|
1997
|
+
}
|
|
1998
|
+
var ns = dat[bt++];
|
|
1999
|
+
if (ns) {
|
|
2000
|
+
if (ns == 255)
|
|
2001
|
+
ns = (dat[bt++] | dat[bt++] << 8) + 32512;
|
|
2002
|
+
else if (ns > 127)
|
|
2003
|
+
ns = ns - 128 << 8 | dat[bt++];
|
|
2004
|
+
var scm = dat[bt++];
|
|
2005
|
+
if (scm & 3)
|
|
2006
|
+
err(0);
|
|
2007
|
+
var dts = [dmlt, doct, dllt];
|
|
2008
|
+
for (var i = 2; i > -1; --i) {
|
|
2009
|
+
var md = scm >> (i << 1) + 2 & 3;
|
|
2010
|
+
if (md == 1) {
|
|
2011
|
+
var rbuf = new u8([0, 0, dat[bt++]]);
|
|
2012
|
+
dts[i] = {
|
|
2013
|
+
s: rbuf.subarray(2, 3),
|
|
2014
|
+
n: rbuf.subarray(0, 1),
|
|
2015
|
+
t: new u16(rbuf.buffer, 0, 1),
|
|
2016
|
+
b: 0
|
|
2017
|
+
};
|
|
2018
|
+
} else if (md == 2) {
|
|
2019
|
+
_a = rfse(dat, bt, 9 - (i & 1)), bt = _a[0], dts[i] = _a[1];
|
|
2020
|
+
} else if (md == 3) {
|
|
2021
|
+
if (!st.t)
|
|
2022
|
+
err(0);
|
|
2023
|
+
dts[i] = st.t[i];
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
var _b = st.t = dts, mlt = _b[0], oct = _b[1], llt = _b[2];
|
|
2027
|
+
var lb = dat[ebt - 1];
|
|
2028
|
+
if (!lb)
|
|
2029
|
+
err(0);
|
|
2030
|
+
var spos = (ebt << 3) - 8 + msb(lb) - llt.b, cbt = spos >> 3, oubt = 0;
|
|
2031
|
+
var lst = (dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << llt.b) - 1;
|
|
2032
|
+
cbt = (spos -= oct.b) >> 3;
|
|
2033
|
+
var ost = (dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << oct.b) - 1;
|
|
2034
|
+
cbt = (spos -= mlt.b) >> 3;
|
|
2035
|
+
var mst = (dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << mlt.b) - 1;
|
|
2036
|
+
for (++ns; --ns; ) {
|
|
2037
|
+
var llc = llt.s[lst];
|
|
2038
|
+
var lbtr = llt.n[lst];
|
|
2039
|
+
var mlc = mlt.s[mst];
|
|
2040
|
+
var mbtr = mlt.n[mst];
|
|
2041
|
+
var ofc = oct.s[ost];
|
|
2042
|
+
var obtr = oct.n[ost];
|
|
2043
|
+
cbt = (spos -= ofc) >> 3;
|
|
2044
|
+
var ofp = 1 << ofc;
|
|
2045
|
+
var off = ofp + ((dat[cbt] | dat[cbt + 1] << 8 | dat[cbt + 2] << 16 | dat[cbt + 3] << 24) >>> (spos & 7) & ofp - 1);
|
|
2046
|
+
cbt = (spos -= mlb[mlc]) >> 3;
|
|
2047
|
+
var ml = mlbl[mlc] + ((dat[cbt] | dat[cbt + 1] << 8 | dat[cbt + 2] << 16) >> (spos & 7) & (1 << mlb[mlc]) - 1);
|
|
2048
|
+
cbt = (spos -= llb[llc]) >> 3;
|
|
2049
|
+
var ll = llbl[llc] + ((dat[cbt] | dat[cbt + 1] << 8 | dat[cbt + 2] << 16) >> (spos & 7) & (1 << llb[llc]) - 1);
|
|
2050
|
+
cbt = (spos -= lbtr) >> 3;
|
|
2051
|
+
lst = llt.t[lst] + ((dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << lbtr) - 1);
|
|
2052
|
+
cbt = (spos -= mbtr) >> 3;
|
|
2053
|
+
mst = mlt.t[mst] + ((dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << mbtr) - 1);
|
|
2054
|
+
cbt = (spos -= obtr) >> 3;
|
|
2055
|
+
ost = oct.t[ost] + ((dat[cbt] | dat[cbt + 1] << 8) >> (spos & 7) & (1 << obtr) - 1);
|
|
2056
|
+
if (off > 3) {
|
|
2057
|
+
st.o[2] = st.o[1];
|
|
2058
|
+
st.o[1] = st.o[0];
|
|
2059
|
+
st.o[0] = off -= 3;
|
|
2060
|
+
} else {
|
|
2061
|
+
var idx = off - (ll != 0);
|
|
2062
|
+
if (idx) {
|
|
2063
|
+
off = idx == 3 ? st.o[0] - 1 : st.o[idx];
|
|
2064
|
+
if (idx > 1)
|
|
2065
|
+
st.o[2] = st.o[1];
|
|
2066
|
+
st.o[1] = st.o[0];
|
|
2067
|
+
st.o[0] = off;
|
|
2068
|
+
} else
|
|
2069
|
+
off = st.o[0];
|
|
2070
|
+
}
|
|
2071
|
+
for (var i = 0; i < ll; ++i) {
|
|
2072
|
+
buf[oubt + i] = buf[spl + i];
|
|
2073
|
+
}
|
|
2074
|
+
oubt += ll, spl += ll;
|
|
2075
|
+
var stin = oubt - off;
|
|
2076
|
+
if (stin < 0) {
|
|
2077
|
+
var len = -stin;
|
|
2078
|
+
var bs = st.e + stin;
|
|
2079
|
+
if (len > ml)
|
|
2080
|
+
len = ml;
|
|
2081
|
+
for (var i = 0; i < len; ++i) {
|
|
2082
|
+
buf[oubt + i] = st.w[bs + i];
|
|
2083
|
+
}
|
|
2084
|
+
oubt += len, ml -= len, stin = 0;
|
|
2085
|
+
}
|
|
2086
|
+
for (var i = 0; i < ml; ++i) {
|
|
2087
|
+
buf[oubt + i] = buf[stin + i];
|
|
2088
|
+
}
|
|
2089
|
+
oubt += ml;
|
|
2090
|
+
}
|
|
2091
|
+
if (oubt != spl) {
|
|
2092
|
+
while (spl < buf.length) {
|
|
2093
|
+
buf[oubt++] = buf[spl++];
|
|
2094
|
+
}
|
|
2095
|
+
} else
|
|
2096
|
+
oubt = buf.length;
|
|
2097
|
+
if (out)
|
|
2098
|
+
st.y += oubt;
|
|
2099
|
+
else
|
|
2100
|
+
buf = slc(buf, 0, oubt);
|
|
2101
|
+
} else if (out) {
|
|
2102
|
+
st.y += lss;
|
|
2103
|
+
if (spl) {
|
|
2104
|
+
for (var i = 0; i < lss; ++i) {
|
|
2105
|
+
buf[i] = buf[spl + i];
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
} else if (spl)
|
|
2109
|
+
buf = slc(buf, spl);
|
|
2110
|
+
st.b = ebt;
|
|
2111
|
+
return buf;
|
|
2112
|
+
}
|
|
2113
|
+
err(2);
|
|
2114
|
+
};
|
|
2115
|
+
var cct = function(bufs, ol) {
|
|
2116
|
+
if (bufs.length == 1)
|
|
2117
|
+
return bufs[0];
|
|
2118
|
+
var buf = new u8(ol);
|
|
2119
|
+
for (var i = 0, b = 0; i < bufs.length; ++i) {
|
|
2120
|
+
var chk = bufs[i];
|
|
2121
|
+
buf.set(chk, b);
|
|
2122
|
+
b += chk.length;
|
|
2123
|
+
}
|
|
2124
|
+
return buf;
|
|
2125
|
+
};
|
|
2126
|
+
function decompress(dat, buf) {
|
|
2127
|
+
var bufs = [], nb = +!buf;
|
|
2128
|
+
var bt = 0, ol = 0;
|
|
2129
|
+
for (; dat.length; ) {
|
|
2130
|
+
var st = rzfh(dat, nb || buf);
|
|
2131
|
+
if (typeof st == "object") {
|
|
2132
|
+
if (nb) {
|
|
2133
|
+
buf = null;
|
|
2134
|
+
if (st.w.length == st.u) {
|
|
2135
|
+
bufs.push(buf = st.w);
|
|
2136
|
+
ol += st.u;
|
|
2137
|
+
}
|
|
2138
|
+
} else {
|
|
2139
|
+
bufs.push(buf);
|
|
2140
|
+
st.e = 0;
|
|
2141
|
+
}
|
|
2142
|
+
for (; !st.l; ) {
|
|
2143
|
+
var blk = rzb(dat, st, buf);
|
|
2144
|
+
if (!blk)
|
|
2145
|
+
err(5);
|
|
2146
|
+
if (buf)
|
|
2147
|
+
st.e = st.y;
|
|
2148
|
+
else {
|
|
2149
|
+
bufs.push(blk);
|
|
2150
|
+
ol += blk.length;
|
|
2151
|
+
cpw(st.w, 0, blk.length);
|
|
2152
|
+
st.w.set(blk, st.w.length - blk.length);
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
bt = st.b + st.c * 4;
|
|
2156
|
+
} else
|
|
2157
|
+
bt = st;
|
|
2158
|
+
dat = dat.subarray(bt);
|
|
2159
|
+
}
|
|
2160
|
+
return cct(bufs, ol);
|
|
2161
|
+
}
|
|
2162
|
+
function detectBlendCompression(u82) {
|
|
2163
|
+
if (u82.length >= 3 && u82[0] === 31 && u82[1] === 139 && u82[2] === 8) return "gzip";
|
|
2164
|
+
if (u82.length >= 4) {
|
|
2165
|
+
if (u82[0] === 40 && u82[1] === 181 && u82[2] === 47 && u82[3] === 253) return "zstd";
|
|
2166
|
+
if ((u82[0] & 240) === 80 && u82[1] === 42 && u82[2] === 77 && u82[3] === 24) return "zstd";
|
|
2167
|
+
}
|
|
2168
|
+
if (u82.length >= 7 && u82[0] === 66 && u82[1] === 76 && u82[2] === 69 && u82[3] === 78 && u82[4] === 68 && u82[5] === 69 && u82[6] === 82) return "none";
|
|
2169
|
+
return "unknown";
|
|
2170
|
+
}
|
|
2171
|
+
function toArrayBuffer(u82) {
|
|
2172
|
+
if (u82.byteOffset === 0 && u82.byteLength === u82.buffer.byteLength) return u82.buffer;
|
|
2173
|
+
return u82.buffer.slice(u82.byteOffset, u82.byteOffset + u82.byteLength);
|
|
2174
|
+
}
|
|
2175
|
+
function decompressBlend(buf) {
|
|
2176
|
+
const u82 = new Uint8Array(buf);
|
|
2177
|
+
const kind = detectBlendCompression(u82);
|
|
2178
|
+
if (kind === "none") return buf;
|
|
2179
|
+
let out;
|
|
2180
|
+
if (kind === "gzip") out = toArrayBuffer(threepipe.gunzipSync(u82));
|
|
2181
|
+
else if (kind === "zstd") out = toArrayBuffer(decompress(u82));
|
|
2182
|
+
else {
|
|
2183
|
+
const hex = [u82[0], u82[1], u82[2], u82[3]].map((b) => (b ?? 0).toString(16).padStart(2, "0")).join(" ");
|
|
2184
|
+
throw new Error(`BlendLoadPlugin: unrecognised file magic (first 4 bytes: ${hex}). Expected 'BLENDER' literal, gzip, or zstd.`);
|
|
2185
|
+
}
|
|
2186
|
+
if (out.byteLength < 12) {
|
|
2187
|
+
throw new Error(`BlendLoadPlugin: ${kind} decompression produced ${out.byteLength} bytes, too short to be a valid .blend file.`);
|
|
2188
|
+
}
|
|
2189
|
+
return out;
|
|
2190
|
+
}
|
|
2191
|
+
function resolveExternalTexture(blenderPath, srgb, importer, blendUrl) {
|
|
2192
|
+
if (typeof document === "undefined") return null;
|
|
2193
|
+
const path = blenderPath.replace(/^\/\//, "").replace(/\\/g, "/").replace(/^\.\//, "");
|
|
2194
|
+
if (!path) return null;
|
|
2195
|
+
let url = importer.resolveURL(path);
|
|
2196
|
+
if (url === path && !/^([a-z][a-z0-9+.-]*:|\/|blob:|data:)/i.test(url)) {
|
|
2197
|
+
url = blendUrl.replace(/[?#].*$/, "").replace(/[^/]*$/, "") + path;
|
|
2198
|
+
}
|
|
2199
|
+
const isData = /\.(exr|hdr|rgbe)$/i.test(path.split(/[?#]/)[0]);
|
|
2200
|
+
let texture;
|
|
2201
|
+
if (isData) {
|
|
2202
|
+
texture = new threepipe.DataTexture(new Uint8Array([255, 255, 255, 255]), 1, 1);
|
|
2203
|
+
} else {
|
|
2204
|
+
const canvas = document.createElement("canvas");
|
|
2205
|
+
canvas.width = canvas.height = 1;
|
|
2206
|
+
const c2d = canvas.getContext("2d");
|
|
2207
|
+
if (c2d) {
|
|
2208
|
+
c2d.fillStyle = "#ffffff";
|
|
2209
|
+
c2d.fillRect(0, 0, 1, 1);
|
|
2210
|
+
}
|
|
2211
|
+
texture = new threepipe.Texture(canvas);
|
|
2212
|
+
}
|
|
2213
|
+
texture.needsUpdate = true;
|
|
2214
|
+
if (srgb) texture.colorSpace = threepipe.SRGBColorSpace;
|
|
2215
|
+
return { texture, url, srgb, path };
|
|
2216
|
+
}
|
|
2217
|
+
function flipDataTextureRowsY(tex) {
|
|
2218
|
+
const img = tex.image;
|
|
2219
|
+
const data = img?.data;
|
|
2220
|
+
if (!data?.length || !img.width || !img.height) return;
|
|
2221
|
+
const { width, height } = img;
|
|
2222
|
+
const elemsPerRow = data.length / height;
|
|
2223
|
+
if (!Number.isInteger(elemsPerRow)) return;
|
|
2224
|
+
const flipped = new data.constructor(data.length);
|
|
2225
|
+
for (let y = 0; y < height; y++) {
|
|
2226
|
+
flipped.set(data.subarray(y * elemsPerRow, (y + 1) * elemsPerRow), (height - 1 - y) * elemsPerRow);
|
|
2227
|
+
}
|
|
2228
|
+
const newImage = { data: flipped, width, height };
|
|
2229
|
+
tex.image = newImage;
|
|
2230
|
+
tex.source = new threepipe.Source(newImage);
|
|
2231
|
+
tex.needsUpdate = true;
|
|
2232
|
+
}
|
|
2233
|
+
async function importExternalTexture(req, importer) {
|
|
2234
|
+
try {
|
|
2235
|
+
const imported = await importer.importSingle(req.url);
|
|
2236
|
+
if (imported && imported.isTexture && imported.image) {
|
|
2237
|
+
const wrapS = req.texture.wrapS, wrapT = req.texture.wrapT;
|
|
2238
|
+
req.texture.copy(imported);
|
|
2239
|
+
req.texture.wrapS = wrapS;
|
|
2240
|
+
req.texture.wrapT = wrapT;
|
|
2241
|
+
req.texture.colorSpace = req.srgb ? threepipe.SRGBColorSpace : imported.colorSpace;
|
|
2242
|
+
if (imported.isDataTexture && imported.flipY === false) flipDataTextureRowsY(req.texture);
|
|
2243
|
+
req.texture.needsUpdate = true;
|
|
2244
|
+
} else {
|
|
2245
|
+
console.warn("BlendLoadPlugin - external texture not found/unsupported:", req.path);
|
|
2246
|
+
}
|
|
2247
|
+
} catch (e) {
|
|
2248
|
+
console.warn("BlendLoadPlugin - external texture failed:", req.path, e);
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
1003
2251
|
const _BlendLoadPlugin = class _BlendLoadPlugin extends threepipe.BaseImporterPlugin {
|
|
1004
2252
|
constructor() {
|
|
1005
2253
|
super();
|
|
1006
2254
|
this._importer = new threepipe.Importer(class extends threepipe.FileLoader {
|
|
1007
2255
|
async loadAsync(url, onProgress) {
|
|
1008
2256
|
this.setResponseType("arraybuffer");
|
|
1009
|
-
|
|
1010
|
-
const
|
|
2257
|
+
let res = await super.loadAsync(url, onProgress);
|
|
2258
|
+
const decompressed = decompressBlend(res);
|
|
2259
|
+
res = null;
|
|
2260
|
+
const blend = await parseBlend(decompressed);
|
|
2261
|
+
const importer = this.assetImporter;
|
|
2262
|
+
const texReqs = [];
|
|
1011
2263
|
const ctx = {
|
|
1012
2264
|
Object3D: threepipe.Object3D2,
|
|
1013
2265
|
Mesh: threepipe.Mesh2,
|
|
1014
2266
|
MeshPhysicalMaterial: threepipe.PhysicalMaterial,
|
|
2267
|
+
MeshBasicMaterial: threepipe.UnlitMaterial,
|
|
1015
2268
|
PerspectiveCamera: threepipe.PerspectiveCamera0,
|
|
1016
2269
|
OrthographicCamera: threepipe.OrthographicCamera0,
|
|
1017
2270
|
PointLight: threepipe.PointLight2,
|
|
2271
|
+
DirectionalLight: threepipe.DirectionalLight2,
|
|
2272
|
+
SpotLight: threepipe.SpotLight2,
|
|
2273
|
+
AmbientLight: threepipe.AmbientLight2,
|
|
1018
2274
|
BufferGeometry: threepipe.BufferGeometry2,
|
|
1019
|
-
BufferAttribute: threepipe.BufferAttribute
|
|
2275
|
+
BufferAttribute: threepipe.BufferAttribute,
|
|
2276
|
+
loadExternalTexture: importer ? (p, srgb) => {
|
|
2277
|
+
const req = resolveExternalTexture(p, srgb, importer, url);
|
|
2278
|
+
if (req) texReqs.push(req);
|
|
2279
|
+
return req ? req.texture : null;
|
|
2280
|
+
} : void 0
|
|
1020
2281
|
};
|
|
1021
2282
|
const objects = await createObjects(blend, ctx);
|
|
2283
|
+
if (importer && texReqs.length) await Promise.all(texReqs.map((r) => importExternalTexture(r, importer)));
|
|
1022
2284
|
const root = new threepipe.Object3D();
|
|
1023
2285
|
root.add(...objects);
|
|
1024
2286
|
blend.scene = root;
|
|
@@ -1030,12 +2292,15 @@
|
|
|
1030
2292
|
}
|
|
1031
2293
|
return res.scene;
|
|
1032
2294
|
}
|
|
1033
|
-
}, ["blend"], ["application/x-blender"], true)
|
|
2295
|
+
}, ["blend"], ["application/x-blender"], true, (loader, assetImporter) => {
|
|
2296
|
+
if (loader) loader.assetImporter = assetImporter;
|
|
2297
|
+
return loader;
|
|
2298
|
+
});
|
|
1034
2299
|
}
|
|
1035
2300
|
};
|
|
1036
2301
|
_BlendLoadPlugin.PluginType = "BlendLoadPlugin";
|
|
1037
2302
|
let BlendLoadPlugin = _BlendLoadPlugin;
|
|
1038
2303
|
exports2.BlendLoadPlugin = BlendLoadPlugin;
|
|
1039
2304
|
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
|
|
1040
|
-
});
|
|
2305
|
+
}));
|
|
1041
2306
|
//# sourceMappingURL=index.js.map
|