circuit-json-to-gltf 0.0.13 → 0.0.14

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/dist/index.d.ts CHANGED
@@ -135,7 +135,7 @@ declare function clearSTLCache(): void;
135
135
  declare function loadOBJ(url: string, transform?: CoordinateTransformConfig): Promise<OBJMesh>;
136
136
  declare function clearOBJCache(): void;
137
137
 
138
- declare function loadGLB(url: string, transform?: CoordinateTransformConfig): Promise<STLMesh>;
138
+ declare function loadGLB(url: string, transform?: CoordinateTransformConfig): Promise<STLMesh | OBJMesh>;
139
139
  declare function clearGLBCache(): void;
140
140
 
141
141
  declare function convertCircuitJsonTo3D(circuitJson: CircuitJson, options?: CircuitTo3DOptions): Promise<Scene3D>;
package/dist/index.js CHANGED
@@ -534,11 +534,59 @@ function parseGLB(buffer, transform) {
534
534
  axisMapping: { x: "x", y: "z", z: "y" }
535
535
  };
536
536
  const transformedTriangles = transformTriangles(triangles, finalConfig);
537
+ const hasColors = transformedTriangles.some((t) => t.color !== void 0);
538
+ if (hasColors) {
539
+ return convertToOBJMesh(transformedTriangles);
540
+ }
537
541
  return {
538
542
  triangles: transformedTriangles,
539
543
  boundingBox: calculateBoundingBox3(transformedTriangles)
540
544
  };
541
545
  }
