poppygl 0.0.24 → 0.0.26
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/README.md +13 -13
- package/dist/index.d.ts +1 -16
- package/dist/index.js +8 -261
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,10 +9,10 @@ Render GLTF files to PNG images in completely native JavaScript without WebGL/Op
|
|
|
9
9
|
Give poppygl a `.gltf` or `.glb` URL and it will fetch every referenced buffer/texture, rasterize the scene, and hand back a PNG buffer.
|
|
10
10
|
|
|
11
11
|
```ts
|
|
12
|
-
import {
|
|
12
|
+
import { renderGLTFToPNGFromURL } from "poppygl"
|
|
13
13
|
import { writeFile } from "node:fs/promises"
|
|
14
14
|
|
|
15
|
-
const png = await
|
|
15
|
+
const png = await renderGLTFToPNGFromURL(
|
|
16
16
|
"https://models.babylonjs.com/DamagedHelmet.glb",
|
|
17
17
|
{
|
|
18
18
|
width: 800,
|
|
@@ -28,14 +28,14 @@ await writeFile("DamagedHelmet.png", png)
|
|
|
28
28
|
|
|
29
29
|
## Render from an in-memory GLB buffer
|
|
30
30
|
|
|
31
|
-
Already have the `.glb` bytes (for example, uploaded by a user or read from disk)? Send the buffer straight to `
|
|
31
|
+
Already have the `.glb` bytes (for example, uploaded by a user or read from disk)? Send the buffer straight to `renderGLTFToPNGFromGLB` and receive the PNG output.
|
|
32
32
|
|
|
33
33
|
```ts
|
|
34
34
|
import { readFile } from "node:fs/promises"
|
|
35
|
-
import {
|
|
35
|
+
import { renderGLTFToPNGFromGLB } from "poppygl"
|
|
36
36
|
|
|
37
37
|
const glb = await readFile("DamagedHelmet.glb")
|
|
38
|
-
const png = await
|
|
38
|
+
const png = await renderGLTFToPNGFromGLB(glb, {
|
|
39
39
|
width: 1024,
|
|
40
40
|
height: 768,
|
|
41
41
|
})
|
|
@@ -43,11 +43,11 @@ const png = await renderGLTFToPNGBufferFromGLBBuffer(glb, {
|
|
|
43
43
|
// write or return the PNG buffer
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
> This helper expects every referenced buffer/image to be embedded in the GLB (the usual single-file package). If the asset links out to external resources, load it with `
|
|
46
|
+
> This helper expects every referenced buffer/image to be embedded in the GLB (the usual single-file package). If the asset links out to external resources, load it with `renderGLTFToPNGFromURL` instead so poppygl can fetch the extras.
|
|
47
47
|
|
|
48
48
|
## Render options
|
|
49
49
|
|
|
50
|
-
`
|
|
50
|
+
`renderGLTFToPNGFromURL` accepts the same render options as the lower-level APIs:
|
|
51
51
|
|
|
52
52
|
- `width`/`height` (default `512`): output resolution in pixels.
|
|
53
53
|
- `supersampling`: render at `width * supersampling` / `height * supersampling`, then downsample (default `1`).
|
|
@@ -76,8 +76,8 @@ import {
|
|
|
76
76
|
bufferFromDataURI,
|
|
77
77
|
createSceneFromGLTF,
|
|
78
78
|
decodeImageFromBuffer,
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
encodePNG,
|
|
80
|
+
createUint8Bitmap,
|
|
81
81
|
renderSceneFromGLTF,
|
|
82
82
|
} from "poppygl"
|
|
83
83
|
import gltfJson from "./CesiumMan.gltf.json" assert { type: "json" }
|
|
@@ -105,8 +105,8 @@ const images = await Promise.all(
|
|
|
105
105
|
)
|
|
106
106
|
|
|
107
107
|
const scene = createSceneFromGLTF(gltfJson, { buffers, images })
|
|
108
|
-
const { bitmap } = renderSceneFromGLTF(scene, { width: 512, height: 512 },
|
|
109
|
-
const png = await
|
|
108
|
+
const { bitmap } = renderSceneFromGLTF(scene, { width: 512, height: 512 }, createUint8Bitmap)
|
|
109
|
+
const png = await encodePNG(bitmap)
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
The only contract is that `buffers` is an array of `Uint8Array` instances and `images` is an array of `BitmapLike` textures (PNG and JPEG are supported out of the box via `decodeImageFromBuffer`).
|
|
@@ -116,7 +116,7 @@ The only contract is that `buffers` is an array of `Uint8Array` instances and `i
|
|
|
116
116
|
- `loadGLTFWithResourcesFromURL` returns `{ gltf, resources }` if you prefer to inspect or cache the parsed data before rendering.
|
|
117
117
|
- `createSceneFromGLTF` builds draw calls ready for the software rasterizer.
|
|
118
118
|
- `computeSmoothNormals` and `computeWorldAABB` expose useful preprocessing helpers.
|
|
119
|
-
- `
|
|
120
|
-
- `
|
|
119
|
+
- `createUint8Bitmap` allocates a portable in-memory bitmap used by the renderer.
|
|
120
|
+
- `encodePNG` packs any `BitmapLike` into a `Uint8Array` PNG that can be written to disk or served over the network.
|
|
121
121
|
|
|
122
122
|
Happy rendering!
|
package/dist/index.d.ts
CHANGED
|
@@ -193,12 +193,8 @@ declare function drawInfiniteGrid(software_renderer: SoftwareRenderer, params: {
|
|
|
193
193
|
gamma_out?: boolean;
|
|
194
194
|
}): void;
|
|
195
195
|
|
|
196
|
-
declare const pureImageFactory: ImageFactory;
|
|
197
|
-
|
|
198
196
|
declare function encodePNG(image: BitmapLike): Promise<Uint8Array>;
|
|
199
197
|
|
|
200
|
-
declare function encodePNGToBuffer(image: BitmapLike): Promise<Buffer>;
|
|
201
|
-
|
|
202
198
|
interface RenderGLTFToPNGFromURLOptions extends RenderOptionsInput, LoadGLTFWithResourcesFromURLOptions {
|
|
203
199
|
}
|
|
204
200
|
declare function renderGLTFToPNGFromURL(url: string, options?: RenderGLTFToPNGFromURLOptions): Promise<Uint8Array>;
|
|
@@ -206,17 +202,6 @@ declare function renderGLTFToPNGFromURL(url: string, options?: RenderGLTFToPNGFr
|
|
|
206
202
|
type RenderGLTFToPNGFromGLBOptions = RenderOptionsInput;
|
|
207
203
|
declare function renderGLTFToPNGFromGLB(glb: ArrayBuffer | Uint8Array, options?: RenderGLTFToPNGFromGLBOptions): Promise<Uint8Array>;
|
|
208
204
|
|
|
209
|
-
interface RenderGLTFToPNGBufferFromURLOptions extends RenderOptionsInput, LoadGLTFWithResourcesFromURLOptions {
|
|
210
|
-
}
|
|
211
|
-
declare function renderGLTFToPNGBufferFromURL(url: string, options?: RenderGLTFToPNGBufferFromURLOptions): Promise<Buffer>;
|
|
212
|
-
|
|
213
|
-
type RenderGLTFToPNGBufferFromGLBBufferOptions = RenderOptionsInput;
|
|
214
|
-
declare function renderGLTFToPNGBufferFromGLBBuffer(glb: ArrayBuffer | Uint8Array, options?: RenderGLTFToPNGBufferFromGLBBufferOptions): Promise<Buffer>;
|
|
215
|
-
|
|
216
|
-
interface RenderGLTFToPNGBufferOptions extends RenderOptionsInput, LoadGLTFWithResourcesFromURLOptions {
|
|
217
|
-
}
|
|
218
|
-
declare function renderGLTFToPNGBuffer(gltfOrJson: string | any, options?: RenderGLTFToPNGBufferOptions, resources?: GLTFResources): Promise<Buffer>;
|
|
219
|
-
|
|
220
205
|
declare function renderSceneFromGLTF(scene: GLTFScene, options?: RenderOptionsInput, imageFactory?: ImageFactory): RenderResult;
|
|
221
206
|
|
|
222
|
-
export { type BitmapLike, type Camera, type CameraRotation, type CameraUp, DEFAULT_LIGHT_DIR, DEFAULT_RENDER_OPTIONS, type DebugPoint, type DrawCall, type FetchLike, type GLTFResources, type GLTFScene, type GridOptions, type ImageFactory, type LightSettings, type LoadGLTFWithResourcesFromURLOptions, type Material, type MutableRGBA, type RGBA, type
|
|
207
|
+
export { type BitmapLike, type Camera, type CameraRotation, type CameraUp, DEFAULT_LIGHT_DIR, DEFAULT_RENDER_OPTIONS, type DebugPoint, type DrawCall, type FetchLike, type GLTFResources, type GLTFScene, type GridOptions, type ImageFactory, type LightSettings, type LoadGLTFWithResourcesFromURLOptions, type Material, type MutableRGBA, type RGBA, type RenderGLTFToPNGFromGLBOptions, type RenderGLTFToPNGFromURLOptions, type RenderOptions, type RenderOptionsInput, type RenderResult, SoftwareRenderer, bufferFromDataURI, buildCamera, computeSmoothNormals, computeWorldAABB, createGrid, createInfiniteGrid, createSceneFromGLTF, createUint8Bitmap, decodeImageFromBuffer, drawInfiniteGrid, encodePNG, getDefaultRenderOptions, hexToRgb, isJPG, isPNG, loadGLTFWithResourcesFromURL, renderDrawCalls, renderGLTFToPNGFromGLB, renderGLTFToPNGFromURL, renderSceneFromGLTF, resolveRenderOptions };
|
package/dist/index.js
CHANGED
|
@@ -745,6 +745,9 @@ var SoftwareRenderer = class {
|
|
|
745
745
|
const alphaMode = material.alphaMode ?? "OPAQUE";
|
|
746
746
|
const alphaCutoff = material.alphaCutoff ?? 0.5;
|
|
747
747
|
if (alphaMode === "MASK" && a < alphaCutoff) continue;
|
|
748
|
+
if (alphaMode !== "BLEND") {
|
|
749
|
+
a = 1;
|
|
750
|
+
}
|
|
748
751
|
const shouldWriteDepth = alphaMode !== "BLEND";
|
|
749
752
|
if (shouldWriteDepth) {
|
|
750
753
|
depth[di] = z01;
|
|
@@ -1620,21 +1623,6 @@ function getNodeBuffer() {
|
|
|
1620
1623
|
}
|
|
1621
1624
|
return maybeBuffer;
|
|
1622
1625
|
}
|
|
1623
|
-
function toUint8Array(chunk) {
|
|
1624
|
-
if (chunk instanceof Uint8Array) return chunk;
|
|
1625
|
-
if (chunk instanceof ArrayBuffer) return new Uint8Array(chunk);
|
|
1626
|
-
return new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength);
|
|
1627
|
-
}
|
|
1628
|
-
function concatUint8Arrays(chunks) {
|
|
1629
|
-
const totalLength = chunks.reduce((length, chunk) => length + chunk.length, 0);
|
|
1630
|
-
const result = new Uint8Array(totalLength);
|
|
1631
|
-
let offset = 0;
|
|
1632
|
-
for (const chunk of chunks) {
|
|
1633
|
-
result.set(chunk, offset);
|
|
1634
|
-
offset += chunk.length;
|
|
1635
|
-
}
|
|
1636
|
-
return result;
|
|
1637
|
-
}
|
|
1638
1626
|
function base64ToUint8Array(base64) {
|
|
1639
1627
|
if (typeof globalThis.atob === "function") {
|
|
1640
1628
|
const binary = globalThis.atob(base64);
|
|
@@ -1646,9 +1634,6 @@ function base64ToUint8Array(base64) {
|
|
|
1646
1634
|
}
|
|
1647
1635
|
return new Uint8Array(getNodeBuffer().from(base64, "base64"));
|
|
1648
1636
|
}
|
|
1649
|
-
function uint8ArrayToNodeBuffer(bytes) {
|
|
1650
|
-
return getNodeBuffer().from(bytes);
|
|
1651
|
-
}
|
|
1652
1637
|
|
|
1653
1638
|
// lib/gltf/resourceUtils.ts
|
|
1654
1639
|
function bufferFromDataURI(uri) {
|
|
@@ -1678,13 +1663,13 @@ async function decodeImageViaFastPng(buf) {
|
|
|
1678
1663
|
};
|
|
1679
1664
|
}
|
|
1680
1665
|
async function decodeImageViaPureImage(buf, mimeType) {
|
|
1681
|
-
const { PassThrough
|
|
1682
|
-
const
|
|
1683
|
-
const stream = new
|
|
1666
|
+
const { PassThrough } = await import("readable-stream");
|
|
1667
|
+
const PImage = await import("pureimage");
|
|
1668
|
+
const stream = new PassThrough();
|
|
1684
1669
|
stream.end(buf);
|
|
1685
|
-
if (mimeType === "image/png") return
|
|
1670
|
+
if (mimeType === "image/png") return PImage.decodePNGFromStream(stream);
|
|
1686
1671
|
if (mimeType === "image/jpeg" || mimeType === "image/jpg")
|
|
1687
|
-
return
|
|
1672
|
+
return PImage.decodeJPEGFromStream(stream);
|
|
1688
1673
|
throw new Error(`Unsupported embedded image mimeType: ${mimeType}`);
|
|
1689
1674
|
}
|
|
1690
1675
|
async function decodeImageFromBuffer(buf, mimeType) {
|
|
@@ -1852,10 +1837,6 @@ async function loadGLTFWithResourcesFromURL(url, options = {}) {
|
|
|
1852
1837
|
};
|
|
1853
1838
|
}
|
|
1854
1839
|
|
|
1855
|
-
// lib/image/pureImageFactory.ts
|
|
1856
|
-
import * as PImage from "pureimage";
|
|
1857
|
-
var pureImageFactory = (width, height) => PImage.make(width, height);
|
|
1858
|
-
|
|
1859
1840
|
// lib/image/encodePNG.ts
|
|
1860
1841
|
import { encode } from "fast-png";
|
|
1861
1842
|
async function encodePNG(image) {
|
|
@@ -1868,28 +1849,6 @@ async function encodePNG(image) {
|
|
|
1868
1849
|
});
|
|
1869
1850
|
}
|
|
1870
1851
|
|
|
1871
|
-
// lib/image/encodePNGToBuffer.ts
|
|
1872
|
-
import { PassThrough } from "readable-stream";
|
|
1873
|
-
import * as PImage2 from "pureimage";
|
|
1874
|
-
async function encodePNGToBuffer(image) {
|
|
1875
|
-
const passThrough = new PassThrough();
|
|
1876
|
-
const chunks = [];
|
|
1877
|
-
passThrough.on(
|
|
1878
|
-
"data",
|
|
1879
|
-
(chunk) => {
|
|
1880
|
-
chunks.push(toUint8Array(chunk));
|
|
1881
|
-
}
|
|
1882
|
-
);
|
|
1883
|
-
const resultPromise = new Promise((resolve, reject) => {
|
|
1884
|
-
passThrough.on("end", () => {
|
|
1885
|
-
resolve(uint8ArrayToNodeBuffer(concatUint8Arrays(chunks)));
|
|
1886
|
-
});
|
|
1887
|
-
passThrough.on("error", reject);
|
|
1888
|
-
});
|
|
1889
|
-
await PImage2.encodePNGToStream(image, passThrough);
|
|
1890
|
-
return await resultPromise;
|
|
1891
|
-
}
|
|
1892
|
-
|
|
1893
1852
|
// lib/render/renderGLTFToPNGFromURL.ts
|
|
1894
1853
|
async function renderGLTFToPNGFromURL(url, options = {}) {
|
|
1895
1854
|
const { fetchImpl, ...renderOptions } = options;
|
|
@@ -1983,213 +1942,6 @@ async function renderGLTFToPNGFromGLB(glb, options = {}) {
|
|
|
1983
1942
|
return encodePNG(bitmap);
|
|
1984
1943
|
}
|
|
1985
1944
|
|
|
1986
|
-
// lib/render/renderGLTFToPNGBufferFromURL.ts
|
|
1987
|
-
async function renderGLTFToPNGBufferFromURL(url, options = {}) {
|
|
1988
|
-
const { fetchImpl, ...renderOptions } = options;
|
|
1989
|
-
const { gltf, resources } = await loadGLTFWithResourcesFromURL(url, {
|
|
1990
|
-
fetchImpl
|
|
1991
|
-
});
|
|
1992
|
-
const scene = createSceneFromGLTF(gltf, resources);
|
|
1993
|
-
const { bitmap } = renderDrawCalls(
|
|
1994
|
-
scene.drawCalls,
|
|
1995
|
-
renderOptions,
|
|
1996
|
-
pureImageFactory
|
|
1997
|
-
);
|
|
1998
|
-
return encodePNGToBuffer(bitmap);
|
|
1999
|
-
}
|
|
2000
|
-
|
|
2001
|
-
// lib/render/renderGLTFToPNGBufferFromGLBBuffer.ts
|
|
2002
|
-
function normalizeToArrayBuffer2(source) {
|
|
2003
|
-
if (source instanceof ArrayBuffer) return source;
|
|
2004
|
-
const { buffer, byteOffset, byteLength } = source;
|
|
2005
|
-
const viewBuffer = buffer;
|
|
2006
|
-
return viewBuffer.slice(byteOffset, byteOffset + byteLength);
|
|
2007
|
-
}
|
|
2008
|
-
async function renderGLTFToPNGBufferFromGLBBuffer(glb, options = {}) {
|
|
2009
|
-
const arrayBuffer = normalizeToArrayBuffer2(glb);
|
|
2010
|
-
const { gltf, binaryChunk } = parseGLB(arrayBuffer);
|
|
2011
|
-
const totalBuffers = Array.isArray(gltf.buffers) ? gltf.buffers.length : 0;
|
|
2012
|
-
const buffers = new Array(totalBuffers);
|
|
2013
|
-
for (let index = 0; index < totalBuffers; index++) {
|
|
2014
|
-
const entry = gltf.buffers[index];
|
|
2015
|
-
if (entry?.uri) {
|
|
2016
|
-
if (!entry.uri.startsWith("data:")) {
|
|
2017
|
-
throw new Error(
|
|
2018
|
-
`Buffer ${index} references external resource ${entry.uri}. Use renderGLTFToPNGBufferFromURL for GLBs with external buffer URIs.`
|
|
2019
|
-
);
|
|
2020
|
-
}
|
|
2021
|
-
buffers[index] = bufferFromDataURI(entry.uri);
|
|
2022
|
-
continue;
|
|
2023
|
-
}
|
|
2024
|
-
if (!binaryChunk) {
|
|
2025
|
-
throw new Error(
|
|
2026
|
-
`GLB is missing the binary chunk required for buffer ${index}.`
|
|
2027
|
-
);
|
|
2028
|
-
}
|
|
2029
|
-
buffers[index] = binaryChunk;
|
|
2030
|
-
}
|
|
2031
|
-
const resolveBufferViewSlice = (bufferViewIndex) => {
|
|
2032
|
-
const bufferView = gltf.bufferViews?.[bufferViewIndex];
|
|
2033
|
-
if (!bufferView) {
|
|
2034
|
-
throw new Error(`Invalid bufferView index ${bufferViewIndex}.`);
|
|
2035
|
-
}
|
|
2036
|
-
const bufferIndex = bufferView.buffer;
|
|
2037
|
-
const buffer = buffers[bufferIndex];
|
|
2038
|
-
if (!buffer) {
|
|
2039
|
-
throw new Error(
|
|
2040
|
-
`Missing buffer data for bufferView ${bufferViewIndex} (buffer ${bufferIndex}).`
|
|
2041
|
-
);
|
|
2042
|
-
}
|
|
2043
|
-
const byteOffset = bufferView.byteOffset ?? 0;
|
|
2044
|
-
const byteLength = bufferView.byteLength;
|
|
2045
|
-
if (typeof byteLength !== "number") {
|
|
2046
|
-
throw new Error(`bufferView ${bufferViewIndex} is missing byteLength.`);
|
|
2047
|
-
}
|
|
2048
|
-
return buffer.subarray(byteOffset, byteOffset + byteLength);
|
|
2049
|
-
};
|
|
2050
|
-
const images = await Promise.all(
|
|
2051
|
-
(gltf.images ?? []).map(async (image, imageIndex) => {
|
|
2052
|
-
if (image.uri) {
|
|
2053
|
-
if (!image.uri.startsWith("data:")) {
|
|
2054
|
-
throw new Error(
|
|
2055
|
-
`Image ${imageIndex} references external resource ${image.uri}. Embed textures or load via renderGLTFToPNGBufferFromURL.`
|
|
2056
|
-
);
|
|
2057
|
-
}
|
|
2058
|
-
const data = bufferFromDataURI(image.uri);
|
|
2059
|
-
return decodeImageFromBuffer(data, image.mimeType);
|
|
2060
|
-
}
|
|
2061
|
-
if (typeof image.bufferView === "number") {
|
|
2062
|
-
const slice = resolveBufferViewSlice(image.bufferView);
|
|
2063
|
-
return decodeImageFromBuffer(slice, image.mimeType);
|
|
2064
|
-
}
|
|
2065
|
-
throw new Error(
|
|
2066
|
-
`Image ${imageIndex} must supply a data URI or bufferView for GLB rendering.`
|
|
2067
|
-
);
|
|
2068
|
-
})
|
|
2069
|
-
);
|
|
2070
|
-
const scene = createSceneFromGLTF(gltf, { buffers, images });
|
|
2071
|
-
const { bitmap } = renderDrawCalls(scene.drawCalls, options, pureImageFactory);
|
|
2072
|
-
return encodePNGToBuffer(bitmap);
|
|
2073
|
-
}
|
|
2074
|
-
|
|
2075
|
-
// lib/gltf/loadGLTFWithResourcesFromPath.ts
|
|
2076
|
-
async function loadGLTFWithResourcesFromPath(gltfPath) {
|
|
2077
|
-
const fs = await import("fs/promises");
|
|
2078
|
-
const path = await import("path");
|
|
2079
|
-
const baseDir = path.dirname(gltfPath);
|
|
2080
|
-
const gltf = JSON.parse(await fs.readFile(gltfPath, "utf8"));
|
|
2081
|
-
const buffers = await Promise.all(
|
|
2082
|
-
(gltf.buffers || []).map(async (buffer) => {
|
|
2083
|
-
if (buffer.uri?.startsWith("data:")) {
|
|
2084
|
-
return bufferFromDataURI(buffer.uri);
|
|
2085
|
-
}
|
|
2086
|
-
if (buffer.uri) {
|
|
2087
|
-
const resolved = path.resolve(baseDir, decodeURIComponent(buffer.uri));
|
|
2088
|
-
return fs.readFile(resolved);
|
|
2089
|
-
}
|
|
2090
|
-
throw new Error("Buffer without uri not supported in this loader.");
|
|
2091
|
-
})
|
|
2092
|
-
);
|
|
2093
|
-
const images = await Promise.all(
|
|
2094
|
-
(gltf.images || []).map(async (image) => {
|
|
2095
|
-
if (image.uri) {
|
|
2096
|
-
if (image.uri.startsWith("data:")) {
|
|
2097
|
-
const bytes = bufferFromDataURI(image.uri);
|
|
2098
|
-
return decodeImageFromBuffer(bytes, image.mimeType);
|
|
2099
|
-
}
|
|
2100
|
-
const filePath = path.resolve(baseDir, decodeURIComponent(image.uri));
|
|
2101
|
-
const fileBytes = await fs.readFile(filePath);
|
|
2102
|
-
const hintedMime = isPNG(image.uri) ? "image/png" : isJPG(image.uri) ? "image/jpeg" : image.mimeType;
|
|
2103
|
-
return decodeImageFromBuffer(fileBytes, hintedMime);
|
|
2104
|
-
}
|
|
2105
|
-
if (typeof image.bufferView === "number") {
|
|
2106
|
-
const bufferView = gltf.bufferViews?.[image.bufferView];
|
|
2107
|
-
if (!bufferView) {
|
|
2108
|
-
throw new Error(`Invalid image bufferView index ${image.bufferView}`);
|
|
2109
|
-
}
|
|
2110
|
-
const buffer = buffers[bufferView.buffer];
|
|
2111
|
-
if (!buffer) {
|
|
2112
|
-
throw new Error(
|
|
2113
|
-
`Missing buffer for image bufferView ${image.bufferView}`
|
|
2114
|
-
);
|
|
2115
|
-
}
|
|
2116
|
-
const byteOffset = bufferView.byteOffset ?? 0;
|
|
2117
|
-
const byteLength = bufferView.byteLength;
|
|
2118
|
-
if (typeof byteLength !== "number") {
|
|
2119
|
-
throw new Error(
|
|
2120
|
-
`bufferView ${image.bufferView} missing byteLength for image.`
|
|
2121
|
-
);
|
|
2122
|
-
}
|
|
2123
|
-
const slice = buffer.subarray(byteOffset, byteOffset + byteLength);
|
|
2124
|
-
return decodeImageFromBuffer(slice, image.mimeType);
|
|
2125
|
-
}
|
|
2126
|
-
throw new Error(
|
|
2127
|
-
"images[*] entry missing uri or bufferView; unsupported in this loader."
|
|
2128
|
-
);
|
|
2129
|
-
})
|
|
2130
|
-
);
|
|
2131
|
-
return {
|
|
2132
|
-
gltf,
|
|
2133
|
-
resources: {
|
|
2134
|
-
buffers,
|
|
2135
|
-
images
|
|
2136
|
-
}
|
|
2137
|
-
};
|
|
2138
|
-
}
|
|
2139
|
-
|
|
2140
|
-
// lib/gltf/resolveGLTFInput.ts
|
|
2141
|
-
function isNodeRuntime() {
|
|
2142
|
-
const runtimeProcess = globalThis.process;
|
|
2143
|
-
return !!runtimeProcess?.versions?.node;
|
|
2144
|
-
}
|
|
2145
|
-
function isFetchableURLInNode(source) {
|
|
2146
|
-
try {
|
|
2147
|
-
const url = new URL(source);
|
|
2148
|
-
return ["http:", "https:", "data:", "blob:"].includes(url.protocol);
|
|
2149
|
-
} catch {
|
|
2150
|
-
return false;
|
|
2151
|
-
}
|
|
2152
|
-
}
|
|
2153
|
-
function parseGLTFJSON(source) {
|
|
2154
|
-
try {
|
|
2155
|
-
return JSON.parse(source);
|
|
2156
|
-
} catch (error) {
|
|
2157
|
-
if (error instanceof SyntaxError) return null;
|
|
2158
|
-
throw error;
|
|
2159
|
-
}
|
|
2160
|
-
}
|
|
2161
|
-
async function resolveGLTFInput(source, options = {}) {
|
|
2162
|
-
const gltf = parseGLTFJSON(source);
|
|
2163
|
-
if (gltf !== null) {
|
|
2164
|
-
return {
|
|
2165
|
-
gltf,
|
|
2166
|
-
resources: { buffers: [], images: [] }
|
|
2167
|
-
};
|
|
2168
|
-
}
|
|
2169
|
-
if (!isNodeRuntime()) {
|
|
2170
|
-
return loadGLTFWithResourcesFromURL(source, options);
|
|
2171
|
-
}
|
|
2172
|
-
if (isFetchableURLInNode(source)) {
|
|
2173
|
-
return loadGLTFWithResourcesFromURL(source, options);
|
|
2174
|
-
}
|
|
2175
|
-
return loadGLTFWithResourcesFromPath(source);
|
|
2176
|
-
}
|
|
2177
|
-
|
|
2178
|
-
// lib/render/renderGLTFToPNGBuffer.ts
|
|
2179
|
-
function renderFromGLTF(gltf, options, resources) {
|
|
2180
|
-
const scene = createSceneFromGLTF(gltf, resources);
|
|
2181
|
-
const { bitmap } = renderDrawCalls(scene.drawCalls, options, pureImageFactory);
|
|
2182
|
-
return encodePNGToBuffer(bitmap);
|
|
2183
|
-
}
|
|
2184
|
-
async function renderGLTFToPNGBuffer(gltfOrJson, options = {}, resources = { buffers: [], images: [] }) {
|
|
2185
|
-
const { fetchImpl, ...renderOptions } = options;
|
|
2186
|
-
if (typeof gltfOrJson !== "string") {
|
|
2187
|
-
return renderFromGLTF(gltfOrJson, renderOptions, resources);
|
|
2188
|
-
}
|
|
2189
|
-
const loaded = await resolveGLTFInput(gltfOrJson, { fetchImpl });
|
|
2190
|
-
return renderFromGLTF(loaded.gltf, renderOptions, loaded.resources);
|
|
2191
|
-
}
|
|
2192
|
-
|
|
2193
1945
|
// lib/index.ts
|
|
2194
1946
|
function renderSceneFromGLTF(scene, options, imageFactory) {
|
|
2195
1947
|
return renderDrawCalls(scene.drawCalls, options, imageFactory);
|
|
@@ -2209,17 +1961,12 @@ export {
|
|
|
2209
1961
|
decodeImageFromBuffer,
|
|
2210
1962
|
drawInfiniteGrid,
|
|
2211
1963
|
encodePNG,
|
|
2212
|
-
encodePNGToBuffer,
|
|
2213
1964
|
getDefaultRenderOptions,
|
|
2214
1965
|
hexToRgb,
|
|
2215
1966
|
isJPG,
|
|
2216
1967
|
isPNG,
|
|
2217
1968
|
loadGLTFWithResourcesFromURL,
|
|
2218
|
-
pureImageFactory,
|
|
2219
1969
|
renderDrawCalls,
|
|
2220
|
-
renderGLTFToPNGBuffer,
|
|
2221
|
-
renderGLTFToPNGBufferFromGLBBuffer,
|
|
2222
|
-
renderGLTFToPNGBufferFromURL,
|
|
2223
1970
|
renderGLTFToPNGFromGLB,
|
|
2224
1971
|
renderGLTFToPNGFromURL,
|
|
2225
1972
|
renderSceneFromGLTF,
|