circuit-json-to-gltf 0.0.12 → 0.0.13

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.
Files changed (2) hide show
  1. package/dist/index.js +107 -16
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -742,6 +742,95 @@ function clearGLBCache() {
742
742
  glbCache.clear();
743
743
  }
744
744
 
745
+ // lib/loaders/gltf.ts
746
+ async function fetchAsArrayBuffer(url) {
747
+ const response = await fetch(url);
748
+ if (!response.ok) {
749
+ throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
750
+ }
751
+ return response.arrayBuffer();
752
+ }
753
+ function dataUriToArrayBuffer(uri) {
754
+ const a = uri.split(",");
755
+ const byteString = atob(a[1]);
756
+ const ab = new ArrayBuffer(byteString.length);
757
+ const ia = new Uint8Array(ab);
758
+ for (let i = 0; i < byteString.length; i++) {
759
+ ia[i] = byteString.charCodeAt(i);
760
+ }
761
+ return ab;
762
+ }
763
+ async function fetchGltfAndConvertToGlb(url) {
764
+ const gltfResponse = await fetch(url);
765
+ if (!gltfResponse.ok) {
766
+ throw new Error(`Failed to fetch glTF file: ${gltfResponse.statusText}`);
767
+ }
768
+ const gltf = await gltfResponse.json();
769
+ const bufferPromises = [];
770
+ if (gltf.buffers) {
771
+ for (const buffer of gltf.buffers) {
772
+ if (buffer.uri) {
773
+ if (buffer.uri.startsWith("data:")) {
774
+ bufferPromises.push(Promise.resolve(dataUriToArrayBuffer(buffer.uri)));
775
+ } else {
776
+ const bufferUrl = new URL(buffer.uri, url).toString();
777
+ bufferPromises.push(fetchAsArrayBuffer(bufferUrl));
778
+ }
779
+ }
780
+ }
781
+ }
782
+ const buffers = await Promise.all(bufferPromises);
783
+ let binaryBuffer = new ArrayBuffer(0);
784
+ if (buffers.length > 0 && buffers[0]) {
785
+ binaryBuffer = buffers[0];
786
+ }
787
+ if (gltf.buffers && gltf.buffers.length > 0) {
788
+ delete gltf.buffers[0].uri;
789
+ gltf.buffers[0].byteLength = binaryBuffer.byteLength;
790
+ }
791
+ const jsonString = JSON.stringify(gltf);
792
+ const jsonBuffer = new TextEncoder().encode(jsonString);
793
+ const jsonPadding = (4 - jsonBuffer.length % 4) % 4;
794
+ const binaryPadding = (4 - binaryBuffer.byteLength % 4) % 4;
795
+ const totalLength = 12 + // header
796
+ (8 + jsonBuffer.length + jsonPadding) + // json chunk
797
+ (binaryBuffer.byteLength > 0 ? 8 + binaryBuffer.byteLength + binaryPadding : 0);
798
+ const glbBuffer = new ArrayBuffer(totalLength);
799
+ const dataView = new DataView(glbBuffer);
800
+ let offset = 0;
801
+ dataView.setUint32(offset, 1179937895, true);
802
+ offset += 4;
803
+ dataView.setUint32(offset, 2, true);
804
+ offset += 4;
805
+ dataView.setUint32(offset, totalLength, true);
806
+ offset += 4;
807
+ dataView.setUint32(offset, jsonBuffer.length + jsonPadding, true);
808
+ offset += 4;
809
+ dataView.setUint32(offset, 1313821514, true);
810
+ offset += 4;
811
+ new Uint8Array(glbBuffer, offset).set(jsonBuffer);
812
+ offset += jsonBuffer.length;
813
+ for (let i = 0; i < jsonPadding; i++) {
814
+ dataView.setUint8(offset++, 32);
815
+ }
816
+ if (binaryBuffer.byteLength > 0) {
817
+ dataView.setUint32(offset, binaryBuffer.byteLength + binaryPadding, true);
818
+ offset += 4;
819
+ dataView.setUint32(offset, 5130562, true);
820
+ offset += 4;
821
+ new Uint8Array(glbBuffer, offset).set(new Uint8Array(binaryBuffer));
822
+ offset += binaryBuffer.byteLength;
823
+ for (let i = 0; i < binaryPadding; i++) {
824
+ dataView.setUint8(offset++, 0);
825
+ }
826
+ }
827
+ return glbBuffer;
828
+ }
829
+ async function loadGLTF(url, transform) {
830
+ const glb_buffer = await fetchGltfAndConvertToGlb(url);
831
+ return parseGLB(glb_buffer, transform);
832
+ }
833
+
745
834
  // lib/converters/board-renderer.ts
