poppygl 0.0.23 → 0.0.25
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 +6 -12
- package/dist/index.js +52 -186
- package/package.json +2 -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,21 +193,15 @@ declare function drawInfiniteGrid(software_renderer: SoftwareRenderer, params: {
|
|
|
193
193
|
gamma_out?: boolean;
|
|
194
194
|
}): void;
|
|
195
195
|
|
|
196
|
-
declare
|
|
196
|
+
declare function encodePNG(image: BitmapLike): Promise<Uint8Array>;
|
|
197
197
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
interface RenderGLTFToPNGBufferFromURLOptions extends RenderOptionsInput, LoadGLTFWithResourcesFromURLOptions {
|
|
198
|
+
interface RenderGLTFToPNGFromURLOptions extends RenderOptionsInput, LoadGLTFWithResourcesFromURLOptions {
|
|
201
199
|
}
|
|
202
|
-
declare function
|
|
203
|
-
|
|
204
|
-
type RenderGLTFToPNGBufferFromGLBBufferOptions = RenderOptionsInput;
|
|
205
|
-
declare function renderGLTFToPNGBufferFromGLBBuffer(glb: ArrayBuffer | Uint8Array, options?: RenderGLTFToPNGBufferFromGLBBufferOptions): Promise<Buffer>;
|
|
200
|
+
declare function renderGLTFToPNGFromURL(url: string, options?: RenderGLTFToPNGFromURLOptions): Promise<Uint8Array>;
|
|
206
201
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
declare function renderGLTFToPNGBuffer(gltfOrJson: string | any, options?: RenderGLTFToPNGBufferOptions, resources?: GLTFResources): Promise<Buffer>;
|
|
202
|
+
type RenderGLTFToPNGFromGLBOptions = RenderOptionsInput;
|
|
203
|
+
declare function renderGLTFToPNGFromGLB(glb: ArrayBuffer | Uint8Array, options?: RenderGLTFToPNGFromGLBOptions): Promise<Uint8Array>;
|
|
210
204
|
|
|
211
205
|
declare function renderSceneFromGLTF(scene: GLTFScene, options?: RenderOptionsInput, imageFactory?: ImageFactory): RenderResult;
|
|
212
206
|
|
|
213
|
-
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
|
@@ -1610,8 +1610,7 @@ function createSceneFromGLTF(gltf, resources) {
|
|
|
1610
1610
|
}
|
|
1611
1611
|
|
|
1612
1612
|
// lib/gltf/resourceUtils.ts
|
|
1613
|
-
import {
|
|
1614
|
-
import * as PImage from "pureimage";
|
|
1613
|
+
import { decode } from "fast-png";
|
|
1615
1614
|
|
|
1616
1615
|
// lib/utils/bytes.ts
|
|
1617
1616
|
function getNodeBuffer() {
|
|
@@ -1621,21 +1620,6 @@ function getNodeBuffer() {
|
|
|
1621
1620
|
}
|
|
1622
1621
|
return maybeBuffer;
|
|
1623
1622
|
}
|
|
1624
|
-
function toUint8Array(chunk) {
|
|
1625
|
-
if (chunk instanceof Uint8Array) return chunk;
|
|
1626
|
-
if (chunk instanceof ArrayBuffer) return new Uint8Array(chunk);
|
|
1627
|
-
return new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength);
|
|
1628
|
-
}
|
|
1629
|
-
function concatUint8Arrays(chunks) {
|
|
1630
|
-
const totalLength = chunks.reduce((length, chunk) => length + chunk.length, 0);
|
|
1631
|
-
const result = new Uint8Array(totalLength);
|
|
1632
|
-
let offset = 0;
|
|
1633
|
-
for (const chunk of chunks) {
|
|
1634
|
-
result.set(chunk, offset);
|
|
1635
|
-
offset += chunk.length;
|
|
1636
|
-
}
|
|
1637
|
-
return result;
|
|
1638
|
-
}
|
|
1639
1623
|
function base64ToUint8Array(base64) {
|
|
1640
1624
|
if (typeof globalThis.atob === "function") {
|
|
1641
1625
|
const binary = globalThis.atob(base64);
|
|
@@ -1647,9 +1631,6 @@ function base64ToUint8Array(base64) {
|
|
|
1647
1631
|
}
|
|
1648
1632
|
return new Uint8Array(getNodeBuffer().from(base64, "base64"));
|
|
1649
1633
|
}
|
|
1650
|
-
function uint8ArrayToNodeBuffer(bytes) {
|
|
1651
|
-
return getNodeBuffer().from(bytes);
|
|
1652
|
-
}
|
|
1653
1634
|
|
|
1654
1635
|
// lib/gltf/resourceUtils.ts
|
|
1655
1636
|
function bufferFromDataURI(uri) {
|
|
@@ -1670,20 +1651,35 @@ function detectMimeTypeFromBuffer(buf, hint) {
|
|
|
1670
1651
|
if (buf.length >= 2 && buf[0] === 255 && buf[1] === 216) return "image/jpeg";
|
|
1671
1652
|
return null;
|
|
1672
1653
|
}
|
|
1673
|
-
function
|
|
1654
|
+
async function decodeImageViaFastPng(buf) {
|
|
1655
|
+
const decoded = decode(buf);
|
|
1656
|
+
return {
|
|
1657
|
+
width: decoded.width,
|
|
1658
|
+
height: decoded.height,
|
|
1659
|
+
data: new Uint8ClampedArray(decoded.data)
|
|
1660
|
+
};
|
|
1661
|
+
}
|
|
1662
|
+
async function decodeImageViaPureImage(buf, mimeType) {
|
|
1663
|
+
const { PassThrough } = await import("readable-stream");
|
|
1664
|
+
const PImage = await import("pureimage");
|
|
1674
1665
|
const stream = new PassThrough();
|
|
1675
1666
|
stream.end(buf);
|
|
1676
|
-
return stream;
|
|
1667
|
+
if (mimeType === "image/png") return PImage.decodePNGFromStream(stream);
|
|
1668
|
+
if (mimeType === "image/jpeg" || mimeType === "image/jpg")
|
|
1669
|
+
return PImage.decodeJPEGFromStream(stream);
|
|
1670
|
+
throw new Error(`Unsupported embedded image mimeType: ${mimeType}`);
|
|
1677
1671
|
}
|
|
1678
1672
|
async function decodeImageFromBuffer(buf, mimeType) {
|
|
1679
1673
|
const type = detectMimeTypeFromBuffer(buf, mimeType);
|
|
1680
|
-
if (type
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1674
|
+
if (!type) {
|
|
1675
|
+
throw new Error(
|
|
1676
|
+
`Unsupported embedded image mimeType: ${mimeType ?? "unknown"}`
|
|
1677
|
+
);
|
|
1678
|
+
}
|
|
1679
|
+
if (type === "image/png") {
|
|
1680
|
+
return decodeImageViaFastPng(buf);
|
|
1681
|
+
}
|
|
1682
|
+
return decodeImageViaPureImage(buf, type);
|
|
1687
1683
|
}
|
|
1688
1684
|
|
|
1689
1685
|
// lib/gltf/parseGLB.ts
|
|
@@ -1838,34 +1834,20 @@ async function loadGLTFWithResourcesFromURL(url, options = {}) {
|
|
|
1838
1834
|
};
|
|
1839
1835
|
}
|
|
1840
1836
|
|
|
1841
|
-
// lib/image/
|
|
1842
|
-
import
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
const chunks = [];
|
|
1851
|
-
passThrough.on(
|
|
1852
|
-
"data",
|
|
1853
|
-
(chunk) => {
|
|
1854
|
-
chunks.push(toUint8Array(chunk));
|
|
1855
|
-
}
|
|
1856
|
-
);
|
|
1857
|
-
const resultPromise = new Promise((resolve, reject) => {
|
|
1858
|
-
passThrough.on("end", () => {
|
|
1859
|
-
resolve(uint8ArrayToNodeBuffer(concatUint8Arrays(chunks)));
|
|
1860
|
-
});
|
|
1861
|
-
passThrough.on("error", reject);
|
|
1837
|
+
// lib/image/encodePNG.ts
|
|
1838
|
+
import { encode } from "fast-png";
|
|
1839
|
+
async function encodePNG(image) {
|
|
1840
|
+
return encode({
|
|
1841
|
+
width: image.width,
|
|
1842
|
+
height: image.height,
|
|
1843
|
+
data: image.data,
|
|
1844
|
+
channels: 4,
|
|
1845
|
+
depth: 8
|
|
1862
1846
|
});
|
|
1863
|
-
await PImage3.encodePNGToStream(image, passThrough);
|
|
1864
|
-
return await resultPromise;
|
|
1865
1847
|
}
|
|
1866
1848
|
|
|
1867
|
-
// lib/render/
|
|
1868
|
-
async function
|
|
1849
|
+
// lib/render/renderGLTFToPNGFromURL.ts
|
|
1850
|
+
async function renderGLTFToPNGFromURL(url, options = {}) {
|
|
1869
1851
|
const { fetchImpl, ...renderOptions } = options;
|
|
1870
1852
|
const { gltf, resources } = await loadGLTFWithResourcesFromURL(url, {
|
|
1871
1853
|
fetchImpl
|
|
@@ -1874,19 +1856,19 @@ async function renderGLTFToPNGBufferFromURL(url, options = {}) {
|
|
|
1874
1856
|
const { bitmap } = renderDrawCalls(
|
|
1875
1857
|
scene.drawCalls,
|
|
1876
1858
|
renderOptions,
|
|
1877
|
-
|
|
1859
|
+
createUint8Bitmap
|
|
1878
1860
|
);
|
|
1879
|
-
return
|
|
1861
|
+
return encodePNG(bitmap);
|
|
1880
1862
|
}
|
|
1881
1863
|
|
|
1882
|
-
// lib/render/
|
|
1864
|
+
// lib/render/renderGLTFToPNGFromGLB.ts
|
|
1883
1865
|
function normalizeToArrayBuffer(source) {
|
|
1884
1866
|
if (source instanceof ArrayBuffer) return source;
|
|
1885
1867
|
const { buffer, byteOffset, byteLength } = source;
|
|
1886
1868
|
const viewBuffer = buffer;
|
|
1887
1869
|
return viewBuffer.slice(byteOffset, byteOffset + byteLength);
|
|
1888
1870
|
}
|
|
1889
|
-
async function
|
|
1871
|
+
async function renderGLTFToPNGFromGLB(glb, options = {}) {
|
|
1890
1872
|
const arrayBuffer = normalizeToArrayBuffer(glb);
|
|
1891
1873
|
const { gltf, binaryChunk } = parseGLB(arrayBuffer);
|
|
1892
1874
|
const totalBuffers = Array.isArray(gltf.buffers) ? gltf.buffers.length : 0;
|
|
@@ -1896,7 +1878,7 @@ async function renderGLTFToPNGBufferFromGLBBuffer(glb, options = {}) {
|
|
|
1896
1878
|
if (entry?.uri) {
|
|
1897
1879
|
if (!entry.uri.startsWith("data:")) {
|
|
1898
1880
|
throw new Error(
|
|
1899
|
-
`Buffer ${index} references external resource ${entry.uri}. Use
|
|
1881
|
+
`Buffer ${index} references external resource ${entry.uri}. Use renderGLTFToPNGFromURL for GLBs with external buffer URIs.`
|
|
1900
1882
|
);
|
|
1901
1883
|
}
|
|
1902
1884
|
buffers[index] = bufferFromDataURI(entry.uri);
|
|
@@ -1933,11 +1915,11 @@ async function renderGLTFToPNGBufferFromGLBBuffer(glb, options = {}) {
|
|
|
1933
1915
|
if (image.uri) {
|
|
1934
1916
|
if (!image.uri.startsWith("data:")) {
|
|
1935
1917
|
throw new Error(
|
|
1936
|
-
`Image ${imageIndex} references external resource ${image.uri}. Embed textures or load via
|
|
1918
|
+
`Image ${imageIndex} references external resource ${image.uri}. Embed textures or load via renderGLTFToPNGFromURL.`
|
|
1937
1919
|
);
|
|
1938
1920
|
}
|
|
1939
|
-
const
|
|
1940
|
-
return decodeImageFromBuffer(
|
|
1921
|
+
const imageBytes = bufferFromDataURI(image.uri);
|
|
1922
|
+
return decodeImageFromBuffer(imageBytes, image.mimeType);
|
|
1941
1923
|
}
|
|
1942
1924
|
if (typeof image.bufferView === "number") {
|
|
1943
1925
|
const slice = resolveBufferViewSlice(image.bufferView);
|
|
@@ -1949,126 +1931,12 @@ async function renderGLTFToPNGBufferFromGLBBuffer(glb, options = {}) {
|
|
|
1949
1931
|
})
|
|
1950
1932
|
);
|
|
1951
1933
|
const scene = createSceneFromGLTF(gltf, { buffers, images });
|
|
1952
|
-
const { bitmap } = renderDrawCalls(
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
// lib/gltf/loadGLTFWithResourcesFromPath.ts
|
|
1957
|
-
async function loadGLTFWithResourcesFromPath(gltfPath) {
|
|
1958
|
-
const fs = await import("fs/promises");
|
|
1959
|
-
const path = await import("path");
|
|
1960
|
-
const baseDir = path.dirname(gltfPath);
|
|
1961
|
-
const gltf = JSON.parse(await fs.readFile(gltfPath, "utf8"));
|
|
1962
|
-
const buffers = await Promise.all(
|
|
1963
|
-
(gltf.buffers || []).map(async (buffer) => {
|
|
1964
|
-
if (buffer.uri?.startsWith("data:")) {
|
|
1965
|
-
return bufferFromDataURI(buffer.uri);
|
|
1966
|
-
}
|
|
1967
|
-
if (buffer.uri) {
|
|
1968
|
-
const resolved = path.resolve(baseDir, decodeURIComponent(buffer.uri));
|
|
1969
|
-
return fs.readFile(resolved);
|
|
1970
|
-
}
|
|
1971
|
-
throw new Error("Buffer without uri not supported in this loader.");
|
|
1972
|
-
})
|
|
1973
|
-
);
|
|
1974
|
-
const images = await Promise.all(
|
|
1975
|
-
(gltf.images || []).map(async (image) => {
|
|
1976
|
-
if (image.uri) {
|
|
1977
|
-
if (image.uri.startsWith("data:")) {
|
|
1978
|
-
const bytes = bufferFromDataURI(image.uri);
|
|
1979
|
-
return decodeImageFromBuffer(bytes, image.mimeType);
|
|
1980
|
-
}
|
|
1981
|
-
const filePath = path.resolve(baseDir, decodeURIComponent(image.uri));
|
|
1982
|
-
const fileBytes = await fs.readFile(filePath);
|
|
1983
|
-
const hintedMime = isPNG(image.uri) ? "image/png" : isJPG(image.uri) ? "image/jpeg" : image.mimeType;
|
|
1984
|
-
return decodeImageFromBuffer(fileBytes, hintedMime);
|
|
1985
|
-
}
|
|
1986
|
-
if (typeof image.bufferView === "number") {
|
|
1987
|
-
const bufferView = gltf.bufferViews?.[image.bufferView];
|
|
1988
|
-
if (!bufferView) {
|
|
1989
|
-
throw new Error(`Invalid image bufferView index ${image.bufferView}`);
|
|
1990
|
-
}
|
|
1991
|
-
const buffer = buffers[bufferView.buffer];
|
|
1992
|
-
if (!buffer) {
|
|
1993
|
-
throw new Error(
|
|
1994
|
-
`Missing buffer for image bufferView ${image.bufferView}`
|
|
1995
|
-
);
|
|
1996
|
-
}
|
|
1997
|
-
const byteOffset = bufferView.byteOffset ?? 0;
|
|
1998
|
-
const byteLength = bufferView.byteLength;
|
|
1999
|
-
if (typeof byteLength !== "number") {
|
|
2000
|
-
throw new Error(
|
|
2001
|
-
`bufferView ${image.bufferView} missing byteLength for image.`
|
|
2002
|
-
);
|
|
2003
|
-
}
|
|
2004
|
-
const slice = buffer.subarray(byteOffset, byteOffset + byteLength);
|
|
2005
|
-
return decodeImageFromBuffer(slice, image.mimeType);
|
|
2006
|
-
}
|
|
2007
|
-
throw new Error(
|
|
2008
|
-
"images[*] entry missing uri or bufferView; unsupported in this loader."
|
|
2009
|
-
);
|
|
2010
|
-
})
|
|
1934
|
+
const { bitmap } = renderDrawCalls(
|
|
1935
|
+
scene.drawCalls,
|
|
1936
|
+
options,
|
|
1937
|
+
createUint8Bitmap
|
|
2011
1938
|
);
|
|
2012
|
-
return
|
|
2013
|
-
gltf,
|
|
2014
|
-
resources: {
|
|
2015
|
-
buffers,
|
|
2016
|
-
images
|
|
2017
|
-
}
|
|
2018
|
-
};
|
|
2019
|
-
}
|
|
2020
|
-
|
|
2021
|
-
// lib/gltf/resolveGLTFInput.ts
|
|
2022
|
-
function isNodeRuntime() {
|
|
2023
|
-
const runtimeProcess = globalThis.process;
|
|
2024
|
-
return !!runtimeProcess?.versions?.node;
|
|
2025
|
-
}
|
|
2026
|
-
function isFetchableURLInNode(source) {
|
|
2027
|
-
try {
|
|
2028
|
-
const url = new URL(source);
|
|
2029
|
-
return ["http:", "https:", "data:", "blob:"].includes(url.protocol);
|
|
2030
|
-
} catch {
|
|
2031
|
-
return false;
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
function parseGLTFJSON(source) {
|
|
2035
|
-
try {
|
|
2036
|
-
return JSON.parse(source);
|
|
2037
|
-
} catch (error) {
|
|
2038
|
-
if (error instanceof SyntaxError) return null;
|
|
2039
|
-
throw error;
|
|
2040
|
-
}
|
|
2041
|
-
}
|
|
2042
|
-
async function resolveGLTFInput(source, options = {}) {
|
|
2043
|
-
const gltf = parseGLTFJSON(source);
|
|
2044
|
-
if (gltf !== null) {
|
|
2045
|
-
return {
|
|
2046
|
-
gltf,
|
|
2047
|
-
resources: { buffers: [], images: [] }
|
|
2048
|
-
};
|
|
2049
|
-
}
|
|
2050
|
-
if (!isNodeRuntime()) {
|
|
2051
|
-
return loadGLTFWithResourcesFromURL(source, options);
|
|
2052
|
-
}
|
|
2053
|
-
if (isFetchableURLInNode(source)) {
|
|
2054
|
-
return loadGLTFWithResourcesFromURL(source, options);
|
|
2055
|
-
}
|
|
2056
|
-
return loadGLTFWithResourcesFromPath(source);
|
|
2057
|
-
}
|
|
2058
|
-
|
|
2059
|
-
// lib/render/renderGLTFToPNGBuffer.ts
|
|
2060
|
-
function renderFromGLTF(gltf, options, resources) {
|
|
2061
|
-
const scene = createSceneFromGLTF(gltf, resources);
|
|
2062
|
-
const { bitmap } = renderDrawCalls(scene.drawCalls, options, pureImageFactory);
|
|
2063
|
-
return encodePNGToBuffer(bitmap);
|
|
2064
|
-
}
|
|
2065
|
-
async function renderGLTFToPNGBuffer(gltfOrJson, options = {}, resources = { buffers: [], images: [] }) {
|
|
2066
|
-
const { fetchImpl, ...renderOptions } = options;
|
|
2067
|
-
if (typeof gltfOrJson !== "string") {
|
|
2068
|
-
return renderFromGLTF(gltfOrJson, renderOptions, resources);
|
|
2069
|
-
}
|
|
2070
|
-
const loaded = await resolveGLTFInput(gltfOrJson, { fetchImpl });
|
|
2071
|
-
return renderFromGLTF(loaded.gltf, renderOptions, loaded.resources);
|
|
1939
|
+
return encodePNG(bitmap);
|
|
2072
1940
|
}
|
|
2073
1941
|
|
|
2074
1942
|
// lib/index.ts
|
|
@@ -2089,17 +1957,15 @@ export {
|
|
|
2089
1957
|
createUint8Bitmap,
|
|
2090
1958
|
decodeImageFromBuffer,
|
|
2091
1959
|
drawInfiniteGrid,
|
|
2092
|
-
|
|
1960
|
+
encodePNG,
|
|
2093
1961
|
getDefaultRenderOptions,
|
|
2094
1962
|
hexToRgb,
|
|
2095
1963
|
isJPG,
|
|
2096
1964
|
isPNG,
|
|
2097
1965
|
loadGLTFWithResourcesFromURL,
|
|
2098
|
-
pureImageFactory,
|
|
2099
1966
|
renderDrawCalls,
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
renderGLTFToPNGBufferFromURL,
|
|
1967
|
+
renderGLTFToPNGFromGLB,
|
|
1968
|
+
renderGLTFToPNGFromURL,
|
|
2103
1969
|
renderSceneFromGLTF,
|
|
2104
1970
|
resolveRenderOptions
|
|
2105
1971
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "poppygl",
|
|
3
3
|
"main": "dist/index.js",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.25",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/tscircuit/poppygl.git"
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"typescript": "^5"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
+
"fast-png": "^8.0.0",
|
|
40
41
|
"gl-matrix": "^3.4.4",
|
|
41
42
|
"pureimage": "^0.4.18",
|
|
42
43
|
"readable-stream": "^4.7.0"
|