@threlte/gltf 0.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/LICENSE +21 -0
- package/cli.js +85 -0
- package/logo.svg +145 -0
- package/package.json +71 -0
- package/readme.md +246 -0
- package/src/bin/DRACOLoader.js +208 -0
- package/src/bin/GLTFLoader.js +2734 -0
- package/src/index.js +76 -0
- package/src/utils/exports.js +5 -0
- package/src/utils/glftLoader.js +4 -0
- package/src/utils/isVarName.js +10 -0
- package/src/utils/parser.js +516 -0
- package/src/utils/transform.js +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Paul Henschel
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/cli.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict'
|
|
3
|
+
import meow from 'meow'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import { fileURLToPath } from 'url'
|
|
6
|
+
import { dirname } from 'path'
|
|
7
|
+
import gltf from './src/index.js'
|
|
8
|
+
import { readPackageUpSync } from 'read-pkg-up'
|
|
9
|
+
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
11
|
+
const __dirname = dirname(__filename)
|
|
12
|
+
|
|
13
|
+
const cli = meow(
|
|
14
|
+
`
|
|
15
|
+
Usage
|
|
16
|
+
$ npx @threlte/gltf [Model.glb] [options]
|
|
17
|
+
|
|
18
|
+
Options
|
|
19
|
+
--output, -o Output file name/path
|
|
20
|
+
--types, -t Add Typescript definitions
|
|
21
|
+
--keepnames, -k Keep original names
|
|
22
|
+
--keepgroups, -K Keep (empty) groups, disable pruning
|
|
23
|
+
--meta, -m Include metadata (as userData)
|
|
24
|
+
--shadows, s Let meshes cast and receive shadows
|
|
25
|
+
--printwidth, w Prettier printWidth (default: 120)
|
|
26
|
+
--precision, -p Number of fractional digits (default: 2)
|
|
27
|
+
--draco, -d Draco binary path
|
|
28
|
+
--root, -r Sets directory from which .gltf file is served
|
|
29
|
+
--transform, -T Transform the asset for the web (draco, prune, resize)
|
|
30
|
+
--resolution, -R Transform resolution for texture resizing (default: 1024)
|
|
31
|
+
--simplify, -S Transform simplification (default: false) (experimental!)
|
|
32
|
+
--weld Weld tolerance (default: 0.0001)
|
|
33
|
+
--ratio Simplifier ratio (default: 0.75)
|
|
34
|
+
--error Simplifier error threshold (default: 0.001)
|
|
35
|
+
--debug, -D Debug output
|
|
36
|
+
`,
|
|
37
|
+
{
|
|
38
|
+
importMeta: import.meta,
|
|
39
|
+
flags: {
|
|
40
|
+
output: { type: 'string', alias: 'o' },
|
|
41
|
+
types: { type: 'boolean', alias: 't' },
|
|
42
|
+
keepnames: { type: 'boolean', alias: 'k' },
|
|
43
|
+
keepgroups: { type: 'boolean', alias: 'K' },
|
|
44
|
+
shadows: { type: 'boolean', alias: 's' },
|
|
45
|
+
printwidth: { type: 'number', alias: 'p', default: 120 },
|
|
46
|
+
meta: { type: 'boolean', alias: 'm' },
|
|
47
|
+
precision: { type: 'number', alias: 'p', default: 2 },
|
|
48
|
+
draco: { type: 'string', alias: 'd' },
|
|
49
|
+
root: { type: 'string', alias: 'r' },
|
|
50
|
+
transform: { type: 'boolean', alias: 'T' },
|
|
51
|
+
resolution: { type: 'number', alias: 'R', default: 1024 },
|
|
52
|
+
simplify: { type: 'boolean', alias: 'S', default: false },
|
|
53
|
+
weld: { type: 'number', default: 0.0001 },
|
|
54
|
+
ratio: { type: 'number', default: 0.75 },
|
|
55
|
+
error: { type: 'number', default: 0.001 },
|
|
56
|
+
debug: { type: 'boolean', alias: 'D' }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
const { packageJson } = readPackageUpSync({ cwd: __dirname, normalize: false })
|
|
62
|
+
|
|
63
|
+
if (cli.input.length === 0) {
|
|
64
|
+
console.log(cli.help)
|
|
65
|
+
} else {
|
|
66
|
+
const config = {
|
|
67
|
+
...cli.flags,
|
|
68
|
+
header: `Auto-generated by: https://github.com/threlte/threlte/tree/main/packages/gltf
|
|
69
|
+
Command: npx @threlte/gltf@${packageJson.version} ${process.argv.slice(2).join(' ')}`
|
|
70
|
+
}
|
|
71
|
+
const file = cli.input[0]
|
|
72
|
+
const filePath = path.resolve(__dirname, file)
|
|
73
|
+
let nameExt = file.match(/[-_\w]+[.][\w]+$/i)[0]
|
|
74
|
+
let name = nameExt.split('.').slice(0, -1).join('.')
|
|
75
|
+
const baseName = name.charAt(0).toUpperCase() + name.slice(1)
|
|
76
|
+
const output = baseName + '.svelte'
|
|
77
|
+
const showLog = (log) => {
|
|
78
|
+
console.info('log:', log)
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const response = await gltf(file, output, { ...config, showLog, timeout: 0, delay: 1 })
|
|
82
|
+
} catch (e) {
|
|
83
|
+
console.error(e)
|
|
84
|
+
}
|
|
85
|
+
}
|
package/logo.svg
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
<svg fill="none" viewBox="0 0 800 400" width="100%" height="auto" xmlns="http://www.w3.org/2000/svg" style="height: auto">
|
|
2
|
+
<foreignObject width="100%" height="100%">
|
|
3
|
+
<div xmlns="http://www.w3.org/1999/xhtml">
|
|
4
|
+
<style>
|
|
5
|
+
@keyframes float {
|
|
6
|
+
0% {
|
|
7
|
+
transform: translate3d(0,0px,0);
|
|
8
|
+
}
|
|
9
|
+
100% {
|
|
10
|
+
transform: translate3d(0,-20px,0);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@keyframes float-mid {
|
|
15
|
+
0% {
|
|
16
|
+
transform: translate3d(0,0px,0);
|
|
17
|
+
}
|
|
18
|
+
100% {
|
|
19
|
+
transform: translate3d(0,-40px,0);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@keyframes float-rotate-mid {
|
|
24
|
+
0% {
|
|
25
|
+
transform: translate3d(0,-50px,0) rotate(0deg);
|
|
26
|
+
}
|
|
27
|
+
100% {
|
|
28
|
+
transform: translate3d(0,0px,0) rotate(180deg);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@keyframes float-hi {
|
|
33
|
+
0% {
|
|
34
|
+
transform: translate3d(0,0px,0);
|
|
35
|
+
}
|
|
36
|
+
100% {
|
|
37
|
+
transform: translate3d(0,-60px,0);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
svg > g > rect {
|
|
42
|
+
animation: float-mid ease-in-out 4s infinite alternate;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
svg > g > rect.r1 {
|
|
46
|
+
transform-origin: 700px 800px;
|
|
47
|
+
animation: float-rotate-mid ease-in-out 3s infinite alternate;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
svg > g > line {
|
|
51
|
+
animation: float-mid ease-in-out 4s infinite alternate;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
svg > g > line.l1 {
|
|
55
|
+
animation: float-mid ease-in-out 4.25s infinite alternate;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
svg > g > line.l2 {
|
|
59
|
+
animation: float-mid ease-in-out 4.5s infinite alternate;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
svg > g > line.l3 {
|
|
63
|
+
animation: float-mid ease-in-out 4.75s infinite alternate;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
svg > g > circle {
|
|
67
|
+
animation: float-hi ease-in-out 3s infinite alternate;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
svg > g > circle.faster {
|
|
71
|
+
animation: float-hi ease-in-out 2s infinite alternate;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
svg > g > circle.f1 {
|
|
75
|
+
animation: float-hi ease-in-out 2.5s infinite alternate;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
svg > g > path {
|
|
79
|
+
animation: float-mid ease-in-out 5s infinite alternate;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@media (prefers-color-scheme: dark) {
|
|
83
|
+
circle, rect, line {
|
|
84
|
+
stroke: #B2EBF2;
|
|
85
|
+
}
|
|
86
|
+
path {
|
|
87
|
+
fill: #B2EBF2;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
</style>
|
|
92
|
+
<svg width="100%" viewBox="0 0 1920 1080" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
93
|
+
<g>
|
|
94
|
+
<circle class="faster" cx="1338" cy="209" r="84" stroke="black" stroke-width="6"/>
|
|
95
|
+
<circle cx="-43" cy="1272" r="619" stroke="black" stroke-width="6"/>
|
|
96
|
+
<circle cx="-43" cy="1272" r="593" stroke="black" stroke-width="6"/>
|
|
97
|
+
<circle cx="-43" cy="1272" r="568" stroke="black" stroke-width="6"/>
|
|
98
|
+
<circle cx="-43" cy="1272" r="540" stroke="black" stroke-width="6"/>
|
|
99
|
+
<circle cx="-43" cy="1272" r="514" stroke="black" stroke-width="6"/>
|
|
100
|
+
<circle cx="-43" cy="1272" r="487" stroke="black" stroke-width="6"/>
|
|
101
|
+
<circle cx="-43" cy="1272" r="461" stroke="black" stroke-width="6"/>
|
|
102
|
+
<circle cx="-43" cy="1272" r="435" stroke="black" stroke-width="6"/>
|
|
103
|
+
<circle cx="-43" cy="1272" r="409" stroke="black" stroke-width="6"/>
|
|
104
|
+
<circle cx="-43" cy="1272" r="382" stroke="black" stroke-width="6"/>
|
|
105
|
+
<circle cx="-43" cy="1272" r="355" stroke="black" stroke-width="6"/>
|
|
106
|
+
<circle cx="-43" cy="1272" r="329" stroke="black" stroke-width="6"/>
|
|
107
|
+
<circle cx="-43" cy="1272" r="303" stroke="black" stroke-width="6"/>
|
|
108
|
+
<circle class="f1" cx="474.5" cy="350.5" r="12" stroke="black" stroke-width="40"/>
|
|
109
|
+
<circle cx="907.5" cy="145.5" r="3" stroke="black" stroke-width="15"/>
|
|
110
|
+
<circle cx="907.5" cy="230.5" r="3" stroke="black" stroke-width="15"/>
|
|
111
|
+
<circle cx="907.5" cy="315.5" r="3" stroke="black" stroke-width="15"/>
|
|
112
|
+
<circle cx="1025.5" cy="145.5" r="3" stroke="black" stroke-width="15"/>
|
|
113
|
+
<circle cx="1025.5" cy="230.5" r="3" stroke="black" stroke-width="15"/>
|
|
114
|
+
<circle cx="1025.5" cy="315.5" r="3" stroke="black" stroke-width="15"/>
|
|
115
|
+
<circle cx="1143.5" cy="145.5" r="3" stroke="black" stroke-width="15"/>
|
|
116
|
+
<circle cx="1143.5" cy="230.5" r="3" stroke="black" stroke-width="15"/>
|
|
117
|
+
<circle cx="1143.5" cy="315.5" r="3" stroke="black" stroke-width="15"/>
|
|
118
|
+
<circle cx="1261.5" cy="145.5" r="3" stroke="black" stroke-width="15"/>
|
|
119
|
+
<circle cx="1261.5" cy="230.5" r="3" stroke="black" stroke-width="15"/>
|
|
120
|
+
<circle cx="1261.5" cy="315.5" r="3" stroke="black" stroke-width="15"/>
|
|
121
|
+
<circle cx="1379.5" cy="145.5" r="3" stroke="black" stroke-width="15"/>
|
|
122
|
+
<circle cx="1379.5" cy="230.5" r="3" stroke="black" stroke-width="15"/>
|
|
123
|
+
<circle cx="1379.5" cy="315.5" r="3" stroke="black" stroke-width="15"/>
|
|
124
|
+
<circle cx="1497.5" cy="145.5" r="3" stroke="black" stroke-width="15"/>
|
|
125
|
+
<circle cx="1497.5" cy="230.5" r="3" stroke="black" stroke-width="15"/>
|
|
126
|
+
<circle cx="1497.5" cy="315.5" r="3" stroke="black" stroke-width="15"/>
|
|
127
|
+
<circle cx="1615.5" cy="145.5" r="3" stroke="black" stroke-width="15"/>
|
|
128
|
+
<circle cx="1615.5" cy="230.5" r="3" stroke="black" stroke-width="15"/>
|
|
129
|
+
<circle cx="1615.5" cy="315.5" r="3" stroke="black" stroke-width="15"/>
|
|
130
|
+
<rect class="r1" x="650" y="750" width="100" height="100" stroke="black" stroke-width="6"/>
|
|
131
|
+
<line class="l1" x1="1275" y1="780" x2="1393" y2="780" stroke="black" stroke-width="6"/>
|
|
132
|
+
<line class="l2" x1="1095" y1="839" x2="1685" y2="839" stroke="black" stroke-width="6"/>
|
|
133
|
+
<line class="l3" x1="1275" y1="898" x2="1518" y2="898" stroke="black" stroke-width="6"/>
|
|
134
|
+
<line x1="101.834" y1="297.925" x2="192.834" y2="202.925" stroke="black" stroke-width="6"/>
|
|
135
|
+
<line x1="299.834" y1="298.925" x2="390.834" y2="203.925" stroke="black" stroke-width="6"/>
|
|
136
|
+
<line x1="301.834" y1="494.925" x2="392.834" y2="399.925" stroke="black" stroke-width="6"/>
|
|
137
|
+
<line x1="104.834" y1="491.925" x2="195.834" y2="396.925" stroke="black" stroke-width="6"/>
|
|
138
|
+
<rect x="103" y="297" width="200" height="197" stroke="black" fill="none" stroke-width="6"/>
|
|
139
|
+
<rect x="192" y="204" width="200" height="197" stroke="black" fill="none" stroke-width="6"/>
|
|
140
|
+
<path d="M652.48 714.273C696.692 714.273 729.291 694.031 729.291 652.163V485.864H691.259V512.923H689.128C683.268 501.098 671.017 483.733 642.146 483.733C604.327 483.733 574.604 513.349 574.604 567.149C574.604 620.523 604.327 647.156 642.04 647.156C670.058 647.156 683.162 632.135 689.128 620.097H691.045V651.098C691.045 675.175 675.065 685.082 653.119 685.082C629.895 685.082 619.668 674.109 614.98 664.521L580.25 672.938C587.281 695.842 610.825 714.273 652.48 714.273ZM652.8 616.901C627.338 616.901 613.915 597.085 613.915 566.936C613.915 537.213 627.125 515.374 652.8 515.374C677.622 515.374 691.259 535.935 691.259 566.936C691.259 598.151 677.409 616.901 652.8 616.901ZM789.381 431.318H750.815V649.5H789.381V431.318ZM892.75 485.864H860.47V446.659H821.904V485.864H798.68V515.693H821.904V606.673C821.691 637.462 844.064 652.589 873.041 651.737C884.014 651.418 891.578 649.287 895.733 647.902L889.234 617.753C887.103 618.286 882.735 619.244 877.941 619.244C868.247 619.244 860.47 615.835 860.47 600.281V515.693H892.75V485.864ZM989.886 485.864H955.902V472.973C955.902 460.189 961.229 453.051 975.611 453.051C981.683 453.051 986.797 454.436 989.993 455.395L997.77 425.565C992.763 423.861 981.79 421.091 968.473 421.091C940.028 421.091 917.337 437.391 917.337 470.416V485.864H893.153V515.693H917.337V649.5H955.902V515.693H989.886V485.864ZM1002.09 485.864V658.342C1002.09 672.085 996.229 679.436 981.421 679.436C979.504 679.436 978.012 679.33 975.881 679.223V710.651C978.651 710.864 980.995 710.864 983.765 710.864C1019.88 710.864 1040.65 694.244 1040.65 658.875V485.864H1002.09ZM1021.26 462.639C1033.52 462.639 1043.53 453.264 1043.53 441.759C1043.53 430.146 1033.52 420.771 1021.26 420.771C1008.91 420.771 998.893 430.146 998.893 441.759C998.893 453.264 1008.91 462.639 1021.26 462.639ZM1191.64 529.116C1186.32 501.418 1164.16 483.733 1125.81 483.733C1086.39 483.733 1059.54 503.122 1059.65 533.378C1059.54 557.241 1074.24 573.009 1105.67 579.507L1133.58 585.366C1148.6 588.669 1155.64 594.741 1155.64 604.01C1155.64 615.196 1143.49 623.612 1125.17 623.612C1107.48 623.612 1095.98 615.942 1092.67 601.24L1055.07 604.862C1059.86 634.905 1085.11 652.696 1125.27 652.696C1166.18 652.696 1195.05 631.496 1195.16 600.494C1195.05 577.163 1180.03 562.888 1149.14 556.176L1121.22 550.21C1104.61 546.482 1098 540.729 1098.11 531.247C1098 520.168 1110.25 512.497 1126.34 512.497C1144.13 512.497 1153.5 522.192 1156.49 532.952L1191.64 529.116ZM1240.49 485.864H1199.58L1248.16 567.682L1198.31 649.5H1239.22L1273.52 590.587L1308.14 649.5H1348.73L1298.56 567.682L1347.88 485.864H1307.08L1273.52 546.268L1240.49 485.864Z" fill="black"/>
|
|
141
|
+
</g>
|
|
142
|
+
</svg>
|
|
143
|
+
</div>
|
|
144
|
+
</foreignObject>
|
|
145
|
+
</svg>
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@threlte/gltf",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "GLTF to Threlte converter",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"cleanup": "rm -rf node_modules"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"gltf",
|
|
11
|
+
"threlte",
|
|
12
|
+
"svelte",
|
|
13
|
+
"three",
|
|
14
|
+
"threejs",
|
|
15
|
+
"webp"
|
|
16
|
+
],
|
|
17
|
+
"author": "Grischa Erbe",
|
|
18
|
+
"contributors": [
|
|
19
|
+
"Paul Henschel"
|
|
20
|
+
],
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/threlte/threlte.git"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/threlte/threlte.git/issues"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/threlte/threlte.git#readme",
|
|
30
|
+
"bin": {
|
|
31
|
+
"@threlte/core": "./cli.js"
|
|
32
|
+
},
|
|
33
|
+
"main": "./src/utils/exports.js",
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=16"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@gltf-transform/core": "3.0.0-alpha.4",
|
|
39
|
+
"@gltf-transform/extensions": "3.0.0-alpha.4",
|
|
40
|
+
"@gltf-transform/functions": "3.0.0-alpha.4",
|
|
41
|
+
"@node-loader/babel": "^2.0.1",
|
|
42
|
+
"draco3dgltf": "^1.5.5",
|
|
43
|
+
"jsdom": "^20.0.3",
|
|
44
|
+
"jsdom-global": "^3.0.2",
|
|
45
|
+
"meow": "^11.0.0",
|
|
46
|
+
"meshoptimizer": "^0.18.1",
|
|
47
|
+
"prettier": "^2.8.3",
|
|
48
|
+
"prettier-plugin-svelte": "^2.9.0",
|
|
49
|
+
"sharp": "^0.31.3",
|
|
50
|
+
"svelte": "^3.55.1",
|
|
51
|
+
"three": "0.122.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"chalk": "^4.1.1",
|
|
55
|
+
"fast-glob": "^3.2.7",
|
|
56
|
+
"fs-extra": "^9.0.1",
|
|
57
|
+
"husky": "^4.3.0",
|
|
58
|
+
"lint-staged": "^10.4.0",
|
|
59
|
+
"read-pkg-up": "^9.1.0"
|
|
60
|
+
},
|
|
61
|
+
"husky": {
|
|
62
|
+
"hooks": {
|
|
63
|
+
"pre-commit": "npx lint-staged"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"lint-staged": {
|
|
67
|
+
"*.{js,jsx,ts,tsx}": [
|
|
68
|
+
"prettier --write"
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
A small command-line tool that turns GLTF assets into declarative and re-usable [Threlte](https://threlte.xyz) components.
|
|
2
|
+
|
|
3
|
+
### The GLTF workflow on the web is not ideal ...
|
|
4
|
+
|
|
5
|
+
- GLTF is thrown wholesale into the scene which prevents re-use, in threejs objects can only be mounted once
|
|
6
|
+
- Contents can only be found by traversal which is cumbersome and slow
|
|
7
|
+
- Changes to queried nodes are made by mutation, which alters the source data and prevents re-use
|
|
8
|
+
- Re-structuring content, making nodes conditional or adding/removing is cumbersome
|
|
9
|
+
- Model compression is complex and not easily achieved
|
|
10
|
+
- Models often have unnecessary nodes that cause extra work and matrix updates
|
|
11
|
+
|
|
12
|
+
### @threlte/gltf fixes that
|
|
13
|
+
|
|
14
|
+
- 🧑💻 It creates a virtual graph of all objects and materials. Now you can easily alter contents and re-use.
|
|
15
|
+
- 🏎️ The graph gets pruned (empty groups, unnecessary transforms, ...) and will perform better.
|
|
16
|
+
- ⚡️ It will optionally compress your model with up to 70%-90% size reduction.
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
Usage
|
|
22
|
+
$ npx @threlte/gltf [Model.glb] [options]
|
|
23
|
+
|
|
24
|
+
Options
|
|
25
|
+
--output, -o Output file name/path
|
|
26
|
+
--types, -t Add Typescript definitions
|
|
27
|
+
--keepnames, -k Keep original names
|
|
28
|
+
--keepgroups, -K Keep (empty) groups, disable pruning
|
|
29
|
+
--meta, -m Include metadata (as userData)
|
|
30
|
+
--shadows, s Let meshes cast and receive shadows
|
|
31
|
+
--printwidth, w Prettier printWidth (default: 120)
|
|
32
|
+
--precision, -p Number of fractional digits (default: 2)
|
|
33
|
+
--draco, -d Draco binary path
|
|
34
|
+
--root, -r Sets directory from which .gltf file is served
|
|
35
|
+
--transform, -T Transform the asset for the web (draco, prune, resize)
|
|
36
|
+
--resolution, -R Transform resolution for texture resizing (default: 1024)
|
|
37
|
+
--simplify, -S Transform simplification (default: false) (experimental!)
|
|
38
|
+
--weld Weld tolerance (default: 0.0001)
|
|
39
|
+
--ratio Simplifier ratio (default: 0.075)
|
|
40
|
+
--error Simplifier error threshold (default: 0.001)
|
|
41
|
+
--debug, -D Debug output
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### A typical use-case
|
|
45
|
+
|
|
46
|
+
First you run your model through `@threlte/gltf`. `npx` allows you to use npm packages without installing them.
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npx @threlte/gltf model.gltf --transform
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
This will create a `Model.svelte` file that plots out all of the assets contents.
|
|
53
|
+
|
|
54
|
+
```svelte
|
|
55
|
+
<!--
|
|
56
|
+
Auto-generated by: https://github.com/pmndrs/gltfjsx
|
|
57
|
+
Command: npx gltfjsx@0.0.1 ./stacy.glb
|
|
58
|
+
-->
|
|
59
|
+
<script>
|
|
60
|
+
import { Group } from 'three'
|
|
61
|
+
import { T, Three } from '@threlte/core'
|
|
62
|
+
import { useGltf, useGltfAnimations } from '@threlte/extras'
|
|
63
|
+
|
|
64
|
+
export const ref = new Group()
|
|
65
|
+
|
|
66
|
+
const { gltf } = useGltf('/stacy.glb')
|
|
67
|
+
export const { actions, mixer } = useGltfAnimations(gltf, ref)
|
|
68
|
+
</script>
|
|
69
|
+
|
|
70
|
+
{#if $gltf}
|
|
71
|
+
<Three type={ref} {...$$restProps}>
|
|
72
|
+
<T.Group name="Scene">
|
|
73
|
+
<T.Group name="Stacy" rotation={[Math.PI / 2, 0, 0]} scale={0.01}>
|
|
74
|
+
<Three type={$gltf.nodes.mixamorigHips} />
|
|
75
|
+
<T.SkinnedMesh
|
|
76
|
+
name="stacy"
|
|
77
|
+
geometry={$gltf.nodes.stacy.geometry}
|
|
78
|
+
material={$gltf.nodes.stacy.material}
|
|
79
|
+
skeleton={$gltf.nodes.stacy.skeleton}
|
|
80
|
+
rotation={[-Math.PI / 2, 0, 0]}
|
|
81
|
+
scale={100}
|
|
82
|
+
/>
|
|
83
|
+
</T.Group>
|
|
84
|
+
</T.Group>
|
|
85
|
+
|
|
86
|
+
<slot {ref} />
|
|
87
|
+
</Three>
|
|
88
|
+
{/if}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Add your model to your `/public` folder as you would normally do. With the `--transform` flag it has created a compressed copy of it (in the above case `model-transformed.glb`). Without the flag just copy the original model.
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
/public
|
|
95
|
+
model-transformed.glb
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The component can now be dropped into your scene.
|
|
99
|
+
|
|
100
|
+
```svelte
|
|
101
|
+
<script>
|
|
102
|
+
import { Canvas } from '@threlte/core'
|
|
103
|
+
import Model from './Model.svelte'
|
|
104
|
+
</script>
|
|
105
|
+
|
|
106
|
+
<Canvas>
|
|
107
|
+
<Model />
|
|
108
|
+
</Canvas>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
You can re-use it, it will re-use geometries and materials out of the box:
|
|
112
|
+
|
|
113
|
+
```svelte
|
|
114
|
+
<Model position={[0, 0, 0]} />
|
|
115
|
+
<Model position={[10, 0, -10]} />
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Or make the model dynamic. Change its colors for example:
|
|
119
|
+
|
|
120
|
+
```svelte
|
|
121
|
+
<T.Mesh geometry={$gltf.nodes.robot.geometry} material={$gltf.materials.metal} material.color="green" />
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Or exchange materials:
|
|
125
|
+
|
|
126
|
+
```svelte
|
|
127
|
+
<T.Mesh geometry={$gltf.nodes.robot.geometry}>
|
|
128
|
+
<T.MeshPhysicalMaterial color="hotpink" />
|
|
129
|
+
</T.Mesh>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Make contents conditional:
|
|
133
|
+
|
|
134
|
+
```svelte
|
|
135
|
+
{#if condition}
|
|
136
|
+
<T.Mesh geometry={$gltf.nodes.robot.geometry} material={$gltf.materials.metal} />}
|
|
137
|
+
{/if}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Features
|
|
141
|
+
|
|
142
|
+
#### ⚡️ Draco and meshopt compression ootb
|
|
143
|
+
|
|
144
|
+
You don't need to do anything if your models are draco compressed, since `useGltf` defaults to a [draco CDN](https://www.gstatic.com/draco/v1/decoders/). By adding the `--draco` flag you can refer to [local binaries](https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/draco/gltf) which must reside in your /public folder.
|
|
145
|
+
|
|
146
|
+
#### ⚡️ Auto-transform (compression, resize)
|
|
147
|
+
|
|
148
|
+
With the `--transform` flag it creates a binary-packed, draco-compressed, texture-resized (1024x1024), webp compressed, deduped, instanced and pruned *.glb ready to be consumed on a web site. It uses [glTF-Transform](https://github.com/donmccurdy/glTF-Transform). This can reduce the size of an asset by 70%-90%.
|
|
149
|
+
|
|
150
|
+
It will not alter the original but create a copy and append `[modelname]-transformed.glb`.
|
|
151
|
+
|
|
152
|
+
#### ⚡️ Type-safety
|
|
153
|
+
|
|
154
|
+
Add the `--types` flag and your component will be typesafe.
|
|
155
|
+
|
|
156
|
+
```svelte
|
|
157
|
+
<!--
|
|
158
|
+
Auto-generated by: https://github.com/pmndrs/gltfjsx
|
|
159
|
+
Command: npx gltfjsx@0.0.1 ./stacy.glb -t
|
|
160
|
+
-->
|
|
161
|
+
<script lang="ts">
|
|
162
|
+
import type * as THREE from 'three'
|
|
163
|
+
import { Group } from 'three'
|
|
164
|
+
import { T, Three, type Props, type Events, type Slots } from '@threlte/core'
|
|
165
|
+
import { useGltf, useGltfAnimations } from '@threlte/extras'
|
|
166
|
+
|
|
167
|
+
type $$Props = Props<THREE.Group>
|
|
168
|
+
type $$Events = Events<THREE.Group>
|
|
169
|
+
type $$Slots = Slots<THREE.Group>
|
|
170
|
+
|
|
171
|
+
export const ref = new Group()
|
|
172
|
+
|
|
173
|
+
type ActionName = 'pockets' | 'rope' | 'swingdance' | 'jump' | 'react' | 'shrug' | 'wave' | 'golf' | 'idle'
|
|
174
|
+
type GLTFResult = {
|
|
175
|
+
nodes: {
|
|
176
|
+
stacy: THREE.SkinnedMesh
|
|
177
|
+
mixamorigHips: THREE.Bone
|
|
178
|
+
}
|
|
179
|
+
materials: {}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const { gltf } = useGltf<GLTFResult>('/stacy.glb')
|
|
183
|
+
export const { actions, mixer } = useGltfAnimations<ActionName>(gltf, ref)
|
|
184
|
+
</script>
|
|
185
|
+
|
|
186
|
+
{#if $gltf}
|
|
187
|
+
<Three type={ref} {...$$restProps}>
|
|
188
|
+
<T.Group name="Scene">
|
|
189
|
+
<T.Group name="Stacy" rotation={[Math.PI / 2, 0, 0]} scale={0.01}>
|
|
190
|
+
<Three type={$gltf.nodes.mixamorigHips} />
|
|
191
|
+
<T.SkinnedMesh
|
|
192
|
+
name="stacy"
|
|
193
|
+
geometry={$gltf.nodes.stacy.geometry}
|
|
194
|
+
material={$gltf.nodes.stacy.material}
|
|
195
|
+
skeleton={$gltf.nodes.stacy.skeleton}
|
|
196
|
+
rotation={[-Math.PI / 2, 0, 0]}
|
|
197
|
+
scale={100}
|
|
198
|
+
/>
|
|
199
|
+
</T.Group>
|
|
200
|
+
</T.Group>
|
|
201
|
+
|
|
202
|
+
<slot {ref} />
|
|
203
|
+
</Three>
|
|
204
|
+
{/if}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### ⚡️ Easier access to animations
|
|
208
|
+
|
|
209
|
+
If your GLTF contains animations it will add [@threlte/extras's `useGltfAnimations`](https://threlte.xyz/extras/use-gltf-animations) hook, which extracts all clips and prepares them as actions:
|
|
210
|
+
|
|
211
|
+
```svelte
|
|
212
|
+
const { gltf } = useGltf('/stacy.glb')
|
|
213
|
+
export const { actions, mixer } = useGltfAnimations(gltf, ref)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
If you want to play an animation you can do so at any time:
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
const onEvent = () => {
|
|
220
|
+
$actions.jump.play()
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Using the parser stand-alone
|
|
225
|
+
|
|
226
|
+
```jsx
|
|
227
|
+
import { parse } from '@threlte/gltf'
|
|
228
|
+
import { GLTFLoader, DRACOLoader } from 'three-stdlib'
|
|
229
|
+
|
|
230
|
+
const gltfLoader = new GLTFLoader()
|
|
231
|
+
const dracoloader = new DRACOLoader()
|
|
232
|
+
dracoloader.setDecoderPath('https://www.gstatic.com/draco/v1/decoders/')
|
|
233
|
+
gltfLoader.setDRACOLoader(dracoloader)
|
|
234
|
+
|
|
235
|
+
gltfLoader.load(url, (gltf) => {
|
|
236
|
+
const component = parse(filename, gltf, config)
|
|
237
|
+
})
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Requirements
|
|
241
|
+
|
|
242
|
+
- Nodejs must be installed
|
|
243
|
+
- The GLTF file has to be present in your projects `/public` folder
|
|
244
|
+
- [three](https://github.com/mrdoob/three.js/) (>= 122.x)
|
|
245
|
+
- @threlte/core > 5.0.0
|
|
246
|
+
- @threlte/core > 4.9.3
|