-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.ts
More file actions
114 lines (93 loc) · 3.45 KB
/
Copy pathapp.ts
File metadata and controls
114 lines (93 loc) · 3.45 KB
1
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
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
#!/usr/bin/env node
// Run with node, give a directory containing two or more glb files:
// node app.ts /path/to/glb/directory
// or give a list of files to merge followed by the output file:
// node app.ts run01.glb walk01.glb idle01.glb merged_output.glb
import { parseArgs } from 'node:util';
import path from 'node:path';
import * as fs from 'node:fs';
import { Document, NodeIO } from '@gltf-transform/core';
import { copyToDocument, dedup, prune, unpartition, flatten } from '@gltf-transform/functions';
async function loadGlb(io: NodeIO, filePath: string): Promise<Document> {
const doc = await io.read(filePath);
doc.getRoot().listScenes()[0].setName('Scene01');
return doc;
}
function moveAnimations(targetDoc: Document, sourceDoc: Document) {
const animations = sourceDoc.getRoot().listAnimations();
copyToDocument(targetDoc, sourceDoc, animations);
// relink animations to target joints
const root = targetDoc.getRoot();
const skins = root.listSkins();
const joints = skins[0].listJoints();
for (const anim of root.listAnimations()) {
for (const channel of anim.listChannels()) {
const targetNode = channel.getTargetNode();
const matchJoint = joints.find(j => j.getName() === targetNode?.getName());
if (matchJoint) {
channel.setTargetNode(matchJoint);
}
}
}
}
async function merge(inputPaths: string[], outputPath: string) {
const io = new NodeIO();
const mergeTarget = inputPaths.shift();
if (mergeTarget) {
const doc = await loadGlb(io, mergeTarget);
for (const glb of inputPaths) {
const doc2 = await loadGlb(io, glb);
moveAnimations(doc, doc2);
}
await doc.transform(
unpartition(),
dedup(),
flatten(),
prune()
);
try {
await io.write(outputPath, doc);
console.log(`Exported merged gltf: ${outputPath}`);
} catch (error) {
console.log(`Could not write gtlf: ${error}`);
}
}
}
async function main() {
// command line arguments
const { positionals } = parseArgs({ allowPositionals: true, });
if (positionals.length == 1) {
// merge all the glbs in one directory
const dir = positionals[0];
if (fs.statSync(dir).isDirectory()) {
const inputPaths = [];
for (const fn of fs.readdirSync(dir)) {
if (fn.endsWith('.glb')) {
const fullPath = path.join(dir, fn);
inputPaths.push(fullPath);
}
}
if (inputPaths.length < 2) {
console.log(`Too few glbs in directory, need at least two files to merge.`);
return;
}
const outfile = path.basename(dir) + ".glb";
const outputPath = path.join(path.dirname(dir), outfile);
merge(inputPaths, outputPath);
}
else {
console.log(`Expected a directory of two or more glb files.`);
}
}
else if (positionals.length >= 3) {
// merge all the listed glbs into the output
const outputPath = positionals.pop();
const inputPaths = positionals;
if (outputPath) {
merge(inputPaths, outputPath);
}
} else {
console.log(`Too few arguments, need at least two files to merge and an output file.`);
}
}
main();