746
835
  import { convertCircuitJsonToPcbSvg } from "circuit-to-svg";
747
836
  async function renderBoardLayer(circuitJson, options) {
@@ -900,12 +989,15 @@ async function convertCircuitJsonTo3D(circuitJson, options = {}) {
900
989
  const cadComponents = db.cad_component?.list?.() ?? [];
901
990
  const pcbComponentIdsWith3D = /* @__PURE__ */ new Set();
902
991
  for (const cad of cadComponents) {
903
- let { model_stl_url, model_obj_url, model_glb_url } = cad;
904
- const hasModelUrl = Boolean(model_stl_url || model_obj_url || model_glb_url);
992
+ let { model_stl_url, model_obj_url, model_glb_url, model_gltf_url } = cad;
993
+ const hasModelUrl = Boolean(
994
+ model_stl_url || model_obj_url || model_glb_url || model_gltf_url
995
+ );
905
996
  if (!hasModelUrl && cad.footprinter_string) {
906
997
  model_glb_url = `https://modelcdn.tscircuit.com/jscad_models/${cad.footprinter_string}.glb`;
907
998
  }
908
- if (!model_stl_url && !model_obj_url && !model_glb_url) continue;
999
+ if (!model_stl_url && !model_obj_url && !model_glb_url && !model_gltf_url)
1000
+ continue;
909
1001
  pcbComponentIdsWith3D.add(cad.pcb_component_id);
910
1002
  const pcbComponent = db.pcb_component.get(cad.pcb_component_id);
911
1003
  const size = cad.size ?? {
@@ -918,26 +1010,25 @@ async function convertCircuitJsonTo3D(circuitJson, options = {}) {
918
1010
  y: boardThickness / 2 + size.y / 2,
919
1011
  z: pcbComponent?.center.y ?? 0
920
1012
  };
1013
+ const meshType = model_stl_url ? "stl" : model_obj_url ? "obj" : model_gltf_url ? "gltf" : "glb";
921
1014
  const box = {
922
1015
  center,
923
1016
  size,
924
- meshUrl: model_stl_url || model_obj_url || model_glb_url,
925
- meshType: model_stl_url ? "stl" : model_obj_url ? "obj" : "glb"
1017
+ meshUrl: model_stl_url || model_obj_url || model_glb_url || model_gltf_url,
1018
+ meshType
926
1019
  };
927
1020
  if (cad.rotation) {
928
1021
  box.rotation = convertRotationFromCadRotation(cad.rotation);
929
1022
  }
930
- const defaultTransform = coordinateTransform ?? (model_glb_url ? void 0 : COORDINATE_TRANSFORMS.Z_UP_TO_Y_UP_USB_FIX);
931
- try {
932
- if (model_stl_url) {
933
- box.mesh = await loadSTL(model_stl_url, defaultTransform);
934
- } else if (model_obj_url) {
935
- box.mesh = await loadOBJ(model_obj_url, defaultTransform);
936
- } else if (model_glb_url) {
937
- box.mesh = await loadGLB(model_glb_url, defaultTransform);
938
- }
939
- } catch (error) {
940
- console.warn(`Failed to load 3D model: ${error}`);
1023
+ const defaultTransform = coordinateTransform ?? (model_glb_url || model_gltf_url ? void 0 : COORDINATE_TRANSFORMS.Z_UP_TO_Y_UP_USB_FIX);
1024
+ if (model_stl_url) {
1025
+ box.mesh = await loadSTL(model_stl_url, defaultTransform);
1026
+ } else if (model_obj_url) {
1027
+ box.mesh = await loadOBJ(model_obj_url, defaultTransform);
1028
+ } else if (model_glb_url) {
1029
+ box.mesh = await loadGLB(model_glb_url, defaultTransform);
1030
+ } else if (model_gltf_url) {
1031
+ box.mesh = await loadGLTF(model_gltf_url, defaultTransform);
941
1032
  }
942
1033
  if (!box.mesh) {
943
1034
  box.color = componentColor;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "circuit-json-to-gltf",
3
3
  "main": "dist/index.js",
4
4
  "type": "module",
5
- "version": "0.0.12",
5
+ "version": "0.0.13",
6
6
  "scripts": {
7
7
  "test": "bun test tests/",
8
8
  "format": "biome format --write .",