circuit-json-to-gltf 0.0.13 → 0.0.15
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 +1 -1
- package/dist/index.js +191 -11
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
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
|
}
|
|
@@ -1000,14 +1145,19 @@ async function convertCircuitJsonTo3D(circuitJson, options = {}) {
|
|
|
1000
1145
|
continue;
|
|
1001
1146
|
pcbComponentIdsWith3D.add(cad.pcb_component_id);
|
|
1002
1147
|
const pcbComponent = db.pcb_component.get(cad.pcb_component_id);
|
|
1148
|
+
const isBottomLayer = pcbComponent?.layer === "bottom";
|
|
1003
1149
|
const size = cad.size ?? {
|
|
1004
1150
|
x: pcbComponent?.width ?? 2,
|
|
1005
1151
|
y: defaultComponentHeight,
|
|
1006
1152
|
z: pcbComponent?.height ?? 2
|
|
1007
1153
|
};
|
|
1008
|
-
const center = cad.position ? {
|
|
1154
|
+
const center = cad.position ? {
|
|
1155
|
+
x: cad.position.x,
|
|
1156
|
+
y: isBottomLayer ? -Math.abs(cad.position.z) : cad.position.z,
|
|
1157
|
+
z: cad.position.y
|
|
1158
|
+
} : {
|
|
1009
1159
|
x: pcbComponent?.center.x ?? 0,
|
|
1010
|
-
y: boardThickness / 2 + size.y / 2,
|
|
1160
|
+
y: isBottomLayer ? -(boardThickness / 2 + size.y / 2) : boardThickness / 2 + size.y / 2,
|
|
1011
1161
|
z: pcbComponent?.center.y ?? 0
|
|
1012
1162
|
};
|
|
1013
1163
|
const meshType = model_stl_url ? "stl" : model_obj_url ? "obj" : model_gltf_url ? "gltf" : "glb";
|
|
@@ -1018,7 +1168,35 @@ async function convertCircuitJsonTo3D(circuitJson, options = {}) {
|
|
|
1018
1168
|
meshType
|
|
1019
1169
|
};
|
|
1020
1170
|
if (cad.rotation) {
|
|
1021
|
-
|
|
1171
|
+
if (model_glb_url || model_gltf_url) {
|
|
1172
|
+
box.rotation = convertRotationFromCadRotation({
|
|
1173
|
+
x: isBottomLayer ? cad.rotation.x + 180 : cad.rotation.x,
|
|
1174
|
+
y: cad.rotation.z,
|
|
1175
|
+
// Circuit Z rotation becomes model Y rotation
|
|
1176
|
+
z: cad.rotation.y
|
|
1177
|
+
// Circuit Y rotation becomes model Z rotation
|
|
1178
|
+
});
|
|
1179
|
+
} else {
|
|
1180
|
+
box.rotation = convertRotationFromCadRotation({
|
|
1181
|
+
x: isBottomLayer ? cad.rotation.x + 180 : cad.rotation.x,
|
|
1182
|
+
y: cad.rotation.y,
|
|
1183
|
+
z: cad.rotation.z
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1186
|
+
} else if (isBottomLayer) {
|
|
1187
|
+
if (model_glb_url || model_gltf_url) {
|
|
1188
|
+
box.rotation = convertRotationFromCadRotation({
|
|
1189
|
+
x: 180,
|
|
1190
|
+
y: 0,
|
|
1191
|
+
z: 0
|
|
1192
|
+
});
|
|
1193
|
+
} else {
|
|
1194
|
+
box.rotation = convertRotationFromCadRotation({
|
|
1195
|
+
x: 180,
|
|
1196
|
+
y: 0,
|
|
1197
|
+
z: 0
|
|
1198
|
+
});
|
|
1199
|
+
}
|
|
1022
1200
|
}
|
|
1023
1201
|
const defaultTransform = coordinateTransform ?? (model_glb_url || model_gltf_url ? void 0 : COORDINATE_TRANSFORMS.Z_UP_TO_Y_UP_USB_FIX);
|
|
1024
1202
|
if (model_stl_url) {
|
|
@@ -1044,10 +1222,11 @@ async function convertCircuitJsonTo3D(circuitJson, options = {}) {
|
|
|
1044
1222
|
Math.min(component.width, component.height),
|
|
1045
1223
|
defaultComponentHeight
|
|
1046
1224
|
);
|
|
1225
|
+
const isBottomLayer = component.layer === "bottom";
|
|
1047
1226
|
boxes.push({
|
|
1048
1227
|
center: {
|
|
1049
1228
|
x: component.center.x,
|
|
1050
|
-
y: boardThickness / 2 + compHeight / 2,
|
|
1229
|
+
y: isBottomLayer ? -(boardThickness / 2 + compHeight / 2) : boardThickness / 2 + compHeight / 2,
|
|
1051
1230
|
z: component.center.y
|
|
1052
1231
|
},
|
|
1053
1232
|
size: {
|
|
@@ -1710,18 +1889,19 @@ var GLTFBuilder = class {
|
|
|
1710
1889
|
const meshDataArray = createMeshFromOBJ(objMesh);
|
|
1711
1890
|
const objMaterialIndices = /* @__PURE__ */ new Map();
|
|
1712
1891
|
for (const [name, objMaterial] of objMesh.materials) {
|
|
1713
|
-
|
|
1714
|
-
const alpha = 1 - dissolve;
|
|
1715
|
-
let baseColor = [0.3, 0.3, 0.3, alpha];
|
|
1892
|
+
let baseColor = [0.3, 0.3, 0.3, 1];
|
|
1716
1893
|
if (objMaterial.color) {
|
|
1717
1894
|
const color = typeof objMaterial.color === "string" ? this.parseColorString(objMaterial.color) : [
|
|
1718
1895
|
objMaterial.color[0] / 255,
|
|
1719
1896
|
objMaterial.color[1] / 255,
|
|
1720
1897
|
objMaterial.color[2] / 255,
|
|
1721
|
-
|
|
1898
|
+
objMaterial.color[3]
|
|
1899
|
+
// Use the alpha from the color
|
|
1722
1900
|
];
|
|
1723
|
-
baseColor = [color[0], color[1], color[2],
|
|
1901
|
+
baseColor = [color[0], color[1], color[2], color[3]];
|
|
1724
1902
|
}
|
|
1903
|
+
const alpha = objMaterial.dissolve !== void 0 ? 1 - objMaterial.dissolve : baseColor[3];
|
|
1904
|
+
baseColor[3] = alpha;
|
|
1725
1905
|
const gltfMaterialIndex = this.addMaterial({
|
|
1726
1906
|
name: `OBJ_${name}`,
|
|
1727
1907
|
pbrMetallicRoughness: {
|