circuit-json-to-gltf 0.0.56 → 0.0.58

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 +137 -43
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -14109,6 +14109,75 @@ function clearOBJCache() {
14109
14109
  objCache.clear();
14110
14110
  }
14111
14111
 
14112
+ // lib/utils/gltf-node-transforms.ts
14113
+ function applyQuaternion(p, q) {
14114
+ const [qx, qy, qz, qw] = q;
14115
+ const { x, y, z } = p;
14116
+ const ix = qw * x + qy * z - qz * y;
14117
+ const iy = qw * y + qz * x - qx * z;
14118
+ const iz = qw * z + qx * y - qy * x;
14119
+ const iw = -qx * x - qy * y - qz * z;
14120
+ return {
14121
+ x: ix * qw + iw * -qx + iy * -qz - iz * -qy,
14122
+ y: iy * qw + iw * -qy + iz * -qx - ix * -qz,
14123
+ z: iz * qw + iw * -qz + ix * -qy - iy * -qx
14124
+ };
14125
+ }
14126
+ function applyNodeTransform(p, node) {
14127
+ let result = { ...p };
14128
+ if (node.scale) {
14129
+ result = {
14130
+ x: result.x * node.scale[0],
14131
+ y: result.y * node.scale[1],
14132
+ z: result.z * node.scale[2]
14133
+ };
14134
+ }
14135
+ if (node.rotation) {
14136
+ result = applyQuaternion(
14137
+ result,
14138
+ node.rotation
14139
+ );
14140
+ }
14141
+ if (node.translation) {
14142
+ result = {
14143
+ x: result.x + node.translation[0],
14144
+ y: result.y + node.translation[1],
14145
+ z: result.z + node.translation[2]
14146
+ };
14147
+ }
14148
+ return result;
14149
+ }
14150
+ function buildMeshTransforms(gltf) {
14151
+ const meshTransforms = /* @__PURE__ */ new Map();
14152
+ if (!gltf.nodes) return meshTransforms;
14153
+ function processNode(nodeIndex, parentTransforms) {
14154
+ const node = gltf.nodes[nodeIndex];
14155
+ if (!node) return;
14156
+ const currentTransforms = [...parentTransforms];
14157
+ if (node.translation || node.rotation || node.scale) {
14158
+ currentTransforms.push({
14159
+ translation: node.translation,
14160
+ rotation: node.rotation,
14161
+ scale: node.scale
14162
+ });
14163
+ }
14164
+ if (node.mesh !== void 0) {
14165
+ meshTransforms.set(node.mesh, currentTransforms);
14166
+ }
14167
+ if (node.children) {
14168
+ for (const childIndex of node.children) {
14169
+ processNode(childIndex, currentTransforms);
14170
+ }
14171
+ }
14172
+ }
14173
+ if (gltf.scenes && gltf.scenes[0]?.nodes) {
14174
+ for (const rootNodeIndex of gltf.scenes[0].nodes) {
14175
+ processNode(rootNodeIndex, []);
14176
+ }
14177
+ }
14178
+ return meshTransforms;
14179
+ }
14180
+
14112
14181
  // lib/loaders/glb.ts
14113
14182
  var glbCache = /* @__PURE__ */ new Map();
