@domgell/gltf-parser 1.0.0 → 1.0.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/package.json +5 -8
- package/src/Parser.ts +15 -12
- package/src/index.ts +2 -2
- package/src/types.ts +242 -244
- package/src/util.ts +59 -67
- package/tsconfig.json +35 -36
- package/.gitattributes +0 -2
- package/gltf-importer.iml +0 -9
- package/index.html +0 -14
- package/res/suzanne.glb +0 -0
package/package.json
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@domgell/gltf-parser",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"main": "src/index.ts",
|
|
5
5
|
"exports": "./src/index.ts",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
-
},
|
|
9
|
-
"keywords": ["gltf", "glb", "mesh", "parser"],
|
|
10
6
|
"author": "domgell",
|
|
11
7
|
"license": "ISC",
|
|
12
8
|
"description": "Parse .GLTF/.GLF files into JS objects",
|
|
9
|
+
"keywords": ["gltf", "glb", "mesh", "parser"],
|
|
13
10
|
"dependencies": {
|
|
14
|
-
"gltf-types": "
|
|
11
|
+
"@domgell/gltf-types": "*",
|
|
12
|
+
"@domgell/ts-util": "*",
|
|
15
13
|
"dom-game-math": "*"
|
|
16
|
-
}
|
|
17
|
-
"devDependencies": {}
|
|
14
|
+
}
|
|
18
15
|
}
|
package/src/Parser.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AccessorArrayType,
|
|
3
3
|
AccessorConstructorType,
|
|
4
|
-
assert,
|
|
5
4
|
chunk,
|
|
6
|
-
fail,
|
|
7
5
|
getTransform,
|
|
8
6
|
} from "./util.ts";
|
|
9
7
|
import * as Parsed from "./types.ts";
|
|
10
|
-
import * as GLTF from "gltf-types";
|
|
8
|
+
import * as GLTF from "@domgell/gltf-types";
|
|
11
9
|
import {mat4, TransformOrder} from "dom-game-math";
|
|
12
10
|
import {Matrix4x4, TextureFilterMap, TextureWrapModeMap} from "./types.ts";
|
|
11
|
+
import {assert, fail} from "@domgell/ts-util";
|
|
13
12
|
|
|
14
13
|
export type ParserOptions = {
|
|
15
14
|
transformOrder: TransformOrder,
|
|
@@ -30,7 +29,6 @@ export class Parser {
|
|
|
30
29
|
|
|
31
30
|
const data = await r.arrayBuffer();
|
|
32
31
|
const dataView = new DataView(data);
|
|
33
|
-
|
|
34
32
|
let offset = 12;
|
|
35
33
|
|
|
36
34
|
// Get JSON Header
|
|
@@ -39,12 +37,12 @@ export class Parser {
|
|
|
39
37
|
const textDecoder = new TextDecoder("utf-8");
|
|
40
38
|
const json = textDecoder.decode(jsonChunkData);
|
|
41
39
|
const header = JSON.parse(json);
|
|
42
|
-
|
|
43
40
|
offset += 8 + jsonChunkLength;
|
|
44
41
|
|
|
45
42
|
// Get binary data
|
|
46
43
|
const binaryChunkLength = dataView.getUint32(offset, true);
|
|
47
44
|
const binary = new ArrayBuffer(binaryChunkLength);
|
|
45
|
+
|
|
48
46
|
const binaryChunkView = new Uint8Array(binary);
|
|
49
47
|
binaryChunkView.set(new Uint8Array(data, offset + 8, binaryChunkLength));
|
|
50
48
|
|
|
@@ -63,7 +61,6 @@ export class Parser {
|
|
|
63
61
|
?? fail(`Accessor at index ${index} not found`);
|
|
64
62
|
|
|
65
63
|
assert(accessor.bufferView !== undefined, "Accessor bufferView is undefined");
|
|
66
|
-
|
|
67
64
|
const bufferView = this.header.bufferViews[accessor.bufferView];
|
|
68
65
|
const byteOffset = (bufferView.byteOffset ?? 0) + (accessor.byteOffset ?? 0);
|
|
69
66
|
|
|
@@ -79,6 +76,7 @@ export class Parser {
|
|
|
79
76
|
5125: Uint32Array,
|
|
80
77
|
5126: Float32Array,
|
|
81
78
|
}[accessor.componentType];
|
|
79
|
+
|
|
82
80
|
assert(assertType.name === type.name, `Mismatched types: requested '${type.name}' but got '${assertType.name}'`);
|
|
83
81
|
|
|
84
82
|
const byteLength = numComponents * accessor.count * type.BYTES_PER_ELEMENT;
|
|
@@ -89,6 +87,7 @@ export class Parser {
|
|
|
89
87
|
|
|
90
88
|
async mesh(gltfMesh: GLTF.Mesh) {
|
|
91
89
|
const primitives = new Array<Parsed.MeshPrimitive>(gltfMesh.primitives.length);
|
|
90
|
+
|
|
92
91
|
for (let i = 0; i < primitives.length; i++) {
|
|
93
92
|
primitives[i] = await this.primitive(gltfMesh.primitives[i]);
|
|
94
93
|
}
|
|
@@ -152,11 +151,8 @@ export class Parser {
|
|
|
152
151
|
|
|
153
152
|
const children = gltfJoint.children?.map(i => this.header.nodes![i].name!) ?? [];
|
|
154
153
|
|
|
155
|
-
//const inverseBindTransform = inverseBindMatrices[jointIndex];
|
|
156
154
|
const inverseBindTransform = inverseBindMatrices[i];
|
|
157
|
-
|
|
158
155
|
joints[gltfJoint.name] = {name: gltfJoint.name, transform, children, inverseBindTransform};
|
|
159
|
-
|
|
160
156
|
i++;
|
|
161
157
|
}
|
|
162
158
|
|
|
@@ -166,6 +162,7 @@ export class Parser {
|
|
|
166
162
|
// Set parents
|
|
167
163
|
for (let name in joints) {
|
|
168
164
|
const joint = joints[name];
|
|
165
|
+
|
|
169
166
|
for (let childName of joint.children) {
|
|
170
167
|
joints[childName].parent = name;
|
|
171
168
|
}
|
|
@@ -183,6 +180,7 @@ export class Parser {
|
|
|
183
180
|
|
|
184
181
|
// TEMP: Calculate global inverse transform
|
|
185
182
|
const skinParentNode = this.header.nodes.find(n => n.children?.includes(gltfSkin.joints[0]));
|
|
183
|
+
|
|
186
184
|
const globalInverseTransform = skinParentNode
|
|
187
185
|
? getTransform(skinParentNode, this.options.transformOrder)
|
|
188
186
|
: Array.from(mat4.idt) as Matrix4x4;
|
|
@@ -192,6 +190,7 @@ export class Parser {
|
|
|
192
190
|
|
|
193
191
|
animation(gltfAnimation: GLTF.Animation): Parsed.Animation {
|
|
194
192
|
assert(this.header.nodes !== undefined, "`Nodes` is undefined");
|
|
193
|
+
|
|
195
194
|
const channels: Record<string, Parsed.AnimationChannel> = {};
|
|
196
195
|
let duration = 0;
|
|
197
196
|
|
|
@@ -201,18 +200,15 @@ export class Parser {
|
|
|
201
200
|
|
|
202
201
|
// Init channel if not already present
|
|
203
202
|
channels[gltfTargetNode.name] ??= {translation: [], rotation: [], scale: []};
|
|
204
|
-
|
|
205
203
|
const sampler = gltfAnimation.samplers[gltfChannel.sampler];
|
|
206
204
|
const times = this.accessor(sampler.input, Float32Array);
|
|
207
205
|
const values = this.accessor(sampler.output, Float32Array);
|
|
208
|
-
|
|
209
206
|
const numComponents = values.length / times.length;
|
|
210
207
|
assert(numComponents === 3 || numComponents === 4, `Invalid number of components: '${numComponents}'`);
|
|
211
208
|
|
|
212
209
|
// Set keyframes array of current 'path', e.g. 'translation'
|
|
213
210
|
const keyframes = chunk(values, numComponents).map((value, i) => ({time: times[i], value}));
|
|
214
211
|
channels[gltfTargetNode.name][gltfChannel.target.path] = keyframes as any;
|
|
215
|
-
|
|
216
212
|
duration = Math.max(duration, ...keyframes.map(k => k.time));
|
|
217
213
|
}
|
|
218
214
|
|
|
@@ -247,8 +243,11 @@ export class Parser {
|
|
|
247
243
|
}
|
|
248
244
|
|
|
249
245
|
const alpha: Parsed.MaterialAlphaInfo = {
|
|
246
|
+
|
|
250
247
|
mode: gltfMaterial.alphaMode ?? "OPAQUE",
|
|
248
|
+
|
|
251
249
|
cutoff: gltfMaterial.alphaCutoff ?? 0.5,
|
|
250
|
+
|
|
252
251
|
};
|
|
253
252
|
|
|
254
253
|
const doubleSided = gltfMaterial.doubleSided ?? false;
|
|
@@ -271,6 +270,7 @@ export class Parser {
|
|
|
271
270
|
|
|
272
271
|
// Parse sampler
|
|
273
272
|
const sampler: Parsed.Sampler = {wrap: {s: "repeat", t: "repeat"}, filter: {min: "linear", mag: "linear"}};
|
|
273
|
+
|
|
274
274
|
if (this.header.samplers !== undefined && gltfTexture.sampler !== undefined) {
|
|
275
275
|
const gltfSampler = this.header.samplers[gltfTexture.sampler];
|
|
276
276
|
|
|
@@ -290,12 +290,14 @@ export class Parser {
|
|
|
290
290
|
const response = await fetch(this.path + gltfImage.uri);
|
|
291
291
|
assert(response.ok, `Failed to fetch image at URI: '${gltfImage.uri}'`);
|
|
292
292
|
const blob = await response.blob();
|
|
293
|
+
|
|
293
294
|
return await createImageBitmap(blob);
|
|
294
295
|
}
|
|
295
296
|
// Image from buffer
|
|
296
297
|
else {
|
|
297
298
|
assert(this.header.bufferViews !== undefined, "Header `BufferViews` property is undefined");
|
|
298
299
|
assert(this.header.buffers !== undefined, "Header `Buffers` property is undefined");
|
|
300
|
+
|
|
299
301
|
const bufferView = this.header.bufferViews[gltfImage.bufferView];
|
|
300
302
|
const buffer = this.header.buffers[bufferView.buffer];
|
|
301
303
|
|
|
@@ -306,6 +308,7 @@ export class Parser {
|
|
|
306
308
|
// TODO: buffer length + bufferView offset (?)
|
|
307
309
|
const data = this.binary.slice(bufferView.byteOffset ?? 0, (bufferView.byteOffset ?? 0) + bufferView.byteLength);
|
|
308
310
|
const blob = new Blob([new Uint8Array(data)]);
|
|
311
|
+
|
|
309
312
|
return await createImageBitmap(blob);
|
|
310
313
|
}
|
|
311
314
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from "./types.ts";
|
|
2
|
-
export * from "./Parser.ts";
|
|
1
|
+
export * from "./types.ts";
|
|
2
|
+
export * from "./Parser.ts";
|
package/src/types.ts
CHANGED
|
@@ -1,244 +1,242 @@
|
|
|
1
|
-
import {Tuple} from "./util.ts";
|
|
2
|
-
|
|
3
|
-
export type Matrix4x4 = Tuple<number, 16>
|
|
4
|
-
export type Vector2 = Tuple<number, 2>
|
|
5
|
-
export type Vector3 = Tuple<number, 3>
|
|
6
|
-
export type Vector4 = Tuple<number, 4>
|
|
7
|
-
|
|
8
|
-
// ------------------------------- Scene -------------------------------
|
|
9
|
-
|
|
10
|
-
export type Scene = {
|
|
11
|
-
/**
|
|
12
|
-
* All nodes in scene
|
|
13
|
-
*/
|
|
14
|
-
nodes: Node[]
|
|
15
|
-
cameras: Camera[],
|
|
16
|
-
meshes: Mesh[],
|
|
17
|
-
skins: Skin[],
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
| { skin: Skin, mesh?: undefined, camera?: undefined }
|
|
30
|
-
| { camera: Camera, mesh?: undefined, skin?: undefined }
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// ------------------------------ Camera -------------------------------
|
|
34
|
-
|
|
35
|
-
export type OrthographicCamera = {
|
|
36
|
-
type: "Orthographic"
|
|
37
|
-
xmag: number,
|
|
38
|
-
ymag: number,
|
|
39
|
-
zfar: number,
|
|
40
|
-
znear: number,
|
|
41
|
-
view: Matrix4x4,
|
|
42
|
-
projection: Matrix4x4,
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export type PerspectiveCamera = {
|
|
46
|
-
type: "Perspective"
|
|
47
|
-
aspectRatio: number,
|
|
48
|
-
yfov: number,
|
|
49
|
-
zfar: number,
|
|
50
|
-
znear: number,
|
|
51
|
-
view: Matrix4x4,
|
|
52
|
-
projection: Matrix4x4,
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export type Camera = OrthographicCamera | PerspectiveCamera
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
export type
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
"nearest"
|
|
138
|
-
| "linear"
|
|
139
|
-
| "nearest-mipmap-
|
|
140
|
-
| "linear-mipmap-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
| "
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
[
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
[
|
|
157
|
-
[
|
|
158
|
-
[
|
|
159
|
-
[
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
244
|
-
|
|
1
|
+
import {Tuple} from "./util.ts";
|
|
2
|
+
|
|
3
|
+
export type Matrix4x4 = Tuple<number, 16>
|
|
4
|
+
export type Vector2 = Tuple<number, 2>
|
|
5
|
+
export type Vector3 = Tuple<number, 3>
|
|
6
|
+
export type Vector4 = Tuple<number, 4>
|
|
7
|
+
|
|
8
|
+
// ------------------------------- Scene -------------------------------
|
|
9
|
+
|
|
10
|
+
export type Scene = {
|
|
11
|
+
/**
|
|
12
|
+
* All nodes in scene
|
|
13
|
+
*/
|
|
14
|
+
nodes: Node[]
|
|
15
|
+
cameras: Camera[],
|
|
16
|
+
meshes: Mesh[],
|
|
17
|
+
skins: Skin[],
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// ------------------------------- Node --------------------------------
|
|
21
|
+
|
|
22
|
+
export type Node = {
|
|
23
|
+
transform: Matrix4x4,
|
|
24
|
+
name?: string,
|
|
25
|
+
children: Node[],
|
|
26
|
+
parent?: Node,
|
|
27
|
+
} & (
|
|
28
|
+
| { mesh: Mesh, skin?: undefined, camera?: undefined }
|
|
29
|
+
| { skin: Skin, mesh?: undefined, camera?: undefined }
|
|
30
|
+
| { camera: Camera, mesh?: undefined, skin?: undefined }
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
// ------------------------------ Camera -------------------------------
|
|
34
|
+
|
|
35
|
+
export type OrthographicCamera = {
|
|
36
|
+
type: "Orthographic"
|
|
37
|
+
xmag: number,
|
|
38
|
+
ymag: number,
|
|
39
|
+
zfar: number,
|
|
40
|
+
znear: number,
|
|
41
|
+
view: Matrix4x4,
|
|
42
|
+
projection: Matrix4x4,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type PerspectiveCamera = {
|
|
46
|
+
type: "Perspective"
|
|
47
|
+
aspectRatio: number,
|
|
48
|
+
yfov: number,
|
|
49
|
+
zfar: number,
|
|
50
|
+
znear: number,
|
|
51
|
+
view: Matrix4x4,
|
|
52
|
+
projection: Matrix4x4,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type Camera = OrthographicCamera | PerspectiveCamera
|
|
56
|
+
|
|
57
|
+
// ------------------------------- Mesh --------------------------------
|
|
58
|
+
|
|
59
|
+
export type MeshPrimitiveAttributes = {
|
|
60
|
+
positions: Vector3[],
|
|
61
|
+
uvs?: Vector2[],
|
|
62
|
+
normals?: Vector3[],
|
|
63
|
+
colors?: Vector4[]
|
|
64
|
+
weights?: Vector4[],
|
|
65
|
+
joints?: Vector4[],
|
|
66
|
+
tangents?: Vector4[], // TODO
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export type MeshPrimitive = {
|
|
70
|
+
/**
|
|
71
|
+
* Vertex attributes of the mesh primitive
|
|
72
|
+
*/
|
|
73
|
+
attributes: MeshPrimitiveAttributes,
|
|
74
|
+
indices?: Uint32Array,
|
|
75
|
+
material?: Material,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export type Mesh = {
|
|
79
|
+
primitives: MeshPrimitive[],
|
|
80
|
+
name?: string,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// -------------------------------- Skin -------------------------------
|
|
84
|
+
|
|
85
|
+
export type Joint = {
|
|
86
|
+
name: string,
|
|
87
|
+
transform: Matrix4x4,
|
|
88
|
+
inverseBindTransform: Matrix4x4,
|
|
89
|
+
children: string[],
|
|
90
|
+
parent?: string,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type Skin = {
|
|
94
|
+
root: Joint,
|
|
95
|
+
joints: Record<string, Joint>,
|
|
96
|
+
animations: Animation[],
|
|
97
|
+
globalInverseTransform: Matrix4x4,
|
|
98
|
+
name?: string,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ----------------------------- Animation -----------------------------
|
|
102
|
+
|
|
103
|
+
export type Animation = {
|
|
104
|
+
duration: number,
|
|
105
|
+
name?: string,
|
|
106
|
+
channels: Record<string, AnimationChannel>,
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export type AnimationChannel = {
|
|
110
|
+
translation: AnimationKeyframe<Vector3>[]
|
|
111
|
+
rotation: AnimationKeyframe<Vector4>[]
|
|
112
|
+
scale: AnimationKeyframe<Vector3>[]
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export type AnimationKeyframe<T> = { time: number, value: T }
|
|
116
|
+
|
|
117
|
+
// ----------------------------- Texture -------------------------------
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
// TODO: If source is undefined, don't create texture, if sampler is undefined create default sampler
|
|
121
|
+
export type Texture = {
|
|
122
|
+
source: ImageBitmap,
|
|
123
|
+
sampler: Sampler,
|
|
124
|
+
name?: string,
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export type Sampler = {
|
|
128
|
+
wrap: { s: TextureWrapMode, t: TextureWrapMode },
|
|
129
|
+
filter: { min: TextureMinFilter, mag: TextureMagFilter },
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export type TextureMagFilter = "nearest" | "linear"
|
|
133
|
+
|
|
134
|
+
export type TextureMinFilter =
|
|
135
|
+
| "nearest"
|
|
136
|
+
| "linear"
|
|
137
|
+
| "nearest-mipmap-nearest"
|
|
138
|
+
| "linear-mipmap-nearest"
|
|
139
|
+
| "nearest-mipmap-linear"
|
|
140
|
+
| "linear-mipmap-linear"
|
|
141
|
+
|
|
142
|
+
export type TextureWrapMode =
|
|
143
|
+
| "clamp-to-edge"
|
|
144
|
+
| "mirrored-repeat"
|
|
145
|
+
| "repeat"
|
|
146
|
+
|
|
147
|
+
export const TextureWrapModeMap = {
|
|
148
|
+
[33071]: "clamp-to-edge",
|
|
149
|
+
[33648]: "mirrored-repeat",
|
|
150
|
+
[10497]: "repeat",
|
|
151
|
+
} as const;
|
|
152
|
+
|
|
153
|
+
export const TextureFilterMap = {
|
|
154
|
+
[9728]: "nearest",
|
|
155
|
+
[9729]: "linear",
|
|
156
|
+
[9984]: "nearest-mipmap-nearest",
|
|
157
|
+
[9985]: "linear-mipmap-nearest",
|
|
158
|
+
[9986]: "nearest-mipmap-linear",
|
|
159
|
+
[9987]: "linear-mipmap-linear",
|
|
160
|
+
} as const;
|
|
161
|
+
|
|
162
|
+
// ----------------------------- Material ------------------------------
|
|
163
|
+
|
|
164
|
+
export type Material = {
|
|
165
|
+
metallicRoughness: MaterialMetallicRoughnessInfo,
|
|
166
|
+
normal?: MaterialNormalInfo,
|
|
167
|
+
emissive?: MaterialEmissiveInfo,
|
|
168
|
+
ambientOcclusion?: MaterialAmbientOcclusionInfo,
|
|
169
|
+
alpha: MaterialAlphaInfo,
|
|
170
|
+
/**
|
|
171
|
+
* Whether the material is double-sided. Default is `false`.
|
|
172
|
+
*/
|
|
173
|
+
doubleSided: boolean,
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export type MaterialAlphaInfo = {
|
|
177
|
+
/**
|
|
178
|
+
* The alpha rendering mode of the material. Default is `"OPAQUE"`.
|
|
179
|
+
*/
|
|
180
|
+
mode: "OPAQUE" | "MASK" | "BLEND",
|
|
181
|
+
/**
|
|
182
|
+
* The alpha cutoff value of the material. Default is `0.5`.
|
|
183
|
+
*/
|
|
184
|
+
cutoff: number,
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export type MaterialMetallicRoughnessInfo = {
|
|
188
|
+
/**
|
|
189
|
+
* The base color factor of the material. Default is `[1, 1, 1, 1]`.
|
|
190
|
+
*/
|
|
191
|
+
baseColor: Vector4,
|
|
192
|
+
/**
|
|
193
|
+
* The base color texture of the material.
|
|
194
|
+
*/
|
|
195
|
+
baseColorTexture?: Texture,
|
|
196
|
+
/**
|
|
197
|
+
* The factor for the metalness of the material. Default is `1`.
|
|
198
|
+
*/
|
|
199
|
+
metallicFactor: number,
|
|
200
|
+
/**
|
|
201
|
+
* The factor for the roughness of the material. Default is `1`.
|
|
202
|
+
*/
|
|
203
|
+
roughnessFactor: number,
|
|
204
|
+
/**
|
|
205
|
+
* The metallic roughness texture of the material.
|
|
206
|
+
*/
|
|
207
|
+
metallicRoughnessTexture?: Texture,
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export type MaterialNormalInfo = {
|
|
211
|
+
/**
|
|
212
|
+
* The normal texture of the material.
|
|
213
|
+
*/
|
|
214
|
+
texture: Texture,
|
|
215
|
+
/**
|
|
216
|
+
* The scale applied to each vector of the normal map. Default is `1`.
|
|
217
|
+
*/
|
|
218
|
+
scale: number,
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export type MaterialEmissiveInfo = {
|
|
222
|
+
/**
|
|
223
|
+
* The emissive texture of the material.
|
|
224
|
+
*/
|
|
225
|
+
texture: Texture,
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* The emissive factor of the material. Default is `[0, 0, 0]`.
|
|
229
|
+
*/
|
|
230
|
+
factor: Vector3,
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export type MaterialAmbientOcclusionInfo = {
|
|
234
|
+
/**
|
|
235
|
+
* The occlusion texture of the material.
|
|
236
|
+
*/
|
|
237
|
+
texture: Texture,
|
|
238
|
+
/**
|
|
239
|
+
* The occlusion strength of the material. Default is `1`.
|
|
240
|
+
*/
|
|
241
|
+
strength: number,
|
|
242
|
+
}
|
package/src/util.ts
CHANGED
|
@@ -1,67 +1,59 @@
|
|
|
1
|
-
import {TransformOrder, mat4, vec3, quat, Matrix4} from "dom-game-math";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
out
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
rotation: transform.rotation && quat.fromArray(transform.rotation),
|
|
61
|
-
scale: transform.scale && vec3.fromArray(transform.scale),
|
|
62
|
-
order,
|
|
63
|
-
}, out as Matrix4);
|
|
64
|
-
|
|
65
|
-
return out;
|
|
66
|
-
}
|
|
67
|
-
|
|
1
|
+
import {TransformOrder, mat4, vec3, quat, Matrix4} from "dom-game-math";
|
|
2
|
+
|
|
3
|
+
// ------------------------------------- Accessor --------------------------------------
|
|
4
|
+
|
|
5
|
+
export type AccessorArrayType =
|
|
6
|
+
| Float32ArrayConstructor
|
|
7
|
+
| Uint32ArrayConstructor
|
|
8
|
+
| Uint16ArrayConstructor
|
|
9
|
+
| Int16ArrayConstructor
|
|
10
|
+
| Uint8ArrayConstructor
|
|
11
|
+
| Int8ArrayConstructor
|
|
12
|
+
|
|
13
|
+
export type AccessorConstructorType<T extends AccessorArrayType> = ReturnType<T["from"]>
|
|
14
|
+
|
|
15
|
+
// --------------------------------------- Tuple ---------------------------------------
|
|
16
|
+
|
|
17
|
+
export type Tuple<T, N extends number> = T[] & { length: N };
|
|
18
|
+
|
|
19
|
+
export function chunk<T, N extends number>(array: Iterable<T>, size: N): Tuple<T, N>[] {
|
|
20
|
+
const result = new Array<T[]>;
|
|
21
|
+
let chunk = new Array<T>();
|
|
22
|
+
|
|
23
|
+
for (const value of Array.from(array)) {
|
|
24
|
+
chunk.push(value);
|
|
25
|
+
|
|
26
|
+
if (chunk.length === size) {
|
|
27
|
+
result.push(chunk);
|
|
28
|
+
chunk = [];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (chunk.length) {
|
|
33
|
+
result.push(chunk);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return result as Tuple<T, N>[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function getTransform(transform: {
|
|
40
|
+
translation?: number[],
|
|
41
|
+
rotation?: number[],
|
|
42
|
+
scale?: number[]
|
|
43
|
+
}, order: TransformOrder, out?: Tuple<number, 16>) {
|
|
44
|
+
out ??= Array.from(mat4.idt) as Tuple<number, 16>;
|
|
45
|
+
|
|
46
|
+
mat4.compose({
|
|
47
|
+
|
|
48
|
+
translation: transform.translation && vec3.fromArray(transform.translation),
|
|
49
|
+
|
|
50
|
+
rotation: transform.rotation && quat.fromArray(transform.rotation),
|
|
51
|
+
|
|
52
|
+
scale: transform.scale && vec3.fromArray(transform.scale),
|
|
53
|
+
|
|
54
|
+
order,
|
|
55
|
+
|
|
56
|
+
}, out as Matrix4);
|
|
57
|
+
|
|
58
|
+
return out;
|
|
59
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,36 +1,35 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
"DOM
|
|
9
|
-
],
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"lib": [
|
|
7
|
+
"ESNext",
|
|
8
|
+
"DOM"
|
|
9
|
+
],
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
/* Bundler mode */
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"noImplicitAny": false,
|
|
18
|
+
/* Linting */
|
|
19
|
+
"strict": true,
|
|
20
|
+
"noUnusedLocals": false,
|
|
21
|
+
"noUnusedParameters": false,
|
|
22
|
+
"noFallthroughCasesInSwitch": true,
|
|
23
|
+
"declaration": true,
|
|
24
|
+
"accessor-pairs": [
|
|
25
|
+
"error",
|
|
26
|
+
{
|
|
27
|
+
"setWithoutGet": true,
|
|
28
|
+
"getWithoutSet": true
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"include": [
|
|
33
|
+
"src"
|
|
34
|
+
]
|
|
35
|
+
}
|
package/.gitattributes
DELETED
package/gltf-importer.iml
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<module type="GENERAL_MODULE" version="4">
|
|
3
|
-
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
|
4
|
-
<exclude-output />
|
|
5
|
-
<content url="file://$MODULE_DIR$" />
|
|
6
|
-
<orderEntry type="sourceFolder" forTests="false" />
|
|
7
|
-
<orderEntry type="module" module-name="gltf-types" />
|
|
8
|
-
</component>
|
|
9
|
-
</module>
|
package/index.html
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<!-- Get rid of "http://localhost:5173/favicon.ico not found" -->
|
|
5
|
-
<link rel="shortcut icon" href="#" />
|
|
6
|
-
|
|
7
|
-
<meta charset="UTF-8"/>
|
|
8
|
-
<script type="module" src="src/index.ts"></script>
|
|
9
|
-
<title></title>
|
|
10
|
-
</head>
|
|
11
|
-
<body>
|
|
12
|
-
<canvas></canvas>
|
|
13
|
-
</body>
|
|
14
|
-
</html>
|
package/res/suzanne.glb
DELETED
|
Binary file
|