@lingbi/studio 0.2.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/Application.d.ts +5 -0
- package/ObjResourceListSource.d.ts +3 -0
- package/ObjResourceSceneSource.d.ts +5 -0
- package/index.d.ts +2 -0
- package/index.js +475 -16
- package/package.json +1 -1
package/Application.d.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import type { ObjImportResult } from './ObjImportResult';
|
|
2
2
|
import type { ObjImportSource } from './ObjImportSource';
|
|
3
|
+
import type { ObjResourceListSource } from './ObjResourceListSource';
|
|
4
|
+
import type { ObjResourceSceneSource } from './ObjResourceSceneSource';
|
|
3
5
|
import type { ObjSceneSource } from './ObjSceneSource';
|
|
4
6
|
export declare class Application {
|
|
5
7
|
private disposed;
|
|
6
8
|
private renderer;
|
|
7
9
|
attach(canvas: HTMLCanvasElement): void;
|
|
8
10
|
importObj(source: ObjImportSource): Promise<ObjImportResult>;
|
|
11
|
+
importObjResources(source: ObjResourceListSource): Promise<ObjImportResult>;
|
|
12
|
+
importObjResourceScene(source: ObjResourceSceneSource): Promise<ObjImportResult>;
|
|
9
13
|
importObjScene(source: ObjSceneSource): Promise<ObjImportResult>;
|
|
10
14
|
resetView(): void;
|
|
15
|
+
takeScreenshot(): Promise<Blob>;
|
|
11
16
|
dispose(): void;
|
|
12
17
|
private assertNotDisposed;
|
|
13
18
|
private getRenderer;
|
package/index.d.ts
CHANGED
|
@@ -2,4 +2,6 @@ export { Application } from './Application';
|
|
|
2
2
|
export type { ObjImportResult } from './ObjImportResult';
|
|
3
3
|
export { ObjImportFailureCode } from './ObjImportResult';
|
|
4
4
|
export type { ObjImportSource } from './ObjImportSource';
|
|
5
|
+
export type { ObjResourceListSource } from './ObjResourceListSource';
|
|
6
|
+
export type { ObjResourceSceneSource } from './ObjResourceSceneSource';
|
|
5
7
|
export type { ObjSceneSource } from './ObjSceneSource';
|
package/index.js
CHANGED
|
@@ -13983,6 +13983,91 @@ class RawShaderMaterial extends ShaderMaterial {
|
|
|
13983
13983
|
this.type = "RawShaderMaterial";
|
|
13984
13984
|
}
|
|
13985
13985
|
}
|
|
13986
|
+
class MeshStandardMaterial extends Material {
|
|
13987
|
+
/**
|
|
13988
|
+
* Constructs a new mesh standard material.
|
|
13989
|
+
*
|
|
13990
|
+
* @param {Object} [parameters] - An object with one or more properties
|
|
13991
|
+
* defining the material's appearance. Any property of the material
|
|
13992
|
+
* (including any property from inherited materials) can be passed
|
|
13993
|
+
* in here. Color values can be passed any type of value accepted
|
|
13994
|
+
* by {@link Color#set}.
|
|
13995
|
+
*/
|
|
13996
|
+
constructor(parameters) {
|
|
13997
|
+
super();
|
|
13998
|
+
this.isMeshStandardMaterial = true;
|
|
13999
|
+
this.type = "MeshStandardMaterial";
|
|
14000
|
+
this.defines = { "STANDARD": "" };
|
|
14001
|
+
this.color = new Color(16777215);
|
|
14002
|
+
this.roughness = 1;
|
|
14003
|
+
this.metalness = 0;
|
|
14004
|
+
this.map = null;
|
|
14005
|
+
this.lightMap = null;
|
|
14006
|
+
this.lightMapIntensity = 1;
|
|
14007
|
+
this.aoMap = null;
|
|
14008
|
+
this.aoMapIntensity = 1;
|
|
14009
|
+
this.emissive = new Color(0);
|
|
14010
|
+
this.emissiveIntensity = 1;
|
|
14011
|
+
this.emissiveMap = null;
|
|
14012
|
+
this.bumpMap = null;
|
|
14013
|
+
this.bumpScale = 1;
|
|
14014
|
+
this.normalMap = null;
|
|
14015
|
+
this.normalMapType = TangentSpaceNormalMap;
|
|
14016
|
+
this.normalScale = new Vector2(1, 1);
|
|
14017
|
+
this.displacementMap = null;
|
|
14018
|
+
this.displacementScale = 1;
|
|
14019
|
+
this.displacementBias = 0;
|
|
14020
|
+
this.roughnessMap = null;
|
|
14021
|
+
this.metalnessMap = null;
|
|
14022
|
+
this.alphaMap = null;
|
|
14023
|
+
this.envMap = null;
|
|
14024
|
+
this.envMapRotation = new Euler();
|
|
14025
|
+
this.envMapIntensity = 1;
|
|
14026
|
+
this.wireframe = false;
|
|
14027
|
+
this.wireframeLinewidth = 1;
|
|
14028
|
+
this.wireframeLinecap = "round";
|
|
14029
|
+
this.wireframeLinejoin = "round";
|
|
14030
|
+
this.flatShading = false;
|
|
14031
|
+
this.fog = true;
|
|
14032
|
+
this.setValues(parameters);
|
|
14033
|
+
}
|
|
14034
|
+
copy(source) {
|
|
14035
|
+
super.copy(source);
|
|
14036
|
+
this.defines = { "STANDARD": "" };
|
|
14037
|
+
this.color.copy(source.color);
|
|
14038
|
+
this.roughness = source.roughness;
|
|
14039
|
+
this.metalness = source.metalness;
|
|
14040
|
+
this.map = source.map;
|
|
14041
|
+
this.lightMap = source.lightMap;
|
|
14042
|
+
this.lightMapIntensity = source.lightMapIntensity;
|
|
14043
|
+
this.aoMap = source.aoMap;
|
|
14044
|
+
this.aoMapIntensity = source.aoMapIntensity;
|
|
14045
|
+
this.emissive.copy(source.emissive);
|
|
14046
|
+
this.emissiveMap = source.emissiveMap;
|
|
14047
|
+
this.emissiveIntensity = source.emissiveIntensity;
|
|
14048
|
+
this.bumpMap = source.bumpMap;
|
|
14049
|
+
this.bumpScale = source.bumpScale;
|
|
14050
|
+
this.normalMap = source.normalMap;
|
|
14051
|
+
this.normalMapType = source.normalMapType;
|
|
14052
|
+
this.normalScale.copy(source.normalScale);
|
|
14053
|
+
this.displacementMap = source.displacementMap;
|
|
14054
|
+
this.displacementScale = source.displacementScale;
|
|
14055
|
+
this.displacementBias = source.displacementBias;
|
|
14056
|
+
this.roughnessMap = source.roughnessMap;
|
|
14057
|
+
this.metalnessMap = source.metalnessMap;
|
|
14058
|
+
this.alphaMap = source.alphaMap;
|
|
14059
|
+
this.envMap = source.envMap;
|
|
14060
|
+
this.envMapRotation.copy(source.envMapRotation);
|
|
14061
|
+
this.envMapIntensity = source.envMapIntensity;
|
|
14062
|
+
this.wireframe = source.wireframe;
|
|
14063
|
+
this.wireframeLinewidth = source.wireframeLinewidth;
|
|
14064
|
+
this.wireframeLinecap = source.wireframeLinecap;
|
|
14065
|
+
this.wireframeLinejoin = source.wireframeLinejoin;
|
|
14066
|
+
this.flatShading = source.flatShading;
|
|
14067
|
+
this.fog = source.fog;
|
|
14068
|
+
return this;
|
|
14069
|
+
}
|
|
14070
|
+
}
|
|
13986
14071
|
class MeshPhongMaterial extends Material {
|
|
13987
14072
|
/**
|
|
13988
14073
|
* Constructs a new mesh phong material.
|
|
@@ -30474,6 +30559,12 @@ class ObjLoader {
|
|
|
30474
30559
|
this.parser = parser;
|
|
30475
30560
|
}
|
|
30476
30561
|
async load(source, signal) {
|
|
30562
|
+
return this.loadInternal(source, signal);
|
|
30563
|
+
}
|
|
30564
|
+
async loadResources(resources, signal) {
|
|
30565
|
+
return this.loadInternal(this.createResourceSource(resources), signal, resources);
|
|
30566
|
+
}
|
|
30567
|
+
async loadInternal(source, signal, resources) {
|
|
30477
30568
|
if (this.hasEmptyRequiredUrl(source)) {
|
|
30478
30569
|
return {
|
|
30479
30570
|
code: ObjImportFailureCode$1.EmptySource,
|
|
@@ -30485,12 +30576,15 @@ class ObjLoader {
|
|
|
30485
30576
|
try {
|
|
30486
30577
|
const objSource = await this.loadText(source.objUrl, signal);
|
|
30487
30578
|
this.assertNotCancelled(signal);
|
|
30488
|
-
const
|
|
30579
|
+
const materialReferences = this.getMaterialLibraryReferences(objSource);
|
|
30580
|
+
resources?.assertMaterialLibraries(materialReferences);
|
|
30581
|
+
const materialUrl = resources === void 0 ? this.getMaterialUrl(source, materialReferences) : resources.mtlUrl;
|
|
30489
30582
|
if (materialUrl !== void 0) {
|
|
30490
30583
|
materialContext = await this.loadMaterialContext(
|
|
30491
30584
|
materialUrl,
|
|
30492
30585
|
source.textureUrls,
|
|
30493
|
-
signal
|
|
30586
|
+
signal,
|
|
30587
|
+
resources
|
|
30494
30588
|
);
|
|
30495
30589
|
}
|
|
30496
30590
|
this.assertNotCancelled(signal);
|
|
@@ -30538,6 +30632,11 @@ class ObjLoader {
|
|
|
30538
30632
|
throw new Error("The OBJ import was cancelled.");
|
|
30539
30633
|
}
|
|
30540
30634
|
}
|
|
30635
|
+
assertMaterialTextures(resources, materialSource, materialBaseUrl, creator) {
|
|
30636
|
+
for (const textureReference of this.getMaterialTextureReferences(materialSource, creator)) {
|
|
30637
|
+
resources.resolveTextureUrl(materialBaseUrl, textureReference);
|
|
30638
|
+
}
|
|
30639
|
+
}
|
|
30541
30640
|
collectMaterials(material, materials) {
|
|
30542
30641
|
if (Array.isArray(material)) {
|
|
30543
30642
|
for (const item of material) {
|
|
@@ -30547,6 +30646,17 @@ class ObjLoader {
|
|
|
30547
30646
|
}
|
|
30548
30647
|
materials.add(material);
|
|
30549
30648
|
}
|
|
30649
|
+
createResourceSource(resources) {
|
|
30650
|
+
if (resources.mtlUrl === void 0) {
|
|
30651
|
+
return {
|
|
30652
|
+
objUrl: resources.objUrl
|
|
30653
|
+
};
|
|
30654
|
+
}
|
|
30655
|
+
return {
|
|
30656
|
+
mtlUrl: resources.mtlUrl,
|
|
30657
|
+
objUrl: resources.objUrl
|
|
30658
|
+
};
|
|
30659
|
+
}
|
|
30550
30660
|
disposeFailedModel(model) {
|
|
30551
30661
|
if (model === void 0) {
|
|
30552
30662
|
return;
|
|
@@ -30570,6 +30680,11 @@ class ObjLoader {
|
|
|
30570
30680
|
const resourceOwner = new Model(new Group(), [...materials]);
|
|
30571
30681
|
resourceOwner.dispose();
|
|
30572
30682
|
}
|
|
30683
|
+
disposeMaterialsWithoutTextures(materials) {
|
|
30684
|
+
for (const material of materials) {
|
|
30685
|
+
material.dispose();
|
|
30686
|
+
}
|
|
30687
|
+
}
|
|
30573
30688
|
getMaterialArray(context) {
|
|
30574
30689
|
if (context === void 0) {
|
|
30575
30690
|
return [];
|
|
@@ -30592,20 +30707,33 @@ class ObjLoader {
|
|
|
30592
30707
|
getTextureFailureCode(outcome) {
|
|
30593
30708
|
return outcome === "cancelled" ? ObjImportFailureCode$1.Cancelled : ObjImportFailureCode$1.InvalidSource;
|
|
30594
30709
|
}
|
|
30595
|
-
|
|
30710
|
+
getMaterialLibraryReferences(objSource) {
|
|
30711
|
+
const materialReferences = [];
|
|
30596
30712
|
for (const line of objSource.split(/\r?\n/u)) {
|
|
30597
30713
|
const materialReference = /^\s*mtllib\s+(.+?)\s*$/u.exec(line)?.[1];
|
|
30598
30714
|
if (materialReference !== void 0) {
|
|
30599
|
-
|
|
30715
|
+
materialReferences.push(materialReference);
|
|
30600
30716
|
}
|
|
30601
30717
|
}
|
|
30602
|
-
return
|
|
30718
|
+
return materialReferences;
|
|
30719
|
+
}
|
|
30720
|
+
getMaterialTextureReferences(materialSource, creator) {
|
|
30721
|
+
const textureReferences = [];
|
|
30722
|
+
for (const line of materialSource.split(/\r?\n/u)) {
|
|
30723
|
+
const textureValue = /^\s*(?:map_\S+|bump|decal|disp|norm|refl)\s+(.+?)\s*$/iu.exec(
|
|
30724
|
+
line
|
|
30725
|
+
)?.[1];
|
|
30726
|
+
if (textureValue !== void 0) {
|
|
30727
|
+
textureReferences.push(creator.getTextureParams(textureValue, {}).url);
|
|
30728
|
+
}
|
|
30729
|
+
}
|
|
30730
|
+
return textureReferences;
|
|
30603
30731
|
}
|
|
30604
|
-
getMaterialUrl(source,
|
|
30732
|
+
getMaterialUrl(source, materialReferences) {
|
|
30605
30733
|
if (source.mtlUrl !== void 0) {
|
|
30606
30734
|
return source.mtlUrl;
|
|
30607
30735
|
}
|
|
30608
|
-
const materialReference =
|
|
30736
|
+
const materialReference = materialReferences[0];
|
|
30609
30737
|
if (materialReference === void 0) {
|
|
30610
30738
|
return void 0;
|
|
30611
30739
|
}
|
|
@@ -30635,21 +30763,29 @@ class ObjLoader {
|
|
|
30635
30763
|
isPoints(object) {
|
|
30636
30764
|
return object instanceof Points;
|
|
30637
30765
|
}
|
|
30638
|
-
async loadMaterialContext(mtlUrl, textureUrls, signal) {
|
|
30766
|
+
async loadMaterialContext(mtlUrl, textureUrls, signal, resources) {
|
|
30639
30767
|
const materialSource = await this.loadText(mtlUrl, signal);
|
|
30640
30768
|
this.assertNotCancelled(signal);
|
|
30641
30769
|
const materialBaseUrl = this.getResourceDirectoryUrl(mtlUrl);
|
|
30642
30770
|
const manager = new LoadingManager();
|
|
30643
|
-
manager.setURLModifier(
|
|
30771
|
+
manager.setURLModifier(
|
|
30772
|
+
resources === void 0 ? this.resolveTextureUrl.bind(this, textureUrls, materialBaseUrl) : resources.resolveTextureUrl.bind(resources, materialBaseUrl)
|
|
30773
|
+
);
|
|
30644
30774
|
const materialLoader = new MTLLoader(manager);
|
|
30645
30775
|
materialLoader.setMaterialOptions({
|
|
30646
30776
|
side: DoubleSide
|
|
30647
30777
|
});
|
|
30648
30778
|
const creator = materialLoader.parse(materialSource, materialBaseUrl);
|
|
30779
|
+
const pbrMaterialReferences = this.parsePbrMaterialReferences(materialSource);
|
|
30780
|
+
if (resources !== void 0) {
|
|
30781
|
+
this.assertMaterialTextures(resources, materialSource, materialBaseUrl, creator);
|
|
30782
|
+
}
|
|
30649
30783
|
this.validateTextureOverrides(textureUrls);
|
|
30784
|
+
this.removeLegacyPbrTextureMappings(creator);
|
|
30650
30785
|
const monitor = new TextureLoadMonitor(manager, creator);
|
|
30651
30786
|
try {
|
|
30652
30787
|
creator.preload();
|
|
30788
|
+
this.replaceMaterialsWithPbr(creator, pbrMaterialReferences, materialBaseUrl);
|
|
30653
30789
|
monitor.finishScheduling();
|
|
30654
30790
|
} catch (error2) {
|
|
30655
30791
|
monitor.finishScheduling();
|
|
@@ -30704,6 +30840,77 @@ class ObjLoader {
|
|
|
30704
30840
|
}
|
|
30705
30841
|
this.disposeMaterials(materialsToDispose);
|
|
30706
30842
|
}
|
|
30843
|
+
createPbrMaterial(source, references, creator, materialBaseUrl) {
|
|
30844
|
+
const material = new MeshStandardMaterial();
|
|
30845
|
+
material.alphaMap = source.alphaMap;
|
|
30846
|
+
material.alphaTest = source.alphaTest;
|
|
30847
|
+
material.color.copy(source.color);
|
|
30848
|
+
material.displacementBias = source.displacementBias;
|
|
30849
|
+
material.displacementMap = source.displacementMap;
|
|
30850
|
+
material.displacementScale = source.displacementScale;
|
|
30851
|
+
material.emissive.copy(source.emissive);
|
|
30852
|
+
material.emissiveIntensity = source.emissiveIntensity;
|
|
30853
|
+
material.emissiveMap = source.emissiveMap;
|
|
30854
|
+
material.map = source.map;
|
|
30855
|
+
material.name = source.name;
|
|
30856
|
+
material.opacity = source.opacity;
|
|
30857
|
+
material.side = source.side;
|
|
30858
|
+
material.transparent = source.transparent;
|
|
30859
|
+
material.vertexColors = source.vertexColors;
|
|
30860
|
+
if (material.map !== null) {
|
|
30861
|
+
material.map.colorSpace = SRGBColorSpace;
|
|
30862
|
+
}
|
|
30863
|
+
if (material.emissiveMap !== null) {
|
|
30864
|
+
material.emissiveMap.colorSpace = SRGBColorSpace;
|
|
30865
|
+
}
|
|
30866
|
+
const roughnessReference = references.roughness ?? references.roughnessFallback;
|
|
30867
|
+
if (roughnessReference !== void 0) {
|
|
30868
|
+
material.roughnessMap = this.loadPbrTexture(
|
|
30869
|
+
creator,
|
|
30870
|
+
materialBaseUrl,
|
|
30871
|
+
roughnessReference
|
|
30872
|
+
).texture;
|
|
30873
|
+
}
|
|
30874
|
+
if (references.metalness !== void 0) {
|
|
30875
|
+
material.metalnessMap = this.loadPbrTexture(
|
|
30876
|
+
creator,
|
|
30877
|
+
materialBaseUrl,
|
|
30878
|
+
references.metalness
|
|
30879
|
+
).texture;
|
|
30880
|
+
}
|
|
30881
|
+
const normalReference = references.normal ?? references.legacyNormal;
|
|
30882
|
+
if (normalReference !== void 0) {
|
|
30883
|
+
const normalTexture = this.loadPbrTexture(creator, materialBaseUrl, normalReference);
|
|
30884
|
+
material.normalMap = normalTexture.texture;
|
|
30885
|
+
if (normalTexture.bumpScale !== void 0) {
|
|
30886
|
+
material.normalScale.set(normalTexture.bumpScale, normalTexture.bumpScale);
|
|
30887
|
+
}
|
|
30888
|
+
}
|
|
30889
|
+
if (references.bump !== void 0) {
|
|
30890
|
+
const bumpTexture = this.loadPbrTexture(creator, materialBaseUrl, references.bump);
|
|
30891
|
+
material.bumpMap = bumpTexture.texture;
|
|
30892
|
+
if (bumpTexture.bumpScale !== void 0) {
|
|
30893
|
+
material.bumpScale = bumpTexture.bumpScale;
|
|
30894
|
+
}
|
|
30895
|
+
}
|
|
30896
|
+
return material;
|
|
30897
|
+
}
|
|
30898
|
+
loadPbrTexture(creator, materialBaseUrl, reference) {
|
|
30899
|
+
const materialParameters = {};
|
|
30900
|
+
const textureParameters = creator.getTextureParams(reference, materialParameters);
|
|
30901
|
+
const texture = creator.loadTexture(
|
|
30902
|
+
this.resolveResourceUrl(textureParameters.url, materialBaseUrl)
|
|
30903
|
+
);
|
|
30904
|
+
texture.colorSpace = NoColorSpace;
|
|
30905
|
+
texture.offset.copy(textureParameters.offset);
|
|
30906
|
+
texture.repeat.copy(textureParameters.scale);
|
|
30907
|
+
texture.wrapS = creator.wrap;
|
|
30908
|
+
texture.wrapT = creator.wrap;
|
|
30909
|
+
return {
|
|
30910
|
+
bumpScale: materialParameters.bumpScale,
|
|
30911
|
+
texture
|
|
30912
|
+
};
|
|
30913
|
+
}
|
|
30707
30914
|
parseObj(source, materials) {
|
|
30708
30915
|
if (materials === void 0) {
|
|
30709
30916
|
return this.parser.parse(source);
|
|
@@ -30712,6 +30919,78 @@ class ObjLoader {
|
|
|
30712
30919
|
parser.setMaterials(materials);
|
|
30713
30920
|
return parser.parse(source);
|
|
30714
30921
|
}
|
|
30922
|
+
parsePbrMaterialReferences(materialSource) {
|
|
30923
|
+
const referencesByMaterial = {};
|
|
30924
|
+
let currentReferences;
|
|
30925
|
+
for (const line of materialSource.split(/\r?\n/u)) {
|
|
30926
|
+
const materialName = /^\s*newmtl\s+(.+?)\s*$/iu.exec(line)?.[1];
|
|
30927
|
+
if (materialName !== void 0) {
|
|
30928
|
+
currentReferences = {
|
|
30929
|
+
bump: void 0,
|
|
30930
|
+
legacyNormal: void 0,
|
|
30931
|
+
metalness: void 0,
|
|
30932
|
+
normal: void 0,
|
|
30933
|
+
roughness: void 0,
|
|
30934
|
+
roughnessFallback: void 0
|
|
30935
|
+
};
|
|
30936
|
+
referencesByMaterial[materialName] = currentReferences;
|
|
30937
|
+
continue;
|
|
30938
|
+
}
|
|
30939
|
+
if (currentReferences === void 0) {
|
|
30940
|
+
continue;
|
|
30941
|
+
}
|
|
30942
|
+
const textureReference = /^\s*(map_pr|map_ns|map_pm|map_bump|bump|norm)\s+(.+?)\s*$/iu.exec(line);
|
|
30943
|
+
if (textureReference === null) {
|
|
30944
|
+
continue;
|
|
30945
|
+
}
|
|
30946
|
+
const [, directive = "", value = ""] = textureReference;
|
|
30947
|
+
switch (directive.toLowerCase()) {
|
|
30948
|
+
case "bump":
|
|
30949
|
+
currentReferences.bump = value;
|
|
30950
|
+
break;
|
|
30951
|
+
case "map_bump":
|
|
30952
|
+
currentReferences.legacyNormal = value;
|
|
30953
|
+
break;
|
|
30954
|
+
case "map_pm":
|
|
30955
|
+
currentReferences.metalness = value;
|
|
30956
|
+
break;
|
|
30957
|
+
case "map_ns":
|
|
30958
|
+
currentReferences.roughnessFallback = value;
|
|
30959
|
+
break;
|
|
30960
|
+
case "map_pr":
|
|
30961
|
+
currentReferences.roughness = value;
|
|
30962
|
+
break;
|
|
30963
|
+
case "norm":
|
|
30964
|
+
currentReferences.normal = value;
|
|
30965
|
+
break;
|
|
30966
|
+
}
|
|
30967
|
+
}
|
|
30968
|
+
return referencesByMaterial;
|
|
30969
|
+
}
|
|
30970
|
+
removeLegacyPbrTextureMappings(creator) {
|
|
30971
|
+
for (const materialInfo of Object.values(creator.materialsInfo)) {
|
|
30972
|
+
delete materialInfo.bump;
|
|
30973
|
+
delete materialInfo.map_bump;
|
|
30974
|
+
delete materialInfo.norm;
|
|
30975
|
+
}
|
|
30976
|
+
}
|
|
30977
|
+
replaceMaterialsWithPbr(creator, referencesByMaterial, materialBaseUrl) {
|
|
30978
|
+
const replacedMaterials = /* @__PURE__ */ new Set();
|
|
30979
|
+
for (const [materialName, references] of Object.entries(referencesByMaterial)) {
|
|
30980
|
+
const sourceMaterial = creator.materials[materialName];
|
|
30981
|
+
if (!(sourceMaterial instanceof MeshPhongMaterial)) {
|
|
30982
|
+
throw new Error("The MTL loader did not create a phong material.");
|
|
30983
|
+
}
|
|
30984
|
+
creator.materials[materialName] = this.createPbrMaterial(
|
|
30985
|
+
sourceMaterial,
|
|
30986
|
+
references,
|
|
30987
|
+
creator,
|
|
30988
|
+
materialBaseUrl
|
|
30989
|
+
);
|
|
30990
|
+
replacedMaterials.add(sourceMaterial);
|
|
30991
|
+
}
|
|
30992
|
+
this.disposeMaterialsWithoutTextures(replacedMaterials);
|
|
30993
|
+
}
|
|
30715
30994
|
resolveResourceUrl(reference, baseUrl) {
|
|
30716
30995
|
return new URL(reference, this.toAbsoluteUrl(baseUrl)).href;
|
|
30717
30996
|
}
|
|
@@ -30740,6 +31019,101 @@ class ObjLoader {
|
|
|
30740
31019
|
}
|
|
30741
31020
|
}
|
|
30742
31021
|
}
|
|
31022
|
+
class ObjResourceList {
|
|
31023
|
+
mtlUrl;
|
|
31024
|
+
objUrl;
|
|
31025
|
+
mtlFileName;
|
|
31026
|
+
textureUrls = /* @__PURE__ */ new Set();
|
|
31027
|
+
textureUrlsByFileName = /* @__PURE__ */ new Map();
|
|
31028
|
+
constructor(fileUrls) {
|
|
31029
|
+
let mtlFileName;
|
|
31030
|
+
let mtlUrl;
|
|
31031
|
+
let objUrl;
|
|
31032
|
+
const seenFileNames = /* @__PURE__ */ new Set();
|
|
31033
|
+
const seenUrls = /* @__PURE__ */ new Set();
|
|
31034
|
+
for (const fileUrl of fileUrls) {
|
|
31035
|
+
const resource = this.createResourceEntry(fileUrl);
|
|
31036
|
+
if (seenUrls.has(resource.url) || seenFileNames.has(resource.fileName)) {
|
|
31037
|
+
throw new Error("The OBJ resource list contains a duplicate resource.");
|
|
31038
|
+
}
|
|
31039
|
+
seenUrls.add(resource.url);
|
|
31040
|
+
seenFileNames.add(resource.fileName);
|
|
31041
|
+
if (this.isObjUrl(resource.url)) {
|
|
31042
|
+
if (objUrl !== void 0) {
|
|
31043
|
+
throw new Error("The OBJ resource list must contain exactly one OBJ file.");
|
|
31044
|
+
}
|
|
31045
|
+
objUrl = resource.url;
|
|
31046
|
+
continue;
|
|
31047
|
+
}
|
|
31048
|
+
if (this.isMtlUrl(resource.url)) {
|
|
31049
|
+
if (mtlUrl !== void 0) {
|
|
31050
|
+
throw new Error("The OBJ resource list cannot contain multiple MTL files.");
|
|
31051
|
+
}
|
|
31052
|
+
mtlFileName = resource.fileName;
|
|
31053
|
+
mtlUrl = resource.url;
|
|
31054
|
+
continue;
|
|
31055
|
+
}
|
|
31056
|
+
this.textureUrls.add(resource.url);
|
|
31057
|
+
this.textureUrlsByFileName.set(resource.fileName, resource.url);
|
|
31058
|
+
}
|
|
31059
|
+
if (objUrl === void 0) {
|
|
31060
|
+
throw new Error("The OBJ resource list must contain an OBJ file.");
|
|
31061
|
+
}
|
|
31062
|
+
this.mtlFileName = mtlFileName;
|
|
31063
|
+
this.mtlUrl = mtlUrl;
|
|
31064
|
+
this.objUrl = objUrl;
|
|
31065
|
+
}
|
|
31066
|
+
assertMaterialLibraries(materialReferences) {
|
|
31067
|
+
if (materialReferences.length === 0) {
|
|
31068
|
+
return;
|
|
31069
|
+
}
|
|
31070
|
+
const mtlUrl = this.mtlUrl;
|
|
31071
|
+
const mtlFileName = this.mtlFileName;
|
|
31072
|
+
const [materialReference, ...remainingReferences] = materialReferences;
|
|
31073
|
+
if (materialReference === void 0 || remainingReferences.length > 0 || mtlUrl === void 0 || mtlFileName === void 0) {
|
|
31074
|
+
throw new Error("The OBJ material library is not present in the resource list.");
|
|
31075
|
+
}
|
|
31076
|
+
const referenceUrl = new URL(materialReference, this.objUrl).href;
|
|
31077
|
+
if (referenceUrl === mtlUrl || this.getFileName(new URL(referenceUrl)) === mtlFileName) {
|
|
31078
|
+
return;
|
|
31079
|
+
}
|
|
31080
|
+
throw new Error("The OBJ material library does not match the resource list.");
|
|
31081
|
+
}
|
|
31082
|
+
resolveTextureUrl(materialBaseUrl, textureUrl) {
|
|
31083
|
+
const resolvedUrl = new URL(textureUrl, materialBaseUrl).href;
|
|
31084
|
+
if (this.textureUrls.has(resolvedUrl)) {
|
|
31085
|
+
return resolvedUrl;
|
|
31086
|
+
}
|
|
31087
|
+
const mappedUrl = this.textureUrlsByFileName.get(this.getFileName(new URL(resolvedUrl)));
|
|
31088
|
+
if (mappedUrl === void 0) {
|
|
31089
|
+
throw new Error("The MTL texture is not present in the resource list.");
|
|
31090
|
+
}
|
|
31091
|
+
return mappedUrl;
|
|
31092
|
+
}
|
|
31093
|
+
createResourceEntry(fileUrl) {
|
|
31094
|
+
const url = new URL(fileUrl);
|
|
31095
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
31096
|
+
throw new Error("The OBJ resource list only accepts HTTP URLs.");
|
|
31097
|
+
}
|
|
31098
|
+
return {
|
|
31099
|
+
fileName: this.getFileName(url),
|
|
31100
|
+
url: url.href
|
|
31101
|
+
};
|
|
31102
|
+
}
|
|
31103
|
+
getFileName(url) {
|
|
31104
|
+
const fileName = decodeURIComponent(url.pathname.slice(url.pathname.lastIndexOf("/") + 1));
|
|
31105
|
+
if (fileName.length === 0) {
|
|
31106
|
+
throw new Error("The OBJ resource URL must include a file name.");
|
|
31107
|
+
}
|
|
31108
|
+
return fileName;
|
|
31109
|
+
}
|
|
31110
|
+
isMtlUrl(url) {
|
|
31111
|
+
return new URL(url).pathname.toLowerCase().endsWith(".mtl");
|
|
31112
|
+
}
|
|
31113
|
+
isObjUrl(url) {
|
|
31114
|
+
return new URL(url).pathname.toLowerCase().endsWith(".obj");
|
|
31115
|
+
}
|
|
31116
|
+
}
|
|
30743
31117
|
const DEFAULT_BACKGROUND_COLOR = 3355443;
|
|
30744
31118
|
class Renderer {
|
|
30745
31119
|
activeModels = [];
|
|
@@ -30911,6 +31285,47 @@ class Renderer {
|
|
|
30911
31285
|
stone: source
|
|
30912
31286
|
});
|
|
30913
31287
|
}
|
|
31288
|
+
importObjResources(source) {
|
|
31289
|
+
this.assertNotDisposed();
|
|
31290
|
+
if (this.contextLost) {
|
|
31291
|
+
return Promise.resolve({
|
|
31292
|
+
code: ObjImportFailureCode$1.RenderFailed,
|
|
31293
|
+
success: false
|
|
31294
|
+
});
|
|
31295
|
+
}
|
|
31296
|
+
const session = this.startImportSession();
|
|
31297
|
+
try {
|
|
31298
|
+
return this.completeResourceListImport(session, new ObjResourceList(source.fileUrls));
|
|
31299
|
+
} catch {
|
|
31300
|
+
this.finishImportSession(session);
|
|
31301
|
+
return Promise.resolve({
|
|
31302
|
+
code: ObjImportFailureCode$1.InvalidSource,
|
|
31303
|
+
success: false
|
|
31304
|
+
});
|
|
31305
|
+
}
|
|
31306
|
+
}
|
|
31307
|
+
importObjResourceScene(source) {
|
|
31308
|
+
this.assertNotDisposed();
|
|
31309
|
+
if (this.contextLost) {
|
|
31310
|
+
return Promise.resolve({
|
|
31311
|
+
code: ObjImportFailureCode$1.RenderFailed,
|
|
31312
|
+
success: false
|
|
31313
|
+
});
|
|
31314
|
+
}
|
|
31315
|
+
const session = this.startImportSession();
|
|
31316
|
+
try {
|
|
31317
|
+
return this.completeSceneImport(session, {
|
|
31318
|
+
base: source.base === void 0 ? void 0 : new ObjResourceList(source.base.fileUrls),
|
|
31319
|
+
stone: source.stone === void 0 ? void 0 : new ObjResourceList(source.stone.fileUrls)
|
|
31320
|
+
});
|
|
31321
|
+
} catch {
|
|
31322
|
+
this.finishImportSession(session);
|
|
31323
|
+
return Promise.resolve({
|
|
31324
|
+
code: ObjImportFailureCode$1.InvalidSource,
|
|
31325
|
+
success: false
|
|
31326
|
+
});
|
|
31327
|
+
}
|
|
31328
|
+
}
|
|
30914
31329
|
importObjScene(source) {
|
|
30915
31330
|
this.assertNotDisposed();
|
|
30916
31331
|
if (this.contextLost) {
|
|
@@ -30928,6 +31343,28 @@ class Renderer {
|
|
|
30928
31343
|
this.controller.reset();
|
|
30929
31344
|
this.requestRender();
|
|
30930
31345
|
}
|
|
31346
|
+
takeScreenshot() {
|
|
31347
|
+
this.assertNotDisposed();
|
|
31348
|
+
if (this.contextLost) {
|
|
31349
|
+
return Promise.reject(new Error("The WebGL context is unavailable."));
|
|
31350
|
+
}
|
|
31351
|
+
try {
|
|
31352
|
+
this.renderScene();
|
|
31353
|
+
} catch (error2) {
|
|
31354
|
+
return Promise.reject(
|
|
31355
|
+
new Error("The screenshot could not be rendered.", { cause: error2 })
|
|
31356
|
+
);
|
|
31357
|
+
}
|
|
31358
|
+
return new Promise((resolve, reject) => {
|
|
31359
|
+
this.canvas.toBlob((blob) => {
|
|
31360
|
+
if (blob === null) {
|
|
31361
|
+
reject(new Error("The screenshot could not be encoded."));
|
|
31362
|
+
return;
|
|
31363
|
+
}
|
|
31364
|
+
resolve(blob);
|
|
31365
|
+
}, "image/png");
|
|
31366
|
+
});
|
|
31367
|
+
}
|
|
30931
31368
|
assertNotDisposed() {
|
|
30932
31369
|
if (this.disposed) {
|
|
30933
31370
|
throw new Error("The renderer has been disposed.");
|
|
@@ -30951,7 +31388,7 @@ class Renderer {
|
|
|
30951
31388
|
success: false
|
|
30952
31389
|
};
|
|
30953
31390
|
}
|
|
30954
|
-
const firstCandidate = await this.
|
|
31391
|
+
const firstCandidate = await this.loadModel(session, firstSource);
|
|
30955
31392
|
if (this.isImportResult(firstCandidate)) {
|
|
30956
31393
|
return firstCandidate;
|
|
30957
31394
|
}
|
|
@@ -30959,7 +31396,7 @@ class Renderer {
|
|
|
30959
31396
|
if (stoneSource === void 0 || baseSource === void 0) {
|
|
30960
31397
|
return this.replaceActiveModels(session, candidateModels);
|
|
30961
31398
|
}
|
|
30962
|
-
const secondCandidate = await this.
|
|
31399
|
+
const secondCandidate = await this.loadModel(session, baseSource);
|
|
30963
31400
|
if (this.isImportResult(secondCandidate)) {
|
|
30964
31401
|
this.releaseModels(candidateModels);
|
|
30965
31402
|
return secondCandidate;
|
|
@@ -30967,10 +31404,17 @@ class Renderer {
|
|
|
30967
31404
|
candidateModels.push(secondCandidate);
|
|
30968
31405
|
return this.replaceActiveModels(session, candidateModels);
|
|
30969
31406
|
}
|
|
30970
|
-
async
|
|
31407
|
+
async completeResourceListImport(session, resources) {
|
|
31408
|
+
const candidate = await this.loadModel(session, resources);
|
|
31409
|
+
if (this.isImportResult(candidate)) {
|
|
31410
|
+
return candidate;
|
|
31411
|
+
}
|
|
31412
|
+
return this.replaceActiveModels(session, [candidate]);
|
|
31413
|
+
}
|
|
31414
|
+
async loadModel(session, source) {
|
|
30971
31415
|
let result;
|
|
30972
31416
|
try {
|
|
30973
|
-
result = await this.modelLoader.load(source, session.controller.signal);
|
|
31417
|
+
result = source instanceof ObjResourceList ? await this.modelLoader.loadResources(source, session.controller.signal) : await this.modelLoader.load(source, session.controller.signal);
|
|
30974
31418
|
} catch {
|
|
30975
31419
|
return this.completeUnexpectedImportFailure(session);
|
|
30976
31420
|
}
|
|
@@ -31098,13 +31542,16 @@ class Renderer {
|
|
|
31098
31542
|
return;
|
|
31099
31543
|
}
|
|
31100
31544
|
const animationActive = this.controller.updateAnimation(timestamp);
|
|
31101
|
-
this.
|
|
31102
|
-
this.renderer.render(this.scene, this.camera);
|
|
31103
|
-
this.renderViewCube();
|
|
31545
|
+
this.renderScene();
|
|
31104
31546
|
if (animationActive) {
|
|
31105
31547
|
this.requestRender();
|
|
31106
31548
|
}
|
|
31107
31549
|
}
|
|
31550
|
+
renderScene() {
|
|
31551
|
+
this.viewCube.update(this.camera);
|
|
31552
|
+
this.renderer.render(this.scene, this.camera);
|
|
31553
|
+
this.renderViewCube();
|
|
31554
|
+
}
|
|
31108
31555
|
renderViewCube() {
|
|
31109
31556
|
const viewport = this.viewCube.getViewport();
|
|
31110
31557
|
const previousAutoClear = this.renderer.autoClear;
|
|
@@ -31256,6 +31703,14 @@ class Application {
|
|
|
31256
31703
|
this.assertNotDisposed();
|
|
31257
31704
|
return this.mapAsyncObjImportResult(this.getRenderer().importObj(source));
|
|
31258
31705
|
}
|
|
31706
|
+
importObjResources(source) {
|
|
31707
|
+
this.assertNotDisposed();
|
|
31708
|
+
return this.mapAsyncObjImportResult(this.getRenderer().importObjResources(source));
|
|
31709
|
+
}
|
|
31710
|
+
importObjResourceScene(source) {
|
|
31711
|
+
this.assertNotDisposed();
|
|
31712
|
+
return this.mapAsyncObjImportResult(this.getRenderer().importObjResourceScene(source));
|
|
31713
|
+
}
|
|
31259
31714
|
importObjScene(source) {
|
|
31260
31715
|
this.assertNotDisposed();
|
|
31261
31716
|
return this.mapAsyncObjImportResult(this.getRenderer().importObjScene(source));
|
|
@@ -31264,6 +31719,10 @@ class Application {
|
|
|
31264
31719
|
this.assertNotDisposed();
|
|
31265
31720
|
this.getRenderer().resetCamera();
|
|
31266
31721
|
}
|
|
31722
|
+
takeScreenshot() {
|
|
31723
|
+
this.assertNotDisposed();
|
|
31724
|
+
return this.getRenderer().takeScreenshot();
|
|
31725
|
+
}
|
|
31267
31726
|
dispose() {
|
|
31268
31727
|
if (this.disposed) {
|
|
31269
31728
|
return;
|