@tscircuit/3d-viewer 0.0.477 → 0.0.478
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 +19 -21
- package/dist/index.js +484 -428
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -44,6 +44,23 @@ declare function useExportGltfUrl(options?: Options): [
|
|
|
44
44
|
error: ErrorEvent | undefined
|
|
45
45
|
];
|
|
46
46
|
|
|
47
|
+
interface LayerTextures {
|
|
48
|
+
topTrace?: THREE.CanvasTexture | null;
|
|
49
|
+
bottomTrace?: THREE.CanvasTexture | null;
|
|
50
|
+
topTraceWithMask?: THREE.CanvasTexture | null;
|
|
51
|
+
bottomTraceWithMask?: THREE.CanvasTexture | null;
|
|
52
|
+
topSilkscreen?: THREE.CanvasTexture | null;
|
|
53
|
+
bottomSilkscreen?: THREE.CanvasTexture | null;
|
|
54
|
+
topSoldermask?: THREE.CanvasTexture | null;
|
|
55
|
+
bottomSoldermask?: THREE.CanvasTexture | null;
|
|
56
|
+
topCopperText?: THREE.CanvasTexture | null;
|
|
57
|
+
bottomCopperText?: THREE.CanvasTexture | null;
|
|
58
|
+
topPanelOutlines?: THREE.CanvasTexture | null;
|
|
59
|
+
bottomPanelOutlines?: THREE.CanvasTexture | null;
|
|
60
|
+
topCopper?: THREE.CanvasTexture | null;
|
|
61
|
+
bottomCopper?: THREE.CanvasTexture | null;
|
|
62
|
+
}
|
|
63
|
+
|
|
47
64
|
interface ManifoldGeoms {
|
|
48
65
|
board?: {
|
|
49
66
|
geometry: THREE.BufferGeometry;
|
|
@@ -66,29 +83,10 @@ interface ManifoldGeoms {
|
|
|
66
83
|
geometry: THREE.BufferGeometry;
|
|
67
84
|
color: THREE.Color;
|
|
68
85
|
}>;
|
|
69
|
-
copperPours?: Array<{
|
|
70
|
-
key: string;
|
|
71
|
-
geometry: THREE.BufferGeometry;
|
|
72
|
-
color: THREE.Color;
|
|
73
|
-
}>;
|
|
74
|
-
}
|
|
75
|
-
interface ManifoldTextures {
|
|
76
|
-
topTrace?: THREE.CanvasTexture | null;
|
|
77
|
-
bottomTrace?: THREE.CanvasTexture | null;
|
|
78
|
-
topTraceWithMask?: THREE.CanvasTexture | null;
|
|
79
|
-
bottomTraceWithMask?: THREE.CanvasTexture | null;
|
|
80
|
-
topSilkscreen?: THREE.CanvasTexture | null;
|
|
81
|
-
bottomSilkscreen?: THREE.CanvasTexture | null;
|
|
82
|
-
topSoldermask?: THREE.CanvasTexture | null;
|
|
83
|
-
bottomSoldermask?: THREE.CanvasTexture | null;
|
|
84
|
-
topCopperText?: THREE.CanvasTexture | null;
|
|
85
|
-
bottomCopperText?: THREE.CanvasTexture | null;
|
|
86
|
-
topPanelOutlines?: THREE.CanvasTexture | null;
|
|
87
|
-
bottomPanelOutlines?: THREE.CanvasTexture | null;
|
|
88
86
|
}
|
|
89
87
|
interface UseManifoldBoardBuilderResult {
|
|
90
88
|
geoms: ManifoldGeoms | null;
|
|
91
|
-
textures:
|
|
89
|
+
textures: LayerTextures | null;
|
|
92
90
|
pcbThickness: number | null;
|
|
93
91
|
error: string | null;
|
|
94
92
|
isLoading: boolean;
|
|
@@ -145,4 +143,4 @@ declare const useCameraSession: () => {
|
|
|
145
143
|
handleControlsChange: () => void;
|
|
146
144
|
};
|
|
147
145
|
|
|
148
|
-
export { CadViewer, CameraAnimatorWithContext, CameraControllerProvider, type ManifoldGeoms,
|
|
146
|
+
export { CadViewer, CameraAnimatorWithContext, CameraControllerProvider, type ManifoldGeoms, applyJsdomShim, convertCircuitJsonTo3dSvg, loadCameraFromSession, saveCameraToSession, useCameraController, useCameraSession, useExportGltfUrl, useManifoldBoardBuilder, useSaveGltfAs };
|
package/dist/index.js
CHANGED
|
@@ -29492,7 +29492,7 @@ import * as THREE15 from "three";
|
|
|
29492
29492
|
// package.json
|
|
29493
29493
|
var package_default = {
|
|
29494
29494
|
name: "@tscircuit/3d-viewer",
|
|
29495
|
-
version: "0.0.
|
|
29495
|
+
version: "0.0.477",
|
|
29496
29496
|
main: "./dist/index.js",
|
|
29497
29497
|
module: "./dist/index.js",
|
|
29498
29498
|
type: "module",
|
|
@@ -29521,6 +29521,7 @@ var package_default = {
|
|
|
29521
29521
|
dependencies: {
|
|
29522
29522
|
"@jscad/regl-renderer": "^2.6.12",
|
|
29523
29523
|
"@jscad/stl-serializer": "^2.1.20",
|
|
29524
|
+
"circuit-to-canvas": "^0.0.26",
|
|
29524
29525
|
"react-hot-toast": "^2.6.0",
|
|
29525
29526
|
three: "^0.165.0",
|
|
29526
29527
|
"three-stdlib": "^2.36.0",
|
|
@@ -34357,7 +34358,7 @@ function JscadBoardTextures({
|
|
|
34357
34358
|
useEffect22(() => {
|
|
34358
34359
|
if (!rootObject || !boardData || !textures) return;
|
|
34359
34360
|
const meshes = [];
|
|
34360
|
-
const
|
|
34361
|
+
const createTexturePlane2 = (texture, zOffset, isBottomLayer, name, usePolygonOffset = false, depthWrite = false) => {
|
|
34361
34362
|
if (!texture) return null;
|
|
34362
34363
|
const boardOutlineBounds = calculateOutlineBounds(boardData);
|
|
34363
34364
|
const planeGeom = new THREE23.PlaneGeometry(
|
|
@@ -34387,7 +34388,7 @@ function JscadBoardTextures({
|
|
|
34387
34388
|
};
|
|
34388
34389
|
const SURFACE_OFFSET = 1e-3;
|
|
34389
34390
|
if (visibility.topMask) {
|
|
34390
|
-
const topSoldermaskMesh =
|
|
34391
|
+
const topSoldermaskMesh = createTexturePlane2(
|
|
34391
34392
|
textures.topSoldermask,
|
|
34392
34393
|
pcbThickness / 2 + SURFACE_OFFSET,
|
|
34393
34394
|
false,
|
|
@@ -34400,7 +34401,7 @@ function JscadBoardTextures({
|
|
|
34400
34401
|
}
|
|
34401
34402
|
}
|
|
34402
34403
|
if (visibility.bottomMask) {
|
|
34403
|
-
const bottomSoldermaskMesh =
|
|
34404
|
+
const bottomSoldermaskMesh = createTexturePlane2(
|
|
34404
34405
|
textures.bottomSoldermask,
|
|
34405
34406
|
-pcbThickness / 2 - SURFACE_OFFSET,
|
|
34406
34407
|
true,
|
|
@@ -34413,7 +34414,7 @@ function JscadBoardTextures({
|
|
|
34413
34414
|
}
|
|
34414
34415
|
}
|
|
34415
34416
|
if (visibility.topCopper && visibility.topMask) {
|
|
34416
|
-
const topTraceWithMaskMesh =
|
|
34417
|
+
const topTraceWithMaskMesh = createTexturePlane2(
|
|
34417
34418
|
textures.topTraceWithMask,
|
|
34418
34419
|
pcbThickness / 2 + BOARD_SURFACE_OFFSET.traces + 4e-3,
|
|
34419
34420
|
false,
|
|
@@ -34425,7 +34426,7 @@ function JscadBoardTextures({
|
|
|
34425
34426
|
}
|
|
34426
34427
|
}
|
|
34427
34428
|
if (visibility.bottomCopper && visibility.bottomMask) {
|
|
34428
|
-
const bottomTraceWithMaskMesh =
|
|
34429
|
+
const bottomTraceWithMaskMesh = createTexturePlane2(
|
|
34429
34430
|
textures.bottomTraceWithMask,
|
|
34430
34431
|
-pcbThickness / 2 - BOARD_SURFACE_OFFSET.traces - 5e-3,
|
|
34431
34432
|
true,
|
|
@@ -34437,7 +34438,7 @@ function JscadBoardTextures({
|
|
|
34437
34438
|
}
|
|
34438
34439
|
}
|
|
34439
34440
|
if (visibility.topSilkscreen) {
|
|
34440
|
-
const topSilkscreenMesh =
|
|
34441
|
+
const topSilkscreenMesh = createTexturePlane2(
|
|
34441
34442
|
textures.topSilkscreen,
|
|
34442
34443
|
pcbThickness / 2 + SURFACE_OFFSET + 2e-3,
|
|
34443
34444
|
false,
|
|
@@ -34449,7 +34450,7 @@ function JscadBoardTextures({
|
|
|
34449
34450
|
}
|
|
34450
34451
|
}
|
|
34451
34452
|
if (visibility.bottomSilkscreen) {
|
|
34452
|
-
const bottomSilkscreenMesh =
|
|
34453
|
+
const bottomSilkscreenMesh = createTexturePlane2(
|
|
34453
34454
|
textures.bottomSilkscreen,
|
|
34454
34455
|
-pcbThickness / 2 - SURFACE_OFFSET - 2e-3,
|
|
34455
34456
|
true,
|
|
@@ -34461,7 +34462,7 @@ function JscadBoardTextures({
|
|
|
34461
34462
|
}
|
|
34462
34463
|
}
|
|
34463
34464
|
if (visibility.topCopper) {
|
|
34464
|
-
const topCopperTextMesh =
|
|
34465
|
+
const topCopperTextMesh = createTexturePlane2(
|
|
34465
34466
|
textures.topCopperText,
|
|
34466
34467
|
pcbThickness / 2 + BOARD_SURFACE_OFFSET.copper,
|
|
34467
34468
|
false,
|
|
@@ -34473,7 +34474,7 @@ function JscadBoardTextures({
|
|
|
34473
34474
|
}
|
|
34474
34475
|
}
|
|
34475
34476
|
if (visibility.bottomCopper) {
|
|
34476
|
-
const bottomCopperTextMesh =
|
|
34477
|
+
const bottomCopperTextMesh = createTexturePlane2(
|
|
34477
34478
|
textures.bottomCopperText,
|
|
34478
34479
|
-pcbThickness / 2 - BOARD_SURFACE_OFFSET.copper,
|
|
34479
34480
|
true,
|
|
@@ -34485,7 +34486,7 @@ function JscadBoardTextures({
|
|
|
34485
34486
|
}
|
|
34486
34487
|
}
|
|
34487
34488
|
if (visibility.boardBody) {
|
|
34488
|
-
const topPanelOutlinesMesh =
|
|
34489
|
+
const topPanelOutlinesMesh = createTexturePlane2(
|
|
34489
34490
|
textures.topPanelOutlines,
|
|
34490
34491
|
pcbThickness / 2 + SURFACE_OFFSET + 3e-3,
|
|
34491
34492
|
// Above silkscreen
|
|
@@ -34498,7 +34499,7 @@ function JscadBoardTextures({
|
|
|
34498
34499
|
meshes.push(topPanelOutlinesMesh);
|
|
34499
34500
|
rootObject.add(topPanelOutlinesMesh);
|
|
34500
34501
|
}
|
|
34501
|
-
const bottomPanelOutlinesMesh =
|
|
34502
|
+
const bottomPanelOutlinesMesh = createTexturePlane2(
|
|
34502
34503
|
textures.bottomPanelOutlines,
|
|
34503
34504
|
-pcbThickness / 2 - SURFACE_OFFSET - 3e-3,
|
|
34504
34505
|
// Below bottom silkscreen
|
|
@@ -34750,7 +34751,7 @@ import { useEffect as useEffect24, useMemo as useMemo22, useState as useState15
|
|
|
34750
34751
|
// src/hooks/useManifoldBoardBuilder.ts
|
|
34751
34752
|
import { useState as useState14, useEffect as useEffect23, useMemo as useMemo21, useRef as useRef9 } from "react";
|
|
34752
34753
|
import { su as su18 } from "@tscircuit/circuit-json-util";
|
|
34753
|
-
import * as
|
|
34754
|
+
import * as THREE30 from "three";
|
|
34754
34755
|
|
|
34755
34756
|
// src/utils/manifold/create-manifold-board.ts
|
|
34756
34757
|
var arePointsClockwise3 = (points) => {
|
|
@@ -34810,202 +34811,6 @@ function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, ma
|
|
|
34810
34811
|
return { boardOp, outlineCrossSection };
|
|
34811
34812
|
}
|
|
34812
34813
|
|
|
34813
|
-
// src/utils/manifold/process-copper-pours.ts
|
|
34814
|
-
import * as THREE25 from "three";
|
|
34815
|
-
|
|
34816
|
-
// src/utils/manifold-mesh-to-three-geometry.ts
|
|
34817
|
-
import * as THREE24 from "three";
|
|
34818
|
-
function manifoldMeshToThreeGeometry(manifoldMesh) {
|
|
34819
|
-
const geometry = new THREE24.BufferGeometry();
|
|
34820
|
-
geometry.setAttribute(
|
|
34821
|
-
"position",
|
|
34822
|
-
new THREE24.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
|
|
34823
|
-
);
|
|
34824
|
-
geometry.setIndex(new THREE24.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
|
|
34825
|
-
if (manifoldMesh.runIndex && manifoldMesh.runIndex.length > 1 && manifoldMesh.runOriginalID) {
|
|
34826
|
-
for (let i = 0; i < manifoldMesh.runIndex.length - 1; i++) {
|
|
34827
|
-
const start = manifoldMesh.runIndex[i];
|
|
34828
|
-
const count3 = manifoldMesh.runIndex[i + 1] - start;
|
|
34829
|
-
geometry.addGroup(start, count3, 0);
|
|
34830
|
-
}
|
|
34831
|
-
} else {
|
|
34832
|
-
geometry.addGroup(0, manifoldMesh.triVerts.length, 0);
|
|
34833
|
-
}
|
|
34834
|
-
return geometry;
|
|
34835
|
-
}
|
|
34836
|
-
|
|
34837
|
-
// src/utils/manifold/process-copper-pours.ts
|
|
34838
|
-
var arePointsClockwise4 = (points) => {
|
|
34839
|
-
let area = 0;
|
|
34840
|
-
for (let i = 0; i < points.length; i++) {
|
|
34841
|
-
const j = (i + 1) % points.length;
|
|
34842
|
-
if (points[i] && points[j]) {
|
|
34843
|
-
area += points[i][0] * points[j][1];
|
|
34844
|
-
area -= points[j][0] * points[i][1];
|
|
34845
|
-
}
|
|
34846
|
-
}
|
|
34847
|
-
const signedArea = area / 2;
|
|
34848
|
-
return signedArea <= 0;
|
|
34849
|
-
};
|
|
34850
|
-
function segmentToPoints2(p1, p2, bulge, arcSegments) {
|
|
34851
|
-
if (!bulge || Math.abs(bulge) < 1e-9) {
|
|
34852
|
-
return [];
|
|
34853
|
-
}
|
|
34854
|
-
const theta = 4 * Math.atan(bulge);
|
|
34855
|
-
const dx = p2[0] - p1[0];
|
|
34856
|
-
const dy = p2[1] - p1[1];
|
|
34857
|
-
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
34858
|
-
if (dist < 1e-9) return [];
|
|
34859
|
-
const radius = Math.abs(dist / (2 * Math.sin(theta / 2)));
|
|
34860
|
-
const m = Math.sqrt(Math.max(0, radius * radius - dist / 2 * (dist / 2)));
|
|
34861
|
-
const midPoint = [(p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2];
|
|
34862
|
-
const ux = dx / dist;
|
|
34863
|
-
const uy = dy / dist;
|
|
34864
|
-
const nx = -uy;
|
|
34865
|
-
const ny = ux;
|
|
34866
|
-
const centerX = midPoint[0] + nx * m * Math.sign(bulge);
|
|
34867
|
-
const centerY = midPoint[1] + ny * m * Math.sign(bulge);
|
|
34868
|
-
const startAngle = Math.atan2(p1[1] - centerY, p1[0] - centerX);
|
|
34869
|
-
const points = [];
|
|
34870
|
-
const numSteps = Math.max(
|
|
34871
|
-
2,
|
|
34872
|
-
Math.ceil(arcSegments * Math.abs(theta) / (Math.PI * 2) * 4)
|
|
34873
|
-
);
|
|
34874
|
-
const angleStep = theta / numSteps;
|
|
34875
|
-
for (let i = 1; i < numSteps; i++) {
|
|
34876
|
-
const angle = startAngle + angleStep * i;
|
|
34877
|
-
points.push([
|
|
34878
|
-
centerX + radius * Math.cos(angle),
|
|
34879
|
-
centerY + radius * Math.sin(angle)
|
|
34880
|
-
]);
|
|
34881
|
-
}
|
|
34882
|
-
return points;
|
|
34883
|
-
}
|
|
34884
|
-
function ringToPoints2(ring2, arcSegments) {
|
|
34885
|
-
const allPoints = [];
|
|
34886
|
-
const vertices = ring2.vertices;
|
|
34887
|
-
for (let i = 0; i < vertices.length; i++) {
|
|
34888
|
-
const p1 = vertices[i];
|
|
34889
|
-
const p2 = vertices[(i + 1) % vertices.length];
|
|
34890
|
-
allPoints.push([p1.x, p1.y]);
|
|
34891
|
-
if (p1.bulge) {
|
|
34892
|
-
const arcPoints = segmentToPoints2(
|
|
34893
|
-
[p1.x, p1.y],
|
|
34894
|
-
[p2.x, p2.y],
|
|
34895
|
-
p1.bulge,
|
|
34896
|
-
arcSegments
|
|
34897
|
-
);
|
|
34898
|
-
allPoints.push(...arcPoints);
|
|
34899
|
-
}
|
|
34900
|
-
}
|
|
34901
|
-
return allPoints;
|
|
34902
|
-
}
|
|
34903
|
-
function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardMaterial, holeUnion, boardClipVolume) {
|
|
34904
|
-
const copperPourGeoms = [];
|
|
34905
|
-
const copperPours = circuitJson.filter(
|
|
34906
|
-
(e) => e.type === "pcb_copper_pour"
|
|
34907
|
-
);
|
|
34908
|
-
for (const pour of copperPours) {
|
|
34909
|
-
const pourThickness = DEFAULT_SMT_PAD_THICKNESS;
|
|
34910
|
-
const layerSign = pour.layer === "bottom" ? -1 : 1;
|
|
34911
|
-
const zPos = layerSign * (pcbThickness / 2 + pourThickness / 2 + MANIFOLD_Z_OFFSET);
|
|
34912
|
-
let pourOp;
|
|
34913
|
-
if (pour.shape === "rect") {
|
|
34914
|
-
pourOp = Manifold.cube([pour.width, pour.height, pourThickness], true);
|
|
34915
|
-
manifoldInstancesForCleanup.push(pourOp);
|
|
34916
|
-
if (pour.rotation) {
|
|
34917
|
-
const rotatedOp = pourOp.rotate([0, 0, pour.rotation]);
|
|
34918
|
-
manifoldInstancesForCleanup.push(rotatedOp);
|
|
34919
|
-
pourOp = rotatedOp;
|
|
34920
|
-
}
|
|
34921
|
-
pourOp = pourOp.translate([pour.center.x, pour.center.y, zPos]);
|
|
34922
|
-
manifoldInstancesForCleanup.push(pourOp);
|
|
34923
|
-
} else if (pour.shape === "polygon") {
|
|
34924
|
-
if (pour.points.length < 3) continue;
|
|
34925
|
-
let pointsVec2 = pour.points.map((p) => [
|
|
34926
|
-
p.x,
|
|
34927
|
-
p.y
|
|
34928
|
-
]);
|
|
34929
|
-
if (arePointsClockwise4(pointsVec2)) {
|
|
34930
|
-
pointsVec2 = pointsVec2.reverse();
|
|
34931
|
-
}
|
|
34932
|
-
const crossSection = CrossSection.ofPolygons([pointsVec2]);
|
|
34933
|
-
manifoldInstancesForCleanup.push(crossSection);
|
|
34934
|
-
pourOp = Manifold.extrude(
|
|
34935
|
-
crossSection,
|
|
34936
|
-
pourThickness,
|
|
34937
|
-
0,
|
|
34938
|
-
// nDivisions
|
|
34939
|
-
0,
|
|
34940
|
-
// twistDegrees
|
|
34941
|
-
[1, 1],
|
|
34942
|
-
// scaleTop
|
|
34943
|
-
true
|
|
34944
|
-
// center extrusion
|
|
34945
|
-
).translate([0, 0, zPos]);
|
|
34946
|
-
manifoldInstancesForCleanup.push(pourOp);
|
|
34947
|
-
} else if (pour.shape === "brep") {
|
|
34948
|
-
const brepShape = pour.brep_shape;
|
|
34949
|
-
if (!brepShape || !brepShape.outer_ring) continue;
|
|
34950
|
-
let outerRingPoints = ringToPoints2(
|
|
34951
|
-
brepShape.outer_ring,
|
|
34952
|
-
SMOOTH_CIRCLE_SEGMENTS
|
|
34953
|
-
);
|
|
34954
|
-
if (arePointsClockwise4(outerRingPoints)) {
|
|
34955
|
-
outerRingPoints = outerRingPoints.reverse();
|
|
34956
|
-
}
|
|
34957
|
-
const polygons = [outerRingPoints];
|
|
34958
|
-
if (brepShape.inner_rings) {
|
|
34959
|
-
const innerRingsPoints = brepShape.inner_rings.map((ring2) => {
|
|
34960
|
-
let points = ringToPoints2(ring2, SMOOTH_CIRCLE_SEGMENTS);
|
|
34961
|
-
if (!arePointsClockwise4(points)) {
|
|
34962
|
-
points = points.reverse();
|
|
34963
|
-
}
|
|
34964
|
-
return points;
|
|
34965
|
-
});
|
|
34966
|
-
polygons.push(...innerRingsPoints);
|
|
34967
|
-
}
|
|
34968
|
-
const crossSection = CrossSection.ofPolygons(polygons);
|
|
34969
|
-
manifoldInstancesForCleanup.push(crossSection);
|
|
34970
|
-
pourOp = Manifold.extrude(
|
|
34971
|
-
crossSection,
|
|
34972
|
-
pourThickness,
|
|
34973
|
-
0,
|
|
34974
|
-
// nDivisions
|
|
34975
|
-
0,
|
|
34976
|
-
// twistDegrees
|
|
34977
|
-
[1, 1],
|
|
34978
|
-
// scaleTop
|
|
34979
|
-
true
|
|
34980
|
-
// center extrusion
|
|
34981
|
-
).translate([0, 0, zPos]);
|
|
34982
|
-
manifoldInstancesForCleanup.push(pourOp);
|
|
34983
|
-
}
|
|
34984
|
-
if (pourOp) {
|
|
34985
|
-
if (holeUnion) {
|
|
34986
|
-
const withHoles = pourOp.subtract(holeUnion);
|
|
34987
|
-
manifoldInstancesForCleanup.push(withHoles);
|
|
34988
|
-
pourOp = withHoles;
|
|
34989
|
-
}
|
|
34990
|
-
if (boardClipVolume) {
|
|
34991
|
-
const clipped = Manifold.intersection([pourOp, boardClipVolume]);
|
|
34992
|
-
manifoldInstancesForCleanup.push(clipped);
|
|
34993
|
-
pourOp = clipped;
|
|
34994
|
-
}
|
|
34995
|
-
const covered = pour.covered_with_solder_mask !== false;
|
|
34996
|
-
const pourColorArr = covered ? tracesMaterialColors[boardMaterial] ?? colors.fr4TracesWithoutMaskTan : colors.copper;
|
|
34997
|
-
const pourColor = new THREE25.Color(...pourColorArr);
|
|
34998
|
-
const threeGeom = manifoldMeshToThreeGeometry(pourOp.getMesh());
|
|
34999
|
-
copperPourGeoms.push({
|
|
35000
|
-
key: `coppour-${pour.pcb_copper_pour_id}`,
|
|
35001
|
-
geometry: threeGeom,
|
|
35002
|
-
color: pourColor
|
|
35003
|
-
});
|
|
35004
|
-
}
|
|
35005
|
-
}
|
|
35006
|
-
return { copperPourGeoms };
|
|
35007
|
-
}
|
|
35008
|
-
|
|
35009
34814
|
// src/utils/manifold/process-cutouts.ts
|
|
35010
34815
|
import { su as su13 } from "@tscircuit/circuit-json-util";
|
|
35011
34816
|
|
|
@@ -35085,7 +34890,7 @@ function createPadManifoldOp({
|
|
|
35085
34890
|
}
|
|
35086
34891
|
|
|
35087
34892
|
// src/utils/manifold/process-cutouts.ts
|
|
35088
|
-
var
|
|
34893
|
+
var arePointsClockwise4 = (points) => {
|
|
35089
34894
|
let area = 0;
|
|
35090
34895
|
for (let i = 0; i < points.length; i++) {
|
|
35091
34896
|
const j = (i + 1) % points.length;
|
|
@@ -35161,7 +34966,7 @@ function processCutoutsForManifold(Manifold, CrossSection, circuitJson, pcbThick
|
|
|
35161
34966
|
p.x,
|
|
35162
34967
|
p.y
|
|
35163
34968
|
]);
|
|
35164
|
-
if (
|
|
34969
|
+
if (arePointsClockwise4(pointsVec2)) {
|
|
35165
34970
|
pointsVec2 = pointsVec2.reverse();
|
|
35166
34971
|
}
|
|
35167
34972
|
const crossSection = CrossSection.ofPolygons([pointsVec2]);
|
|
@@ -35296,8 +35101,31 @@ function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, m
|
|
|
35296
35101
|
|
|
35297
35102
|
// src/utils/manifold/process-plated-holes.ts
|
|
35298
35103
|
import { su as su15 } from "@tscircuit/circuit-json-util";
|
|
35299
|
-
import * as
|
|
35300
|
-
|
|
35104
|
+
import * as THREE25 from "three";
|
|
35105
|
+
|
|
35106
|
+
// src/utils/manifold-mesh-to-three-geometry.ts
|
|
35107
|
+
import * as THREE24 from "three";
|
|
35108
|
+
function manifoldMeshToThreeGeometry(manifoldMesh) {
|
|
35109
|
+
const geometry = new THREE24.BufferGeometry();
|
|
35110
|
+
geometry.setAttribute(
|
|
35111
|
+
"position",
|
|
35112
|
+
new THREE24.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
|
|
35113
|
+
);
|
|
35114
|
+
geometry.setIndex(new THREE24.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
|
|
35115
|
+
if (manifoldMesh.runIndex && manifoldMesh.runIndex.length > 1 && manifoldMesh.runOriginalID) {
|
|
35116
|
+
for (let i = 0; i < manifoldMesh.runIndex.length - 1; i++) {
|
|
35117
|
+
const start = manifoldMesh.runIndex[i];
|
|
35118
|
+
const count3 = manifoldMesh.runIndex[i + 1] - start;
|
|
35119
|
+
geometry.addGroup(start, count3, 0);
|
|
35120
|
+
}
|
|
35121
|
+
} else {
|
|
35122
|
+
geometry.addGroup(0, manifoldMesh.triVerts.length, 0);
|
|
35123
|
+
}
|
|
35124
|
+
return geometry;
|
|
35125
|
+
}
|
|
35126
|
+
|
|
35127
|
+
// src/utils/manifold/process-plated-holes.ts
|
|
35128
|
+
var arePointsClockwise5 = (points) => {
|
|
35301
35129
|
let area = 0;
|
|
35302
35130
|
for (let i = 0; i < points.length; i++) {
|
|
35303
35131
|
const j = (i + 1) % points.length;
|
|
@@ -35317,7 +35145,7 @@ var createEllipsePoints = (width10, height10, segments) => {
|
|
|
35317
35145
|
}
|
|
35318
35146
|
return points;
|
|
35319
35147
|
};
|
|
35320
|
-
var COPPER_COLOR = new
|
|
35148
|
+
var COPPER_COLOR = new THREE25.Color(...colors.copper);
|
|
35321
35149
|
var PLATED_HOLE_LIP_HEIGHT = 0.05;
|
|
35322
35150
|
function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
|
|
35323
35151
|
const platedHoleBoardDrills = [];
|
|
@@ -35344,7 +35172,7 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
|
|
|
35344
35172
|
point2.x,
|
|
35345
35173
|
point2.y
|
|
35346
35174
|
]);
|
|
35347
|
-
if (
|
|
35175
|
+
if (arePointsClockwise5(points)) {
|
|
35348
35176
|
points = points.reverse();
|
|
35349
35177
|
}
|
|
35350
35178
|
const crossSection = CrossSection.ofPolygons([points]);
|
|
@@ -35389,7 +35217,7 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
|
|
|
35389
35217
|
const height10 = Math.max(baseHeight + sizeDelta, M);
|
|
35390
35218
|
if (holeShape === "oval") {
|
|
35391
35219
|
let points = createEllipsePoints(width10, height10, SMOOTH_CIRCLE_SEGMENTS);
|
|
35392
|
-
if (
|
|
35220
|
+
if (arePointsClockwise5(points)) {
|
|
35393
35221
|
points = points.reverse();
|
|
35394
35222
|
}
|
|
35395
35223
|
const crossSection = CrossSection.ofPolygons([points]);
|
|
@@ -35704,7 +35532,7 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
|
|
|
35704
35532
|
drillH,
|
|
35705
35533
|
SMOOTH_CIRCLE_SEGMENTS
|
|
35706
35534
|
);
|
|
35707
|
-
if (
|
|
35535
|
+
if (arePointsClockwise5(boardDrillPoints)) {
|
|
35708
35536
|
boardDrillPoints = boardDrillPoints.reverse();
|
|
35709
35537
|
}
|
|
35710
35538
|
const boardDrillCrossSection = CrossSection.ofPolygons([boardDrillPoints]);
|
|
@@ -35732,7 +35560,7 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
|
|
|
35732
35560
|
outerH,
|
|
35733
35561
|
SMOOTH_CIRCLE_SEGMENTS
|
|
35734
35562
|
);
|
|
35735
|
-
if (
|
|
35563
|
+
if (arePointsClockwise5(outerPoints)) {
|
|
35736
35564
|
outerPoints = outerPoints.reverse();
|
|
35737
35565
|
}
|
|
35738
35566
|
const outerCrossSection = CrossSection.ofPolygons([outerPoints]);
|
|
@@ -35751,7 +35579,7 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
|
|
|
35751
35579
|
holeH,
|
|
35752
35580
|
SMOOTH_CIRCLE_SEGMENTS
|
|
35753
35581
|
);
|
|
35754
|
-
if (
|
|
35582
|
+
if (arePointsClockwise5(innerPoints)) {
|
|
35755
35583
|
innerPoints = innerPoints.reverse();
|
|
35756
35584
|
}
|
|
35757
35585
|
const innerCrossSection = CrossSection.ofPolygons([innerPoints]);
|
|
@@ -35891,8 +35719,8 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
|
|
|
35891
35719
|
|
|
35892
35720
|
// src/utils/manifold/process-smt-pads.ts
|
|
35893
35721
|
import { su as su16 } from "@tscircuit/circuit-json-util";
|
|
35894
|
-
import * as
|
|
35895
|
-
var COPPER_COLOR2 = new
|
|
35722
|
+
import * as THREE26 from "three";
|
|
35723
|
+
var COPPER_COLOR2 = new THREE26.Color(...colors.copper);
|
|
35896
35724
|
function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, holeUnion, boardClipVolume) {
|
|
35897
35725
|
const smtPadGeoms = [];
|
|
35898
35726
|
const smtPads = su16(circuitJson).pcb_smtpad.list();
|
|
@@ -35931,7 +35759,7 @@ function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifold
|
|
|
35931
35759
|
|
|
35932
35760
|
// src/utils/manifold/process-vias.ts
|
|
35933
35761
|
import { su as su17 } from "@tscircuit/circuit-json-util";
|
|
35934
|
-
import * as
|
|
35762
|
+
import * as THREE27 from "three";
|
|
35935
35763
|
|
|
35936
35764
|
// src/utils/via-geoms.ts
|
|
35937
35765
|
function createViaCopper2({
|
|
@@ -35984,7 +35812,7 @@ function createViaCopper2({
|
|
|
35984
35812
|
}
|
|
35985
35813
|
|
|
35986
35814
|
// src/utils/manifold/process-vias.ts
|
|
35987
|
-
var COPPER_COLOR3 = new
|
|
35815
|
+
var COPPER_COLOR3 = new THREE27.Color(...colors.copper);
|
|
35988
35816
|
function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
|
|
35989
35817
|
const viaBoardDrills = [];
|
|
35990
35818
|
const pcbVias = su17(circuitJson).pcb_via.list();
|
|
@@ -36035,6 +35863,397 @@ function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldIns
|
|
|
36035
35863
|
return { viaBoardDrills, viaCopperGeoms };
|
|
36036
35864
|
}
|
|
36037
35865
|
|
|
35866
|
+
// src/textures/create-copper-pour-texture-for-layer.ts
|
|
35867
|
+
import * as THREE28 from "three";
|
|
35868
|
+
import { CircuitToCanvasDrawer } from "circuit-to-canvas";
|
|
35869
|
+
function drawPolygon({
|
|
35870
|
+
ctx,
|
|
35871
|
+
points,
|
|
35872
|
+
canvasXFromPcb,
|
|
35873
|
+
canvasYFromPcb
|
|
35874
|
+
}) {
|
|
35875
|
+
if (points.length < 3) return;
|
|
35876
|
+
ctx.beginPath();
|
|
35877
|
+
points.forEach((point2, index2) => {
|
|
35878
|
+
const canvasX = canvasXFromPcb(point2[0]);
|
|
35879
|
+
const canvasY = canvasYFromPcb(point2[1]);
|
|
35880
|
+
if (index2 === 0) {
|
|
35881
|
+
ctx.moveTo(canvasX, canvasY);
|
|
35882
|
+
} else {
|
|
35883
|
+
ctx.lineTo(canvasX, canvasY);
|
|
35884
|
+
}
|
|
35885
|
+
});
|
|
35886
|
+
ctx.closePath();
|
|
35887
|
+
ctx.fill();
|
|
35888
|
+
}
|
|
35889
|
+
function drawBrepShape({
|
|
35890
|
+
ctx,
|
|
35891
|
+
pour,
|
|
35892
|
+
canvasXFromPcb,
|
|
35893
|
+
canvasYFromPcb
|
|
35894
|
+
}) {
|
|
35895
|
+
const brepShape = pour.brep_shape;
|
|
35896
|
+
if (!brepShape || !brepShape.outer_ring) return;
|
|
35897
|
+
const outerRingPoints = ringToPoints(brepShape.outer_ring, 32);
|
|
35898
|
+
if (outerRingPoints.length >= 3) {
|
|
35899
|
+
drawPolygon({
|
|
35900
|
+
ctx,
|
|
35901
|
+
points: outerRingPoints,
|
|
35902
|
+
canvasXFromPcb,
|
|
35903
|
+
canvasYFromPcb
|
|
35904
|
+
});
|
|
35905
|
+
}
|
|
35906
|
+
if (brepShape.inner_rings && brepShape.inner_rings.length > 0) {
|
|
35907
|
+
ctx.globalCompositeOperation = "destination-out";
|
|
35908
|
+
for (const innerRing of brepShape.inner_rings) {
|
|
35909
|
+
const innerRingPoints = ringToPoints(innerRing, 32);
|
|
35910
|
+
if (innerRingPoints.length >= 3) {
|
|
35911
|
+
drawPolygon({
|
|
35912
|
+
ctx,
|
|
35913
|
+
points: innerRingPoints,
|
|
35914
|
+
canvasXFromPcb,
|
|
35915
|
+
canvasYFromPcb
|
|
35916
|
+
});
|
|
35917
|
+
}
|
|
35918
|
+
}
|
|
35919
|
+
ctx.globalCompositeOperation = "source-over";
|
|
35920
|
+
}
|
|
35921
|
+
}
|
|
35922
|
+
function createCopperPourTextureForLayer({
|
|
35923
|
+
layer,
|
|
35924
|
+
circuitJson,
|
|
35925
|
+
boardData,
|
|
35926
|
+
traceTextureResolution = TRACE_TEXTURE_RESOLUTION
|
|
35927
|
+
}) {
|
|
35928
|
+
const copperPours = circuitJson.filter(
|
|
35929
|
+
(e) => e.type === "pcb_copper_pour"
|
|
35930
|
+
);
|
|
35931
|
+
const poursOnLayer = copperPours.filter((p) => p.layer === layer);
|
|
35932
|
+
if (poursOnLayer.length === 0) return null;
|
|
35933
|
+
const boardOutlineBounds = calculateOutlineBounds(boardData);
|
|
35934
|
+
const canvas = document.createElement("canvas");
|
|
35935
|
+
const canvasWidth = Math.floor(
|
|
35936
|
+
boardOutlineBounds.width * traceTextureResolution
|
|
35937
|
+
);
|
|
35938
|
+
const canvasHeight = Math.floor(
|
|
35939
|
+
boardOutlineBounds.height * traceTextureResolution
|
|
35940
|
+
);
|
|
35941
|
+
canvas.width = canvasWidth;
|
|
35942
|
+
canvas.height = canvasHeight;
|
|
35943
|
+
const ctx = canvas.getContext("2d");
|
|
35944
|
+
if (!ctx) return null;
|
|
35945
|
+
if (layer === "bottom") {
|
|
35946
|
+
ctx.translate(0, canvasHeight);
|
|
35947
|
+
ctx.scale(1, -1);
|
|
35948
|
+
}
|
|
35949
|
+
const canvasXFromPcb = (pcbX) => (pcbX - boardOutlineBounds.minX) * traceTextureResolution;
|
|
35950
|
+
const canvasYFromPcb = (pcbY) => (boardOutlineBounds.maxY - pcbY) * traceTextureResolution;
|
|
35951
|
+
const rectAndPolygonPours = poursOnLayer.filter(
|
|
35952
|
+
(pour) => pour.shape === "rect" || pour.shape === "polygon"
|
|
35953
|
+
);
|
|
35954
|
+
const brepPours = poursOnLayer.filter((pour) => pour.shape === "brep");
|
|
35955
|
+
if (rectAndPolygonPours.length > 0) {
|
|
35956
|
+
const drawer = new CircuitToCanvasDrawer(ctx);
|
|
35957
|
+
drawer.setCameraBounds({
|
|
35958
|
+
minX: boardOutlineBounds.minX,
|
|
35959
|
+
maxX: boardOutlineBounds.maxX,
|
|
35960
|
+
minY: boardOutlineBounds.minY,
|
|
35961
|
+
maxY: boardOutlineBounds.maxY
|
|
35962
|
+
});
|
|
35963
|
+
const coveredPours = rectAndPolygonPours.filter(
|
|
35964
|
+
(p) => p.covered_with_solder_mask !== false
|
|
35965
|
+
);
|
|
35966
|
+
const uncoveredPours = rectAndPolygonPours.filter(
|
|
35967
|
+
(p) => p.covered_with_solder_mask === false
|
|
35968
|
+
);
|
|
35969
|
+
const coveredColor = `rgb(${colors.fr4TracesWithMaskGreen.map((c) => c * 255).join(",")})`;
|
|
35970
|
+
const uncoveredColor = `rgb(${colors.copper.map((c) => c * 255).join(",")})`;
|
|
35971
|
+
if (coveredPours.length > 0) {
|
|
35972
|
+
drawer.configure({
|
|
35973
|
+
colorOverrides: {
|
|
35974
|
+
copper: {
|
|
35975
|
+
top: coveredColor,
|
|
35976
|
+
bottom: coveredColor,
|
|
35977
|
+
inner1: coveredColor,
|
|
35978
|
+
inner2: coveredColor,
|
|
35979
|
+
inner3: coveredColor,
|
|
35980
|
+
inner4: coveredColor,
|
|
35981
|
+
inner5: coveredColor,
|
|
35982
|
+
inner6: coveredColor
|
|
35983
|
+
}
|
|
35984
|
+
}
|
|
35985
|
+
});
|
|
35986
|
+
drawer.drawElements(coveredPours, { layers: [layer] });
|
|
35987
|
+
}
|
|
35988
|
+
if (uncoveredPours.length > 0) {
|
|
35989
|
+
drawer.configure({
|
|
35990
|
+
colorOverrides: {
|
|
35991
|
+
copper: {
|
|
35992
|
+
top: uncoveredColor,
|
|
35993
|
+
bottom: uncoveredColor,
|
|
35994
|
+
inner1: uncoveredColor,
|
|
35995
|
+
inner2: uncoveredColor,
|
|
35996
|
+
inner3: uncoveredColor,
|
|
35997
|
+
inner4: uncoveredColor,
|
|
35998
|
+
inner5: uncoveredColor,
|
|
35999
|
+
inner6: uncoveredColor
|
|
36000
|
+
}
|
|
36001
|
+
}
|
|
36002
|
+
});
|
|
36003
|
+
drawer.drawElements(uncoveredPours, { layers: [layer] });
|
|
36004
|
+
}
|
|
36005
|
+
}
|
|
36006
|
+
for (const pour of brepPours) {
|
|
36007
|
+
const covered = pour.covered_with_solder_mask !== false;
|
|
36008
|
+
const colorArr = covered ? colors.fr4TracesWithMaskGreen : colors.copper;
|
|
36009
|
+
const copperColor = `rgb(${colorArr[0] * 255}, ${colorArr[1] * 255}, ${colorArr[2] * 255})`;
|
|
36010
|
+
ctx.fillStyle = copperColor;
|
|
36011
|
+
drawBrepShape({ ctx, pour, canvasXFromPcb, canvasYFromPcb });
|
|
36012
|
+
}
|
|
36013
|
+
const texture = new THREE28.CanvasTexture(canvas);
|
|
36014
|
+
texture.generateMipmaps = true;
|
|
36015
|
+
texture.minFilter = THREE28.LinearMipmapLinearFilter;
|
|
36016
|
+
texture.magFilter = THREE28.LinearFilter;
|
|
36017
|
+
texture.anisotropy = 16;
|
|
36018
|
+
texture.needsUpdate = true;
|
|
36019
|
+
return texture;
|
|
36020
|
+
}
|
|
36021
|
+
|
|
36022
|
+
// src/textures/create-three-texture-meshes.ts
|
|
36023
|
+
import * as THREE29 from "three";
|
|
36024
|
+
function createTexturePlane(config, boardData) {
|
|
36025
|
+
const {
|
|
36026
|
+
texture,
|
|
36027
|
+
yOffset,
|
|
36028
|
+
isBottomLayer,
|
|
36029
|
+
textureType,
|
|
36030
|
+
usePolygonOffset = false,
|
|
36031
|
+
renderOrder = 0
|
|
36032
|
+
} = config;
|
|
36033
|
+
if (!texture) return null;
|
|
36034
|
+
const boardOutlineBounds = calculateOutlineBounds(boardData);
|
|
36035
|
+
const planeGeom = new THREE29.PlaneGeometry(
|
|
36036
|
+
boardOutlineBounds.width,
|
|
36037
|
+
boardOutlineBounds.height
|
|
36038
|
+
);
|
|
36039
|
+
const material = new THREE29.MeshBasicMaterial({
|
|
36040
|
+
map: texture,
|
|
36041
|
+
transparent: true,
|
|
36042
|
+
side: THREE29.DoubleSide,
|
|
36043
|
+
depthWrite: textureType === "panel-outlines",
|
|
36044
|
+
polygonOffset: usePolygonOffset,
|
|
36045
|
+
polygonOffsetFactor: usePolygonOffset ? -4 : 0,
|
|
36046
|
+
// Increased for better z-fighting prevention
|
|
36047
|
+
polygonOffsetUnits: usePolygonOffset ? -4 : 0
|
|
36048
|
+
});
|
|
36049
|
+
const mesh = new THREE29.Mesh(planeGeom, material);
|
|
36050
|
+
mesh.position.set(
|
|
36051
|
+
boardOutlineBounds.centerX,
|
|
36052
|
+
boardOutlineBounds.centerY,
|
|
36053
|
+
yOffset
|
|
36054
|
+
);
|
|
36055
|
+
if (isBottomLayer) {
|
|
36056
|
+
mesh.rotation.set(Math.PI, 0, 0);
|
|
36057
|
+
}
|
|
36058
|
+
mesh.name = `${isBottomLayer ? "bottom" : "top"}-${textureType}-texture-plane`;
|
|
36059
|
+
mesh.renderOrder = renderOrder;
|
|
36060
|
+
return mesh;
|
|
36061
|
+
}
|
|
36062
|
+
function createTextureMeshes(textures, boardData, pcbThickness) {
|
|
36063
|
+
const meshes = [];
|
|
36064
|
+
if (!textures || !boardData || pcbThickness === null) return meshes;
|
|
36065
|
+
const topTraceMesh = createTexturePlane(
|
|
36066
|
+
{
|
|
36067
|
+
texture: textures.topTrace,
|
|
36068
|
+
yOffset: pcbThickness / 2 + BOARD_SURFACE_OFFSET.traces,
|
|
36069
|
+
// Use consistent copper offset
|
|
36070
|
+
isBottomLayer: false,
|
|
36071
|
+
textureType: "trace",
|
|
36072
|
+
usePolygonOffset: false,
|
|
36073
|
+
renderOrder: 2
|
|
36074
|
+
// Render after soldermask
|
|
36075
|
+
},
|
|
36076
|
+
boardData
|
|
36077
|
+
);
|
|
36078
|
+
if (topTraceMesh) meshes.push(topTraceMesh);
|
|
36079
|
+
const topTraceWithMaskMesh = createTexturePlane(
|
|
36080
|
+
{
|
|
36081
|
+
texture: textures.topTraceWithMask,
|
|
36082
|
+
yOffset: pcbThickness / 2 + BOARD_SURFACE_OFFSET.traces,
|
|
36083
|
+
isBottomLayer: false,
|
|
36084
|
+
textureType: "trace-with-mask",
|
|
36085
|
+
usePolygonOffset: false,
|
|
36086
|
+
renderOrder: 2
|
|
36087
|
+
// Render after soldermask
|
|
36088
|
+
},
|
|
36089
|
+
boardData
|
|
36090
|
+
);
|
|
36091
|
+
if (topTraceWithMaskMesh) meshes.push(topTraceWithMaskMesh);
|
|
36092
|
+
const topSilkscreenMesh = createTexturePlane(
|
|
36093
|
+
{
|
|
36094
|
+
texture: textures.topSilkscreen,
|
|
36095
|
+
yOffset: pcbThickness / 2 + 3e-3,
|
|
36096
|
+
// Slightly above soldermask
|
|
36097
|
+
isBottomLayer: false,
|
|
36098
|
+
textureType: "silkscreen",
|
|
36099
|
+
usePolygonOffset: false,
|
|
36100
|
+
renderOrder: 3
|
|
36101
|
+
// Render after traces
|
|
36102
|
+
},
|
|
36103
|
+
boardData
|
|
36104
|
+
);
|
|
36105
|
+
if (topSilkscreenMesh) meshes.push(topSilkscreenMesh);
|
|
36106
|
+
const bottomTraceMesh = createTexturePlane(
|
|
36107
|
+
{
|
|
36108
|
+
texture: textures.bottomTrace,
|
|
36109
|
+
yOffset: -pcbThickness / 2 - BOARD_SURFACE_OFFSET.traces,
|
|
36110
|
+
// Use consistent copper offset
|
|
36111
|
+
isBottomLayer: true,
|
|
36112
|
+
textureType: "trace",
|
|
36113
|
+
usePolygonOffset: false,
|
|
36114
|
+
renderOrder: 2
|
|
36115
|
+
// Render after soldermask
|
|
36116
|
+
},
|
|
36117
|
+
boardData
|
|
36118
|
+
);
|
|
36119
|
+
if (bottomTraceMesh) meshes.push(bottomTraceMesh);
|
|
36120
|
+
const bottomTraceWithMaskMesh = createTexturePlane(
|
|
36121
|
+
{
|
|
36122
|
+
texture: textures.bottomTraceWithMask,
|
|
36123
|
+
yOffset: -pcbThickness / 2 - BOARD_SURFACE_OFFSET.traces,
|
|
36124
|
+
isBottomLayer: true,
|
|
36125
|
+
textureType: "trace-with-mask",
|
|
36126
|
+
usePolygonOffset: false,
|
|
36127
|
+
renderOrder: 2
|
|
36128
|
+
// Render after soldermask
|
|
36129
|
+
},
|
|
36130
|
+
boardData
|
|
36131
|
+
);
|
|
36132
|
+
if (bottomTraceWithMaskMesh) meshes.push(bottomTraceWithMaskMesh);
|
|
36133
|
+
const bottomSilkscreenMesh = createTexturePlane(
|
|
36134
|
+
{
|
|
36135
|
+
texture: textures.bottomSilkscreen,
|
|
36136
|
+
yOffset: -pcbThickness / 2 - 3e-3,
|
|
36137
|
+
isBottomLayer: true,
|
|
36138
|
+
textureType: "silkscreen",
|
|
36139
|
+
usePolygonOffset: false,
|
|
36140
|
+
renderOrder: 3
|
|
36141
|
+
// Render after traces
|
|
36142
|
+
},
|
|
36143
|
+
boardData
|
|
36144
|
+
);
|
|
36145
|
+
if (bottomSilkscreenMesh) meshes.push(bottomSilkscreenMesh);
|
|
36146
|
+
const topSoldermaskMesh = createTexturePlane(
|
|
36147
|
+
{
|
|
36148
|
+
texture: textures.topSoldermask,
|
|
36149
|
+
yOffset: pcbThickness / 2 + 1e-3,
|
|
36150
|
+
// Just above board surface
|
|
36151
|
+
isBottomLayer: false,
|
|
36152
|
+
textureType: "soldermask",
|
|
36153
|
+
usePolygonOffset: true,
|
|
36154
|
+
// Enable polygon offset
|
|
36155
|
+
renderOrder: 1
|
|
36156
|
+
// Render after board (renderOrder)
|
|
36157
|
+
},
|
|
36158
|
+
boardData
|
|
36159
|
+
);
|
|
36160
|
+
if (topSoldermaskMesh) meshes.push(topSoldermaskMesh);
|
|
36161
|
+
const bottomSoldermaskMesh = createTexturePlane(
|
|
36162
|
+
{
|
|
36163
|
+
texture: textures.bottomSoldermask,
|
|
36164
|
+
yOffset: -pcbThickness / 2 - 1e-3,
|
|
36165
|
+
// Just below board surface (bottom side)
|
|
36166
|
+
isBottomLayer: true,
|
|
36167
|
+
textureType: "soldermask",
|
|
36168
|
+
usePolygonOffset: true,
|
|
36169
|
+
// Enable polygon offset
|
|
36170
|
+
renderOrder: 1
|
|
36171
|
+
// Render after board (renderOrder)
|
|
36172
|
+
},
|
|
36173
|
+
boardData
|
|
36174
|
+
);
|
|
36175
|
+
if (bottomSoldermaskMesh) meshes.push(bottomSoldermaskMesh);
|
|
36176
|
+
const topCopperTextMesh = createTexturePlane(
|
|
36177
|
+
{
|
|
36178
|
+
texture: textures.topCopperText,
|
|
36179
|
+
yOffset: pcbThickness / 2 + BOARD_SURFACE_OFFSET.copper,
|
|
36180
|
+
isBottomLayer: false,
|
|
36181
|
+
textureType: "copper-text",
|
|
36182
|
+
usePolygonOffset: false,
|
|
36183
|
+
renderOrder: 2
|
|
36184
|
+
// Render after soldermask
|
|
36185
|
+
},
|
|
36186
|
+
boardData
|
|
36187
|
+
);
|
|
36188
|
+
if (topCopperTextMesh) meshes.push(topCopperTextMesh);
|
|
36189
|
+
const bottomCopperTextMesh = createTexturePlane(
|
|
36190
|
+
{
|
|
36191
|
+
texture: textures.bottomCopperText,
|
|
36192
|
+
yOffset: -pcbThickness / 2 - BOARD_SURFACE_OFFSET.copper,
|
|
36193
|
+
isBottomLayer: true,
|
|
36194
|
+
textureType: "copper-text",
|
|
36195
|
+
usePolygonOffset: false,
|
|
36196
|
+
renderOrder: 2
|
|
36197
|
+
// Render after soldermask
|
|
36198
|
+
},
|
|
36199
|
+
boardData
|
|
36200
|
+
);
|
|
36201
|
+
if (bottomCopperTextMesh) meshes.push(bottomCopperTextMesh);
|
|
36202
|
+
const topCopperMesh = createTexturePlane(
|
|
36203
|
+
{
|
|
36204
|
+
texture: textures.topCopper,
|
|
36205
|
+
yOffset: pcbThickness / 2 + BOARD_SURFACE_OFFSET.copper,
|
|
36206
|
+
isBottomLayer: false,
|
|
36207
|
+
textureType: "copper",
|
|
36208
|
+
usePolygonOffset: false,
|
|
36209
|
+
renderOrder: 2
|
|
36210
|
+
// Render after soldermask
|
|
36211
|
+
},
|
|
36212
|
+
boardData
|
|
36213
|
+
);
|
|
36214
|
+
if (topCopperMesh) meshes.push(topCopperMesh);
|
|
36215
|
+
const bottomCopperMesh = createTexturePlane(
|
|
36216
|
+
{
|
|
36217
|
+
texture: textures.bottomCopper,
|
|
36218
|
+
yOffset: -pcbThickness / 2 - BOARD_SURFACE_OFFSET.copper,
|
|
36219
|
+
isBottomLayer: true,
|
|
36220
|
+
textureType: "copper",
|
|
36221
|
+
usePolygonOffset: false,
|
|
36222
|
+
renderOrder: 2
|
|
36223
|
+
// Render after soldermask
|
|
36224
|
+
},
|
|
36225
|
+
boardData
|
|
36226
|
+
);
|
|
36227
|
+
if (bottomCopperMesh) meshes.push(bottomCopperMesh);
|
|
36228
|
+
const topPanelOutlinesMesh = createTexturePlane(
|
|
36229
|
+
{
|
|
36230
|
+
texture: textures.topPanelOutlines,
|
|
36231
|
+
yOffset: pcbThickness / 2 + 4e-3,
|
|
36232
|
+
// Above silkscreen
|
|
36233
|
+
isBottomLayer: false,
|
|
36234
|
+
textureType: "panel-outlines",
|
|
36235
|
+
usePolygonOffset: false,
|
|
36236
|
+
renderOrder: 4
|
|
36237
|
+
},
|
|
36238
|
+
boardData
|
|
36239
|
+
);
|
|
36240
|
+
if (topPanelOutlinesMesh) meshes.push(topPanelOutlinesMesh);
|
|
36241
|
+
const bottomPanelOutlinesMesh = createTexturePlane(
|
|
36242
|
+
{
|
|
36243
|
+
texture: textures.bottomPanelOutlines,
|
|
36244
|
+
yOffset: -pcbThickness / 2 - 4e-3,
|
|
36245
|
+
// Below bottom silkscreen
|
|
36246
|
+
isBottomLayer: true,
|
|
36247
|
+
textureType: "panel-outlines",
|
|
36248
|
+
usePolygonOffset: false,
|
|
36249
|
+
renderOrder: 4
|
|
36250
|
+
},
|
|
36251
|
+
boardData
|
|
36252
|
+
);
|
|
36253
|
+
if (bottomPanelOutlinesMesh) meshes.push(bottomPanelOutlinesMesh);
|
|
36254
|
+
return meshes;
|
|
36255
|
+
}
|
|
36256
|
+
|
|
36038
36257
|
// src/hooks/useManifoldBoardBuilder.ts
|
|
36039
36258
|
var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
36040
36259
|
const [geoms, setGeoms] = useState14(null);
|
|
@@ -36104,7 +36323,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
36104
36323
|
manifoldInstancesForCleanup.current = [];
|
|
36105
36324
|
let boardManifold = null;
|
|
36106
36325
|
const currentGeoms = {};
|
|
36107
|
-
const
|
|
36326
|
+
const layerTextureMap = {};
|
|
36108
36327
|
try {
|
|
36109
36328
|
const currentPcbThickness = boardData.thickness || 1.6;
|
|
36110
36329
|
setPcbThickness(currentPcbThickness);
|
|
@@ -36203,7 +36422,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
36203
36422
|
{
|
|
36204
36423
|
key: "plated-holes-union",
|
|
36205
36424
|
geometry: cutPlatedGeom,
|
|
36206
|
-
color: new
|
|
36425
|
+
color: new THREE30.Color(
|
|
36207
36426
|
colors.copper[0],
|
|
36208
36427
|
colors.copper[1],
|
|
36209
36428
|
colors.copper[2]
|
|
@@ -36233,7 +36452,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
36233
36452
|
const matColorArray = boardMaterialColors[boardData.material] ?? colors.fr4Tan;
|
|
36234
36453
|
currentGeoms.board = {
|
|
36235
36454
|
geometry: finalBoardGeom,
|
|
36236
|
-
color: new
|
|
36455
|
+
color: new THREE30.Color(
|
|
36237
36456
|
matColorArray[0],
|
|
36238
36457
|
matColorArray[1],
|
|
36239
36458
|
matColorArray[2]
|
|
@@ -36251,28 +36470,17 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
36251
36470
|
boardClipVolume
|
|
36252
36471
|
);
|
|
36253
36472
|
currentGeoms.smtPads = smtPadGeoms;
|
|
36254
|
-
const { copperPourGeoms } = processCopperPoursForManifold(
|
|
36255
|
-
Manifold,
|
|
36256
|
-
CrossSection,
|
|
36257
|
-
circuitJson,
|
|
36258
|
-
currentPcbThickness,
|
|
36259
|
-
manifoldInstancesForCleanup.current,
|
|
36260
|
-
boardData.material,
|
|
36261
|
-
holeUnion,
|
|
36262
|
-
boardClipVolume
|
|
36263
|
-
);
|
|
36264
|
-
currentGeoms.copperPours = copperPourGeoms;
|
|
36265
36473
|
setGeoms(currentGeoms);
|
|
36266
36474
|
const traceColorWithoutMaskArr = colors.fr4TracesWithoutMaskTan;
|
|
36267
36475
|
const traceColorWithoutMask = `rgb(${Math.round(traceColorWithoutMaskArr[0] * 255)}, ${Math.round(traceColorWithoutMaskArr[1] * 255)}, ${Math.round(traceColorWithoutMaskArr[2] * 255)})`;
|
|
36268
|
-
|
|
36476
|
+
layerTextureMap.topTrace = createTraceTextureForLayer({
|
|
36269
36477
|
layer: "top",
|
|
36270
36478
|
circuitJson,
|
|
36271
36479
|
boardData,
|
|
36272
36480
|
traceColor: traceColorWithoutMask,
|
|
36273
36481
|
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
36274
36482
|
});
|
|
36275
|
-
|
|
36483
|
+
layerTextureMap.bottomTrace = createTraceTextureForLayer({
|
|
36276
36484
|
layer: "bottom",
|
|
36277
36485
|
circuitJson,
|
|
36278
36486
|
boardData,
|
|
@@ -36281,14 +36489,14 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
36281
36489
|
});
|
|
36282
36490
|
const traceColorWithMaskArr = colors.fr4TracesWithMaskGreen;
|
|
36283
36491
|
const traceColorWithMask = `rgb(${Math.round(traceColorWithMaskArr[0] * 255)}, ${Math.round(traceColorWithMaskArr[1] * 255)}, ${Math.round(traceColorWithMaskArr[2] * 255)})`;
|
|
36284
|
-
|
|
36492
|
+
layerTextureMap.topTraceWithMask = createTraceTextureForLayer({
|
|
36285
36493
|
layer: "top",
|
|
36286
36494
|
circuitJson,
|
|
36287
36495
|
boardData,
|
|
36288
36496
|
traceColor: traceColorWithMask,
|
|
36289
36497
|
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
36290
36498
|
});
|
|
36291
|
-
|
|
36499
|
+
layerTextureMap.bottomTraceWithMask = createTraceTextureForLayer({
|
|
36292
36500
|
layer: "bottom",
|
|
36293
36501
|
circuitJson,
|
|
36294
36502
|
boardData,
|
|
@@ -36296,14 +36504,14 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
36296
36504
|
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
36297
36505
|
});
|
|
36298
36506
|
const silkscreenColor = "rgb(255,255,255)";
|
|
36299
|
-
|
|
36507
|
+
layerTextureMap.topSilkscreen = createSilkscreenTextureForLayer({
|
|
36300
36508
|
layer: "top",
|
|
36301
36509
|
circuitJson,
|
|
36302
36510
|
boardData,
|
|
36303
36511
|
silkscreenColor,
|
|
36304
36512
|
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
36305
36513
|
});
|
|
36306
|
-
|
|
36514
|
+
layerTextureMap.bottomSilkscreen = createSilkscreenTextureForLayer({
|
|
36307
36515
|
layer: "bottom",
|
|
36308
36516
|
circuitJson,
|
|
36309
36517
|
boardData,
|
|
@@ -36312,14 +36520,14 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
36312
36520
|
});
|
|
36313
36521
|
const soldermaskColorArr = soldermaskColors[boardData.material] ?? colors.fr4SolderMaskGreen;
|
|
36314
36522
|
const soldermaskColor = `rgb(${Math.round(soldermaskColorArr[0] * 255)}, ${Math.round(soldermaskColorArr[1] * 255)}, ${Math.round(soldermaskColorArr[2] * 255)})`;
|
|
36315
|
-
|
|
36523
|
+
layerTextureMap.topSoldermask = createSoldermaskTextureForLayer({
|
|
36316
36524
|
layer: "top",
|
|
36317
36525
|
circuitJson,
|
|
36318
36526
|
boardData,
|
|
36319
36527
|
soldermaskColor,
|
|
36320
36528
|
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
36321
36529
|
});
|
|
36322
|
-
|
|
36530
|
+
layerTextureMap.bottomSoldermask = createSoldermaskTextureForLayer({
|
|
36323
36531
|
layer: "bottom",
|
|
36324
36532
|
circuitJson,
|
|
36325
36533
|
boardData,
|
|
@@ -36328,33 +36536,45 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
36328
36536
|
});
|
|
36329
36537
|
const copperColorArr = colors.copper;
|
|
36330
36538
|
const copperColor = `rgb(${Math.round(copperColorArr[0] * 255)}, ${Math.round(copperColorArr[1] * 255)}, ${Math.round(copperColorArr[2] * 255)})`;
|
|
36331
|
-
|
|
36539
|
+
layerTextureMap.topCopperText = createCopperTextTextureForLayer({
|
|
36332
36540
|
layer: "top",
|
|
36333
36541
|
circuitJson,
|
|
36334
36542
|
boardData,
|
|
36335
36543
|
copperColor,
|
|
36336
36544
|
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
36337
36545
|
});
|
|
36338
|
-
|
|
36546
|
+
layerTextureMap.bottomCopperText = createCopperTextTextureForLayer({
|
|
36339
36547
|
layer: "bottom",
|
|
36340
36548
|
circuitJson,
|
|
36341
36549
|
boardData,
|
|
36342
36550
|
copperColor,
|
|
36343
36551
|
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
36344
36552
|
});
|
|
36345
|
-
|
|
36553
|
+
layerTextureMap.topPanelOutlines = createPanelOutlineTextureForLayer({
|
|
36346
36554
|
layer: "top",
|
|
36347
36555
|
circuitJson,
|
|
36348
36556
|
panelData: boardData,
|
|
36349
36557
|
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
36350
36558
|
});
|
|
36351
|
-
|
|
36559
|
+
layerTextureMap.bottomPanelOutlines = createPanelOutlineTextureForLayer({
|
|
36352
36560
|
layer: "bottom",
|
|
36353
36561
|
circuitJson,
|
|
36354
36562
|
panelData: boardData,
|
|
36355
36563
|
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
36356
36564
|
});
|
|
36357
|
-
|
|
36565
|
+
layerTextureMap.topCopper = createCopperPourTextureForLayer({
|
|
36566
|
+
layer: "top",
|
|
36567
|
+
circuitJson,
|
|
36568
|
+
boardData,
|
|
36569
|
+
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
36570
|
+
});
|
|
36571
|
+
layerTextureMap.bottomCopper = createCopperPourTextureForLayer({
|
|
36572
|
+
layer: "bottom",
|
|
36573
|
+
circuitJson,
|
|
36574
|
+
boardData,
|
|
36575
|
+
traceTextureResolution: TRACE_TEXTURE_RESOLUTION
|
|
36576
|
+
});
|
|
36577
|
+
setTextures(layerTextureMap);
|
|
36358
36578
|
} catch (e) {
|
|
36359
36579
|
console.error("Error processing geometry with Manifold in hook:", e);
|
|
36360
36580
|
setError(
|
|
@@ -36382,11 +36602,11 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
36382
36602
|
};
|
|
36383
36603
|
|
|
36384
36604
|
// src/utils/manifold/create-three-geometry-meshes.ts
|
|
36385
|
-
import * as
|
|
36605
|
+
import * as THREE32 from "three";
|
|
36386
36606
|
|
|
36387
36607
|
// src/utils/create-board-material.ts
|
|
36388
|
-
import * as
|
|
36389
|
-
var DEFAULT_SIDE =
|
|
36608
|
+
import * as THREE31 from "three";
|
|
36609
|
+
var DEFAULT_SIDE = THREE31.DoubleSide;
|
|
36390
36610
|
var createBoardMaterial = ({
|
|
36391
36611
|
material,
|
|
36392
36612
|
color,
|
|
@@ -36394,7 +36614,7 @@ var createBoardMaterial = ({
|
|
|
36394
36614
|
isFaux = false
|
|
36395
36615
|
}) => {
|
|
36396
36616
|
if (material === "fr4") {
|
|
36397
|
-
return new
|
|
36617
|
+
return new THREE31.MeshPhysicalMaterial({
|
|
36398
36618
|
color,
|
|
36399
36619
|
side,
|
|
36400
36620
|
metalness: 0,
|
|
@@ -36408,7 +36628,7 @@ var createBoardMaterial = ({
|
|
|
36408
36628
|
flatShading: true
|
|
36409
36629
|
});
|
|
36410
36630
|
}
|
|
36411
|
-
return new
|
|
36631
|
+
return new THREE31.MeshStandardMaterial({
|
|
36412
36632
|
color,
|
|
36413
36633
|
side,
|
|
36414
36634
|
flatShading: true,
|
|
@@ -36424,12 +36644,12 @@ function createGeometryMeshes(geoms) {
|
|
|
36424
36644
|
const meshes = [];
|
|
36425
36645
|
if (!geoms) return meshes;
|
|
36426
36646
|
if (geoms.board && geoms.board.geometry) {
|
|
36427
|
-
const mesh = new
|
|
36647
|
+
const mesh = new THREE32.Mesh(
|
|
36428
36648
|
geoms.board.geometry,
|
|
36429
36649
|
createBoardMaterial({
|
|
36430
36650
|
material: geoms.board.material,
|
|
36431
36651
|
color: geoms.board.color,
|
|
36432
|
-
side:
|
|
36652
|
+
side: THREE32.DoubleSide,
|
|
36433
36653
|
isFaux: geoms.board.isFaux
|
|
36434
36654
|
})
|
|
36435
36655
|
);
|
|
@@ -36439,11 +36659,11 @@ function createGeometryMeshes(geoms) {
|
|
|
36439
36659
|
const createMeshesFromArray = (geomArray) => {
|
|
36440
36660
|
if (geomArray) {
|
|
36441
36661
|
geomArray.forEach((comp) => {
|
|
36442
|
-
const mesh = new
|
|
36662
|
+
const mesh = new THREE32.Mesh(
|
|
36443
36663
|
comp.geometry,
|
|
36444
|
-
new
|
|
36664
|
+
new THREE32.MeshStandardMaterial({
|
|
36445
36665
|
color: comp.color,
|
|
36446
|
-
side:
|
|
36666
|
+
side: THREE32.DoubleSide,
|
|
36447
36667
|
flatShading: true,
|
|
36448
36668
|
// Consistent with board
|
|
36449
36669
|
polygonOffset: true,
|
|
@@ -36459,172 +36679,6 @@ function createGeometryMeshes(geoms) {
|
|
|
36459
36679
|
createMeshesFromArray(geoms.platedHoles);
|
|
36460
36680
|
createMeshesFromArray(geoms.smtPads);
|
|
36461
36681
|
createMeshesFromArray(geoms.vias);
|
|
36462
|
-
createMeshesFromArray(geoms.copperPours);
|
|
36463
|
-
return meshes;
|
|
36464
|
-
}
|
|
36465
|
-
|
|
36466
|
-
// src/utils/manifold/create-three-texture-meshes.ts
|
|
36467
|
-
import * as THREE32 from "three";
|
|
36468
|
-
function createTextureMeshes(textures, boardData, pcbThickness) {
|
|
36469
|
-
const meshes = [];
|
|
36470
|
-
if (!textures || !boardData || pcbThickness === null) return meshes;
|
|
36471
|
-
const createTexturePlane = (texture, yOffset, isBottomLayer, keySuffix, usePolygonOffset = false, renderOrder = 0) => {
|
|
36472
|
-
if (!texture) return null;
|
|
36473
|
-
const boardOutlineBounds = calculateOutlineBounds(boardData);
|
|
36474
|
-
const planeGeom = new THREE32.PlaneGeometry(
|
|
36475
|
-
boardOutlineBounds.width,
|
|
36476
|
-
boardOutlineBounds.height
|
|
36477
|
-
);
|
|
36478
|
-
const material = new THREE32.MeshBasicMaterial({
|
|
36479
|
-
map: texture,
|
|
36480
|
-
transparent: true,
|
|
36481
|
-
side: THREE32.DoubleSide,
|
|
36482
|
-
depthWrite: keySuffix === "panel-outlines",
|
|
36483
|
-
polygonOffset: usePolygonOffset,
|
|
36484
|
-
polygonOffsetFactor: usePolygonOffset ? -4 : 0,
|
|
36485
|
-
// Increased for better z-fighting prevention
|
|
36486
|
-
polygonOffsetUnits: usePolygonOffset ? -4 : 0
|
|
36487
|
-
});
|
|
36488
|
-
const mesh = new THREE32.Mesh(planeGeom, material);
|
|
36489
|
-
mesh.position.set(
|
|
36490
|
-
boardOutlineBounds.centerX,
|
|
36491
|
-
boardOutlineBounds.centerY,
|
|
36492
|
-
yOffset
|
|
36493
|
-
);
|
|
36494
|
-
if (isBottomLayer) {
|
|
36495
|
-
mesh.rotation.set(Math.PI, 0, 0);
|
|
36496
|
-
}
|
|
36497
|
-
mesh.name = `${isBottomLayer ? "bottom" : "top"}-${keySuffix}-texture-plane`;
|
|
36498
|
-
mesh.renderOrder = renderOrder;
|
|
36499
|
-
return mesh;
|
|
36500
|
-
};
|
|
36501
|
-
const topTraceMesh = createTexturePlane(
|
|
36502
|
-
textures.topTrace,
|
|
36503
|
-
pcbThickness / 2 + BOARD_SURFACE_OFFSET.traces,
|
|
36504
|
-
// Use consistent copper offset
|
|
36505
|
-
false,
|
|
36506
|
-
"trace",
|
|
36507
|
-
false,
|
|
36508
|
-
2
|
|
36509
|
-
// Render after soldermask
|
|
36510
|
-
);
|
|
36511
|
-
if (topTraceMesh) meshes.push(topTraceMesh);
|
|
36512
|
-
const topTraceWithMaskMesh = createTexturePlane(
|
|
36513
|
-
textures.topTraceWithMask,
|
|
36514
|
-
pcbThickness / 2 + BOARD_SURFACE_OFFSET.traces,
|
|
36515
|
-
false,
|
|
36516
|
-
"trace-with-mask",
|
|
36517
|
-
false,
|
|
36518
|
-
2
|
|
36519
|
-
// Render after soldermask
|
|
36520
|
-
);
|
|
36521
|
-
if (topTraceWithMaskMesh) meshes.push(topTraceWithMaskMesh);
|
|
36522
|
-
const topSilkscreenMesh = createTexturePlane(
|
|
36523
|
-
textures.topSilkscreen,
|
|
36524
|
-
pcbThickness / 2 + 3e-3,
|
|
36525
|
-
// Slightly above soldermask
|
|
36526
|
-
false,
|
|
36527
|
-
"silkscreen",
|
|
36528
|
-
false,
|
|
36529
|
-
3
|
|
36530
|
-
// Render after traces
|
|
36531
|
-
);
|
|
36532
|
-
if (topSilkscreenMesh) meshes.push(topSilkscreenMesh);
|
|
36533
|
-
const bottomTraceMesh = createTexturePlane(
|
|
36534
|
-
textures.bottomTrace,
|
|
36535
|
-
-pcbThickness / 2 - BOARD_SURFACE_OFFSET.traces,
|
|
36536
|
-
// Use consistent copper offset
|
|
36537
|
-
true,
|
|
36538
|
-
"trace",
|
|
36539
|
-
false,
|
|
36540
|
-
2
|
|
36541
|
-
// Render after soldermask
|
|
36542
|
-
);
|
|
36543
|
-
if (bottomTraceMesh) meshes.push(bottomTraceMesh);
|
|
36544
|
-
const bottomTraceWithMaskMesh = createTexturePlane(
|
|
36545
|
-
textures.bottomTraceWithMask,
|
|
36546
|
-
-pcbThickness / 2 - BOARD_SURFACE_OFFSET.traces,
|
|
36547
|
-
true,
|
|
36548
|
-
"trace-with-mask",
|
|
36549
|
-
false,
|
|
36550
|
-
2
|
|
36551
|
-
// Render after soldermask
|
|
36552
|
-
);
|
|
36553
|
-
if (bottomTraceWithMaskMesh) meshes.push(bottomTraceWithMaskMesh);
|
|
36554
|
-
const bottomSilkscreenMesh = createTexturePlane(
|
|
36555
|
-
textures.bottomSilkscreen,
|
|
36556
|
-
-pcbThickness / 2 - 3e-3,
|
|
36557
|
-
true,
|
|
36558
|
-
"silkscreen",
|
|
36559
|
-
false,
|
|
36560
|
-
3
|
|
36561
|
-
// Render after traces
|
|
36562
|
-
);
|
|
36563
|
-
if (bottomSilkscreenMesh) meshes.push(bottomSilkscreenMesh);
|
|
36564
|
-
const topSoldermaskMesh = createTexturePlane(
|
|
36565
|
-
textures.topSoldermask,
|
|
36566
|
-
pcbThickness / 2 + 1e-3,
|
|
36567
|
-
// Just above board surface
|
|
36568
|
-
false,
|
|
36569
|
-
"soldermask",
|
|
36570
|
-
true,
|
|
36571
|
-
// Enable polygon offset
|
|
36572
|
-
1
|
|
36573
|
-
// Render after board (renderOrder)
|
|
36574
|
-
);
|
|
36575
|
-
if (topSoldermaskMesh) meshes.push(topSoldermaskMesh);
|
|
36576
|
-
const bottomSoldermaskMesh = createTexturePlane(
|
|
36577
|
-
textures.bottomSoldermask,
|
|
36578
|
-
-pcbThickness / 2 - 1e-3,
|
|
36579
|
-
// Just below board surface (bottom side)
|
|
36580
|
-
true,
|
|
36581
|
-
"soldermask",
|
|
36582
|
-
true,
|
|
36583
|
-
// Enable polygon offset
|
|
36584
|
-
1
|
|
36585
|
-
// Render after board (renderOrder)
|
|
36586
|
-
);
|
|
36587
|
-
if (bottomSoldermaskMesh) meshes.push(bottomSoldermaskMesh);
|
|
36588
|
-
const topCopperTextMesh = createTexturePlane(
|
|
36589
|
-
textures.topCopperText,
|
|
36590
|
-
pcbThickness / 2 + BOARD_SURFACE_OFFSET.copper,
|
|
36591
|
-
false,
|
|
36592
|
-
"copper-text",
|
|
36593
|
-
false,
|
|
36594
|
-
2
|
|
36595
|
-
// Render after soldermask
|
|
36596
|
-
);
|
|
36597
|
-
if (topCopperTextMesh) meshes.push(topCopperTextMesh);
|
|
36598
|
-
const bottomCopperTextMesh = createTexturePlane(
|
|
36599
|
-
textures.bottomCopperText,
|
|
36600
|
-
-pcbThickness / 2 - BOARD_SURFACE_OFFSET.copper,
|
|
36601
|
-
true,
|
|
36602
|
-
"copper-text",
|
|
36603
|
-
false,
|
|
36604
|
-
2
|
|
36605
|
-
// Render after soldermask
|
|
36606
|
-
);
|
|
36607
|
-
if (bottomCopperTextMesh) meshes.push(bottomCopperTextMesh);
|
|
36608
|
-
const topPanelOutlinesMesh = createTexturePlane(
|
|
36609
|
-
textures.topPanelOutlines,
|
|
36610
|
-
pcbThickness / 2 + 4e-3,
|
|
36611
|
-
// Above silkscreen
|
|
36612
|
-
false,
|
|
36613
|
-
"panel-outlines",
|
|
36614
|
-
false,
|
|
36615
|
-
4
|
|
36616
|
-
);
|
|
36617
|
-
if (topPanelOutlinesMesh) meshes.push(topPanelOutlinesMesh);
|
|
36618
|
-
const bottomPanelOutlinesMesh = createTexturePlane(
|
|
36619
|
-
textures.bottomPanelOutlines,
|
|
36620
|
-
-pcbThickness / 2 - 4e-3,
|
|
36621
|
-
// Below bottom silkscreen
|
|
36622
|
-
true,
|
|
36623
|
-
"panel-outlines",
|
|
36624
|
-
false,
|
|
36625
|
-
4
|
|
36626
|
-
);
|
|
36627
|
-
if (bottomPanelOutlinesMesh) meshes.push(bottomPanelOutlinesMesh);
|
|
36628
36682
|
return meshes;
|
|
36629
36683
|
}
|
|
36630
36684
|
|
|
@@ -36652,8 +36706,6 @@ var BoardMeshes = ({
|
|
|
36652
36706
|
}
|
|
36653
36707
|
} else if (mesh.name.includes("plated_hole") || mesh.name.includes("via")) {
|
|
36654
36708
|
shouldShow = visibility.topCopper || visibility.bottomCopper;
|
|
36655
|
-
} else if (mesh.name.includes("copper_pour")) {
|
|
36656
|
-
shouldShow = visibility.topCopper || visibility.bottomCopper;
|
|
36657
36709
|
}
|
|
36658
36710
|
if (shouldShow) {
|
|
36659
36711
|
rootObject.add(mesh);
|
|
@@ -36681,6 +36733,10 @@ var BoardMeshes = ({
|
|
|
36681
36733
|
shouldShow = visibility.topCopper;
|
|
36682
36734
|
} else if (mesh.name.includes("bottom-copper-text")) {
|
|
36683
36735
|
shouldShow = visibility.bottomCopper;
|
|
36736
|
+
} else if (mesh.name.includes("top-copper")) {
|
|
36737
|
+
shouldShow = visibility.topCopper;
|
|
36738
|
+
} else if (mesh.name.includes("bottom-copper")) {
|
|
36739
|
+
shouldShow = visibility.bottomCopper;
|
|
36684
36740
|
} else if (mesh.name.includes("panel-outlines")) {
|
|
36685
36741
|
shouldShow = visibility.boardBody;
|
|
36686
36742
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/3d-viewer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.478",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"module": "./dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@jscad/regl-renderer": "^2.6.12",
|
|
31
31
|
"@jscad/stl-serializer": "^2.1.20",
|
|
32
|
+
"circuit-to-canvas": "^0.0.26",
|
|
32
33
|
"react-hot-toast": "^2.6.0",
|
|
33
34
|
"three": "^0.165.0",
|
|
34
35
|
"three-stdlib": "^2.36.0",
|