@threepipe/plugin-blend-importer 0.0.2 → 0.0.4
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/dist/BlendLoadPlugin.d.ts +10 -10
- package/dist/BlendLoadPlugin.d.ts.map +1 -1
- package/dist/index.js +689 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +677 -5
- package/dist/index.mjs.map +1 -1
- package/dist/js-blend/main.d.ts +1 -0
- package/dist/loader/geometry.d.ts +1 -1
- package/dist/loader/geometry.d.ts.map +1 -1
- package/dist/loader/index.d.ts +2 -2
- package/dist/loader/index.d.ts.map +1 -1
- package/dist/loader/light.d.ts +1 -1
- package/dist/loader/light.d.ts.map +1 -1
- package/dist/loader/material.d.ts +1 -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/package.json +19 -11
- package/src/loader/index.ts +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,526 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @license
|
|
3
|
-
* @threepipe/plugin-blend-importer v0.0.
|
|
4
|
-
* Copyright 2022-
|
|
3
|
+
* @threepipe/plugin-blend-importer v0.0.4
|
|
4
|
+
* Copyright 2022-2025 repalash <palash@shaders.app>
|
|
5
5
|
* Apache-2.0 License
|
|
6
|
-
* See ./dependencies.txt for bundled third-party dependencies and licenses.
|
|
6
|
+
* See ./dependencies.txt for any bundled third-party dependencies and licenses.
|
|
7
7
|
*/
|
|
8
|
-
import
|
|
8
|
+
import { PointLight, BufferGeometry, BufferAttribute, MeshPhysicalMaterial, Mesh, BaseImporterPlugin, Importer, FileLoader, Object3D } from "threepipe";
|
|
9
|
+
const DNA1 = 826363460;
|
|
10
|
+
const ENDB = 1111772741;
|
|
11
|
+
let worker = null;
|
|
12
|
+
const return_object = {
|
|
13
|
+
loadBlendFromArrayBuffer: function(array_buffer) {
|
|
14
|
+
return_object.ready = false;
|
|
15
|
+
{
|
|
16
|
+
worker.onmessage({
|
|
17
|
+
data: array_buffer
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
// loadBlendFromBlob: function (blob) {
|
|
22
|
+
// FR.onload = function () {
|
|
23
|
+
// return_object.loadBlendFromArrayBuffer(this.result);
|
|
24
|
+
// };
|
|
25
|
+
// FR.readAsArrayBuffer(blob);
|
|
26
|
+
// },
|
|
27
|
+
ready: true,
|
|
28
|
+
onParseReady: function() {
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
function worker_code() {
|
|
32
|
+
let data = null, _data = null, BIG_ENDIAN = false, pointer_size = 0, struct_names = [], offset = 0, current_SDNA_template = null, templates = {}, FILE = null, ERROR = null, AB = null;
|
|
33
|
+
const self = this;
|
|
34
|
+
function parseFile(msg) {
|
|
35
|
+
if (typeof msg.data == "object") {
|
|
36
|
+
AB = null;
|
|
37
|
+
data = null;
|
|
38
|
+
BIG_ENDIAN = false;
|
|
39
|
+
pointer_size = 0;
|
|
40
|
+
struct_names = [];
|
|
41
|
+
offset = 0;
|
|
42
|
+
current_SDNA_template = null;
|
|
43
|
+
_data = msg.data;
|
|
44
|
+
AB = _data.slice();
|
|
45
|
+
data = new DataView(_data);
|
|
46
|
+
FILE = new BLENDER_FILE(AB);
|
|
47
|
+
readFile();
|
|
48
|
+
self.postMessage(FILE, ERROR);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
var BLENDER_FILE = function(AB2) {
|
|
52
|
+
this.AB = AB2;
|
|
53
|
+
this.byte = new Uint8Array(AB2);
|
|
54
|
+
this.dv = new DataView(AB2);
|
|
55
|
+
this.objects = {};
|
|
56
|
+
this.memory_lookup = {}, this.object_array = [];
|
|
57
|
+
this.template = null;
|
|
58
|
+
};
|
|
59
|
+
BLENDER_FILE.prototype = {
|
|
60
|
+
addObject: function(obj) {
|
|
61
|
+
this.object_array.push(obj);
|
|
62
|
+
if (!this.objects[obj.blender_name]) this.objects[obj.blender_name] = [];
|
|
63
|
+
this.objects[obj.blender_name].push(obj);
|
|
64
|
+
},
|
|
65
|
+
getPointer: function(offset2) {
|
|
66
|
+
const pointerLow = this.dv.getUint32(offset2, this.template.endianess);
|
|
67
|
+
if (this.template.pointer_size > 4) {
|
|
68
|
+
const pointerHigh = this.dv.getUint32(offset2 + 4, this.template.endianess);
|
|
69
|
+
if (this.template.endianess) {
|
|
70
|
+
return pointerLow + "l|h" + pointerHigh;
|
|
71
|
+
} else {
|
|
72
|
+
return pointerHigh + "h|l" + pointerLow;
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
return pointerLow;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
self.onmessage = parseFile;
|
|
80
|
+
function float64Prop(offset2, Blender_Array_Length, length) {
|
|
81
|
+
return {
|
|
82
|
+
get: function() {
|
|
83
|
+
return Blender_Array_Length > 1 ? new Float64Array(this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getFloat64(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
84
|
+
},
|
|
85
|
+
set: function(float) {
|
|
86
|
+
if (Blender_Array_Length > 1) ;
|
|
87
|
+
else {
|
|
88
|
+
this.__blender_file__.dv.setFloat64(this.__data_address__ + offset2, float, this.__blender_file__.template.endianess);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function floatProp(offset2, Blender_Array_Length, length) {
|
|
94
|
+
return {
|
|
95
|
+
get: function() {
|
|
96
|
+
return Blender_Array_Length > 1 ? new Float32Array(this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getFloat32(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
97
|
+
},
|
|
98
|
+
set: function(float) {
|
|
99
|
+
if (Blender_Array_Length > 1) ;
|
|
100
|
+
else {
|
|
101
|
+
this.__blender_file__.dv.setFloat32(this.__data_address__ + offset2, float, this.__blender_file__.template.endianess);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function intProp(offset2, Blender_Array_Length, length) {
|
|
107
|
+
return {
|
|
108
|
+
get: function() {
|
|
109
|
+
return Blender_Array_Length > 1 ? new Int32Array(this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getInt32(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
110
|
+
},
|
|
111
|
+
set: function(float) {
|
|
112
|
+
if (Blender_Array_Length > 1) ;
|
|
113
|
+
else {
|
|
114
|
+
this.__blender_file__.dv.setInt32(this.__data_address__ + offset2, float, this.__blender_file__.template.endianess);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function shortProp(offset2, Blender_Array_Length, length) {
|
|
120
|
+
return {
|
|
121
|
+
get: function() {
|
|
122
|
+
return Blender_Array_Length > 1 ? new Int16Array(this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getInt16(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
123
|
+
},
|
|
124
|
+
set: function(float) {
|
|
125
|
+
if (Blender_Array_Length > 1) ;
|
|
126
|
+
else {
|
|
127
|
+
this.__blender_file__.dv.setInt16(this.__data_address__ + offset2, float, this.__blender_file__.template.endianess);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function charProp(offset2, Blender_Array_Length, length) {
|
|
133
|
+
return {
|
|
134
|
+
get: function() {
|
|
135
|
+
if (Blender_Array_Length > 1) {
|
|
136
|
+
let start = this.__data_address__ + offset2;
|
|
137
|
+
let end = start;
|
|
138
|
+
let buffer_guard = 0;
|
|
139
|
+
while (this.__blender_file__.byte[end] != 0 && buffer_guard++ < length) end++;
|
|
140
|
+
return toString(this.__blender_file__.AB, start, end);
|
|
141
|
+
}
|
|
142
|
+
return this.__blender_file__.byte[this.__data_address__ + offset2];
|
|
143
|
+
},
|
|
144
|
+
set: function(byte) {
|
|
145
|
+
if (Blender_Array_Length > 1) {
|
|
146
|
+
const string = byte + "";
|
|
147
|
+
let i = 0;
|
|
148
|
+
const l = string.length;
|
|
149
|
+
while (i < length) {
|
|
150
|
+
if (i < l) {
|
|
151
|
+
this.__blender_file__.byte[this.__data_address__ + offset2 + i] = string.charCodeAt(i) | 0;
|
|
152
|
+
} else {
|
|
153
|
+
this.__blender_file__.byte[this.__data_address__ + offset2 + i] = 0;
|
|
154
|
+
}
|
|
155
|
+
i++;
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
this.__blender_file__.byte[this.__data_address__ + offset2] = byte | 0;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function pointerProp2(offset2) {
|
|
164
|
+
return {
|
|
165
|
+
get: function() {
|
|
166
|
+
let pointer = this.__blender_file__.getPointer(this.__data_address__ + offset2, this.__blender_file__);
|
|
167
|
+
const link = this.__blender_file__.memory_lookup[pointer];
|
|
168
|
+
const results = [];
|
|
169
|
+
if (link) {
|
|
170
|
+
const address = link.__data_address__;
|
|
171
|
+
let j = 0;
|
|
172
|
+
while (true) {
|
|
173
|
+
pointer = this.__blender_file__.getPointer(address + j * 8, this.__blender_file__);
|
|
174
|
+
let obj = this.__blender_file__.memory_lookup[pointer];
|
|
175
|
+
if (!obj) break;
|
|
176
|
+
results.push(obj);
|
|
177
|
+
j++;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return results;
|
|
181
|
+
},
|
|
182
|
+
set: function() {
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function pointerProp(offset2, Blender_Array_Length, length) {
|
|
187
|
+
return {
|
|
188
|
+
get: function() {
|
|
189
|
+
if (Blender_Array_Length > 1) {
|
|
190
|
+
let array = [];
|
|
191
|
+
let j = 0;
|
|
192
|
+
let off = offset2;
|
|
193
|
+
while (j < Blender_Array_Length) {
|
|
194
|
+
let pointer = this.__blender_file__.getPointer(this.__data_address__ + off, this.__blender_file__);
|
|
195
|
+
array.push(this.__blender_file__.memory_lookup[pointer]);
|
|
196
|
+
off += length;
|
|
197
|
+
j++;
|
|
198
|
+
}
|
|
199
|
+
return array;
|
|
200
|
+
} else {
|
|
201
|
+
let pointer = this.__blender_file__.getPointer(this.__data_address__ + offset2, this.__blender_file__);
|
|
202
|
+
return this.__blender_file__.memory_lookup[pointer];
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
set: function() {
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function compileProp(obj, name, type, offset2, array_size, IS_POINTER, pointer_size2, length) {
|
|
210
|
+
if (!IS_POINTER) {
|
|
211
|
+
switch (type) {
|
|
212
|
+
case "double":
|
|
213
|
+
Object.defineProperty(obj, name, float64Prop(offset2, array_size, length >> 3));
|
|
214
|
+
break;
|
|
215
|
+
case "float":
|
|
216
|
+
Object.defineProperty(obj, name, floatProp(offset2, array_size, length >> 2));
|
|
217
|
+
break;
|
|
218
|
+
case "int":
|
|
219
|
+
Object.defineProperty(obj, name, intProp(offset2, array_size, length >> 2));
|
|
220
|
+
break;
|
|
221
|
+
case "short":
|
|
222
|
+
case "ushort":
|
|
223
|
+
Object.defineProperty(obj, name, shortProp(offset2, array_size, length >> 1));
|
|
224
|
+
break;
|
|
225
|
+
case "char":
|
|
226
|
+
case "uchar":
|
|
227
|
+
Object.defineProperty(obj, name, charProp(offset2, array_size, length));
|
|
228
|
+
break;
|
|
229
|
+
default:
|
|
230
|
+
obj[name] = {};
|
|
231
|
+
obj.__list__.push(name, type, length, offset2, array_size, IS_POINTER);
|
|
232
|
+
}
|
|
233
|
+
obj._length += length;
|
|
234
|
+
offset2 += length;
|
|
235
|
+
} else {
|
|
236
|
+
Object.defineProperty(obj, name, pointerProp(offset2, array_size, pointer_size2));
|
|
237
|
+
offset2 += pointer_size2 * array_size;
|
|
238
|
+
}
|
|
239
|
+
return offset2;
|
|
240
|
+
}
|
|
241
|
+
const MASTER_SDNA_SCHEMA = function(version) {
|
|
242
|
+
this.version = version;
|
|
243
|
+
this.SDNA_SET = false;
|
|
244
|
+
this.byte_size = 0;
|
|
245
|
+
this.struct_index = 0;
|
|
246
|
+
this.structs = {};
|
|
247
|
+
this.SDNA = {};
|
|
248
|
+
this.endianess = false;
|
|
249
|
+
};
|
|
250
|
+
MASTER_SDNA_SCHEMA.prototype = {
|
|
251
|
+
getSDNAStructureConstructor: function(name, struct) {
|
|
252
|
+
if (struct) {
|
|
253
|
+
const blen_struct = Function("function " + name + "(){}; return " + name)();
|
|
254
|
+
blen_struct.prototype = new BLENDER_STRUCTURE();
|
|
255
|
+
blen_struct.prototype.blender_name = name;
|
|
256
|
+
blen_struct.prototype.__pointers = [];
|
|
257
|
+
blen_struct.prototype.__list__ = [];
|
|
258
|
+
let offset2 = 0;
|
|
259
|
+
for (let i = 0; i < struct.length; i += 3) {
|
|
260
|
+
let _name = struct[i];
|
|
261
|
+
const n = _name, type = struct[i + 1];
|
|
262
|
+
let length = struct[i + 2], array_length = 0, match = null, Blender_Array_Length = 1, Suparray_match = 1, PointerToArray = false, Pointer_Match = 0;
|
|
263
|
+
const DNA = this.SDNA[name] = {
|
|
264
|
+
constructor: blen_struct
|
|
265
|
+
};
|
|
266
|
+
if (match = _name.match(/(\*?)(\*?)(\w+)(\[(\w*)\])?(\[(\w*)\])?/)) {
|
|
267
|
+
_name = match[3];
|
|
268
|
+
if (match[1]) {
|
|
269
|
+
Pointer_Match = 10;
|
|
270
|
+
blen_struct.prototype.__pointers.push(_name);
|
|
271
|
+
}
|
|
272
|
+
if (match[2]) {
|
|
273
|
+
PointerToArray = true;
|
|
274
|
+
}
|
|
275
|
+
if (match[4]) {
|
|
276
|
+
if (match[6]) {
|
|
277
|
+
Suparray_match = parseInt(match[5]);
|
|
278
|
+
Blender_Array_Length = parseInt(match[7]);
|
|
279
|
+
} else {
|
|
280
|
+
Blender_Array_Length = parseInt(match[5]);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
array_length = Blender_Array_Length * length;
|
|
284
|
+
length = array_length * Suparray_match;
|
|
285
|
+
}
|
|
286
|
+
DNA[n] = {
|
|
287
|
+
type,
|
|
288
|
+
length,
|
|
289
|
+
isArray: Blender_Array_Length > 0
|
|
290
|
+
};
|
|
291
|
+
if (PointerToArray) {
|
|
292
|
+
Object.defineProperty(blen_struct.prototype, _name, pointerProp2(offset2));
|
|
293
|
+
offset2 += pointer_size;
|
|
294
|
+
} else if (Suparray_match > 1) {
|
|
295
|
+
const array_names = new Array(Suparray_match);
|
|
296
|
+
for (let j = 0; j < Suparray_match; j++) {
|
|
297
|
+
let array_name_ = `__${_name}[${j}]__`;
|
|
298
|
+
array_names[j] = array_name_;
|
|
299
|
+
offset2 = compileProp(blen_struct.prototype, array_name_, type, offset2, Blender_Array_Length, Pointer_Match, pointer_size, array_length);
|
|
300
|
+
}
|
|
301
|
+
Object.defineProperty(blen_struct.prototype, _name, {
|
|
302
|
+
get: /* @__PURE__ */ function(array_names2) {
|
|
303
|
+
return function() {
|
|
304
|
+
const array = [];
|
|
305
|
+
for (let i2 = 0; i2 < array_names2.length; i2++) {
|
|
306
|
+
array.push(this[array_names2[i2]]);
|
|
307
|
+
}
|
|
308
|
+
return array;
|
|
309
|
+
};
|
|
310
|
+
}(array_names)
|
|
311
|
+
});
|
|
312
|
+
} else {
|
|
313
|
+
offset2 = compileProp(blen_struct.prototype, _name, type, offset2, Blender_Array_Length, Pointer_Match, pointer_size, length);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return this.SDNA[name].constructor;
|
|
317
|
+
} else {
|
|
318
|
+
if (!this.SDNA[name]) {
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
return this.SDNA[name].constructor;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
var BLENDER_STRUCTURE = function() {
|
|
326
|
+
this.__blender_file__ = null;
|
|
327
|
+
this.__list__ = null;
|
|
328
|
+
this.__super_array_list__ = null;
|
|
329
|
+
this.blender_name = "";
|
|
330
|
+
this.__pointers = null;
|
|
331
|
+
this.address = null;
|
|
332
|
+
this.length = 0;
|
|
333
|
+
this.__data_address__ = 0;
|
|
334
|
+
this.blender_name = "";
|
|
335
|
+
this._length = 0;
|
|
336
|
+
};
|
|
337
|
+
BLENDER_STRUCTURE.prototype = {
|
|
338
|
+
setData: function(pointer, _data_offset, data_block_length, BLENDER_FILE2) {
|
|
339
|
+
if (this.__list__ === null) return this;
|
|
340
|
+
BLENDER_FILE2.addObject(this);
|
|
341
|
+
this.__blender_file__ = BLENDER_FILE2;
|
|
342
|
+
const struct = this.__list__;
|
|
343
|
+
let j = 0, i = 0, name = "", type, length, Blender_Array_Length, offset2, constructor;
|
|
344
|
+
this.__data_address__ = _data_offset;
|
|
345
|
+
if (struct === null) return this;
|
|
346
|
+
for (i = 0; i < struct.length; i += 6) {
|
|
347
|
+
name = struct[i];
|
|
348
|
+
type = struct[i + 1];
|
|
349
|
+
Blender_Array_Length = struct[i + 4];
|
|
350
|
+
struct[i + 5];
|
|
351
|
+
offset2 = this.__data_address__ + struct[i + 3];
|
|
352
|
+
if (Blender_Array_Length > 1) {
|
|
353
|
+
this[name] = [];
|
|
354
|
+
j = 0;
|
|
355
|
+
while (j < Blender_Array_Length) {
|
|
356
|
+
if (current_SDNA_template.getSDNAStructureConstructor(type)) {
|
|
357
|
+
constructor = current_SDNA_template.getSDNAStructureConstructor(type);
|
|
358
|
+
this[name].push(new constructor().setData(0, offset2, offset2 + length / Blender_Array_Length, BLENDER_FILE2));
|
|
359
|
+
} else this[name].push(null);
|
|
360
|
+
offset2 += length / Blender_Array_Length;
|
|
361
|
+
j++;
|
|
362
|
+
}
|
|
363
|
+
} else {
|
|
364
|
+
if (current_SDNA_template.getSDNAStructureConstructor(type)) {
|
|
365
|
+
constructor = current_SDNA_template.getSDNAStructureConstructor(type);
|
|
366
|
+
this[name] = new constructor().setData(0, offset2, length + offset2, BLENDER_FILE2);
|
|
367
|
+
} else this[name] = null;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
this.__list__ = null;
|
|
371
|
+
return this;
|
|
372
|
+
},
|
|
373
|
+
get aname() {
|
|
374
|
+
if (this.id) return this.id.name.slice(2);
|
|
375
|
+
else return void 0;
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
function toString(buffer, _in, _out) {
|
|
379
|
+
return String.fromCharCode.apply(String, new Uint8Array(buffer, _in, _out - _in));
|
|
380
|
+
}
|
|
381
|
+
function readFile() {
|
|
382
|
+
let count = 0;
|
|
383
|
+
let offset2 = 0;
|
|
384
|
+
let data_offset = 0;
|
|
385
|
+
let sdna_index = 0;
|
|
386
|
+
let code = "";
|
|
387
|
+
let block_length = 0;
|
|
388
|
+
let curr_count = 0;
|
|
389
|
+
let curr_count2 = 0;
|
|
390
|
+
FILE.memory_lookup = {};
|
|
391
|
+
struct_names = [];
|
|
392
|
+
offset = 0;
|
|
393
|
+
if (toString(_data, offset, 7) !== "BLENDER") return ERROR = "File supplied is not a .blend compatible Blender file.";
|
|
394
|
+
offset += 7;
|
|
395
|
+
pointer_size = toString(_data, offset++, offset) == "_" ? 4 : 8;
|
|
396
|
+
BIG_ENDIAN = toString(_data, offset++, offset) !== "V";
|
|
397
|
+
const version = toString(_data, offset, offset + 3);
|
|
398
|
+
if (!templates[version]) {
|
|
399
|
+
templates[version] = new MASTER_SDNA_SCHEMA(version);
|
|
400
|
+
}
|
|
401
|
+
current_SDNA_template = templates[version];
|
|
402
|
+
FILE.template = current_SDNA_template;
|
|
403
|
+
offset += 3;
|
|
404
|
+
if (!current_SDNA_template.SDNA_SET) {
|
|
405
|
+
current_SDNA_template.endianess = BIG_ENDIAN;
|
|
406
|
+
current_SDNA_template.pointer_size = pointer_size;
|
|
407
|
+
offset2 = offset;
|
|
408
|
+
while (true) {
|
|
409
|
+
sdna_index = data.getInt32(offset2 + pointer_size + 8, BIG_ENDIAN);
|
|
410
|
+
code = toString(_data, offset2, offset2 + 4).replace(/\u0000/g, "");
|
|
411
|
+
block_length = data.getInt32(offset2 + 4, true);
|
|
412
|
+
offset2 += 16 + pointer_size;
|
|
413
|
+
if (code === "DNA1") {
|
|
414
|
+
count = 0;
|
|
415
|
+
let types = [], names = [], lengths = [], curr_name = "";
|
|
416
|
+
offset2 += 8;
|
|
417
|
+
count = data.getInt32(offset2, true);
|
|
418
|
+
offset2 += 4;
|
|
419
|
+
curr_count = 0;
|
|
420
|
+
while (curr_count < count) {
|
|
421
|
+
curr_name = "";
|
|
422
|
+
while (data.getInt8(offset2) !== 0) {
|
|
423
|
+
curr_name += toString(_data, offset2, offset2 + 1);
|
|
424
|
+
offset2++;
|
|
425
|
+
}
|
|
426
|
+
names.push(curr_name);
|
|
427
|
+
offset2++;
|
|
428
|
+
curr_count++;
|
|
429
|
+
}
|
|
430
|
+
if (offset2 % 4 > 0) offset2 = 4 - offset2 % 4 + offset2;
|
|
431
|
+
offset2 += 4;
|
|
432
|
+
count = data.getInt32(offset2, true);
|
|
433
|
+
offset2 += 4;
|
|
434
|
+
curr_count = 0;
|
|
435
|
+
while (curr_count < count) {
|
|
436
|
+
curr_name = "";
|
|
437
|
+
while (data.getInt8(offset2) !== 0) {
|
|
438
|
+
curr_name += toString(_data, offset2, offset2 + 1);
|
|
439
|
+
offset2++;
|
|
440
|
+
}
|
|
441
|
+
types.push(curr_name);
|
|
442
|
+
offset2++;
|
|
443
|
+
curr_count++;
|
|
444
|
+
}
|
|
445
|
+
if (offset2 % 4 > 0) offset2 = 4 - offset2 % 4 + offset2;
|
|
446
|
+
offset2 += 4;
|
|
447
|
+
curr_count = 0;
|
|
448
|
+
while (curr_count < count) {
|
|
449
|
+
lengths.push(data.getInt16(offset2, BIG_ENDIAN));
|
|
450
|
+
offset2 += 2;
|
|
451
|
+
curr_count++;
|
|
452
|
+
}
|
|
453
|
+
if (offset2 % 4 > 0) offset2 = 4 - offset2 % 4 + offset2;
|
|
454
|
+
offset2 += 4;
|
|
455
|
+
const structure_count = data.getInt32(offset2, BIG_ENDIAN);
|
|
456
|
+
offset2 += 4;
|
|
457
|
+
curr_count = 0;
|
|
458
|
+
while (curr_count < structure_count) {
|
|
459
|
+
const struct_name = types[data.getInt16(offset2, BIG_ENDIAN)];
|
|
460
|
+
offset2 += 2;
|
|
461
|
+
const obj = [];
|
|
462
|
+
count = data.getInt16(offset2, BIG_ENDIAN);
|
|
463
|
+
offset2 += 2;
|
|
464
|
+
curr_count2 = 0;
|
|
465
|
+
struct_names.push(struct_name);
|
|
466
|
+
while (curr_count2 < count) {
|
|
467
|
+
obj.push(names[data.getInt16(offset2 + 2, BIG_ENDIAN)], types[data.getInt16(offset2, BIG_ENDIAN)], lengths[data.getInt16(offset2, BIG_ENDIAN)]);
|
|
468
|
+
offset2 += 4;
|
|
469
|
+
curr_count2++;
|
|
470
|
+
}
|
|
471
|
+
current_SDNA_template.getSDNAStructureConstructor(struct_name, obj);
|
|
472
|
+
curr_count++;
|
|
473
|
+
}
|
|
474
|
+
current_SDNA_template.SDNA_SET = true;
|
|
475
|
+
current_SDNA_template.SDNA_NAMES = struct_names;
|
|
476
|
+
break;
|
|
477
|
+
}
|
|
478
|
+
offset2 += block_length;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
while (true) {
|
|
482
|
+
if (offset % 4 > 0) {
|
|
483
|
+
offset = 4 - offset % 4 + offset;
|
|
484
|
+
}
|
|
485
|
+
data_offset = offset;
|
|
486
|
+
sdna_index = data.getInt32(offset + pointer_size + 8, BIG_ENDIAN);
|
|
487
|
+
let code_uint = data.getUint32(offset, BIG_ENDIAN);
|
|
488
|
+
offset2 = offset + 16 + pointer_size;
|
|
489
|
+
offset += data.getInt32(offset + 4, true) + 16 + pointer_size;
|
|
490
|
+
if (code_uint === DNA1) ;
|
|
491
|
+
else if (code_uint === ENDB) break;
|
|
492
|
+
else {
|
|
493
|
+
const data_start = data_offset + pointer_size + 16;
|
|
494
|
+
const constructor = current_SDNA_template.getSDNAStructureConstructor(current_SDNA_template.SDNA_NAMES[sdna_index]);
|
|
495
|
+
const size = data.getInt32(data_offset + 4, BIG_ENDIAN);
|
|
496
|
+
count = data.getInt32(data_offset + 12 + pointer_size, BIG_ENDIAN);
|
|
497
|
+
if (count > 0) {
|
|
498
|
+
let obj = new constructor();
|
|
499
|
+
const length = constructor.prototype._length;
|
|
500
|
+
const address = FILE.getPointer(data_offset + 8);
|
|
501
|
+
obj.address = address + "";
|
|
502
|
+
obj.setData(address, data_start, data_start + size, FILE);
|
|
503
|
+
if (count > 1) {
|
|
504
|
+
let array = [];
|
|
505
|
+
array.push(obj);
|
|
506
|
+
for (let u = 1; u < count; u++) {
|
|
507
|
+
obj = new constructor();
|
|
508
|
+
obj.setData(address, data_start + length * u, data_start + length * u + length, FILE);
|
|
509
|
+
array.push(obj);
|
|
510
|
+
}
|
|
511
|
+
FILE.memory_lookup[address] = array;
|
|
512
|
+
} else {
|
|
513
|
+
FILE.memory_lookup[address] = obj;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
worker = new worker_code();
|
|
521
|
+
worker.postMessage = function(message) {
|
|
522
|
+
return_object.onParseReady(message);
|
|
523
|
+
};
|
|
9
524
|
/**
|
|
10
525
|
* JS.Blend
|
|
11
526
|
* Original Repo: https://github.com/acweathersby/js.blend
|
|
@@ -14,5 +529,162 @@ import{PointLight as t,BufferGeometry as e,BufferAttribute as n,MeshPhysicalMate
|
|
|
14
529
|
* MIT License
|
|
15
530
|
* Copyright (c) 2020 Anthony C, Weathersby
|
|
16
531
|
* @license
|
|
17
|
-
*/
|
|
532
|
+
*/
|
|
533
|
+
async function parseBlend(buffer, name = "") {
|
|
534
|
+
return new Promise((res, rej) => {
|
|
535
|
+
return_object.onParseReady = (file, error) => {
|
|
536
|
+
if (error) rej(error);
|
|
537
|
+
else res(file);
|
|
538
|
+
};
|
|
539
|
+
return_object.loadBlendFromArrayBuffer(buffer, name);
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
const blenderLightTypes = {
|
|
543
|
+
point: 0,
|
|
544
|
+
sun: 1,
|
|
545
|
+
spot: 0,
|
|
546
|
+
hemi: 0,
|
|
547
|
+
area: 0
|
|
548
|
+
};
|
|
549
|
+
function createLight(lamp) {
|
|
550
|
+
const ldata = lamp.data;
|
|
551
|
+
const position = [lamp.loc[0], lamp.loc[2], -lamp.loc[1]];
|
|
552
|
+
const color = ldata.r * 255 << 16 | ldata.g * 255 << 8 | ldata.b * 255 << 0;
|
|
553
|
+
const intensity = ldata.energy;
|
|
554
|
+
const distance = 0;
|
|
555
|
+
let light = null;
|
|
556
|
+
switch (ldata.type) {
|
|
557
|
+
case blenderLightTypes.point:
|
|
558
|
+
light = new PointLight(color, intensity, distance);
|
|
559
|
+
light.position.fromArray(position, 0);
|
|
560
|
+
light.castShadow = true;
|
|
561
|
+
break;
|
|
562
|
+
case blenderLightTypes.sun:
|
|
563
|
+
light = new PointLight(color, intensity, distance);
|
|
564
|
+
light.position.fromArray(position, 0);
|
|
565
|
+
light.castShadow = true;
|
|
566
|
+
light.shadow.mapSize.width = 1024;
|
|
567
|
+
light.shadow.mapSize.height = 1024;
|
|
568
|
+
light.shadow.camera.near = 0.01;
|
|
569
|
+
light.shadow.camera.far = 500;
|
|
570
|
+
break;
|
|
571
|
+
default:
|
|
572
|
+
console.warn("Unsupported light type", ldata.type);
|
|
573
|
+
}
|
|
574
|
+
return light;
|
|
575
|
+
}
|
|
576
|
+
function createBufferGeometry(mesh, origin) {
|
|
577
|
+
const faces = Array.isArray(mesh.mpoly) ? mesh.mpoly : [mesh.mpoly], loops = mesh.mloop, uv = mesh.mloopuv, vertices = mesh.mvert;
|
|
578
|
+
const geometry = new BufferGeometry();
|
|
579
|
+
if (!faces) return geometry;
|
|
580
|
+
const size = faces.reduce((acc, face) => acc + Math.floor(face.totloop * 3 / 2), 0);
|
|
581
|
+
const indices = new Uint32Array(size);
|
|
582
|
+
const uvs = new Float32Array(size * 2);
|
|
583
|
+
const normals = new Float32Array(size * 3);
|
|
584
|
+
const positions = new Float32Array(size * 3);
|
|
585
|
+
let currentIndex = 0;
|
|
586
|
+
for (const face of faces) {
|
|
587
|
+
const len = face.totloop;
|
|
588
|
+
const start = face.loopstart;
|
|
589
|
+
let indexi = 1;
|
|
590
|
+
while (indexi < len) {
|
|
591
|
+
let index = 0;
|
|
592
|
+
for (let l = 0; l < 3; l++) {
|
|
593
|
+
index = start;
|
|
594
|
+
if (indexi - 1 + l < len)
|
|
595
|
+
index += indexi - 1 + l;
|
|
596
|
+
const loop = loops[index];
|
|
597
|
+
const vert = vertices[loop.v];
|
|
598
|
+
indices[currentIndex] = currentIndex;
|
|
599
|
+
positions[currentIndex * 3 + 0] = vert.co[0] + origin[0];
|
|
600
|
+
positions[currentIndex * 3 + 1] = vert.co[2] + origin[2];
|
|
601
|
+
positions[currentIndex * 3 + 2] = -vert.co[1] + -0;
|
|
602
|
+
normals[currentIndex * 3 + 0] = vert.no[0];
|
|
603
|
+
normals[currentIndex * 3 + 1] = vert.no[2];
|
|
604
|
+
normals[currentIndex * 3 + 2] = -vert.no[1];
|
|
605
|
+
if (uv) {
|
|
606
|
+
uvs[currentIndex * 2 + 0] = uv[index].uv[0];
|
|
607
|
+
uvs[currentIndex * 2 + 1] = uv[index].uv[1];
|
|
608
|
+
}
|
|
609
|
+
currentIndex++;
|
|
610
|
+
}
|
|
611
|
+
indexi += 2;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
geometry.setAttribute("position", new BufferAttribute(positions, 3));
|
|
615
|
+
geometry.setIndex(new BufferAttribute(indices, 1));
|
|
616
|
+
geometry.setAttribute("normal", new BufferAttribute(normals, 3));
|
|
617
|
+
geometry.setAttribute("uv", new BufferAttribute(uvs, 2));
|
|
618
|
+
return geometry;
|
|
619
|
+
}
|
|
620
|
+
function createMaterial(mat) {
|
|
621
|
+
const material = new MeshPhysicalMaterial();
|
|
622
|
+
material.color.setRGB(mat.r, mat.g, mat.b);
|
|
623
|
+
material.roughness = mat.roughness !== void 0 ? mat.roughness : 0.4;
|
|
624
|
+
material.metalness = mat.metallic !== void 0 ? mat.metallic : 0;
|
|
625
|
+
material.opacity = mat.alpha !== void 0 ? mat.alpha : 0;
|
|
626
|
+
material.transparent = material.opacity < 1;
|
|
627
|
+
return material;
|
|
628
|
+
}
|
|
629
|
+
function createMesh(object) {
|
|
630
|
+
if (!object.data) return null;
|
|
631
|
+
const geometry = createBufferGeometry(object.data, [0, 0, 0]);
|
|
632
|
+
const mat = object.data.mat[0];
|
|
633
|
+
const material = mat ? createMaterial(mat) : void 0;
|
|
634
|
+
const mesh = new Mesh(geometry, material);
|
|
635
|
+
mesh.castShadow = true;
|
|
636
|
+
mesh.receiveShadow = true;
|
|
637
|
+
mesh.rotateZ(object.rot[2]);
|
|
638
|
+
mesh.rotateY(object.rot[1]);
|
|
639
|
+
mesh.rotateX(object.rot[0]);
|
|
640
|
+
mesh.scale.fromArray(object.size, 0);
|
|
641
|
+
mesh.position.fromArray([object.loc[0], object.loc[2], -object.loc[1]], 0);
|
|
642
|
+
return mesh;
|
|
643
|
+
}
|
|
644
|
+
const blenderObjectTypes = {
|
|
645
|
+
mesh: 1,
|
|
646
|
+
lamp: 10
|
|
647
|
+
};
|
|
648
|
+
async function createObjects(file) {
|
|
649
|
+
const objects = [];
|
|
650
|
+
const blendObjects = file.objects.Object;
|
|
651
|
+
for (const object of blendObjects) {
|
|
652
|
+
switch (object.type) {
|
|
653
|
+
case blenderObjectTypes.mesh:
|
|
654
|
+
objects.push(createMesh(object));
|
|
655
|
+
break;
|
|
656
|
+
case blenderObjectTypes.lamp:
|
|
657
|
+
objects.push(createLight(object));
|
|
658
|
+
break;
|
|
659
|
+
default:
|
|
660
|
+
console.warn("Unsupported object type", object.type);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
return objects.filter((o) => !!o);
|
|
664
|
+
}
|
|
665
|
+
const _BlendLoadPlugin = class _BlendLoadPlugin extends BaseImporterPlugin {
|
|
666
|
+
constructor() {
|
|
667
|
+
super();
|
|
668
|
+
this._importer = new Importer(class extends FileLoader {
|
|
669
|
+
async loadAsync(url, onProgress) {
|
|
670
|
+
this.setResponseType("arraybuffer");
|
|
671
|
+
const res = await super.loadAsync(url, onProgress);
|
|
672
|
+
const blend = await parseBlend(res);
|
|
673
|
+
const objects = await createObjects(blend);
|
|
674
|
+
const root = new Object3D();
|
|
675
|
+
root.add(...objects);
|
|
676
|
+
blend.scene = root;
|
|
677
|
+
return blend;
|
|
678
|
+
}
|
|
679
|
+
transform(res, _) {
|
|
680
|
+
return res.scene;
|
|
681
|
+
}
|
|
682
|
+
}, ["blend"], ["application/x-blender"], true);
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
_BlendLoadPlugin.PluginType = "BlendLoadPlugin";
|
|
686
|
+
let BlendLoadPlugin = _BlendLoadPlugin;
|
|
687
|
+
export {
|
|
688
|
+
BlendLoadPlugin
|
|
689
|
+
};
|
|
18
690
|
//# sourceMappingURL=index.mjs.map
|