@driftengine/assets 3.61.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.
- package/LICENSE +202 -0
- package/NOTICE +9 -0
- package/README.md +9 -0
- package/dist/assetPath.d.ts +51 -0
- package/dist/assetPath.js +59 -0
- package/dist/coarseLevel.d.ts +94 -0
- package/dist/coarseLevel.js +606 -0
- package/dist/dds.d.ts +41 -0
- package/dist/dds.js +425 -0
- package/dist/drawKey.d.ts +64 -0
- package/dist/drawKey.js +42 -0
- package/dist/drftLoader.d.ts +420 -0
- package/dist/drftLoader.js +996 -0
- package/dist/drftTextures.d.ts +87 -0
- package/dist/drftTextures.js +138 -0
- package/dist/fbx.d.ts +86 -0
- package/dist/fbx.js +792 -0
- package/dist/fbxHarness.d.ts +68 -0
- package/dist/fbxHarness.js +185 -0
- package/dist/fbxInflate.d.ts +60 -0
- package/dist/fbxInflate.js +204 -0
- package/dist/fbxMaterial.d.ts +87 -0
- package/dist/fbxMaterial.js +345 -0
- package/dist/fbxRig.d.ts +130 -0
- package/dist/fbxRig.js +601 -0
- package/dist/gltf.d.ts +242 -0
- package/dist/gltf.js +904 -0
- package/dist/gltfAccessor.d.ts +2 -0
- package/dist/gltfAccessor.js +106 -0
- package/dist/gltfSkin.d.ts +32 -0
- package/dist/gltfSkin.js +144 -0
- package/dist/iesPhotometry.d.ts +44 -0
- package/dist/iesPhotometry.js +94 -0
- package/dist/imageInfo.d.ts +31 -0
- package/dist/imageInfo.js +119 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +132 -0
- package/dist/kn5.d.ts +158 -0
- package/dist/kn5.js +557 -0
- package/dist/loadProgress.d.ts +118 -0
- package/dist/loadProgress.js +1 -0
- package/dist/localise.d.ts +35 -0
- package/dist/localise.js +253 -0
- package/dist/obj.d.ts +54 -0
- package/dist/obj.js +335 -0
- package/dist/orient.d.ts +104 -0
- package/dist/orient.js +241 -0
- package/dist/radianceHdr.d.ts +36 -0
- package/dist/radianceHdr.js +172 -0
- package/dist/readModel.d.ts +153 -0
- package/dist/readModel.js +386 -0
- package/dist/recognise.d.ts +38 -0
- package/dist/recognise.js +97 -0
- package/dist/stl.d.ts +22 -0
- package/dist/stl.js +131 -0
- package/dist/tangentOrder.d.ts +24 -0
- package/dist/tangentOrder.js +31 -0
- package/dist/threemf.d.ts +46 -0
- package/dist/threemf.js +254 -0
- package/dist/uploadBudget.d.ts +82 -0
- package/dist/uploadBudget.js +86 -0
- package/dist/usd.d.ts +49 -0
- package/dist/usd.js +542 -0
- package/dist/weld.d.ts +44 -0
- package/dist/weld.js +237 -0
- package/dist/zip.d.ts +35 -0
- package/dist/zip.js +110 -0
- package/package.json +61 -0
- package/src/assetPath.ts +79 -0
- package/src/coarseLevel.ts +720 -0
- package/src/dds.ts +507 -0
- package/src/drawKey.ts +91 -0
- package/src/drftLoader.ts +1197 -0
- package/src/drftTextures.ts +153 -0
- package/src/fbx.ts +934 -0
- package/src/fbxHarness.ts +215 -0
- package/src/fbxInflate.ts +258 -0
- package/src/fbxMaterial.ts +410 -0
- package/src/fbxRig.ts +652 -0
- package/src/gltf.ts +1161 -0
- package/src/gltfAccessor.ts +127 -0
- package/src/gltfSkin.ts +210 -0
- package/src/iesPhotometry.ts +136 -0
- package/src/imageInfo.ts +130 -0
- package/src/index.ts +162 -0
- package/src/kn5.ts +705 -0
- package/src/loadProgress.ts +131 -0
- package/src/localise.ts +275 -0
- package/src/obj.ts +386 -0
- package/src/orient.ts +262 -0
- package/src/radianceHdr.ts +195 -0
- package/src/readModel.ts +515 -0
- package/src/recognise.ts +124 -0
- package/src/stl.ts +147 -0
- package/src/tangentOrder.ts +32 -0
- package/src/threemf.ts +303 -0
- package/src/uploadBudget.ts +90 -0
- package/src/usd.ts +642 -0
- package/src/weld.ts +264 -0
- package/src/zip.ts +130 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/** The Radiance `.hdr` container (RGBE), decoded to linear floats. */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* An equirectangular image, linear, three floats a texel, row 0 at the top.
|
|
5
|
+
*
|
|
6
|
+
* Three rather than four because an environment has no alpha and never will: the fourth channel
|
|
7
|
+
* would be a byte a texel of ones, and at 2048x1024 that is eight megabytes of nothing.
|
|
8
|
+
*/
|
|
9
|
+
export interface RadianceImage {
|
|
10
|
+
readonly width: number;
|
|
11
|
+
readonly height: number;
|
|
12
|
+
/** `width * height * 3` linear values, row-major from the top. */
|
|
13
|
+
readonly data: Float32Array;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Where a decoded byte sits inside its bucket.
|
|
18
|
+
*
|
|
19
|
+
* Radiance's own `colr_color` is `ldexp(mantissa + 0.5, exponent - (128 + 8))`, and the half is
|
|
20
|
+
* the part every reimplementation drops. Dropping it makes an image about 0.2% dark, which is
|
|
21
|
+
* invisible on its own, survives every eyeball comparison, and is exactly the kind of thing that
|
|
22
|
+
* is never found. It is written as a named constant so that nobody removes it as a typo.
|
|
23
|
+
*/
|
|
24
|
+
const BUCKET_CENTRE = 0.5;
|
|
25
|
+
|
|
26
|
+
/** `2^-(128 + 8)`, the scale a stored exponent of zero would otherwise land on. */
|
|
27
|
+
const EXPONENT_BIAS = 128 + 8;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Read a Radiance RGBE file into linear radiance.
|
|
31
|
+
*
|
|
32
|
+
* **Pure, and it takes bytes rather than a URL.** It knows nothing about a device, a fetch or a
|
|
33
|
+
* texture, which is what lets it be tested exactly and what keeps the fetching decision — cache
|
|
34
|
+
* headers, retries, where the file lives — with the consumer who has to make it.
|
|
35
|
+
*
|
|
36
|
+
* **Both scanline encodings, because only one of them is optional in practice.** A file narrower
|
|
37
|
+
* than 8 or wider than 0x7fff stores flat RGBE quadruples; everything else is new-style
|
|
38
|
+
* run-length, and that is every environment map anybody actually has. A decoder that handles only
|
|
39
|
+
* the flat path passes a hand-built test and fails on every real file.
|
|
40
|
+
*
|
|
41
|
+
* **Every refusal names what it found.** `AGENTS.md` requires failing loudly at load with an
|
|
42
|
+
* actionable message: a decoder that quietly answers black for a header it does not recognise
|
|
43
|
+
* hands a scene an environment of nothing, which is indistinguishable from a probe that has not
|
|
44
|
+
* baked yet and is diagnosed as the renderer's fault.
|
|
45
|
+
*
|
|
46
|
+
* **What it costs** is `width * height * 12` bytes for the result, which at 2048x1024 is 25 MB
|
|
47
|
+
* held while the faces are built. **What would make it wrong** is a consumer streaming an
|
|
48
|
+
* environment larger than memory; this reads whole files, and a tiled format is what that consumer
|
|
49
|
+
* wants — which is one of the reasons KTX2 is named and deliberately not taken.
|
|
50
|
+
*/
|
|
51
|
+
export function readRadianceHdr(bytes: Uint8Array): RadianceImage {
|
|
52
|
+
const signature = readLine(bytes, 0);
|
|
53
|
+
if (!signature.text.startsWith('#?RADIANCE') && !signature.text.startsWith('#?RGBE')) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`readRadianceHdr: not a Radiance file — expected a "#?RADIANCE" signature, found ` +
|
|
56
|
+
`"${signature.text.slice(0, 20)}"`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let at = signature.next;
|
|
61
|
+
let format: string | null = null;
|
|
62
|
+
/* The header runs to a blank line, and the resolution line is the one after it. */
|
|
63
|
+
for (;;) {
|
|
64
|
+
const line = readLine(bytes, at);
|
|
65
|
+
at = line.next;
|
|
66
|
+
if (line.text === '') break;
|
|
67
|
+
if (line.text.startsWith('FORMAT=')) format = line.text.slice('FORMAT='.length).trim();
|
|
68
|
+
if (at >= bytes.length) throw new Error('readRadianceHdr: the header never ended');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (format !== null && format !== '32-bit_rle_rgbe') {
|
|
72
|
+
throw new Error(
|
|
73
|
+
`readRadianceHdr: only 32-bit_rle_rgbe is decoded here, and this file declares ` +
|
|
74
|
+
`"${format}". An XYZE file carries CIE primaries rather than RGB and converting it is a ` +
|
|
75
|
+
'colour decision rather than a decoding one.',
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const resolution = readLine(bytes, at);
|
|
80
|
+
at = resolution.next;
|
|
81
|
+
/*
|
|
82
|
+
* `-Y height +X width` only. Radiance permits eight orientations, six of which nothing has
|
|
83
|
+
* produced in decades, and treating one as another silently returns an image that is flipped —
|
|
84
|
+
* which in an environment map puts the sky underfoot and is the most confusing available failure.
|
|
85
|
+
*/
|
|
86
|
+
const match = /^-Y\s+(\d+)\s+\+X\s+(\d+)$/.exec(resolution.text.trim());
|
|
87
|
+
if (match === null) {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`readRadianceHdr: only "-Y height +X width" is handled, and this file says ` +
|
|
90
|
+
`"${resolution.text.trim()}". Any other orientation would decode to a flipped image.`,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
const height = Number(match[1]);
|
|
94
|
+
const width = Number(match[2]);
|
|
95
|
+
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
|
|
96
|
+
throw new Error(`readRadianceHdr: a ${width} by ${height} image is not decodable`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const data = new Float32Array(width * height * 3);
|
|
100
|
+
/* One scanline of RGBE, reused, because a 2048-wide image would otherwise allocate per row. */
|
|
101
|
+
const scanline = new Uint8Array(width * 4);
|
|
102
|
+
|
|
103
|
+
for (let y = 0; y < height; y++) {
|
|
104
|
+
at = readScanline(bytes, at, scanline, width);
|
|
105
|
+
for (let x = 0; x < width; x++) {
|
|
106
|
+
const exponent = scanline[x * 4 + 3] ?? 0;
|
|
107
|
+
const out = (y * width + x) * 3;
|
|
108
|
+
/*
|
|
109
|
+
* A stored exponent of zero is exactly black and Radiance reserves it for that. Running it
|
|
110
|
+
* through the same arithmetic gives `0.5 * 2^-136`: denormal, nonzero, and enough to make
|
|
111
|
+
* every black texel of a night sky something a prefilter will average into a grey haze.
|
|
112
|
+
*/
|
|
113
|
+
if (exponent === 0) {
|
|
114
|
+
data[out] = 0;
|
|
115
|
+
data[out + 1] = 0;
|
|
116
|
+
data[out + 2] = 0;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const scale = 2 ** (exponent - EXPONENT_BIAS);
|
|
120
|
+
data[out] = ((scanline[x * 4] ?? 0) + BUCKET_CENTRE) * scale;
|
|
121
|
+
data[out + 1] = ((scanline[x * 4 + 1] ?? 0) + BUCKET_CENTRE) * scale;
|
|
122
|
+
data[out + 2] = ((scanline[x * 4 + 2] ?? 0) + BUCKET_CENTRE) * scale;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return { width, height, data };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** One newline-terminated line as text, and where the next one starts. */
|
|
130
|
+
function readLine(bytes: Uint8Array, from: number): { text: string; next: number } {
|
|
131
|
+
let end = from;
|
|
132
|
+
while (end < bytes.length && bytes[end] !== 0x0a) end++;
|
|
133
|
+
let text = '';
|
|
134
|
+
for (let i = from; i < end; i++) text += String.fromCharCode(bytes[i] ?? 0);
|
|
135
|
+
return { text: text.replace(/\r$/, ''), next: end + 1 };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* One scanline of RGBE into `out`, in either encoding, returning where the next one starts.
|
|
140
|
+
*
|
|
141
|
+
* The new-style marker is `2, 2, hi, lo` with `hi<<8 | lo` equal to the width. That third and
|
|
142
|
+
* fourth byte being the width is what distinguishes it from an old-style scanline whose first
|
|
143
|
+
* pixel happens to be `(2, 2, ...)`, which is a real colour and does occur.
|
|
144
|
+
*/
|
|
145
|
+
function readScanline(bytes: Uint8Array, from: number, out: Uint8Array, width: number): number {
|
|
146
|
+
const declared = ((bytes[from + 2] ?? 0) << 8) | (bytes[from + 3] ?? 0);
|
|
147
|
+
const isRle =
|
|
148
|
+
width >= 8 &&
|
|
149
|
+
width < 0x8000 &&
|
|
150
|
+
bytes[from] === 2 &&
|
|
151
|
+
bytes[from + 1] === 2 &&
|
|
152
|
+
declared === width;
|
|
153
|
+
|
|
154
|
+
if (!isRle) {
|
|
155
|
+
/* Flat quadruples, which is what a narrow image and an old encoder both produce. */
|
|
156
|
+
for (let x = 0; x < width; x++) {
|
|
157
|
+
out[x * 4] = bytes[from + x * 4] ?? 0;
|
|
158
|
+
out[x * 4 + 1] = bytes[from + x * 4 + 1] ?? 0;
|
|
159
|
+
out[x * 4 + 2] = bytes[from + x * 4 + 2] ?? 0;
|
|
160
|
+
out[x * 4 + 3] = bytes[from + x * 4 + 3] ?? 0;
|
|
161
|
+
}
|
|
162
|
+
return from + width * 4;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
let at = from + 4;
|
|
166
|
+
/*
|
|
167
|
+
* The four channels are stored one after another rather than interleaved, which is the whole
|
|
168
|
+
* reason this encoding compresses: a sky's red channel is a smooth ramp and its exponent channel
|
|
169
|
+
* is nearly constant, and neither is compressible while they are interleaved with the others.
|
|
170
|
+
*/
|
|
171
|
+
for (let channel = 0; channel < 4; channel++) {
|
|
172
|
+
let x = 0;
|
|
173
|
+
while (x < width) {
|
|
174
|
+
const count = bytes[at] ?? 0;
|
|
175
|
+
at++;
|
|
176
|
+
if (count > 128) {
|
|
177
|
+
/* A run: repeat the next byte this many times, minus the flag bit. */
|
|
178
|
+
const value = bytes[at] ?? 0;
|
|
179
|
+
at++;
|
|
180
|
+
const run = count - 128;
|
|
181
|
+
if (x + run > width) throw new Error('readRadianceHdr: a run overran its scanline');
|
|
182
|
+
for (let i = 0; i < run; i++) out[(x + i) * 4 + channel] = value;
|
|
183
|
+
x += run;
|
|
184
|
+
} else {
|
|
185
|
+
if (count === 0) throw new Error('readRadianceHdr: a zero-length literal run');
|
|
186
|
+
if (x + count > width)
|
|
187
|
+
throw new Error('readRadianceHdr: a literal run overran its scanline');
|
|
188
|
+
for (let i = 0; i < count; i++) out[(x + i) * 4 + channel] = bytes[at + i] ?? 0;
|
|
189
|
+
at += count;
|
|
190
|
+
x += count;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return at;
|
|
195
|
+
}
|