@thi.ng/geom-io-obj 0.3.87 → 0.3.89

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 (4) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/api.js +0 -1
  3. package/package.json +9 -6
  4. package/parser.js +163 -162
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2023-12-09T19:12:03Z
3
+ - **Last updated**: 2023-12-11T10:07:09Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
package/api.js CHANGED
@@ -1 +0,0 @@
1
- export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/geom-io-obj",
3
- "version": "0.3.87",
3
+ "version": "0.3.89",
4
4
  "description": "Wavefront OBJ parser (& exporter soon)",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -24,7 +24,9 @@
24
24
  "author": "Karsten Schmidt (https://thi.ng)",
25
25
  "license": "Apache-2.0",
26
26
  "scripts": {
27
- "build": "yarn clean && tsc --declaration",
27
+ "build": "yarn build:esbuild && yarn build:decl",
28
+ "build:decl": "tsc --declaration --emitDeclarationOnly",
29
+ "build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts",
28
30
  "clean": "rimraf --glob '*.js' '*.d.ts' '*.map' doc",
29
31
  "doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts",
30
32
  "doc:ae": "mkdir -p .ae/doc .ae/temp && api-extractor run --local --verbose",
@@ -33,12 +35,13 @@
33
35
  "test": "bun test"
34
36
  },
35
37
  "dependencies": {
36
- "@thi.ng/api": "^8.9.11",
37
- "@thi.ng/errors": "^2.4.5",
38
- "@thi.ng/vectors": "^7.8.8"
38
+ "@thi.ng/api": "^8.9.12",
39
+ "@thi.ng/errors": "^2.4.6",
40
+ "@thi.ng/vectors": "^7.8.10"
39
41
  },
40
42
  "devDependencies": {
41
43
  "@microsoft/api-extractor": "^7.38.3",
44
+ "esbuild": "^0.19.8",
42
45
  "rimraf": "^5.0.5",
43
46
  "tools": "^0.0.1",
44
47
  "typedoc": "^0.25.4",
@@ -82,5 +85,5 @@
82
85
  "status": "alpha",
83
86
  "year": 2016
84
87
  },
85
- "gitHead": "25f2ac8ff795a432a930119661b364d4d93b59a0\n"
88
+ "gitHead": "22e36fa838e5431d40165384918b395603bbd92f\n"
86
89
  }
package/parser.js CHANGED
@@ -1,176 +1,177 @@
1
1
  import { assert } from "@thi.ng/errors/assert";
