bg2e-js 2.1.2 → 2.2.0

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.
Files changed (147) hide show
  1. package/dist/bg2e-js.js +7031 -6989
  2. package/dist/bg2e-js.js.map +1 -1
  3. package/package.json +20 -2
  4. package/src/app/AppController.ts +39 -0
  5. package/src/app/Bg2KeyboardEvent.ts +54 -0
  6. package/src/app/Bg2MouseEvent.ts +82 -0
  7. package/src/app/Bg2TouchEvent.ts +18 -0
  8. package/src/app/Canvas.ts +108 -0
  9. package/src/app/EventBase.ts +10 -0
  10. package/src/app/MainLoop.ts +273 -0
  11. package/src/app/index.ts +25 -0
  12. package/src/base/Color.ts +134 -0
  13. package/src/base/Environment.ts +183 -0
  14. package/src/base/Light.ts +192 -0
  15. package/src/base/Material.ts +616 -0
  16. package/src/base/PolyList.ts +365 -0
  17. package/src/base/Texture.ts +620 -0
  18. package/src/base/index.ts +81 -0
  19. package/src/db/Bg2LoaderPlugin.ts +129 -0
  20. package/src/db/DBPluginApi.ts +48 -0
  21. package/src/db/Loader.ts +116 -0
  22. package/src/db/LoaderPlugin.ts +34 -0
  23. package/src/db/MtlParser.ts +7 -0
  24. package/src/db/ObjLoaderPlugin.ts +55 -0
  25. package/src/db/ObjParser.ts +252 -0
  26. package/src/db/ObjWriterPlugin.ts +19 -0
  27. package/src/db/VitscnjLoaderPlugin.ts +100 -0
  28. package/src/db/Writer.ts +52 -0
  29. package/src/db/WriterPlugin.ts +22 -0
  30. package/src/db/index.ts +44 -0
  31. package/src/debug/DebugRenderer.ts +173 -0
  32. package/src/debug/WebGLTextureViewer.ts +75 -0
  33. package/src/debug/index.ts +7 -0
  34. package/src/index.html +11 -0
  35. package/src/index.ts +33 -0
  36. package/src/manipulation/SelectionBuffer.ts +82 -0
  37. package/src/manipulation/SelectionHighlight.ts +85 -0
  38. package/src/manipulation/SelectionIdAssignVisitor.ts +97 -0
  39. package/src/manipulation/SelectionManager.ts +166 -0
  40. package/src/manipulation/SelectionMode.ts +6 -0
  41. package/src/math/Mat3.ts +259 -0
  42. package/src/math/Mat4.ts +706 -0
  43. package/src/math/MatrixStrategy.ts +25 -0
  44. package/src/math/Quat.ts +65 -0
  45. package/src/math/Vec.ts +753 -0
  46. package/src/math/constants.ts +47 -0
  47. package/src/math/functions.ts +103 -0
  48. package/src/math/index.ts +74 -0
  49. package/src/phsics/joint.ts +137 -0
  50. package/src/primitives/arrow.ts +58 -0
  51. package/src/primitives/cone.ts +138 -0
  52. package/src/primitives/cube.ts +60 -0
  53. package/src/primitives/cylinder.ts +216 -0
  54. package/src/primitives/index.ts +13 -0
  55. package/src/primitives/plane.ts +31 -0
  56. package/src/primitives/sphere.ts +809 -0
  57. package/src/render/BRDFIntegrationMap.ts +4 -0
  58. package/src/render/Environment.ts +136 -0
  59. package/src/render/FrameBuffer.ts +35 -0
  60. package/src/render/MaterialRenderer.ts +34 -0
  61. package/src/render/Pipeline.ts +109 -0
  62. package/src/render/PolyListRenderer.ts +47 -0
  63. package/src/render/RenderBuffer.ts +197 -0
  64. package/src/render/RenderQueue.ts +199 -0
  65. package/src/render/RenderState.ts +116 -0
  66. package/src/render/Renderer.ts +248 -0
  67. package/src/render/SceneAppController.ts +238 -0
  68. package/src/render/SceneRenderer.ts +373 -0
  69. package/src/render/Shader.ts +32 -0
  70. package/src/render/ShadowRenderer.ts +176 -0
  71. package/src/render/SkyCube.ts +106 -0
  72. package/src/render/SkySphere.ts +118 -0
  73. package/src/render/TextureMergerRenderer.ts +70 -0
  74. package/src/render/TextureRenderer.ts +34 -0
  75. package/src/render/index.ts +67 -0
  76. package/src/render/webgl/FrameBuffer.ts +10 -0
  77. package/src/render/webgl/MaterialRenderer.ts +113 -0
  78. package/src/render/webgl/Pipeline.ts +89 -0
  79. package/src/render/webgl/PolyListRenderer.ts +260 -0
  80. package/src/render/webgl/RenderBuffer.ts +227 -0
  81. package/src/render/webgl/Renderer.ts +262 -0
  82. package/src/render/webgl/SceneRenderer.ts +68 -0
  83. package/src/render/webgl/ShaderProgram.ts +424 -0
  84. package/src/render/webgl/ShadowRenderer.ts +6 -0
  85. package/src/render/webgl/SkyCube.ts +16 -0
  86. package/src/render/webgl/SkySphere.ts +16 -0
  87. package/src/render/webgl/State.ts +152 -0
  88. package/src/render/webgl/TextureRenderer.ts +167 -0
  89. package/src/render/webgl/VertexBuffer.ts +137 -0
  90. package/src/render/webgl/index.ts +35 -0
  91. package/src/scene/Camera.ts +458 -0
  92. package/src/scene/Chain.ts +44 -0
  93. package/src/scene/ChainJoint.ts +58 -0
  94. package/src/scene/Component.ts +173 -0
  95. package/src/scene/ComponentMap.ts +107 -0
  96. package/src/scene/Drawable.ts +154 -0
  97. package/src/scene/EnvironmentComponent.ts +142 -0
  98. package/src/scene/FindNodeVisitor.ts +60 -0
  99. package/src/scene/LightComponent.ts +155 -0
  100. package/src/scene/MatrixState.ts +46 -0
  101. package/src/scene/Node.ts +314 -0
  102. package/src/scene/NodeVisitor.ts +15 -0
  103. package/src/scene/OrbitCameraController.ts +450 -0
  104. package/src/scene/SmoothOrbitCameraController.ts +99 -0
  105. package/src/scene/Transform.ts +73 -0
  106. package/src/scene/index.ts +57 -0
  107. package/src/shaders/BasicDiffuseColorShader.ts +111 -0
  108. package/src/shaders/BasicPBRLightShader.ts +277 -0
  109. package/src/shaders/DebugRenderShader.ts +98 -0
  110. package/src/shaders/DepthRenderShader.ts +91 -0
  111. package/src/shaders/IrradianceMapCubeShader.ts +116 -0
  112. package/src/shaders/PBRLightIBLShader.ts +487 -0
  113. package/src/shaders/PickSelectionShader.ts +101 -0
  114. package/src/shaders/PresentDebugFramebufferShader.ts +118 -0
  115. package/src/shaders/PresentTextureShader.ts +99 -0
  116. package/src/shaders/SelectionHighlightShader.ts +127 -0
  117. package/src/shaders/ShaderFunction.ts +318 -0
  118. package/src/shaders/SkyCubeShader.ts +94 -0
  119. package/src/shaders/SkySphereShader.ts +102 -0
  120. package/src/shaders/SpecularMapCubeShader.ts +165 -0
  121. package/src/shaders/TextureMergerShader.ts +171 -0
  122. package/src/shaders/index.ts +37 -0
  123. package/src/shaders/webgl/color_correction.glsl +47 -0
  124. package/src/shaders/webgl/constants.glsl +6 -0
  125. package/src/shaders/webgl/index.ts +70 -0
  126. package/src/shaders/webgl/normal_map.glsl +9 -0
  127. package/src/shaders/webgl/pbr.glsl +173 -0
  128. package/src/shaders/webgl/uniforms.glsl +91 -0
  129. package/src/shaders/webgl_shader_lib.ts +213 -0
  130. package/src/tools/BinaryResourceProvider.ts +14 -0
  131. package/src/tools/ImageResourceProvider.ts +66 -0
  132. package/src/tools/MaterialModifier.ts +276 -0
  133. package/src/tools/Resource.ts +203 -0
  134. package/src/tools/ResourceProvider.ts +69 -0
  135. package/src/tools/TextResourceProvider.ts +24 -0
  136. package/src/tools/TextureCache.ts +52 -0
  137. package/src/tools/TextureResourceDatabase.ts +100 -0
  138. package/src/tools/UserAgent.ts +362 -0
  139. package/src/tools/VideoResourceProvider.ts +50 -0
  140. package/src/tools/WriteStrategy.ts +22 -0
  141. package/src/tools/base64.ts +11 -0
  142. package/src/tools/crypto.ts +19 -0
  143. package/src/tools/endiantess.ts +13 -0
  144. package/src/tools/image.ts +18 -0
  145. package/src/tools/index.ts +41 -0
  146. package/src/tools/processType.ts +38 -0
  147. package/src/vite-env.d.ts +12 -0