546
+ function convertToOBJMesh(triangles) {
547
+ const colorGroups = /* @__PURE__ */ new Map();
548
+ for (const triangle of triangles) {
549
+ const colorKey = triangle.color ? JSON.stringify(triangle.color) : "default";
550
+ if (!colorGroups.has(colorKey)) {
551
+ colorGroups.set(colorKey, []);
552
+ }
553
+ colorGroups.get(colorKey).push(triangle);
554
+ }
555
+ const materials = /* @__PURE__ */ new Map();
556
+ const materialIndexMap = /* @__PURE__ */ new Map();
557
+ let materialIndex = 0;
558
+ const trianglesWithMaterialIndex = [];
559
+ for (const [colorKey, groupTriangles] of colorGroups) {
560
+ const materialName = `Material_${materialIndex}`;
561
+ materialIndexMap.set(materialName, materialIndex);
562
+ if (colorKey === "default") {
563
+ materials.set(materialName, {
564
+ name: materialName,
565
+ color: [179, 179, 179, 1]
566
+ // 0.7 * 255 = 179
567
+ });
568
+ } else {
569
+ const color = JSON.parse(colorKey);
570
+ materials.set(materialName, {
571
+ name: materialName,
572
+ color
573
+ });
574
+ }
575
+ for (const triangle of groupTriangles) {
576
+ trianglesWithMaterialIndex.push({
577
+ ...triangle,
578
+ materialIndex
579
+ });
580
+ }
581
+ materialIndex++;
582
+ }
583
+ return {
584
+ triangles: trianglesWithMaterialIndex,
585
+ boundingBox: calculateBoundingBox3(trianglesWithMaterialIndex),
586
+ materials,
587
+ materialIndexMap
588
+ };
589
+ }
542
590
  function extractTrianglesFromGLTF(gltf, binaryBuffer) {
543
591
  const triangles = [];
544
592
  if (!gltf.meshes || !gltf.accessors || !gltf.bufferViews) {
@@ -570,6 +618,29 @@ function extractTrianglesFromGLTF(gltf, binaryBuffer) {
570
618
  binaryBuffer
571
619
  );
572
620
  }
621
+ let vertexColors;
622
+ const colorAccessorIndex = primitive.attributes.COLOR_0;
623
+ if (colorAccessorIndex !== void 0) {
624
+ const colorAccessor = gltf.accessors[colorAccessorIndex];
625
+ vertexColors = getAccessorData(
626
+ colorAccessor,
627
+ gltf.bufferViews,
628
+ binaryBuffer
629
+ );
630
+ }
631
+ let materialColor;
632
+ if (!vertexColors && primitive.material !== void 0 && gltf.materials) {
633
+ const material = gltf.materials[primitive.material];
634
+ if (material?.pbrMetallicRoughness?.baseColorFactor) {
635
+ const factor = material.pbrMetallicRoughness.baseColorFactor;
636
+ materialColor = [
637
+ Math.round(factor[0] * 255),
638
+ Math.round(factor[1] * 255),
639
+ Math.round(factor[2] * 255),
640
+ factor[3]
641
+ ];
642
+ }
643
+ }
573
644
  let indices;
574
645
  if (primitive.indices !== void 0) {
575
646
  const indexAccessor = gltf.accessors[primitive.indices];
@@ -619,7 +690,44 @@ function extractTrianglesFromGLTF(gltf, binaryBuffer) {
619
690
  } else {
620
691
  normal = computeNormal(v0, v1, v2);
621
692
  }
622
- triangles.push({ vertices: [v0, v1, v2], normal });
693
+ let triangleColor;
694
+ if (vertexColors) {
695
+ const componentsPerColor = vertexColors.length / vertexCount;
696
+ if (componentsPerColor === 3) {
697
+ triangleColor = [
698
+ Math.round(
699
+ (vertexColors[i0 * 3] + vertexColors[i1 * 3] + vertexColors[i2 * 3]) / 3 * 255
700
+ ),
701
+ Math.round(
702
+ (vertexColors[i0 * 3 + 1] + vertexColors[i1 * 3 + 1] + vertexColors[i2 * 3 + 1]) / 3 * 255
703
+ ),
704
+ Math.round(
705
+ (vertexColors[i0 * 3 + 2] + vertexColors[i1 * 3 + 2] + vertexColors[i2 * 3 + 2]) / 3 * 255
706
+ ),
707
+ 1
708
+ ];
709
+ } else if (componentsPerColor === 4) {
710
+ triangleColor = [
711
+ Math.round(
712
+ (vertexColors[i0 * 4] + vertexColors[i1 * 4] + vertexColors[i2 * 4]) / 3 * 255
713
+ ),
714
+ Math.round(
715
+ (vertexColors[i0 * 4 + 1] + vertexColors[i1 * 4 + 1] + vertexColors[i2 * 4 + 1]) / 3 * 255
716
+ ),
717
+ Math.round(
718
+ (vertexColors[i0 * 4 + 2] + vertexColors[i1 * 4 + 2] + vertexColors[i2 * 4 + 2]) / 3 * 255
719
+ ),
720
+ (vertexColors[i0 * 4 + 3] + vertexColors[i1 * 4 + 3] + vertexColors[i2 * 4 + 3]) / 3
721
+ ];
722
+ }
723
+ } else {
724
+ triangleColor = materialColor;
725
+ }
726
+ triangles.push({
727
+ vertices: [v0, v1, v2],
728
+ normal,
729
+ color: triangleColor
730
+ });
623
731
  }
624
732
  } else {
625
733
  for (let i = 0; i < vertexCount; i += 3) {
@@ -648,7 +756,44 @@ function extractTrianglesFromGLTF(gltf, binaryBuffer) {
648
756
  } else {
649
757
  normal = computeNormal(v0, v1, v2);
650
758
  }
651
- triangles.push({ vertices: [v0, v1, v2], normal });
759
+ let triangleColor;
760
+ if (vertexColors) {
761
+ const componentsPerColor = vertexColors.length / vertexCount;
762
+ if (componentsPerColor === 3) {
763
+ triangleColor = [
764
+ Math.round(
765
+ (vertexColors[i * 3] + vertexColors[(i + 1) * 3] + vertexColors[(i + 2) * 3]) / 3 * 255
766
+ ),
767
+ Math.round(
768
+ (vertexColors[i * 3 + 1] + vertexColors[(i + 1) * 3 + 1] + vertexColors[(i + 2) * 3 + 1]) / 3 * 255
769
+ ),
770
+ Math.round(
771
+ (vertexColors[i * 3 + 2] + vertexColors[(i + 1) * 3 + 2] + vertexColors[(i + 2) * 3 + 2]) / 3 * 255
772
+ ),
773
+ 1
774
+ ];
775
+ } else if (componentsPerColor === 4) {
776
+ triangleColor = [
777
+ Math.round(
778
+ (vertexColors[i * 4] + vertexColors[(i + 1) * 4] + vertexColors[(i + 2) * 4]) / 3 * 255
779
+ ),
780
+ Math.round(
781
+ (vertexColors[i * 4 + 1] + vertexColors[(i + 1) * 4 + 1] + vertexColors[(i + 2) * 4 + 1]) / 3 * 255
782
+ ),
783
+ Math.round(
784
+ (vertexColors[i * 4 + 2] + vertexColors[(i + 1) * 4 + 2] + vertexColors[(i + 2) * 4 + 2]) / 3 * 255
785
+ ),
786
+ (vertexColors[i * 4 + 3] + vertexColors[(i + 1) * 4 + 3] + vertexColors[(i + 2) * 4 + 3]) / 3
787
+ ];
788
+ }
789
+ } else {
790
+ triangleColor = materialColor;
791
+ }
792
+ triangles.push({
793
+ vertices: [v0, v1, v2],
794
+ normal,
795
+ color: triangleColor
796
+ });
652
797
  }
653
798
  }
