@needle-tools/three 0.162.11 → 0.162.12
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.
|
@@ -458,12 +458,17 @@ class OBJLoader extends Loader {
|
|
|
458
458
|
try {
|
|
459
459
|
|
|
460
460
|
const state = scope.parse( text, true );
|
|
461
|
+
|
|
461
462
|
|
|
462
463
|
for ( let i = 0, l = state.materialLibraries.length; i < l; i ++ ) {
|
|
463
464
|
|
|
464
465
|
const mtlfile = state.materialLibraries[ i ];
|
|
465
466
|
|
|
466
|
-
const newUrl =
|
|
467
|
+
const newUrl = url.startsWith("blob:")
|
|
468
|
+
? (url + "/" + mtlfile)
|
|
469
|
+
: new URL(mtlfile, url);
|
|
470
|
+
|
|
471
|
+
console.debug( 'Loading MTL file: ' + newUrl );
|
|
467
472
|
|
|
468
473
|
await (new Promise((resolve, reject) => {
|
|
469
474
|
scope.materialsLoader.load( newUrl.toString(), creator => {
|
|
@@ -0,0 +1,832 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BufferGeometry,
|
|
3
|
+
Color,
|
|
4
|
+
DefaultLoadingManager,
|
|
5
|
+
FileLoader,
|
|
6
|
+
Float32BufferAttribute,
|
|
7
|
+
FrontSide,
|
|
8
|
+
Group,
|
|
9
|
+
LineBasicMaterial,
|
|
10
|
+
LineSegments,
|
|
11
|
+
Loader,
|
|
12
|
+
LoaderUtils,
|
|
13
|
+
Material,
|
|
14
|
+
Mesh,
|
|
15
|
+
MeshPhongMaterial,
|
|
16
|
+
Points,
|
|
17
|
+
PointsMaterial,
|
|
18
|
+
RepeatWrapping,
|
|
19
|
+
SRGBColorSpace,
|
|
20
|
+
TextureLoader,
|
|
21
|
+
Vector2,
|
|
22
|
+
Vector3
|
|
23
|
+
} from "/node_modules/.vite/deps/chunk-VUIPKYI2.js?v=df97e3aa";
|
|
24
|
+
import "/node_modules/.vite/deps/chunk-2TUXWMP5.js?v=df97e3aa";
|
|
25
|
+
|
|
26
|
+
// ../../needle-engine-dev/modules/needle-engine/js/package~/node_modules/three/examples/jsm/loaders/MTLLoader.js
|
|
27
|
+
var MTLLoader = class extends Loader {
|
|
28
|
+
constructor(manager) {
|
|
29
|
+
super(manager);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Loads and parses a MTL asset from a URL.
|
|
33
|
+
*
|
|
34
|
+
* @param {String} url - URL to the MTL file.
|
|
35
|
+
* @param {Function} [onLoad] - Callback invoked with the loaded object.
|
|
36
|
+
* @param {Function} [onProgress] - Callback for download progress.
|
|
37
|
+
* @param {Function} [onError] - Callback for download errors.
|
|
38
|
+
*
|
|
39
|
+
* @see setPath setResourcePath
|
|
40
|
+
*
|
|
41
|
+
* @note In order for relative texture references to resolve correctly
|
|
42
|
+
* you must call setResourcePath() explicitly prior to load.
|
|
43
|
+
*/
|
|
44
|
+
load(url, onLoad, onProgress, onError) {
|
|
45
|
+
const scope = this;
|
|
46
|
+
const path = this.path === "" ? LoaderUtils.extractUrlBase(url) : this.path;
|
|
47
|
+
const loader = new FileLoader(this.manager);
|
|
48
|
+
loader.setPath(this.path);
|
|
49
|
+
loader.setRequestHeader(this.requestHeader);
|
|
50
|
+
loader.setWithCredentials(this.withCredentials);
|
|
51
|
+
loader.load(url, function(text) {
|
|
52
|
+
try {
|
|
53
|
+
onLoad(scope.parse(text, path));
|
|
54
|
+
} catch (e) {
|
|
55
|
+
if (onError) {
|
|
56
|
+
onError(e);
|
|
57
|
+
} else {
|
|
58
|
+
console.error(e);
|
|
59
|
+
}
|
|
60
|
+
scope.manager.itemError(url);
|
|
61
|
+
}
|
|
62
|
+
}, onProgress, onError);
|
|
63
|
+
}
|
|
64
|
+
setMaterialOptions(value) {
|
|
65
|
+
this.materialOptions = value;
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Parses a MTL file.
|
|
70
|
+
*
|
|
71
|
+
* @param {String} text - Content of MTL file
|
|
72
|
+
* @return {MaterialCreator}
|
|
73
|
+
*
|
|
74
|
+
* @see setPath setResourcePath
|
|
75
|
+
*
|
|
76
|
+
* @note In order for relative texture references to resolve correctly
|
|
77
|
+
* you must call setResourcePath() explicitly prior to parse.
|
|
78
|
+
*/
|
|
79
|
+
parse(text, path) {
|
|
80
|
+
const lines = text.split("\n");
|
|
81
|
+
let info = {};
|
|
82
|
+
const delimiter_pattern = /\s+/;
|
|
83
|
+
const materialsInfo = {};
|
|
84
|
+
for (let i = 0; i < lines.length; i++) {
|
|
85
|
+
let line = lines[i];
|
|
86
|
+
line = line.trim();
|
|
87
|
+
if (line.length === 0 || line.charAt(0) === "#") {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const pos = line.indexOf(" ");
|
|
91
|
+
let key = pos >= 0 ? line.substring(0, pos) : line;
|
|
92
|
+
key = key.toLowerCase();
|
|
93
|
+
let value = pos >= 0 ? line.substring(pos + 1) : "";
|
|
94
|
+
value = value.trim();
|
|
95
|
+
if (key === "newmtl") {
|
|
96
|
+
info = { name: value };
|
|
97
|
+
materialsInfo[value] = info;
|
|
98
|
+
} else {
|
|
99
|
+
if (key === "ka" || key === "kd" || key === "ks" || key === "ke") {
|
|
100
|
+
const ss = value.split(delimiter_pattern, 3);
|
|
101
|
+
info[key] = [parseFloat(ss[0]), parseFloat(ss[1]), parseFloat(ss[2])];
|
|
102
|
+
} else {
|
|
103
|
+
info[key] = value;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const materialCreator = new MaterialCreator(this.resourcePath || path, this.materialOptions);
|
|
108
|
+
materialCreator.setCrossOrigin(this.crossOrigin);
|
|
109
|
+
materialCreator.setManager(this.manager);
|
|
110
|
+
materialCreator.setMaterials(materialsInfo);
|
|
111
|
+
return materialCreator;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
var MaterialCreator = class {
|
|
115
|
+
constructor(baseUrl = "", options = {}) {
|
|
116
|
+
this.baseUrl = baseUrl;
|
|
117
|
+
this.options = options;
|
|
118
|
+
this.materialsInfo = {};
|
|
119
|
+
this.materials = {};
|
|
120
|
+
this.materialsArray = [];
|
|
121
|
+
this.nameLookup = {};
|
|
122
|
+
this.crossOrigin = "anonymous";
|
|
123
|
+
this.side = this.options.side !== void 0 ? this.options.side : FrontSide;
|
|
124
|
+
this.wrap = this.options.wrap !== void 0 ? this.options.wrap : RepeatWrapping;
|
|
125
|
+
}
|
|
126
|
+
setCrossOrigin(value) {
|
|
127
|
+
this.crossOrigin = value;
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
130
|
+
setManager(value) {
|
|
131
|
+
this.manager = value;
|
|
132
|
+
}
|
|
133
|
+
setMaterials(materialsInfo) {
|
|
134
|
+
this.materialsInfo = this.convert(materialsInfo);
|
|
135
|
+
this.materials = {};
|
|
136
|
+
this.materialsArray = [];
|
|
137
|
+
this.nameLookup = {};
|
|
138
|
+
}
|
|
139
|
+
convert(materialsInfo) {
|
|
140
|
+
if (!this.options) return materialsInfo;
|
|
141
|
+
const converted = {};
|
|
142
|
+
for (const mn in materialsInfo) {
|
|
143
|
+
const mat = materialsInfo[mn];
|
|
144
|
+
const covmat = {};
|
|
145
|
+
converted[mn] = covmat;
|
|
146
|
+
for (const prop in mat) {
|
|
147
|
+
let save = true;
|
|
148
|
+
let value = mat[prop];
|
|
149
|
+
const lprop = prop.toLowerCase();
|
|
150
|
+
switch (lprop) {
|
|
151
|
+
case "kd":
|
|
152
|
+
case "ka":
|
|
153
|
+
case "ks":
|
|
154
|
+
if (this.options && this.options.normalizeRGB) {
|
|
155
|
+
value = [value[0] / 255, value[1] / 255, value[2] / 255];
|
|
156
|
+
}
|
|
157
|
+
if (this.options && this.options.ignoreZeroRGBs) {
|
|
158
|
+
if (value[0] === 0 && value[1] === 0 && value[2] === 0) {
|
|
159
|
+
save = false;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
break;
|
|
163
|
+
default:
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
if (save) {
|
|
167
|
+
covmat[lprop] = value;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return converted;
|
|
172
|
+
}
|
|
173
|
+
preload() {
|
|
174
|
+
for (const mn in this.materialsInfo) {
|
|
175
|
+
this.create(mn);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
getIndex(materialName) {
|
|
179
|
+
return this.nameLookup[materialName];
|
|
180
|
+
}
|
|
181
|
+
getAsArray() {
|
|
182
|
+
let index = 0;
|
|
183
|
+
for (const mn in this.materialsInfo) {
|
|
184
|
+
this.materialsArray[index] = this.create(mn);
|
|
185
|
+
this.nameLookup[mn] = index;
|
|
186
|
+
index++;
|
|
187
|
+
}
|
|
188
|
+
return this.materialsArray;
|
|
189
|
+
}
|
|
190
|
+
create(materialName) {
|
|
191
|
+
if (this.materials[materialName] === void 0) {
|
|
192
|
+
this.createMaterial_(materialName);
|
|
193
|
+
}
|
|
194
|
+
return this.materials[materialName];
|
|
195
|
+
}
|
|
196
|
+
createMaterial_(materialName) {
|
|
197
|
+
const scope = this;
|
|
198
|
+
const mat = this.materialsInfo[materialName];
|
|
199
|
+
const params = {
|
|
200
|
+
name: materialName,
|
|
201
|
+
side: this.side
|
|
202
|
+
};
|
|
203
|
+
function resolveURL(baseUrl, url) {
|
|
204
|
+
if (typeof url !== "string" || url === "")
|
|
205
|
+
return "";
|
|
206
|
+
if (/^https?:\/\//i.test(url)) return url;
|
|
207
|
+
return baseUrl + url;
|
|
208
|
+
}
|
|
209
|
+
function setMapForType(mapType, value) {
|
|
210
|
+
if (params[mapType]) return;
|
|
211
|
+
const texParams = scope.getTextureParams(value, params);
|
|
212
|
+
const map = scope.loadTexture(resolveURL(scope.baseUrl, texParams.url));
|
|
213
|
+
map.repeat.copy(texParams.scale);
|
|
214
|
+
map.offset.copy(texParams.offset);
|
|
215
|
+
map.wrapS = scope.wrap;
|
|
216
|
+
map.wrapT = scope.wrap;
|
|
217
|
+
if (mapType === "map" || mapType === "emissiveMap") {
|
|
218
|
+
map.colorSpace = SRGBColorSpace;
|
|
219
|
+
}
|
|
220
|
+
params[mapType] = map;
|
|
221
|
+
}
|
|
222
|
+
for (const prop in mat) {
|
|
223
|
+
const value = mat[prop];
|
|
224
|
+
let n;
|
|
225
|
+
if (value === "") continue;
|
|
226
|
+
switch (prop.toLowerCase()) {
|
|
227
|
+
case "kd":
|
|
228
|
+
params.color = new Color().fromArray(value).convertSRGBToLinear();
|
|
229
|
+
break;
|
|
230
|
+
case "ks":
|
|
231
|
+
params.specular = new Color().fromArray(value).convertSRGBToLinear();
|
|
232
|
+
break;
|
|
233
|
+
case "ke":
|
|
234
|
+
params.emissive = new Color().fromArray(value).convertSRGBToLinear();
|
|
235
|
+
break;
|
|
236
|
+
case "map_kd":
|
|
237
|
+
setMapForType("map", value);
|
|
238
|
+
break;
|
|
239
|
+
case "map_ks":
|
|
240
|
+
setMapForType("specularMap", value);
|
|
241
|
+
break;
|
|
242
|
+
case "map_ke":
|
|
243
|
+
setMapForType("emissiveMap", value);
|
|
244
|
+
break;
|
|
245
|
+
case "norm":
|
|
246
|
+
setMapForType("normalMap", value);
|
|
247
|
+
break;
|
|
248
|
+
case "map_bump":
|
|
249
|
+
case "bump":
|
|
250
|
+
setMapForType("bumpMap", value);
|
|
251
|
+
break;
|
|
252
|
+
case "map_d":
|
|
253
|
+
setMapForType("alphaMap", value);
|
|
254
|
+
params.transparent = true;
|
|
255
|
+
break;
|
|
256
|
+
case "ns":
|
|
257
|
+
params.shininess = parseFloat(value);
|
|
258
|
+
break;
|
|
259
|
+
case "d":
|
|
260
|
+
n = parseFloat(value);
|
|
261
|
+
if (n < 1) {
|
|
262
|
+
params.opacity = n;
|
|
263
|
+
params.transparent = true;
|
|
264
|
+
}
|
|
265
|
+
break;
|
|
266
|
+
case "tr":
|
|
267
|
+
n = parseFloat(value);
|
|
268
|
+
if (this.options && this.options.invertTrProperty) n = 1 - n;
|
|
269
|
+
if (n > 0) {
|
|
270
|
+
params.opacity = 1 - n;
|
|
271
|
+
params.transparent = true;
|
|
272
|
+
}
|
|
273
|
+
break;
|
|
274
|
+
default:
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
this.materials[materialName] = new MeshPhongMaterial(params);
|
|
279
|
+
return this.materials[materialName];
|
|
280
|
+
}
|
|
281
|
+
getTextureParams(value, matParams) {
|
|
282
|
+
const texParams = {
|
|
283
|
+
scale: new Vector2(1, 1),
|
|
284
|
+
offset: new Vector2(0, 0)
|
|
285
|
+
};
|
|
286
|
+
const items = value.split(/\s+/);
|
|
287
|
+
let pos;
|
|
288
|
+
pos = items.indexOf("-bm");
|
|
289
|
+
if (pos >= 0) {
|
|
290
|
+
matParams.bumpScale = parseFloat(items[pos + 1]);
|
|
291
|
+
items.splice(pos, 2);
|
|
292
|
+
}
|
|
293
|
+
pos = items.indexOf("-s");
|
|
294
|
+
if (pos >= 0) {
|
|
295
|
+
texParams.scale.set(parseFloat(items[pos + 1]), parseFloat(items[pos + 2]));
|
|
296
|
+
items.splice(pos, 4);
|
|
297
|
+
}
|
|
298
|
+
pos = items.indexOf("-o");
|
|
299
|
+
if (pos >= 0) {
|
|
300
|
+
texParams.offset.set(parseFloat(items[pos + 1]), parseFloat(items[pos + 2]));
|
|
301
|
+
items.splice(pos, 4);
|
|
302
|
+
}
|
|
303
|
+
texParams.url = items.join(" ").trim();
|
|
304
|
+
return texParams;
|
|
305
|
+
}
|
|
306
|
+
loadTexture(url, mapping, onLoad, onProgress, onError) {
|
|
307
|
+
const manager = this.manager !== void 0 ? this.manager : DefaultLoadingManager;
|
|
308
|
+
let loader = manager.getHandler(url);
|
|
309
|
+
if (loader === null) {
|
|
310
|
+
loader = new TextureLoader(manager);
|
|
311
|
+
}
|
|
312
|
+
if (loader.setCrossOrigin) loader.setCrossOrigin(this.crossOrigin);
|
|
313
|
+
const texture = loader.load(url, onLoad, onProgress, onError);
|
|
314
|
+
if (mapping !== void 0) texture.mapping = mapping;
|
|
315
|
+
return texture;
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
// ../../needle-engine-dev/modules/needle-engine/js/package~/node_modules/three/examples/jsm/loaders/OBJLoader.js
|
|
320
|
+
var _object_pattern = /^[og]\s*(.+)?/;
|
|
321
|
+
var _material_library_pattern = /^mtllib /;
|
|
322
|
+
var _material_use_pattern = /^usemtl /;
|
|
323
|
+
var _map_use_pattern = /^usemap /;
|
|
324
|
+
var _face_vertex_data_separator_pattern = /\s+/;
|
|
325
|
+
var _vA = new Vector3();
|
|
326
|
+
var _vB = new Vector3();
|
|
327
|
+
var _vC = new Vector3();
|
|
328
|
+
var _ab = new Vector3();
|
|
329
|
+
var _cb = new Vector3();
|
|
330
|
+
var _color = new Color();
|
|
331
|
+
function ParserState() {
|
|
332
|
+
const state = {
|
|
333
|
+
objects: [],
|
|
334
|
+
object: {},
|
|
335
|
+
vertices: [],
|
|
336
|
+
normals: [],
|
|
337
|
+
colors: [],
|
|
338
|
+
uvs: [],
|
|
339
|
+
materials: {},
|
|
340
|
+
materialLibraries: [],
|
|
341
|
+
startObject: function(name, fromDeclaration) {
|
|
342
|
+
if (this.object && this.object.fromDeclaration === false) {
|
|
343
|
+
this.object.name = name;
|
|
344
|
+
this.object.fromDeclaration = fromDeclaration !== false;
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
const previousMaterial = this.object && typeof this.object.currentMaterial === "function" ? this.object.currentMaterial() : void 0;
|
|
348
|
+
if (this.object && typeof this.object._finalize === "function") {
|
|
349
|
+
this.object._finalize(true);
|
|
350
|
+
}
|
|
351
|
+
this.object = {
|
|
352
|
+
name: name || "",
|
|
353
|
+
fromDeclaration: fromDeclaration !== false,
|
|
354
|
+
geometry: {
|
|
355
|
+
vertices: [],
|
|
356
|
+
normals: [],
|
|
357
|
+
colors: [],
|
|
358
|
+
uvs: [],
|
|
359
|
+
hasUVIndices: false
|
|
360
|
+
},
|
|
361
|
+
materials: [],
|
|
362
|
+
smooth: true,
|
|
363
|
+
startMaterial: function(name2, libraries) {
|
|
364
|
+
const previous = this._finalize(false);
|
|
365
|
+
if (previous && (previous.inherited || previous.groupCount <= 0)) {
|
|
366
|
+
this.materials.splice(previous.index, 1);
|
|
367
|
+
}
|
|
368
|
+
const material = {
|
|
369
|
+
index: this.materials.length,
|
|
370
|
+
name: name2 || "",
|
|
371
|
+
mtllib: Array.isArray(libraries) && libraries.length > 0 ? libraries[libraries.length - 1] : "",
|
|
372
|
+
smooth: previous !== void 0 ? previous.smooth : this.smooth,
|
|
373
|
+
groupStart: previous !== void 0 ? previous.groupEnd : 0,
|
|
374
|
+
groupEnd: -1,
|
|
375
|
+
groupCount: -1,
|
|
376
|
+
inherited: false,
|
|
377
|
+
clone: function(index) {
|
|
378
|
+
const cloned = {
|
|
379
|
+
index: typeof index === "number" ? index : this.index,
|
|
380
|
+
name: this.name,
|
|
381
|
+
mtllib: this.mtllib,
|
|
382
|
+
smooth: this.smooth,
|
|
383
|
+
groupStart: 0,
|
|
384
|
+
groupEnd: -1,
|
|
385
|
+
groupCount: -1,
|
|
386
|
+
inherited: false
|
|
387
|
+
};
|
|
388
|
+
cloned.clone = this.clone.bind(cloned);
|
|
389
|
+
return cloned;
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
this.materials.push(material);
|
|
393
|
+
return material;
|
|
394
|
+
},
|
|
395
|
+
currentMaterial: function() {
|
|
396
|
+
if (this.materials.length > 0) {
|
|
397
|
+
return this.materials[this.materials.length - 1];
|
|
398
|
+
}
|
|
399
|
+
return void 0;
|
|
400
|
+
},
|
|
401
|
+
_finalize: function(end) {
|
|
402
|
+
const lastMultiMaterial = this.currentMaterial();
|
|
403
|
+
if (lastMultiMaterial && lastMultiMaterial.groupEnd === -1) {
|
|
404
|
+
lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;
|
|
405
|
+
lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;
|
|
406
|
+
lastMultiMaterial.inherited = false;
|
|
407
|
+
}
|
|
408
|
+
if (end && this.materials.length > 1) {
|
|
409
|
+
for (let mi = this.materials.length - 1; mi >= 0; mi--) {
|
|
410
|
+
if (this.materials[mi].groupCount <= 0) {
|
|
411
|
+
this.materials.splice(mi, 1);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (end && this.materials.length === 0) {
|
|
416
|
+
this.materials.push({
|
|
417
|
+
name: "",
|
|
418
|
+
smooth: this.smooth
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
return lastMultiMaterial;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
if (previousMaterial && previousMaterial.name && typeof previousMaterial.clone === "function") {
|
|
425
|
+
const declared = previousMaterial.clone(0);
|
|
426
|
+
declared.inherited = true;
|
|
427
|
+
this.object.materials.push(declared);
|
|
428
|
+
}
|
|
429
|
+
this.objects.push(this.object);
|
|
430
|
+
},
|
|
431
|
+
finalize: function() {
|
|
432
|
+
if (this.object && typeof this.object._finalize === "function") {
|
|
433
|
+
this.object._finalize(true);
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
parseVertexIndex: function(value, len) {
|
|
437
|
+
const index = parseInt(value, 10);
|
|
438
|
+
return (index >= 0 ? index - 1 : index + len / 3) * 3;
|
|
439
|
+
},
|
|
440
|
+
parseNormalIndex: function(value, len) {
|
|
441
|
+
const index = parseInt(value, 10);
|
|
442
|
+
return (index >= 0 ? index - 1 : index + len / 3) * 3;
|
|
443
|
+
},
|
|
444
|
+
parseUVIndex: function(value, len) {
|
|
445
|
+
const index = parseInt(value, 10);
|
|
446
|
+
return (index >= 0 ? index - 1 : index + len / 2) * 2;
|
|
447
|
+
},
|
|
448
|
+
addVertex: function(a, b, c) {
|
|
449
|
+
const src = this.vertices;
|
|
450
|
+
const dst = this.object.geometry.vertices;
|
|
451
|
+
dst.push(src[a + 0], src[a + 1], src[a + 2]);
|
|
452
|
+
dst.push(src[b + 0], src[b + 1], src[b + 2]);
|
|
453
|
+
dst.push(src[c + 0], src[c + 1], src[c + 2]);
|
|
454
|
+
},
|
|
455
|
+
addVertexPoint: function(a) {
|
|
456
|
+
const src = this.vertices;
|
|
457
|
+
const dst = this.object.geometry.vertices;
|
|
458
|
+
dst.push(src[a + 0], src[a + 1], src[a + 2]);
|
|
459
|
+
},
|
|
460
|
+
addVertexLine: function(a) {
|
|
461
|
+
const src = this.vertices;
|
|
462
|
+
const dst = this.object.geometry.vertices;
|
|
463
|
+
dst.push(src[a + 0], src[a + 1], src[a + 2]);
|
|
464
|
+
},
|
|
465
|
+
addNormal: function(a, b, c) {
|
|
466
|
+
const src = this.normals;
|
|
467
|
+
const dst = this.object.geometry.normals;
|
|
468
|
+
dst.push(src[a + 0], src[a + 1], src[a + 2]);
|
|
469
|
+
dst.push(src[b + 0], src[b + 1], src[b + 2]);
|
|
470
|
+
dst.push(src[c + 0], src[c + 1], src[c + 2]);
|
|
471
|
+
},
|
|
472
|
+
addFaceNormal: function(a, b, c) {
|
|
473
|
+
const src = this.vertices;
|
|
474
|
+
const dst = this.object.geometry.normals;
|
|
475
|
+
_vA.fromArray(src, a);
|
|
476
|
+
_vB.fromArray(src, b);
|
|
477
|
+
_vC.fromArray(src, c);
|
|
478
|
+
_cb.subVectors(_vC, _vB);
|
|
479
|
+
_ab.subVectors(_vA, _vB);
|
|
480
|
+
_cb.cross(_ab);
|
|
481
|
+
_cb.normalize();
|
|
482
|
+
dst.push(_cb.x, _cb.y, _cb.z);
|
|
483
|
+
dst.push(_cb.x, _cb.y, _cb.z);
|
|
484
|
+
dst.push(_cb.x, _cb.y, _cb.z);
|
|
485
|
+
},
|
|
486
|
+
addColor: function(a, b, c) {
|
|
487
|
+
const src = this.colors;
|
|
488
|
+
const dst = this.object.geometry.colors;
|
|
489
|
+
if (src[a] !== void 0) dst.push(src[a + 0], src[a + 1], src[a + 2]);
|
|
490
|
+
if (src[b] !== void 0) dst.push(src[b + 0], src[b + 1], src[b + 2]);
|
|
491
|
+
if (src[c] !== void 0) dst.push(src[c + 0], src[c + 1], src[c + 2]);
|
|
492
|
+
},
|
|
493
|
+
addUV: function(a, b, c) {
|
|
494
|
+
const src = this.uvs;
|
|
495
|
+
const dst = this.object.geometry.uvs;
|
|
496
|
+
dst.push(src[a + 0], src[a + 1]);
|
|
497
|
+
dst.push(src[b + 0], src[b + 1]);
|
|
498
|
+
dst.push(src[c + 0], src[c + 1]);
|
|
499
|
+
},
|
|
500
|
+
addDefaultUV: function() {
|
|
501
|
+
const dst = this.object.geometry.uvs;
|
|
502
|
+
dst.push(0, 0);
|
|
503
|
+
dst.push(0, 0);
|
|
504
|
+
dst.push(0, 0);
|
|
505
|
+
},
|
|
506
|
+
addUVLine: function(a) {
|
|
507
|
+
const src = this.uvs;
|
|
508
|
+
const dst = this.object.geometry.uvs;
|
|
509
|
+
dst.push(src[a + 0], src[a + 1]);
|
|
510
|
+
},
|
|
511
|
+
addFace: function(a, b, c, ua, ub, uc, na, nb, nc) {
|
|
512
|
+
const vLen = this.vertices.length;
|
|
513
|
+
let ia = this.parseVertexIndex(a, vLen);
|
|
514
|
+
let ib = this.parseVertexIndex(b, vLen);
|
|
515
|
+
let ic = this.parseVertexIndex(c, vLen);
|
|
516
|
+
this.addVertex(ia, ib, ic);
|
|
517
|
+
this.addColor(ia, ib, ic);
|
|
518
|
+
if (na !== void 0 && na !== "") {
|
|
519
|
+
const nLen = this.normals.length;
|
|
520
|
+
ia = this.parseNormalIndex(na, nLen);
|
|
521
|
+
ib = this.parseNormalIndex(nb, nLen);
|
|
522
|
+
ic = this.parseNormalIndex(nc, nLen);
|
|
523
|
+
this.addNormal(ia, ib, ic);
|
|
524
|
+
} else {
|
|
525
|
+
this.addFaceNormal(ia, ib, ic);
|
|
526
|
+
}
|
|
527
|
+
if (ua !== void 0 && ua !== "") {
|
|
528
|
+
const uvLen = this.uvs.length;
|
|
529
|
+
ia = this.parseUVIndex(ua, uvLen);
|
|
530
|
+
ib = this.parseUVIndex(ub, uvLen);
|
|
531
|
+
ic = this.parseUVIndex(uc, uvLen);
|
|
532
|
+
this.addUV(ia, ib, ic);
|
|
533
|
+
this.object.geometry.hasUVIndices = true;
|
|
534
|
+
} else {
|
|
535
|
+
this.addDefaultUV();
|
|
536
|
+
}
|
|
537
|
+
},
|
|
538
|
+
addPointGeometry: function(vertices) {
|
|
539
|
+
this.object.geometry.type = "Points";
|
|
540
|
+
const vLen = this.vertices.length;
|
|
541
|
+
for (let vi = 0, l = vertices.length; vi < l; vi++) {
|
|
542
|
+
const index = this.parseVertexIndex(vertices[vi], vLen);
|
|
543
|
+
this.addVertexPoint(index);
|
|
544
|
+
this.addColor(index);
|
|
545
|
+
}
|
|
546
|
+
},
|
|
547
|
+
addLineGeometry: function(vertices, uvs) {
|
|
548
|
+
this.object.geometry.type = "Line";
|
|
549
|
+
const vLen = this.vertices.length;
|
|
550
|
+
const uvLen = this.uvs.length;
|
|
551
|
+
for (let vi = 0, l = vertices.length; vi < l; vi++) {
|
|
552
|
+
this.addVertexLine(this.parseVertexIndex(vertices[vi], vLen));
|
|
553
|
+
}
|
|
554
|
+
for (let uvi = 0, l = uvs.length; uvi < l; uvi++) {
|
|
555
|
+
this.addUVLine(this.parseUVIndex(uvs[uvi], uvLen));
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
};
|
|
559
|
+
state.startObject("", false);
|
|
560
|
+
return state;
|
|
561
|
+
}
|
|
562
|
+
var OBJLoader = class extends Loader {
|
|
563
|
+
constructor(manager) {
|
|
564
|
+
super(manager);
|
|
565
|
+
this.materials = null;
|
|
566
|
+
this.materialsLoader = new MTLLoader(manager);
|
|
567
|
+
}
|
|
568
|
+
load(url, onLoad, onProgress, onError) {
|
|
569
|
+
const scope = this;
|
|
570
|
+
const loader = new FileLoader(this.manager);
|
|
571
|
+
loader.setPath(this.path);
|
|
572
|
+
loader.setRequestHeader(this.requestHeader);
|
|
573
|
+
loader.setWithCredentials(this.withCredentials);
|
|
574
|
+
loader.load(url, async function(text) {
|
|
575
|
+
try {
|
|
576
|
+
const state = scope.parse(text, true);
|
|
577
|
+
for (let i = 0, l = state.materialLibraries.length; i < l; i++) {
|
|
578
|
+
const mtlfile = state.materialLibraries[i];
|
|
579
|
+
const newUrl = new URL(mtlfile, url);
|
|
580
|
+
await new Promise((resolve, reject) => {
|
|
581
|
+
scope.materialsLoader.load(newUrl.toString(), (creator) => {
|
|
582
|
+
scope.setMaterials(creator);
|
|
583
|
+
resolve();
|
|
584
|
+
}, null, reject);
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
onLoad(scope.createObjects(state));
|
|
588
|
+
} catch (e) {
|
|
589
|
+
if (onError) {
|
|
590
|
+
onError(e);
|
|
591
|
+
} else {
|
|
592
|
+
console.error(e);
|
|
593
|
+
}
|
|
594
|
+
scope.manager.itemError(url);
|
|
595
|
+
}
|
|
596
|
+
}, onProgress, onError);
|
|
597
|
+
}
|
|
598
|
+
setMTLLoader(loader) {
|
|
599
|
+
this.materialsLoader = loader;
|
|
600
|
+
return this;
|
|
601
|
+
}
|
|
602
|
+
setMaterials(materials) {
|
|
603
|
+
this.materials = materials;
|
|
604
|
+
return this;
|
|
605
|
+
}
|
|
606
|
+
parse(text, parseOnly = false) {
|
|
607
|
+
const state = new ParserState();
|
|
608
|
+
if (text.indexOf("\r\n") !== -1) {
|
|
609
|
+
text = text.replace(/\r\n/g, "\n");
|
|
610
|
+
}
|
|
611
|
+
if (text.indexOf("\\\n") !== -1) {
|
|
612
|
+
text = text.replace(/\\\n/g, "");
|
|
613
|
+
}
|
|
614
|
+
const lines = text.split("\n");
|
|
615
|
+
let result = [];
|
|
616
|
+
for (let i = 0, l = lines.length; i < l; i++) {
|
|
617
|
+
const line = lines[i].trimStart();
|
|
618
|
+
if (line.length === 0) continue;
|
|
619
|
+
const lineFirstChar = line.charAt(0);
|
|
620
|
+
if (lineFirstChar === "#") continue;
|
|
621
|
+
if (lineFirstChar === "v") {
|
|
622
|
+
const data = line.split(_face_vertex_data_separator_pattern);
|
|
623
|
+
switch (data[0]) {
|
|
624
|
+
case "v":
|
|
625
|
+
state.vertices.push(
|
|
626
|
+
parseFloat(data[1]),
|
|
627
|
+
parseFloat(data[2]),
|
|
628
|
+
parseFloat(data[3])
|
|
629
|
+
);
|
|
630
|
+
if (data.length >= 7) {
|
|
631
|
+
_color.setRGB(
|
|
632
|
+
parseFloat(data[4]),
|
|
633
|
+
parseFloat(data[5]),
|
|
634
|
+
parseFloat(data[6])
|
|
635
|
+
).convertSRGBToLinear();
|
|
636
|
+
state.colors.push(_color.r, _color.g, _color.b);
|
|
637
|
+
} else {
|
|
638
|
+
state.colors.push(void 0, void 0, void 0);
|
|
639
|
+
}
|
|
640
|
+
break;
|
|
641
|
+
case "vn":
|
|
642
|
+
state.normals.push(
|
|
643
|
+
parseFloat(data[1]),
|
|
644
|
+
parseFloat(data[2]),
|
|
645
|
+
parseFloat(data[3])
|
|
646
|
+
);
|
|
647
|
+
break;
|
|
648
|
+
case "vt":
|
|
649
|
+
state.uvs.push(
|
|
650
|
+
parseFloat(data[1]),
|
|
651
|
+
parseFloat(data[2])
|
|
652
|
+
);
|
|
653
|
+
break;
|
|
654
|
+
}
|
|
655
|
+
} else if (lineFirstChar === "f") {
|
|
656
|
+
const lineData = line.slice(1).trim();
|
|
657
|
+
const vertexData = lineData.split(_face_vertex_data_separator_pattern);
|
|
658
|
+
const faceVertices = [];
|
|
659
|
+
for (let j = 0, jl = vertexData.length; j < jl; j++) {
|
|
660
|
+
const vertex = vertexData[j];
|
|
661
|
+
if (vertex.length > 0) {
|
|
662
|
+
const vertexParts = vertex.split("/");
|
|
663
|
+
faceVertices.push(vertexParts);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
const v1 = faceVertices[0];
|
|
667
|
+
for (let j = 1, jl = faceVertices.length - 1; j < jl; j++) {
|
|
668
|
+
const v2 = faceVertices[j];
|
|
669
|
+
const v3 = faceVertices[j + 1];
|
|
670
|
+
state.addFace(
|
|
671
|
+
v1[0],
|
|
672
|
+
v2[0],
|
|
673
|
+
v3[0],
|
|
674
|
+
v1[1],
|
|
675
|
+
v2[1],
|
|
676
|
+
v3[1],
|
|
677
|
+
v1[2],
|
|
678
|
+
v2[2],
|
|
679
|
+
v3[2]
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
} else if (lineFirstChar === "l") {
|
|
683
|
+
const lineParts = line.substring(1).trim().split(" ");
|
|
684
|
+
let lineVertices = [];
|
|
685
|
+
const lineUVs = [];
|
|
686
|
+
if (line.indexOf("/") === -1) {
|
|
687
|
+
lineVertices = lineParts;
|
|
688
|
+
} else {
|
|
689
|
+
for (let li = 0, llen = lineParts.length; li < llen; li++) {
|
|
690
|
+
const parts = lineParts[li].split("/");
|
|
691
|
+
if (parts[0] !== "") lineVertices.push(parts[0]);
|
|
692
|
+
if (parts[1] !== "") lineUVs.push(parts[1]);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
state.addLineGeometry(lineVertices, lineUVs);
|
|
696
|
+
} else if (lineFirstChar === "p") {
|
|
697
|
+
const lineData = line.slice(1).trim();
|
|
698
|
+
const pointData = lineData.split(" ");
|
|
699
|
+
state.addPointGeometry(pointData);
|
|
700
|
+
} else if ((result = _object_pattern.exec(line)) !== null) {
|
|
701
|
+
const name = (" " + result[0].slice(1).trim()).slice(1);
|
|
702
|
+
state.startObject(name);
|
|
703
|
+
} else if (_material_use_pattern.test(line)) {
|
|
704
|
+
state.object.startMaterial(line.substring(7).trim(), state.materialLibraries);
|
|
705
|
+
} else if (_material_library_pattern.test(line)) {
|
|
706
|
+
state.materialLibraries.push(line.substring(7).trim());
|
|
707
|
+
} else if (_map_use_pattern.test(line)) {
|
|
708
|
+
console.warn('THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.');
|
|
709
|
+
} else if (lineFirstChar === "s") {
|
|
710
|
+
result = line.split(" ");
|
|
711
|
+
if (result.length > 1) {
|
|
712
|
+
const value = result[1].trim().toLowerCase();
|
|
713
|
+
state.object.smooth = value !== "0" && value !== "off";
|
|
714
|
+
} else {
|
|
715
|
+
state.object.smooth = true;
|
|
716
|
+
}
|
|
717
|
+
const material = state.object.currentMaterial();
|
|
718
|
+
if (material) material.smooth = state.object.smooth;
|
|
719
|
+
} else {
|
|
720
|
+
if (line === "\0") continue;
|
|
721
|
+
console.warn('THREE.OBJLoader: Unexpected line: "' + line + '"');
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
state.finalize();
|
|
725
|
+
if (parseOnly) return state;
|
|
726
|
+
return this.createObjects(state);
|
|
727
|
+
}
|
|
728
|
+
createObjects(state) {
|
|
729
|
+
const container = new Group();
|
|
730
|
+
container.materialLibraries = [].concat(state.materialLibraries);
|
|
731
|
+
const hasPrimitives = !(state.objects.length === 1 && state.objects[0].geometry.vertices.length === 0);
|
|
732
|
+
if (hasPrimitives === true) {
|
|
733
|
+
for (let i = 0, l = state.objects.length; i < l; i++) {
|
|
734
|
+
const object = state.objects[i];
|
|
735
|
+
const geometry = object.geometry;
|
|
736
|
+
const materials = object.materials;
|
|
737
|
+
const isLine = geometry.type === "Line";
|
|
738
|
+
const isPoints = geometry.type === "Points";
|
|
739
|
+
let hasVertexColors = false;
|
|
740
|
+
if (geometry.vertices.length === 0) continue;
|
|
741
|
+
const buffergeometry = new BufferGeometry();
|
|
742
|
+
buffergeometry.setAttribute("position", new Float32BufferAttribute(geometry.vertices, 3));
|
|
743
|
+
if (geometry.normals.length > 0) {
|
|
744
|
+
buffergeometry.setAttribute("normal", new Float32BufferAttribute(geometry.normals, 3));
|
|
745
|
+
}
|
|
746
|
+
if (geometry.colors.length > 0) {
|
|
747
|
+
hasVertexColors = true;
|
|
748
|
+
buffergeometry.setAttribute("color", new Float32BufferAttribute(geometry.colors, 3));
|
|
749
|
+
}
|
|
750
|
+
if (geometry.hasUVIndices === true) {
|
|
751
|
+
buffergeometry.setAttribute("uv", new Float32BufferAttribute(geometry.uvs, 2));
|
|
752
|
+
}
|
|
753
|
+
const createdMaterials = [];
|
|
754
|
+
for (let mi = 0, miLen = materials.length; mi < miLen; mi++) {
|
|
755
|
+
const sourceMaterial = materials[mi];
|
|
756
|
+
const materialHash = sourceMaterial.name + "_" + sourceMaterial.smooth + "_" + hasVertexColors;
|
|
757
|
+
let material = state.materials[materialHash];
|
|
758
|
+
if (this.materials !== null) {
|
|
759
|
+
material = this.materials.create(sourceMaterial.name);
|
|
760
|
+
if (isLine && material && !(material instanceof LineBasicMaterial)) {
|
|
761
|
+
const materialLine = new LineBasicMaterial();
|
|
762
|
+
Material.prototype.copy.call(materialLine, material);
|
|
763
|
+
materialLine.color.copy(material.color);
|
|
764
|
+
material = materialLine;
|
|
765
|
+
} else if (isPoints && material && !(material instanceof PointsMaterial)) {
|
|
766
|
+
const materialPoints = new PointsMaterial({ size: 10, sizeAttenuation: false });
|
|
767
|
+
Material.prototype.copy.call(materialPoints, material);
|
|
768
|
+
materialPoints.color.copy(material.color);
|
|
769
|
+
materialPoints.map = material.map;
|
|
770
|
+
material = materialPoints;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
if (material === void 0) {
|
|
774
|
+
if (isLine) {
|
|
775
|
+
material = new LineBasicMaterial();
|
|
776
|
+
} else if (isPoints) {
|
|
777
|
+
material = new PointsMaterial({ size: 1, sizeAttenuation: false });
|
|
778
|
+
} else {
|
|
779
|
+
material = new MeshPhongMaterial();
|
|
780
|
+
}
|
|
781
|
+
material.name = sourceMaterial.name;
|
|
782
|
+
material.flatShading = sourceMaterial.smooth ? false : true;
|
|
783
|
+
material.vertexColors = hasVertexColors;
|
|
784
|
+
state.materials[materialHash] = material;
|
|
785
|
+
}
|
|
786
|
+
createdMaterials.push(material);
|
|
787
|
+
}
|
|
788
|
+
let mesh;
|
|
789
|
+
if (createdMaterials.length > 1) {
|
|
790
|
+
for (let mi = 0, miLen = materials.length; mi < miLen; mi++) {
|
|
791
|
+
const sourceMaterial = materials[mi];
|
|
792
|
+
buffergeometry.addGroup(sourceMaterial.groupStart, sourceMaterial.groupCount, mi);
|
|
793
|
+
}
|
|
794
|
+
if (isLine) {
|
|
795
|
+
mesh = new LineSegments(buffergeometry, createdMaterials);
|
|
796
|
+
} else if (isPoints) {
|
|
797
|
+
mesh = new Points(buffergeometry, createdMaterials);
|
|
798
|
+
} else {
|
|
799
|
+
mesh = new Mesh(buffergeometry, createdMaterials);
|
|
800
|
+
}
|
|
801
|
+
} else {
|
|
802
|
+
if (isLine) {
|
|
803
|
+
mesh = new LineSegments(buffergeometry, createdMaterials[0]);
|
|
804
|
+
} else if (isPoints) {
|
|
805
|
+
mesh = new Points(buffergeometry, createdMaterials[0]);
|
|
806
|
+
} else {
|
|
807
|
+
mesh = new Mesh(buffergeometry, createdMaterials[0]);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
mesh.name = object.name;
|
|
811
|
+
container.add(mesh);
|
|
812
|
+
}
|
|
813
|
+
} else {
|
|
814
|
+
if (state.vertices.length > 0) {
|
|
815
|
+
const material = new PointsMaterial({ size: 1, sizeAttenuation: false });
|
|
816
|
+
const buffergeometry = new BufferGeometry();
|
|
817
|
+
buffergeometry.setAttribute("position", new Float32BufferAttribute(state.vertices, 3));
|
|
818
|
+
if (state.colors.length > 0 && state.colors[0] !== void 0) {
|
|
819
|
+
buffergeometry.setAttribute("color", new Float32BufferAttribute(state.colors, 3));
|
|
820
|
+
material.vertexColors = true;
|
|
821
|
+
}
|
|
822
|
+
const points = new Points(buffergeometry, material);
|
|
823
|
+
container.add(points);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
return container;
|
|
827
|
+
}
|
|
828
|
+
};
|
|
829
|
+
export {
|
|
830
|
+
OBJLoader
|
|
831
|
+
};
|
|
832
|
+
//# sourceMappingURL=three_examples_jsm_loaders_OBJLoader__js.js.map
|