@@ -0,0 +1,129 @@
1
+ import LoaderPlugin from "./LoaderPlugin";
2
+ import { ResourceType, getFileName, removeExtension, removeFileName } from "./../tools/Resource";
3
+ import Resource from "../tools/Resource";
4
+ import PolyList from "../base/PolyList";
5
+ import Drawable from "../scene/Drawable";
6
+ import Node from "../scene/Node";
7
+ import Material from "../base/Material";
8
+ import { deserializeComponent } from "../scene/Component";
9
+
10
+ // @ts-ignore: module not typed
11
+ import Bg2ioWrapper from 'bg2io/Bg2ioBrowser';
12
+ import Loader from './Loader';
13
+
14
+ let g_bg2Wrapper: any = null;
15
+
16
+ const bg2ioFactory = async (path?: string | null): Promise<any> => {
17
+ if (g_bg2Wrapper === null) {
18
+ const params = path ? { wasmPath: path } : {};
19
+ g_bg2Wrapper = await Bg2ioWrapper(params);
20
+ if (!g_bg2Wrapper) {
21
+ throw new Error("Bg2LoaderPlugin: unable to initialize bg2io library");
22
+ }
23
+ }
24
+ return g_bg2Wrapper;
25
+ }
26
+
27
+ const createPolyList = (jsonData: any, loader: Loader): Array<{ plist: PolyList, materialData: any }> => {
28
+ const result = jsonData.polyLists.map((plData: any) => {
29
+ const plist = new PolyList();
30
+ const materialData = jsonData.materials.find((m: any) => m.name === plData.matName);
31
+ plist.name = plData.name
32
+ plist.visible = plData.visible;
33
+ if (materialData) {
34
+ plist.groupName = materialData.groupName || "";
35
+ plist.enableCullFace = materialData.cullFace;
36
+ }
37
+ plist.vertex = plData.vertex;
38
+ plist.normal = plData.normal;
39
+ plist.texCoord0 = plData.texCoord0
40
+ plist.texCoord1 = plData.texCoord1
41
+ plist.texCoord2 = plData.texCoord2
42
+ plist.index = plData.index;
43
+ return { plist, materialData };
44
+ });
45
+
46
+ return result;
47
+ }
48
+
49
+ const createDrawable = async (jsonData: any, filePath: string, loader: Loader): Promise<Drawable> => {
50
+ const name = removeExtension(getFileName(filePath));
51
+ const relativePath = removeFileName(filePath);
52
+ const drawable = new Drawable(name);
53
+ for (const item of createPolyList(jsonData, loader)) {
54
+ const mat = new Material(loader.canvas);
55
+ await mat.deserialize(item.materialData, relativePath);
56
+ drawable.addPolyList(item.plist, mat);
57
+ }
58
+ //createPolyList(jsonData).forEach(item => {
59
+ // const mat = new Material();
60
+ // mat.deserialize(item.materialData, relativePath);
61
+ // drawable.addPolyList(item.plist, mat);
62
+ //});
63
+ return drawable;
64
+ }
65
+
66
+ const createNode = async (jsonData: any, filePath: string, loader: Loader): Promise<Node> => {
67
+ const name = removeExtension(getFileName(filePath));
68
+ const drawable = await createDrawable(jsonData,filePath,loader);
69
+ const node = new Node(name);
70
+ node.addComponent(drawable);
71
+ for (const compData of jsonData.components) {
72
+ try {
73
+ const comp = await deserializeComponent(compData,loader);
74
+ comp && node.addComponent(comp);
75
+ }
76
+ catch (err: any) {
77
+ console.warn(err.message);
78
+ }
79
+ }
80
+ console.log(jsonData);
81
+ return node;
82
+ }
83
+
84
+ export default class Bg2LoaderPlugin extends LoaderPlugin {
85
+ private _bg2ioPath: string | null;
86
+ private _resource: Resource;
87
+
88
+ constructor( { bg2ioPath = null }: { bg2ioPath?: string | null } = {}) {
89
+ super();
90
+ this._bg2ioPath = bg2ioPath;
91
+ this._resource = new Resource();
92
+ }
93
+
94
+ get supportedExtensions(): string[] { return ["bg2","vwglb"]; }
95
+
96
+ get resourceTypes(): ResourceType[] {
97
+ return [
98
+ ResourceType.PolyList,
99
+ ResourceType.Drawable,
100
+ ResourceType.Node
101
+ ];
102
+ }
103
+
104
+ async load(path: string, resourceType: ResourceType, loader: Loader): Promise<any> {
105
+ const bg2io = await bg2ioFactory(this._bg2ioPath);
106
+
107
+ const buffer = await this._resource.load(path);
108
+ const jsonData = bg2io.loadBg2FileAsJson(buffer);
109
+
110
+ // Compatibility with 1.4 models
111
+ jsonData.materials.forEach((mat: any) => {
112
+ if (!mat.type) {
113
+ mat.type = mat["class"];
114
+ delete mat["class"];
115
+ }
116
+ });
117
+
118
+ switch (resourceType) {
119
+ case ResourceType.PolyList:
120
+ return createPolyList(jsonData,loader).map(item => item.plist);
121
+ case ResourceType.Drawable:
122
+ return createDrawable(jsonData,path,loader);
123
+ case ResourceType.Node:
124
+ return await createNode(jsonData,path,loader);
125
+ default:
126
+ throw new Error(`Bg2LoaderPlugin.load() unexpected resource type received: ${resourceType}`);
127
+ }
128
+ }
129
+ }
@@ -0,0 +1,48 @@
1
+ import { getExtension, ResourceType } from '../tools/Resource';
2
+ import LoaderPlugin from './LoaderPlugin';
3
+
4
+ export const PluginOperationType = {
5
+ Read: "read",
6
+ Write: "write"
7
+ } as const;
8
+
9
+ export type PluginOperationTypeValue = typeof PluginOperationType[keyof typeof PluginOperationType];
10
+
11
+ export interface PluginDatabase {
12
+ operationType: PluginOperationTypeValue;
13
+ plugins: Partial<Record<ResourceType, LoaderPlugin[]>>;
14
+ }
15
+
16
+ export const createPluginDatabase = (operationType: PluginOperationTypeValue): PluginDatabase => {
17
+ return {
18
+ operationType,
19
+ plugins: {}
20
+ }
21
+ }
22
+
23
+ export const registerPluginInDatabase = (pluginInstance: LoaderPlugin, pluginDatabase: PluginDatabase): void => {
24
+ pluginInstance.resourceTypes.forEach(type => {
25
+ pluginDatabase.plugins[type] = pluginDatabase.plugins[type] || [];
26
+ pluginDatabase.plugins[type]!.push(pluginInstance);
27
+ });
28
+ }
29
+
30
+ export const getPluginFromDatabase = function(path: string, type: ResourceType, pluginDatabase: PluginDatabase): LoaderPlugin {
31
+ const ext = getExtension(path);
32
+ const extCheck = new RegExp(ext, "i");
33
+ const errMsg = `Could not find a plugin to ${pluginDatabase.operationType} file '${path}' of type '${type}'.`;
34
+
35
+ const plugins = pluginDatabase.plugins[type];
36
+ if (!plugins) {
37
+ throw new Error(errMsg);
38
+ }
39
+ else {
40
+ for (const plugin of plugins) {
41
+ if (plugin.supportedExtensions.find(e => extCheck.test(e))) {
42
+ return plugin;
43
+ }
44
+ }
45
+ throw new Error(errMsg);
46
+ }
47
+ }
48
+
@@ -0,0 +1,116 @@
1
+
2
+ import { isAbsolute, jointUrl, ResourceType } from '../tools/Resource';
3
+ import {
4
+ PluginOperationType,
5
+ createPluginDatabase,
6
+ registerPluginInDatabase,
7
+ getPluginFromDatabase
8
+ } from './DBPluginApi';
9
+ import Canvas from '../app/Canvas';
10
+ import LoaderPlugin from './LoaderPlugin';
11
+ import PolyList from '../base/PolyList';
12
+ import Texture from '../base/Texture';
13
+
14
+ const g_loadPluginDatabase = createPluginDatabase(PluginOperationType.Read);
15
+
16
+ type ResourceCache = {
17
+ [ResourceType.PolyList]: Record<string, PolyList>;
18
+ [ResourceType.Drawable]: Record<string, any>;
19
+ [ResourceType.Node]: Record<string, any>;
20
+ [ResourceType.Texture]: Record<string, Texture>;
21
+ [ResourceType.Material]: Record<string, any>;
22
+ }
23
+
24
+ export const registerLoaderPlugin = (pluginInstance: LoaderPlugin): void => {
25
+ pluginInstance.dependencies.forEach(dep => registerPluginInDatabase(dep, g_loadPluginDatabase));
26
+ registerPluginInDatabase(pluginInstance, g_loadPluginDatabase);
27
+ }
28
+
29
+ export const getLoaderPlugin = (path: string, type: ResourceType): LoaderPlugin => {
30
+ return getPluginFromDatabase(path, type, g_loadPluginDatabase);
31
+ }
32
+
33
+ const getClearedCache = (): ResourceCache => {
34
+ return {
35
+ [ResourceType.PolyList]: {},
36
+ [ResourceType.Drawable]: {},
37
+ [ResourceType.Node]: {},
38
+ [ResourceType.Texture]: {},
39
+ [ResourceType.Material]: {}
40
+ }
41
+ }
42
+
43
+ export default class Loader {
44
+ private _canvas: Canvas;
45
+ private _cache: ResourceCache;
46
+ private _currentPath: string;
47
+
48
+ constructor(canvas?: Canvas | null) {
49
+ this._canvas = canvas || Canvas.FirstCanvas();
50
+ this._cache = getClearedCache();
51
+ this._currentPath = "";
52
+ }
53
+
54
+ get canvas(): Canvas {
55
+ return this._canvas;
56
+ }
57
+
58
+ get currentPath(): string {
59
+ return this._currentPath;
60
+ }
61
+
62
+ set currentPath(p: string) {
63
+ this._currentPath = p;
64
+ }
65
+
66
+ clearCache(): void {
67
+ this._cache = getClearedCache();
68
+ }
69
+
70
+ findCache(path: string, type: ResourceType): any {
71
+ return this._cache[type] && this._cache[type][path];
72
+ }
73
+
74
+ async loadResource(path: string, type: ResourceType): Promise<any> {
75
+ if (!isAbsolute(path) && this.currentPath !== "") {
76
+ path = jointUrl(this.currentPath, path);
77
+ }
78
+ let result = this.findCache(path, type);
79
+ if (!result) {
80
+ const plugin = getLoaderPlugin(path, type);
81
+ result = await plugin.load(path, type, this);
82
+ }
83
+ return result;
84
+ }
85
+
86
+ async loadResourceBuffer(buffer: ArrayBuffer, format: string, dependencies: string[], type: ResourceType): Promise<any> {
87
+ const plugin = getLoaderPlugin(`file.${ format }`, type);
88
+ const result = await plugin.loadBuffer(buffer, format, dependencies, type, this);
89
+ return result;
90
+ }
91
+
92
+ async loadPolyList(path: string): Promise<PolyList> {
93
+ return await this.loadResource(path, ResourceType.PolyList);
94
+ }
95
+
96
+ async loadDrawable(path: string): Promise<any> {
97
+ return await this.loadResource(path, ResourceType.Drawable);
98
+ }
99
+
100
+ async loadDrawableBuffer(buffer: ArrayBuffer, format: string, dependencies: string[]): Promise<any> {
101
+ return await this.loadResourceBuffer(buffer, format, dependencies, ResourceType.Drawable);
102
+ }
103
+
104
+ async loadNode(path: string): Promise<any> {
105
+ return await this.loadResource(path, ResourceType.Node);
106
+ }
107
+
108
+ async loadTexture(path: string): Promise<Texture> {
109
+ return await this.loadResource(path, ResourceType.Texture);
110
+ }
111
+
112
+ async loadMaterial(path: string): Promise<any> {
113
+ return await this.loadResource(path, ResourceType.Material);
114
+ }
115
+ }
116
+
@@ -0,0 +1,34 @@
1
+ import { ResourceType } from "../tools/Resource.js";
2
+
3
+ export default class LoaderPlugin {
4
+ // Returns an array of valid file extensions for this plugin
5
+ // example: ["obj","dae"]
6
+ get supportedExtensions(): string[] {
7
+ throw new Error("LoaderPlugin.supportedExtensions: attribute not implemented");
8
+ }
9
+
10
+ // Returns the resource types that the loader plugin can handle
11
+ // example: [ ResourceType.PolyList, ResourceType.Scene ]
12
+ get resourceTypes(): ResourceType[] {
13
+ throw new Error("LoaderPlugin.resourceTypes: attribute not implemented");
14
+ }
15
+
16
+ // Returns the resource loaded with the path. The resource type must be one
17
+ // of the specified in the resourceTypes attribute
18
+ async load(path: string, type: ResourceType, loader: any): Promise<any> {
19
+ throw new Error("LoaderPlugin.load(): method not implemented");
20
+ }
21
+
22
+ async loadBuffer(buffer: ArrayBuffer, format: string, dependencies: string[], type: ResourceType, loader: any): Promise<any> {
23
+ throw new Error("LoaderPlugin.loadBuffer(): method not implemented");
24
+ }
25
+
26
+ // Returns an array of LoaderPlugin objects that are necessary for this plugin to work.
27
+ get dependencies(): LoaderPlugin[] {
28
+ return [];
29
+ }
30
+
31
+ async write(path: string, data: any, type: ResourceType, writer: any): Promise<any> {
32
+ throw new Error("LoaderPlugin.write(): method not implemented");
33
+ }
34
+ }
@@ -0,0 +1,7 @@
1
+
2
+
3
+ export default class MtlParser {
4
+ constructor(mtlText: string) {
5
+
6
+ }
7
+ }
@@ -0,0 +1,55 @@
1
+ import LoaderPlugin from './LoaderPlugin';
2
+ import Resource, { getFileName, removeExtension, removeFileName, ResourceType } from './../tools/Resource';
3
+ import ObjParser from './ObjParser';
4
+ import Drawable from '../scene/Drawable';
5
+ import Material from '../base/Material';
6
+ import PolyList from '../base/PolyList';
7
+ import Loader from './Loader';
8
+
9
+ const buildDrawable = (polyListArray: PolyList[], mtlData: any, filePath: string): Drawable => {
10
+ const name = removeExtension(getFileName(filePath));
11
+ const drawable = new Drawable(name);
12
+
13
+ polyListArray.forEach((plist: PolyList) => {
14
+ // TODO: set mtl data
15
+ const mat = new Material();
16
+ drawable.addPolyList(plist,mat);
17
+ });
18
+
19
+ return drawable;
20
+ }
21
+
22
+ export default class ObjLoaderPlugin extends LoaderPlugin {
23
+ private _resource: Resource;
24
+
25
+ constructor() {
26
+ super();
27
+ this._resource = new Resource();
28
+ }
29
+
30
+ get supportedExtensions(): string[] { return ['obj']; }
31
+
32
+ get resourceTypes(): ResourceType[] {
33
+ return [
34
+ ResourceType.PolyList,
35
+ ResourceType.Drawable
36
+ ];
37
+ }
38
+
39
+ async load(path: string, resourceType: ResourceType, loader: Loader): Promise<PolyList[] | Drawable> {
40
+ const objText = await this._resource.load(path);
41
+ const parser = new ObjParser(objText);
42
+
43
+ // TODO: load material from mtl file
44
+ // const relativePath = removeFileName(filePath);
45
+
46
+ switch (resourceType) {
47
+ case ResourceType.PolyList:
48
+ return parser.polyListArray;
49
+ case ResourceType.Drawable:
50
+ return buildDrawable(parser.polyListArray, null, path);
51
+ default:
52
+ throw new Error(`ObjLoaderPlugin.load() unexpected resource type received: ${resourceType}`);
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,252 @@
1
+
2
+ import PolyList from "../base/PolyList";
3
+
4
+ function parseM(this: ObjParser, line: string) {
5
+ // mtllib
6
+ let res = /mtllib\s+(.*)/.exec(line);
7
+ if (res) {
8
+ this._mtlLib = res[1];
9
+ }
10
+ }
11
+
12
+ function parseG(this: ObjParser, line: string) {
13
+ // g
14
+ let res = /g\s+(.*)/.exec(line);
15
+ if (res && this._currentPlist) {
16
+ this._currentPlist.name = res[1];
17
+ }
18
+ }
19
+
20
+ function parseU(this: ObjParser, line: string) {
21
+ // usemtl
22
+ let res = /usemtl\s+(.*)/.exec(line);
23
+ if (res && this._currentPlist) {
24
+ // Temporarily store the material name in a custom property
25
+ (this._currentPlist as any)._matName = res[1];
26
+ if (this._currentPlist.name=="") {
27
+ this._currentPlist.name = res[1];
28
+ }
29
+ }
30
+ }
31
+
32
+ function parseS(this: ObjParser, line: string) {
33
+ // s
34
+ let res = /s\s+(.*)/.exec(line);
35
+ if (res) {
36
+ // TODO: Do something with smoothing groups
37
+ }
38
+ }
39
+
40
+ function addPoint(this: ObjParser, pointData: any) {
41
+ if (!this._currentPlist) return;
42
+ this._currentPlist.vertex.push(pointData.vertex[0],pointData.vertex[1],pointData.vertex[2]);
43
+ if (pointData.normal) {
44
+ this._currentPlist.normal.push(pointData.normal[0],pointData.normal[1],pointData.normal[2]);
45
+ }
46
+ if (pointData.tex) {
47
+ this._currentPlist.texCoord0.push(pointData.tex[0],pointData.tex[1]);
48
+ }
49
+ this._currentPlist.index.push(this._currentPlist.index.length);
50
+ }
51
+
52
+ function isValid(point: any): boolean {
53
+ return point && point.vertex && point.tex && point.normal;
54
+ }
55
+
56
+ function addPolygon(this: ObjParser, polygonData: any[]) {
57
+ let currentVertex = 0;
58
+ let sides = polygonData.length;
59
+ if (sides<3) return;
60
+ while (currentVertex<sides) {
61
+ let i0 = currentVertex;
62
+ let i1 = currentVertex + 1;
63
+ let i2 = currentVertex + 2;
64
+ if (i2==sides) {
65
+ i2 = 0;
66
+ }
67
+ else if (i1==sides) {
68
+ i1 = 0;
69
+ i2 = 2;
70
+ }
71
+
72
+ let p0 = polygonData[i0];
73
+ let p1 = polygonData[i1];
74
+ let p2 = polygonData[i2];
75
+
76
+ if (isValid(p0) && isValid(p1) && isValid(p2)) {
77
+ addPoint.apply(this,[p0]);
78
+ addPoint.apply(this,[p1]);
79
+ addPoint.apply(this,[p2]);
80
+ }
81
+ else {
82
+ console.warn("Invalid point data found loading OBJ file");
83
+ }
84
+ currentVertex+=3;
85
+ }
86
+ }
87
+
88
+ function parseF(this: ObjParser, line: string) {
89
+ // f
90
+ this._addPlist = true;
91
+ let res = /f\s+(.*)/.exec(line);
92
+ if (res) {
93
+ let params = res[1];
94
+ let vtnRE = /([\d\-]+)\/([\d\-]*)\/([\d\-]*)/g;
95
+ if (params.indexOf('/')==-1) {
96
+ let vRE = /([\d\-]+)/g;
97
+ }
98
+ let polygon = [];
99
+ while ( (res=vtnRE.exec(params)) ) {
100
+ let iV = Number(res[1]);
101
+ let iN = res[3] ? Number(res[3]):null;
102
+ let iT = res[2] ? Number(res[2]):null;
103
+ iV = iV<0 ? this._vertexArray.length + iV : iV - 1;
104
+
105
+ let v = this._vertexArray[iV];
106
+ let n: number[] | null = null;
107
+ let t: number[] | null = null;
108
+
109
+ if (iN !== null) {
110
+ iN = iN<0 ? this._normalArray.length + iN : (iN===null ? null : iN - 1);
111
+ n = iN!==null ? this._normalArray[iN] : null;
112
+ }
113
+ if (iT !== null) {
114
+ iT = iT<0 ? this._texCoordArray.length + iT : (iT===null ? null : iT - 1);
115
+ t = iT!==null ? this._texCoordArray[iT] : null;
116
+ }
117
+
118
+ polygon.push({
119
+ vertex:v,
120
+ normal:n,
121
+ tex:t
122
+ });
123
+ }
124
+ addPolygon.apply(this,[polygon]);
125
+ }
126
+ }
127
+
128
+ function parseO(this: ObjParser, line: string) {
129
+ // o
130
+ let res = /s\s+(.*)/.exec(line);
131
+ if (res && this._currentPlist?.name=="") {
132
+ this._currentPlist.name = res[1];
133
+ }
134
+ }
135
+
136
+ function checkAddPlist(this: ObjParser) {
137
+ if (this._addPlist) {
138
+ if (this._currentPlist) {
139
+ this._plistArray.push(this._currentPlist);
140
+ }
141
+ this._currentPlist = new PolyList();
142
+ this._addPlist = false;
143
+ }
144
+ }
145
+
146
+ function loadObjData(this: ObjParser) {
147
+ let lines = this._textData.split('\n');
148
+ let multiLine = "";
149
+ lines.forEach(line => {
150
+ line = line.trim();
151
+
152
+ // This section controls the break line character \
153
+ // to concatenate this new line with the next one
154
+ if (multiLine) {
155
+ line = multiLine + line;
156
+ }
157
+ if (line[line.length - 1] === '\\') {
158
+ line = line.substring(0,line.length - 1);
159
+ multiLine += line;
160
+ return;
161
+ }
162
+ else {
163
+ multiLine = "";
164
+ }
165
+
166
+ // First optimization: parse the first character and string length
167
+ if (line.length>1 && line[0] !== '#') {
168
+ // Second optimization: parse by the first character
169
+ switch (line[0]) {
170
+ case 'v':
171
+ let res = /v\s+([\d\.\-e]+)\s+([\d\.\-e]+)\s+([\d\.\-e]+)/.exec(line);
172
+ if (res) {
173
+ this._vertexArray.push(
174
+ [ Number(res[1]), Number(res[2]), Number(res[3]) ]
175
+ );
176
+ }
177
+ else if ( (res = /vn\s+([\d\.\-e]+)\s+([\d\.\-e]+)\s+([\d\.\-e]+)/.exec(line)) ) {
178
+ this._normalArray.push(
179
+ [ Number(res[1]), Number(res[2]), Number(res[3]) ]
180
+ );
181
+ }
182
+ else if ( (res = /vt\s+([\d\.\-e]+)\s+([\d\.\-e]+)/.exec(line)) ) {
183
+ this._texCoordArray.push(
184
+ [ Number(res[1]), Number(res[2]) ]
185
+ );
186
+ }
187
+ else {
188
+ console.warn("Error parsing line " + line);
189
+ }
190
+ break;
191
+ case 'm':
192
+ checkAddPlist.apply(this);
193
+ parseM.apply(this,[line]);
194
+ break;
195
+ case 'g':
196
+ checkAddPlist.apply(this);
197
+ parseG.apply(this,[line]);
198
+ break;
199
+ case 'u':
200
+ checkAddPlist.apply(this);
201
+ parseU.apply(this,[line]);
202
+ break;
203
+ case 's':
204
+ parseS.apply(this,[line]);
205
+ break;
206
+ case 'f':
207
+ parseF.apply(this,[line]);
208
+ break;
209
+ case 'o':
210
+ checkAddPlist.apply(this);
211
+ parseO.apply(this,[line]);
212
+ break;
213
+ }
214
+ }
215
+ });
216
+
217
+ if (this._currentPlist && this._addPlist) {
218
+ this._plistArray.push(this._currentPlist);
219
+ }
220
+ }
221
+
222
+ export default class ObjParser {
223
+ _textData: string;
224
+ _plistArray: PolyList[];
225
+ _vertexArray: number[][];
226
+ _normalArray: number[][];
227
+ _texCoordArray: number[][];
228
+ _mtlLib: string;
229
+ _currentPlist?: PolyList | null;
230
+ _addPlist: boolean;
231
+
232
+ constructor(objText: string) {
233
+ this._textData = objText;
234
+
235
+ this._plistArray = [];
236
+
237
+ this._vertexArray = [];
238
+ this._normalArray = [];
239
+ this._texCoordArray = [];
240
+
241
+ this._mtlLib = "";
242
+
243
+ this._addPlist = true;
244
+
245
+ loadObjData.apply(this);
246
+ }
247
+
248
+
249
+ get polyListArray() {
250
+ return this._plistArray;
251
+ }
252
+ }
@@ -0,0 +1,19 @@
1
+ import { ResourceType } from "../tools/Resource";
2
+ import WriterPlugin from "./WriterPlugin";
3
+ import Writer from "./Writer";
4
+
5
+ export default class ObjWriterPlugin extends WriterPlugin {
6
+ get supportedExtensions(): string[] {
7
+ return ["obj"];
8
+ }
9
+
10
+ get resourceTypes(): ResourceType[] {
11
+ return [ResourceType.Drawable];
12
+ }
13
+
14
+ async write(path: string, data: any, type: ResourceType, writer: Writer): Promise<void> {
15
+ console.log(path);
16
+ console.log(data);
17
+ console.log(type);
18
+ }
19
+ }