654
799
  }
@@ -1018,7 +1163,17 @@ async function convertCircuitJsonTo3D(circuitJson, options = {}) {
1018
1163
  meshType
1019
1164
  };
1020
1165
  if (cad.rotation) {
1021
- box.rotation = convertRotationFromCadRotation(cad.rotation);
1166
+ if (model_glb_url || model_gltf_url) {
1167
+ box.rotation = convertRotationFromCadRotation({
1168
+ x: cad.rotation.x,
1169
+ y: cad.rotation.z,
1170
+ // Circuit Z rotation becomes model Y rotation
1171
+ z: cad.rotation.y
1172
+ // Circuit Y rotation becomes model Z rotation
1173
+ });
1174
+ } else {
1175
+ box.rotation = convertRotationFromCadRotation(cad.rotation);
1176
+ }
1022
1177
  }
1023
1178
  const defaultTransform = coordinateTransform ?? (model_glb_url || model_gltf_url ? void 0 : COORDINATE_TRANSFORMS.Z_UP_TO_Y_UP_USB_FIX);
1024
1179
  if (model_stl_url) {
@@ -1710,18 +1865,19 @@ var GLTFBuilder = class {
1710
1865
  const meshDataArray = createMeshFromOBJ(objMesh);
1711
1866
  const objMaterialIndices = /* @__PURE__ */ new Map();
1712
1867
  for (const [name, objMaterial] of objMesh.materials) {
1713
- const dissolve = objMaterial.dissolve ?? 1;
1714
- const alpha = 1 - dissolve;
1715
- let baseColor = [0.3, 0.3, 0.3, alpha];
1868
+ let baseColor = [0.3, 0.3, 0.3, 1];
1716
1869
  if (objMaterial.color) {
1717
1870
  const color = typeof objMaterial.color === "string" ? this.parseColorString(objMaterial.color) : [
1718
1871
  objMaterial.color[0] / 255,
1719
1872
  objMaterial.color[1] / 255,
1720
1873
  objMaterial.color[2] / 255,
1721
- alpha
1874
+ objMaterial.color[3]
1875
+ // Use the alpha from the color
1722
1876
  ];
1723
- baseColor = [color[0], color[1], color[2], alpha];
1877
+ baseColor = [color[0], color[1], color[2], color[3]];
1724
1878
  }
1879
+ const alpha = objMaterial.dissolve !== void 0 ? 1 - objMaterial.dissolve : baseColor[3];
1880
+ baseColor[3] = alpha;
1725
1881
  const gltfMaterialIndex = this.addMaterial({
1726
1882
  name: `OBJ_${name}`,
1727
1883
  pbrMetallicRoughness: {
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.13",
5
+ "version": "0.0.14",
6
6
  "scripts": {
7
7
  "test": "bun test tests/",
8
8
  "format": "biome format --write .",