poppygl 0.0.4 → 0.0.6

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.
@@ -0,0 +1,127 @@
1
+ import { mat4 } from 'gl-matrix';
2
+
3
+ type RGBA = readonly [number, number, number, number];
4
+ type MutableRGBA = [number, number, number, number];
5
+ interface BitmapLike {
6
+ width: number;
7
+ height: number;
8
+ data: Uint8Array | Uint8ClampedArray;
9
+ }
10
+ type ImageFactory = (width: number, height: number) => BitmapLike;
11
+ declare const createUint8Bitmap: ImageFactory;
12
+
13
+ declare const DEFAULT_LIGHT_DIR: readonly [-0.4, -0.9, -0.2];
14
+ interface RenderOptions {
15
+ width: number;
16
+ height: number;
17
+ fov: number;
18
+ cull: boolean;
19
+ gamma: boolean;
20
+ ambient: number;
21
+ lightDir: readonly [number, number, number];
22
+ camPos?: readonly [number, number, number] | null;
23
+ lookAt?: readonly [number, number, number] | null;
24
+ }
25
+ type RenderOptionsInput = Partial<RenderOptions>;
26
+ declare const DEFAULT_RENDER_OPTIONS: RenderOptions;
27
+ declare function getDefaultRenderOptions(): RenderOptions;
28
+
29
+ interface Material {
30
+ baseColorFactor: [number, number, number, number];
31
+ baseColorTexture: BitmapLike | null;
32
+ }
33
+ interface DrawCall {
34
+ positions: Float32Array;
35
+ normals: Float32Array | null;
36
+ uvs: Float32Array | null;
37
+ indices: Uint32Array | null;
38
+ model: mat4;
39
+ material: Material;
40
+ }
41
+ interface GLTFResources {
42
+ buffers: Uint8Array[];
43
+ images: BitmapLike[];
44
+ }
45
+ interface GLTFScene {
46
+ drawCalls: DrawCall[];
47
+ gltf: any;
48
+ }
49
+
50
+ interface Camera {
51
+ view: mat4;
52
+ proj: mat4;
53
+ }
54
+ declare function buildCamera(drawCalls: DrawCall[], width: number, height: number, fovDeg: number, camPos: readonly [number, number, number] | null | undefined, lookAt: readonly [number, number, number] | null | undefined): Camera;
55
+
56
+ interface RenderResult {
57
+ bitmap: BitmapLike;
58
+ camera: Camera;
59
+ options: RenderOptions;
60
+ }
61
+ declare function renderDrawCalls(drawCalls: DrawCall[], optionsInput?: RenderOptionsInput, imageFactory?: ImageFactory): RenderResult;
62
+
63
+ declare function resolveRenderOptions(options?: RenderOptionsInput): RenderOptions;
64
+
65
+ type GLTF = any;
66
+ declare function createSceneFromGLTF(gltf: GLTF, resources: GLTFResources): GLTFScene;
67
+
68
+ declare function computeSmoothNormals(positions: Float32Array, indices: Uint32Array | null): Float32Array;
69
+
70
+ declare function computeWorldAABB(drawCalls: DrawCall[]): {
71
+ min: number[];
72
+ max: number[];
73
+ };
74
+
75
+ interface FetchLikeResponse {
76
+ ok: boolean;
77
+ status: number;
78
+ statusText: string;
79
+ url?: string;
80
+ arrayBuffer(): Promise<ArrayBuffer>;
81
+ }
82
+ type FetchLike = (input: string, init?: Record<string, unknown>) => Promise<FetchLikeResponse>;
83
+ interface LoadGLTFWithResourcesFromURLOptions {
84
+ fetchImpl?: FetchLike;
85
+ }
86
+ declare function loadGLTFWithResourcesFromURL(url: string, options?: LoadGLTFWithResourcesFromURLOptions): Promise<{
87
+ gltf: any;
88
+ resources: GLTFResources;
89
+ }>;
90
+
91
+ declare function bufferFromDataURI(uri: string): Uint8Array;
92
+ declare function isPNG(filenameOrUri: string): boolean;
93
+ declare function isJPG(filenameOrUri: string): boolean;
94
+ declare function decodeImageFromBuffer(buf: Uint8Array, mimeType?: string | null): Promise<BitmapLike>;
95
+
96
+ interface LightSettings {
97
+ dir: readonly [number, number, number];
98
+ ambient: number;
99
+ }
100
+ declare class SoftwareRenderer {
101
+ readonly width: number;
102
+ readonly height: number;
103
+ readonly bitmap: BitmapLike;
104
+ readonly depth: Float32Array;
105
+ constructor(width: number, height: number, imageFactory?: ImageFactory);
106
+ get buffer(): Uint8Array<ArrayBufferLike> | Uint8ClampedArray<ArrayBufferLike>;
107
+ clear(colorRGBA?: [number, number, number, number]): void;
108
+ setPixel(x: number, y: number, r: number, g: number, b: number, a: number): void;
109
+ sampleTextureNearest(img: BitmapLike | null, u: number, v: number): MutableRGBA;
110
+ perspInterp(attrs: number[][], invWs: number[], lambdas: number[]): number[];
111
+ drawMesh(mesh: DrawCall, camera: Camera, light: LightSettings, material: Material, cullBackFaces?: boolean, gammaOut?: boolean): void;
112
+ }
113
+
114
+ declare const pureImageFactory: ImageFactory;
115
+
116
+ declare function encodePNGToBuffer(image: BitmapLike): Promise<Buffer>;
117
+
118
+ interface RenderGLTFToPNGBufferFromURLOptions extends RenderOptionsInput, LoadGLTFWithResourcesFromURLOptions {
119
+ }
120
+ declare function renderGLTFToPNGBufferFromURL(url: string, options?: RenderGLTFToPNGBufferFromURLOptions): Promise<Buffer>;
121
+
122
+ type RenderGLTFToPNGBufferFromGLBBufferOptions = RenderOptionsInput;
123
+ declare function renderGLTFToPNGBufferFromGLBBuffer(glb: ArrayBuffer | Uint8Array, options?: RenderGLTFToPNGBufferFromGLBBufferOptions): Promise<Buffer>;
124
+
125
+ declare function renderSceneFromGLTF(scene: GLTFScene, options?: RenderOptionsInput, imageFactory?: ImageFactory): RenderResult;
126
+
127
+ export { type BitmapLike, type Camera, DEFAULT_LIGHT_DIR, DEFAULT_RENDER_OPTIONS, type DrawCall, type FetchLike, type GLTFResources, type GLTFScene, type ImageFactory, type LightSettings, type LoadGLTFWithResourcesFromURLOptions, type Material, type MutableRGBA, type RGBA, type RenderGLTFToPNGBufferFromGLBBufferOptions, type RenderGLTFToPNGBufferFromURLOptions, type RenderOptions, type RenderOptionsInput, type RenderResult, SoftwareRenderer, bufferFromDataURI, buildCamera, computeSmoothNormals, computeWorldAABB, createSceneFromGLTF, createUint8Bitmap, decodeImageFromBuffer, encodePNGToBuffer, getDefaultRenderOptions, isJPG, isPNG, loadGLTFWithResourcesFromURL, pureImageFactory, renderDrawCalls, renderGLTFToPNGBufferFromGLBBuffer, renderGLTFToPNGBufferFromURL, renderSceneFromGLTF, resolveRenderOptions };
package/dist/index.js CHANGED
@@ -10,13 +10,7 @@ function computeWorldAABB(drawCalls) {
10
10
  for (const dc of drawCalls) {
11
11
  const { positions, model } = dc;
12
12
  for (let i = 0; i < positions.length; i += 3) {
13
- vec4.set(
14
- tmp,
15
- positions[i],
16
- positions[i + 1],
17
- positions[i + 2],
18
- 1
19
- );
13
+ vec4.set(tmp, positions[i], positions[i + 1], positions[i + 2], 1);
20
14
  vec4.transformMat4(tmp, tmp, model);
21
15
  const x = tmp[0];
22
16
  const y = tmp[1];
@@ -799,7 +793,8 @@ function parseGLB(arrayBuffer) {
799
793
  const chunkLength = view.getUint32(offset, true);
800
794
  const chunkType = view.getUint32(offset + 4, true);
801
795
  offset += 8;
802
- if (offset + chunkLength > length) throw new Error("Truncated GLB chunk data.");
796
+ if (offset + chunkLength > length)
797
+ throw new Error("Truncated GLB chunk data.");
803
798
  const chunkData = new Uint8Array(arrayBuffer, offset, chunkLength);
804
799
  offset += chunkLength;
805
800
  if (chunkType === JSON_CHUNK_TYPE) {
@@ -817,7 +812,8 @@ function parseGLB(arrayBuffer) {
817
812
  // lib/gltf/loadGLTFWithResourcesFromURL.ts
818
813
  function ensureFetch(fetchImpl) {
819
814
  const impl = fetchImpl ?? globalThis.fetch;
820
- if (!impl) throw new Error("Global fetch API is not available; provide fetchImpl.");
815
+ if (!impl)
816
+ throw new Error("Global fetch API is not available; provide fetchImpl.");
821
817
  return impl;
822
818
  }
823
819
  async function fetchBinary(fetchImpl, url) {
@@ -832,7 +828,9 @@ async function loadGLTFWithResourcesFromURL(url, options = {}) {
832
828
  const fetchImpl = ensureFetch(options.fetchImpl);
833
829
  const response = await fetchImpl(url);
834
830
  if (!response.ok)
835
- throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
831
+ throw new Error(
832
+ `Failed to fetch ${url}: ${response.status} ${response.statusText}`
833
+ );
836
834
  const resolvedURL = new URL(response.url || url);
837
835
  const baseURL = resolvedURL;
838
836
  const sourceBuffer = await response.arrayBuffer();
@@ -867,7 +865,9 @@ async function loadGLTFWithResourcesFromURL(url, options = {}) {
867
865
  buffers[index] = buf;
868
866
  return buf;
869
867
  }
870
- throw new Error(`Buffer ${index} is missing a uri and no GLB chunk was provided.`);
868
+ throw new Error(
869
+ `Buffer ${index} is missing a uri and no GLB chunk was provided.`
870
+ );
871
871
  }
872
872
  await Promise.all(
873
873
  (gltf.buffers || []).map(async (entry, idx) => {
@@ -892,7 +892,10 @@ async function loadGLTFWithResourcesFromURL(url, options = {}) {
892
892
  const bufferView = gltf.bufferViews?.[img.bufferView];
893
893
  if (!bufferView)
894
894
  throw new Error(`Invalid image bufferView index ${img.bufferView}`);
895
- const buffer = await resolveBuffer(bufferView.buffer, gltf.buffers?.[bufferView.buffer]);
895
+ const buffer = await resolveBuffer(
896
+ bufferView.buffer,
897
+ gltf.buffers?.[bufferView.buffer]
898
+ );
896
899
  if (!buffer)
897
900
  throw new Error(`Missing buffer for image bufferView ${img.bufferView}`);
898
901
  const byteOffset = bufferView.byteOffset ?? 0;
@@ -981,7 +984,9 @@ async function renderGLTFToPNGBufferFromGLBBuffer(glb, options = {}) {
981
984
  continue;
982
985
  }
983
986
  if (!binaryChunk) {
984
- throw new Error(`GLB is missing the binary chunk required for buffer ${index}.`);
987
+ throw new Error(
988
+ `GLB is missing the binary chunk required for buffer ${index}.`
989
+ );
985
990
  }
986
991
  buffers[index] = binaryChunk;
987
992
  }
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",
4
+ "version": "0.0.6",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/tscircuit/poppygl.git"
@@ -12,7 +12,7 @@
12
12
  "scripts": {
13
13
  "start": "cosmos",
14
14
  "build:site": "cosmos-export",
15
- "build": "tsup-node ./lib/index.ts --format esm",
15
+ "build": "tsup-node ./lib/index.ts --format esm --dts",
16
16
  "format": "biome format --write .",
17
17
  "format:check": "biome format .",
18
18
  "test": "bun test"
@@ -21,6 +21,7 @@
21
21
  "devDependencies": {
22
22
  "@biomejs/biome": "^2.2.4",
23
23
  "@types/bun": "^1.2.23",
24
+ "@types/readable-stream": "^4.0.21",
24
25
  "looks-same": "^10.0.1",
25
26
  "react": "^19.1.1",
26
27
  "react-cosmos": "^7.0.0",