2
- export const parseOBJ = (src, opts) => {
3
- opts = {
4
- normals: true,
5
- uvs: true,
6
- objects: true,
7
- groups: true,
8
- comments: false,
9
- tessellate: false,
10
- ...opts,
11
- };
12
- const vertices = [];
13
- const normals = [];
14
- const uvs = [];
15
- const result = {
16
- vertices,
17
- normals,
18
- uvs,
19
- objects: [],
20
- mtlLibs: [],
21
- comments: [],
22
- };
23
- let faces;
24
- let currGroup;
25
- let nextID = 0;
26
- const newGroup = (id, force = false) => {
27
- id = id || `group-${nextID++}`;
28
- (force || opts.groups) &&
29
- result.objects[result.objects.length - 1].groups.push((currGroup = {
30
- id,
31
- smooth: false,
32
- faces: (faces = []),
33
- lines: [],
34
- mtl: currGroup ? currGroup.mtl : undefined,
35
- }));
36
- };
37
- const newObject = (id, force = false) => {
38
- (force || opts.objects) &&
39
- result.objects.push({ id: id || `object-${nextID++}`, groups: [] });
40
- newGroup("default", force);
41
- };
42
- const readFace = (line) => {
43
- const face = { v: [] };
44
- const n = line.length;
45
- const nv = vertices.length;
46
- const nuv = uvs.length;
47
- const nn = normals.length;
48
- const items = line[1].split("/");
49
- switch (items.length) {
50
- case 1:
51
- for (let i = 1; i < n; i++) {
52
- addID(face.v, line[i], nv);
53
- }
54
- break;
55
- case 2:
56
- opts.uvs && (face.uv = []);
57
- for (let i = 1; i < n; i++) {
58
- const f = line[i].split("/");
59
- addID(face.v, f[0], nv);
60
- face.uv && addID(face.uv, f[1], nuv);
61
- }
62
- break;
63
- case 3:
64
- opts.uvs && items[1].length && (face.uv = []);
65
- opts.normals && items[2].length && (face.n = []);
66
- for (let i = 1; i < n; i++) {
67
- const f = line[i].split("/");
68
- addID(face.v, f[0], nv);
69
- face.uv && addID(face.uv, f[1], nuv);
70
- face.n && addID(face.n, f[2], nn);
71
- }
72
- break;
73
- default:
2
+ const parseOBJ = (src, opts) => {
3
+ opts = {
4
+ normals: true,
5
+ uvs: true,
6
+ objects: true,
7
+ groups: true,
8
+ comments: false,
9
+ tessellate: false,
10
+ ...opts
11
+ };
12
+ const vertices = [];
13
+ const normals = [];
14
+ const uvs = [];
15
+ const result = {
16
+ vertices,
17
+ normals,
18
+ uvs,
19
+ objects: [],
20
+ mtlLibs: [],
21
+ comments: []
22
+ };
23
+ let faces;
24
+ let currGroup;
25
+ let nextID = 0;
26
+ const newGroup = (id, force = false) => {
27
+ id = id || `group-${nextID++}`;
28
+ (force || opts.groups) && result.objects[result.objects.length - 1].groups.push(
29
+ currGroup = {
30
+ id,
31
+ smooth: false,
32
+ faces: faces = [],
33
+ lines: [],
34
+ mtl: currGroup ? currGroup.mtl : void 0
35
+ }
36
+ );
37
+ };
38
+ const newObject = (id, force = false) => {
39
+ (force || opts.objects) && result.objects.push({ id: id || `object-${nextID++}`, groups: [] });
40
+ newGroup("default", force);
41
+ };
42
+ const readFace = (line) => {
43
+ const face = { v: [] };
44
+ const n = line.length;
45
+ const nv = vertices.length;
46
+ const nuv = uvs.length;
47
+ const nn = normals.length;
48
+ const items = line[1].split("/");
49
+ switch (items.length) {
50
+ case 1:
51
+ for (let i = 1; i < n; i++) {
52
+ addID(face.v, line[i], nv);
74
53
  }
75
- return face;
76
- };
77
- const readPolyLine = (items) => {
78
- const nv = vertices.length;
79
- const verts = [];
80
- for (let i = 1, n = items.length; i < n; i++) {
81
- addID(verts, items[i], nv);
54
+ break;
55
+ case 2:
56
+ opts.uvs && (face.uv = []);
57
+ for (let i = 1; i < n; i++) {
58
+ const f = line[i].split("/");
59
+ addID(face.v, f[0], nv);
60
+ face.uv && addID(face.uv, f[1], nuv);
82
61
  }
83
- return verts;
84
- };
85
- newObject("default", true);
86
- const { xform, xformUV, tessellate, comments } = opts;
87
- const lines = src.split(/[\n\r]+/g);
88
- for (let i = 0, n = lines.length; i < n; i++) {
89
- const l = lines[i];
90
- if (!l.length)
91
- continue;
92
- if (l[0] === "#") {
93
- comments && result.comments.push(l.substring(1).trim());
94
- continue;
95
- }
96
- const items = l.trim().split(/\s+/g);
97
- const len = items.length;
98
- switch (items[0]) {
99
- case "v": {
100
- assert(len > 3, `invalid vertex @ line ${i}`);
101
- const v = readVec3(items);
102
- vertices.push(xform ? xform(v) : v);
103
- break;
104
- }
105
- case "vn": {
106
- assert(len > 3, `invalid normal @ line ${i}`);
107
- const v = readVec3(items);
108
- normals.push(xform ? xform(v) : v);
109
- break;
110
- }
111
- case "vt": {
112
- assert(len > 2, `invalid uv @ line ${i}`);
113
- const v = readVec2(items);
114
- uvs.push(xformUV ? xformUV(v) : v);
115
- break;
116
- }
117
- case "f": {
118
- assert(len > 3, `invalid face @ line ${i}`);
119
- const f = readFace(items);
120
- tessellate && f.v.length > 3
121
- ? faces.push(...tessellateFace(f))
122
- : faces.push(f);
123
- break;
124
- }
125
- case "l":
126
- assert(len > 2, `invalid polyline @ line ${i}`);
127
- currGroup.lines.push(readPolyLine(items));
128
- break;
129
- case "o":
130
- opts.objects && newObject(items[1]);
131
- break;
132
- case "g":
133
- opts.groups && newGroup(items[1]);
134
- break;
135
- case "s":
136
- currGroup.smooth = items[1] !== "0" && items[1] !== "off";
137
- break;
138
- case "mtllib":
139
- result.mtlLibs.push(items[1]);
140
- break;
141
- case "usemtl":
142
- currGroup.mtl = items[1];
143
- break;
144
- default:
145
- console.log(`ignoring token: ${items[0]} @ line ${i}`);
62
+ break;
63
+ case 3:
64
+ opts.uvs && items[1].length && (face.uv = []);
65
+ opts.normals && items[2].length && (face.n = []);
66
+ for (let i = 1; i < n; i++) {
67
+ const f = line[i].split("/");
68
+ addID(face.v, f[0], nv);
69
+ face.uv && addID(face.uv, f[1], nuv);
70
+ face.n && addID(face.n, f[2], nn);
146
71
  }
72
+ break;
73
+ default:
74
+ }
75
+ return face;
76
+ };
77
+ const readPolyLine = (items) => {
78
+ const nv = vertices.length;
79
+ const verts = [];
80
+ for (let i = 1, n = items.length; i < n; i++) {
81
+ addID(verts, items[i], nv);
82
+ }
83
+ return verts;
84
+ };
85
+ newObject("default", true);
86
+ const { xform, xformUV, tessellate, comments } = opts;
87
+ const lines = src.split(/[\n\r]+/g);
88
+ for (let i = 0, n = lines.length; i < n; i++) {
89
+ const l = lines[i];
90
+ if (!l.length)
91
+ continue;
92
+ if (l[0] === "#") {
93
+ comments && result.comments.push(l.substring(1).trim());
94
+ continue;
147
95
  }
148
- return result;
96
+ const items = l.trim().split(/\s+/g);
97
+ const len = items.length;
98
+ switch (items[0]) {
99
+ case "v": {
100
+ assert(len > 3, `invalid vertex @ line ${i}`);
101
+ const v = readVec3(items);
102
+ vertices.push(xform ? xform(v) : v);
103
+ break;
104
+ }
105
+ case "vn": {
106
+ assert(len > 3, `invalid normal @ line ${i}`);
107
+ const v = readVec3(items);
108
+ normals.push(xform ? xform(v) : v);
109
+ break;
110
+ }
111
+ case "vt": {
112
+ assert(len > 2, `invalid uv @ line ${i}`);
113
+ const v = readVec2(items);
114
+ uvs.push(xformUV ? xformUV(v) : v);
115
+ break;
116
+ }
117
+ case "f": {
118
+ assert(len > 3, `invalid face @ line ${i}`);
119
+ const f = readFace(items);
120
+ tessellate && f.v.length > 3 ? faces.push(...tessellateFace(f)) : faces.push(f);
121
+ break;
122
+ }
123
+ case "l":
124
+ assert(len > 2, `invalid polyline @ line ${i}`);
125
+ currGroup.lines.push(readPolyLine(items));
126
+ break;
127
+ case "o":
128
+ opts.objects && newObject(items[1]);
129
+ break;
130
+ case "g":
131
+ opts.groups && newGroup(items[1]);
132
+ break;
133
+ case "s":
134
+ currGroup.smooth = items[1] !== "0" && items[1] !== "off";
135
+ break;
136
+ case "mtllib":
137
+ result.mtlLibs.push(items[1]);
138
+ break;
139
+ case "usemtl":
140
+ currGroup.mtl = items[1];
141
+ break;
142
+ default:
143
+ console.log(`ignoring token: ${items[0]} @ line ${i}`);
144
+ }
145
+ }
146
+ return result;
149
147
  };
150
148
  const addID = (acc, x, num) => {
151
- const v = parseInt(x);
152
- acc.push(v < 0 ? v + num : v - 1);
149
+ const v = parseInt(x);
150
+ acc.push(v < 0 ? v + num : v - 1);
153
151
  };
154
152
  const readVec2 = (items) => [
155
- parseFloat(items[1]),
156
- parseFloat(items[2]),
153
+ parseFloat(items[1]),
154
+ parseFloat(items[2])
157
155
  ];
158
156
  const readVec3 = (items) => [
159
- parseFloat(items[1]),
160
- parseFloat(items[2]),
161
- parseFloat(items[3]),
157
+ parseFloat(items[1]),
158
+ parseFloat(items[2]),
159
+ parseFloat(items[3])
162
160
  ];
163
161
  const tessellateFace = (face) => {
164
- const { v, uv, n } = face;
165
- const v0 = v[0];
166
- const uv0 = uv && uv[0];
167
- const n0 = n && n[0];
168
- const acc = [];
169
- for (let i = 1, num = v.length - 1; i < num; i++) {
170
- const tri = { v: [v0, v[i], v[i + 1]] };
171
- uv && (tri.uv = [uv0, uv[i], uv[i + 1]]);
172
- n && (tri.n = [n0, n[i], n[i + 1]]);
173
- acc.push(tri);
174
- }
175
- return acc;
162
+ const { v, uv, n } = face;
163
+ const v0 = v[0];
164
+ const uv0 = uv && uv[0];
165
+ const n0 = n && n[0];
166
+ const acc = [];
167
+ for (let i = 1, num = v.length - 1; i < num; i++) {
168
+ const tri = { v: [v0, v[i], v[i + 1]] };
169
+ uv && (tri.uv = [uv0, uv[i], uv[i + 1]]);
170
+ n && (tri.n = [n0, n[i], n[i + 1]]);
171
+ acc.push(tri);
172
+ }
173
+ return acc;
174
+ };
175
+ export {
176
+ parseOBJ
176
177
  };