14114
14183
  async function loadGLB(url, transform) {
@@ -14117,6 +14186,11 @@ async function loadGLB(url, transform) {
14117
14186
  return glbCache.get(cacheKey);
14118
14187
  }
14119
14188
  const response = await fetch(url);
14189
+ if (!response.ok) {
14190
+ throw new Error(
14191
+ `Failed to fetch GLB: ${response.status} ${response.statusText}`
14192
+ );
14193
+ }
14120
14194
  const buffer = await response.arrayBuffer();
14121
14195
  const mesh = parseGLB(buffer, transform);
14122
14196
  glbCache.set(cacheKey, mesh);
@@ -14162,7 +14236,7 @@ function parseGLB(buffer, transform) {
14162
14236
  const finalConfig = transform ?? {
14163
14237
  axisMapping: { x: "x", y: "z", z: "y" }
14164
14238
  };
14165
- const transformedTriangles = transformTriangles(triangles, finalConfig);
14239
+ let transformedTriangles = transformTriangles(triangles, finalConfig);
14166
14240
  const hasColors = transformedTriangles.some((t) => t.color !== void 0);
14167
14241
  if (hasColors) {
14168
14242
  return convertToOBJMesh(transformedTriangles);
@@ -14221,7 +14295,10 @@ function extractTrianglesFromGLTF(gltf, binaryBuffer) {
14221
14295
  if (!gltf.meshes || !gltf.accessors || !gltf.bufferViews) {
14222
14296
  return triangles;
14223
14297
  }
14224
- for (const mesh of gltf.meshes) {
14298
+ const meshTransforms = buildMeshTransforms(gltf);
14299
+ for (let meshIndex = 0; meshIndex < gltf.meshes.length; meshIndex++) {
14300
+ const mesh = gltf.meshes[meshIndex];
14301
+ const transforms = meshTransforms.get(meshIndex) || [];
14225
14302
  for (const primitive of mesh.primitives) {
14226
14303
  const mode = primitive.mode ?? 4;
14227
14304
  if (mode !== 4) {
@@ -14273,20 +14350,7 @@ function extractTrianglesFromGLTF(gltf, binaryBuffer) {
14273
14350
  let indices;
14274
14351
  if (primitive.indices !== void 0) {
14275
14352
  const indexAccessor = gltf.accessors[primitive.indices];
14276
- const indexData = getAccessorData(
14277
- indexAccessor,
14278
- gltf.bufferViews,
14279
- binaryBuffer
14280
- );
14281
- indices = indexAccessor.componentType === 5123 ? new Uint16Array(
14282
- indexData.buffer,
14283
- indexData.byteOffset,
14284
- indexData.length
14285
- ) : new Uint32Array(
14286
- indexData.buffer,
14287
- indexData.byteOffset,
14288
- indexData.length
14289
- );
14353
+ indices = getAccessorData(indexAccessor, gltf.bufferViews, binaryBuffer);
14290
14354
  }
14291
14355
  const vertexCount = positions.length / 3;
14292
14356
  if (indices) {
@@ -14294,28 +14358,42 @@ function extractTrianglesFromGLTF(gltf, binaryBuffer) {
14294
14358
  const i0 = indices[i];
14295
14359
  const i1 = indices[i + 1];
14296
14360
  const i2 = indices[i + 2];
14297
- const v0 = {
14361
+ let v0 = {
14298
14362
  x: positions[i0 * 3],
14299
14363
  y: positions[i0 * 3 + 1],
14300
14364
  z: positions[i0 * 3 + 2]
14301
14365
  };
14302
- const v1 = {
14366
+ let v1 = {
14303
14367
  x: positions[i1 * 3],
14304
14368
  y: positions[i1 * 3 + 1],
14305
14369
  z: positions[i1 * 3 + 2]
14306
14370
  };
14307
- const v2 = {
14371
+ let v2 = {
14308
14372
  x: positions[i2 * 3],
14309
14373
  y: positions[i2 * 3 + 1],
14310
14374
  z: positions[i2 * 3 + 2]
14311
14375
  };
14376
+ for (const transform of transforms) {
14377
+ v0 = applyNodeTransform(v0, transform);
14378
+ v1 = applyNodeTransform(v1, transform);
14379
+ v2 = applyNodeTransform(v2, transform);
14380
+ }
14312
14381
  let normal;
14313
14382
  if (normals) {
14314
- normal = {
14383
+ let n = {
14315
14384
  x: (normals[i0 * 3] + normals[i1 * 3] + normals[i2 * 3]) / 3,
14316
14385
  y: (normals[i0 * 3 + 1] + normals[i1 * 3 + 1] + normals[i2 * 3 + 1]) / 3,
14317
14386
  z: (normals[i0 * 3 + 2] + normals[i1 * 3 + 2] + normals[i2 * 3 + 2]) / 3
14318
14387
  };
14388
+ for (const transform of transforms) {
14389
+ if (transform.rotation) {
14390
+ n = applyQuaternion(
14391
+ n,
14392
+ transform.rotation
14393
+ );
14394
+ }
14395
+ }
14396
+ normal = n;
14319
14397
  } else {
14320
14398
  normal = computeNormal(v0, v1, v2);
14321
14399
  }
@@ -14360,28 +14438,42 @@ function extractTrianglesFromGLTF(gltf, binaryBuffer) {
14360
14438
  }
14361
14439
  } else {
14362
14440
  for (let i = 0; i < vertexCount; i += 3) {
14363
- const v0 = {
14441
+ let v0 = {
14364
14442
  x: positions[i * 3],
14365
14443
  y: positions[i * 3 + 1],
14366
14444
  z: positions[i * 3 + 2]
14367
14445
  };
14368
- const v1 = {
14446
+ let v1 = {
14369
14447
  x: positions[(i + 1) * 3],
14370
14448
  y: positions[(i + 1) * 3 + 1],
14371
14449
  z: positions[(i + 1) * 3 + 2]
14372
14450
  };
14373
- const v2 = {
14451
+ let v2 = {
14374
14452
  x: positions[(i + 2) * 3],
14375
14453
  y: positions[(i + 2) * 3 + 1],
14376
14454
  z: positions[(i + 2) * 3 + 2]
14377
14455
  };
14456
+ for (const transform of transforms) {
14457
+ v0 = applyNodeTransform(v0, transform);
14458
+ v1 = applyNodeTransform(v1, transform);
14459
+ v2 = applyNodeTransform(v2, transform);
14460
+ }
14378
14461
  let normal;
14379
14462
  if (normals) {
14380
- normal = {
14463
+ let n = {
14381
14464
  x: (normals[i * 3] + normals[(i + 1) * 3] + normals[(i + 2) * 3]) / 3,
14382
14465
  y: (normals[i * 3 + 1] + normals[(i + 1) * 3 + 1] + normals[(i + 2) * 3 + 1]) / 3,
14383
14466
  z: (normals[i * 3 + 2] + normals[(i + 1) * 3 + 2] + normals[(i + 2) * 3 + 2]) / 3
14384
14467
  };
14468
+ for (const transform of transforms) {
14469
+ if (transform.rotation) {
14470
+ n = applyQuaternion(
14471
+ n,
14472
+ transform.rotation
14473
+ );
14474
+ }
14475
+ }
14476
+ normal = n;
14385
14477
  } else {
14386
14478
  normal = computeNormal(v0, v1, v2);
14387
14479
  }
@@ -14725,20 +14817,18 @@ async function convertSvgToCanvasBrowser(svgString, resolution, backgroundColor)
14725
14817
  });
14726
14818
  }
14727
14819
  async function renderBoardTextures(circuitJson, resolution = 1024) {
14728
- const [top, bottom] = await Promise.all([
14729
- renderBoardLayer(circuitJson, {
14730
- layer: "top",
14731
- resolution,
14732
- backgroundColor: "#0F3812"
14733
- // Green PCB background
14734
- }),
14735
- renderBoardLayer(circuitJson, {
14736
- layer: "bottom",
14737
- resolution,
14738
- backgroundColor: "#0F3812"
14739
- // Darker green for bottom layer
14740
- })
14741
- ]);
14820
+ const top = await renderBoardLayer(circuitJson, {
14821
+ layer: "top",
14822
+ resolution,
14823
+ backgroundColor: "#0F3812"
14824
+ // Green PCB background
14825
+ });
14826
+ const bottom = await renderBoardLayer(circuitJson, {
14827
+ layer: "bottom",
14828
+ resolution,
14829
+ backgroundColor: "#0F3812"
14830
+ // Darker green for bottom layer
14831
+ });
14742
14832
  return { top, bottom };
14743
14833
  }
14744
14834
 
@@ -15187,7 +15277,11 @@ async function convertCircuitJsonTo3D(circuitJson, options = {}) {
15187
15277
  } else if (model_obj_url) {
15188
15278
  box.mesh = await loadOBJ(model_obj_url, defaultTransform);
15189
15279
  } else if (model_glb_url) {
15190
- box.mesh = await loadGLB(model_glb_url, defaultTransform);
15280
+ try {
15281
+ box.mesh = await loadGLB(model_glb_url, defaultTransform);
15282
+ } catch (err) {
15283
+ console.error(`Failed to load GLB from ${model_glb_url}:`, err);
15284
+ }
15191
15285
  } else if (model_gltf_url) {
15192
15286
  box.mesh = await loadGLTF(model_gltf_url, defaultTransform);
15193
15287
  } else if (hasFootprinterModel && cad.footprinter_string) {
@@ -15914,7 +16008,8 @@ var GLTFBuilder = class {
15914
16008
  },
15915
16009
  alphaMode: "BLEND"
15916
16010
  });
15917
- for (const box of scene3D.boxes) {
16011
+ for (let i = 0; i < scene3D.boxes.length; i++) {
16012
+ const box = scene3D.boxes[i];
15918
16013
  await this.addBox(box, defaultMaterialIndex);
15919
16014
  }
15920
16015
  }
@@ -15998,9 +16093,8 @@ var GLTFBuilder = class {
15998
16093
  }
15999
16094
  const primitives = [];
16000
16095
  for (const { meshData, materialIndex } of meshDataArray) {
16001
- const transformedMeshData = convertMeshToGLTFOrientation(
16002
- transformMesh(meshData, box.center, box.rotation)
16003
- );
16096
+ const translatedMesh = transformMesh(meshData, box.center, box.rotation);
16097
+ const transformedMeshData = convertMeshToGLTFOrientation(translatedMesh);
16004
16098
  const positionAccessorIndex = this.addAccessor(
16005
16099
  transformedMeshData.positions,
16006
16100
  "VEC3",
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.56",
5
+ "version": "0.0.58",
6
6
  "scripts": {
7
7
  "test": "bun test tests/",
8
8
  "format": "biome format --write .",