@tscircuit/3d-viewer 0.0.605 → 0.0.607
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.js +54 -50
- package/package.json +6 -4
package/dist/index.js
CHANGED
|
@@ -39224,7 +39224,7 @@ import * as THREE23 from "three";
|
|
|
39224
39224
|
// package.json
|
|
39225
39225
|
var package_default = {
|
|
39226
39226
|
name: "@tscircuit/3d-viewer",
|
|
39227
|
-
version: "0.0.
|
|
39227
|
+
version: "0.0.606",
|
|
39228
39228
|
repository: {
|
|
39229
39229
|
type: "git",
|
|
39230
39230
|
url: "https://github.com/tscircuit/3d-viewer"
|
|
@@ -39270,7 +39270,7 @@ var package_default = {
|
|
|
39270
39270
|
"troika-three-text": "^0.52.4"
|
|
39271
39271
|
},
|
|
39272
39272
|
peerDependencies: {
|
|
39273
|
-
zod: "
|
|
39273
|
+
zod: "*",
|
|
39274
39274
|
react: "19.1.0",
|
|
39275
39275
|
"react-dom": "19.1.0",
|
|
39276
39276
|
"@tscircuit/core": "*",
|
|
@@ -39289,7 +39289,7 @@ var package_default = {
|
|
|
39289
39289
|
"@tscircuit/alphabet": "^0.0.25",
|
|
39290
39290
|
"@tscircuit/circuit-json-util": "^0.0.116",
|
|
39291
39291
|
"@tscircuit/copper-pour-solver": "^0.0.29",
|
|
39292
|
-
"@tscircuit/core": "^0.0.
|
|
39292
|
+
"@tscircuit/core": "^0.0.1972",
|
|
39293
39293
|
"@tscircuit/props": "^0.0.666",
|
|
39294
39294
|
"@tscircuit/solver-utils": "^0.0.4",
|
|
39295
39295
|
"@types/jsdom": "^21.1.7",
|
|
@@ -39312,7 +39312,9 @@ var package_default = {
|
|
|
39312
39312
|
typescript: "^5.7.3",
|
|
39313
39313
|
vite: "^7.1.5",
|
|
39314
39314
|
"vite-tsconfig-paths": "^4.3.2",
|
|
39315
|
-
"circuit-json-to-gltf": "0.0.129"
|
|
39315
|
+
"circuit-json-to-gltf": "0.0.129",
|
|
39316
|
+
modelprinter: "https://jscdn.tscircuit.com/@tscircuit/modelprinter/0.0.4.tgz",
|
|
39317
|
+
zod: "^3.25.67"
|
|
39316
39318
|
},
|
|
39317
39319
|
patchedDependencies: {
|
|
39318
39320
|
"@tscircuit/fanout-solver@0.0.78": "patches/@tscircuit%2Ffanout-solver@0.0.78.patch"
|
|
@@ -39872,16 +39874,23 @@ var Canvas = forwardRef(
|
|
|
39872
39874
|
onCreatedRef.current?.({ camera, renderer });
|
|
39873
39875
|
let animationFrameId;
|
|
39874
39876
|
const clock = new THREE16.Clock();
|
|
39877
|
+
let isVisible = true;
|
|
39878
|
+
const visibilityObserver = new IntersectionObserver(([entry]) => {
|
|
39879
|
+
isVisible = entry?.isIntersecting ?? false;
|
|
39880
|
+
if (isVisible) handleResize();
|
|
39881
|
+
});
|
|
39882
|
+
visibilityObserver.observe(mountRef.current);
|
|
39875
39883
|
const animate = () => {
|
|
39884
|
+
animationFrameId = requestAnimationFrame(animate);
|
|
39885
|
+
if (!isVisible) return;
|
|
39876
39886
|
const time = clock.getElapsedTime();
|
|
39877
39887
|
const delta = clock.getDelta();
|
|
39878
39888
|
frameListeners.current.forEach((listener) => listener(time, delta));
|
|
39879
39889
|
renderer.render(scene, camera);
|
|
39880
|
-
animationFrameId = requestAnimationFrame(animate);
|
|
39881
39890
|
};
|
|
39882
39891
|
animate();
|
|
39883
39892
|
const handleResize = () => {
|
|
39884
|
-
if (mountRef.current) {
|
|
39893
|
+
if (mountRef.current?.clientWidth && mountRef.current.clientHeight) {
|
|
39885
39894
|
const newAspect = mountRef.current.clientWidth / mountRef.current.clientHeight;
|
|
39886
39895
|
if (camera instanceof THREE16.PerspectiveCamera) {
|
|
39887
39896
|
camera.aspect = newAspect;
|
|
@@ -39907,6 +39916,7 @@ var Canvas = forwardRef(
|
|
|
39907
39916
|
};
|
|
39908
39917
|
window.removeEventListener("resize", handleResize);
|
|
39909
39918
|
cancelAnimationFrame(animationFrameId);
|
|
39919
|
+
visibilityObserver.disconnect();
|
|
39910
39920
|
if (mountRef.current && renderer.domElement) {
|
|
39911
39921
|
mountRef.current.removeChild(renderer.domElement);
|
|
39912
39922
|
}
|
|
@@ -40404,7 +40414,14 @@ var OrientationCubeCanvas = () => {
|
|
|
40404
40414
|
group.add(topText);
|
|
40405
40415
|
group.add(bottomText);
|
|
40406
40416
|
let animationFrameId = null;
|
|
40417
|
+
let isVisible = true;
|
|
40418
|
+
const visibilityObserver = new IntersectionObserver(([entry]) => {
|
|
40419
|
+
isVisible = entry?.isIntersecting ?? false;
|
|
40420
|
+
});
|
|
40421
|
+
visibilityObserver.observe(canvas);
|
|
40407
40422
|
const animate = () => {
|
|
40423
|
+
animationFrameId = requestAnimationFrame(animate);
|
|
40424
|
+
if (!isVisible) return;
|
|
40408
40425
|
if (mainCameraRef.current) {
|
|
40409
40426
|
const cameraPosition = computePointInFront(
|
|
40410
40427
|
mainCameraRef.current.rotation ?? new THREE20.Euler(0, 0, 0),
|
|
@@ -40416,10 +40433,10 @@ var OrientationCubeCanvas = () => {
|
|
|
40416
40433
|
}
|
|
40417
40434
|
}
|
|
40418
40435
|
renderer.render(scene, camera);
|
|
40419
|
-
animationFrameId = requestAnimationFrame(animate);
|
|
40420
40436
|
};
|
|
40421
40437
|
animate();
|
|
40422
40438
|
return () => {
|
|
40439
|
+
visibilityObserver.disconnect();
|
|
40423
40440
|
canvas.remove();
|
|
40424
40441
|
if (animationFrameId !== null) {
|
|
40425
40442
|
cancelAnimationFrame(animationFrameId);
|
|
@@ -44657,6 +44674,7 @@ var createDataTexture = (canvas) => {
|
|
|
44657
44674
|
var createBoardReliefTextures = (texture, maskedCopperMask) => {
|
|
44658
44675
|
const sourceCanvas = texture.image;
|
|
44659
44676
|
if (!sourceCanvas?.width || !sourceCanvas.height) return null;
|
|
44677
|
+
const { width: canvasWidth, height: canvasHeight } = sourceCanvas;
|
|
44660
44678
|
const sourceCtx = sourceCanvas.getContext("2d");
|
|
44661
44679
|
if (!sourceCtx) return null;
|
|
44662
44680
|
const maskCanvas = maskedCopperMask?.image;
|
|
@@ -44664,48 +44682,37 @@ var createBoardReliefTextures = (texture, maskedCopperMask) => {
|
|
|
44664
44682
|
const maskWidth = maskCanvas?.width ?? 0;
|
|
44665
44683
|
const maskHeight = maskCanvas?.height ?? 0;
|
|
44666
44684
|
const maskImageData = maskCtx && maskWidth && maskHeight ? maskCtx.getImageData(0, 0, maskWidth, maskHeight) : null;
|
|
44667
|
-
const imageData = sourceCtx.getImageData(
|
|
44668
|
-
0,
|
|
44669
|
-
0,
|
|
44670
|
-
sourceCanvas.width,
|
|
44671
|
-
sourceCanvas.height
|
|
44672
|
-
);
|
|
44685
|
+
const imageData = sourceCtx.getImageData(0, 0, canvasWidth, canvasHeight);
|
|
44673
44686
|
const data = imageData.data;
|
|
44674
|
-
const heights = new Float32Array(
|
|
44687
|
+
const heights = new Float32Array(canvasWidth * canvasHeight);
|
|
44675
44688
|
const roughnessCanvas = document.createElement("canvas");
|
|
44676
44689
|
const metalnessCanvas = document.createElement("canvas");
|
|
44677
|
-
roughnessCanvas.width = metalnessCanvas.width =
|
|
44678
|
-
roughnessCanvas.height = metalnessCanvas.height =
|
|
44690
|
+
roughnessCanvas.width = metalnessCanvas.width = canvasWidth;
|
|
44691
|
+
roughnessCanvas.height = metalnessCanvas.height = canvasHeight;
|
|
44679
44692
|
const roughnessCtx = roughnessCanvas.getContext("2d");
|
|
44680
44693
|
const metalnessCtx = metalnessCanvas.getContext("2d");
|
|
44681
44694
|
if (!roughnessCtx || !metalnessCtx) return null;
|
|
44682
44695
|
const roughnessImageData = roughnessCtx.createImageData(
|
|
44683
|
-
|
|
44684
|
-
|
|
44696
|
+
canvasWidth,
|
|
44697
|
+
canvasHeight
|
|
44685
44698
|
);
|
|
44686
44699
|
const metalnessImageData = metalnessCtx.createImageData(
|
|
44687
|
-
|
|
44688
|
-
|
|
44700
|
+
canvasWidth,
|
|
44701
|
+
canvasHeight
|
|
44689
44702
|
);
|
|
44690
44703
|
const roughnessData = roughnessImageData.data;
|
|
44691
44704
|
const metalnessData = metalnessImageData.data;
|
|
44692
44705
|
for (let i = 0; i < data.length; i += 4) {
|
|
44693
44706
|
const pixelIndex = i / 4;
|
|
44694
|
-
const x = pixelIndex %
|
|
44695
|
-
const y = Math.floor(pixelIndex /
|
|
44707
|
+
const x = pixelIndex % canvasWidth;
|
|
44708
|
+
const y = Math.floor(pixelIndex / canvasWidth);
|
|
44696
44709
|
const alpha = data[i + 3] ?? 0;
|
|
44697
44710
|
if (alpha < 16) {
|
|
44698
44711
|
heights[pixelIndex] = invertSurfaceHeight(PLAIN_SOLDERMASK_HEIGHT);
|
|
44699
44712
|
continue;
|
|
44700
44713
|
}
|
|
44701
|
-
const maskX = maskImageData ? Math.min(
|
|
44702
|
-
|
|
44703
|
-
Math.floor(x / sourceCanvas.width * maskWidth)
|
|
44704
|
-
) : 0;
|
|
44705
|
-
const maskY = maskImageData ? Math.min(
|
|
44706
|
-
maskHeight - 1,
|
|
44707
|
-
Math.floor(y / sourceCanvas.height * maskHeight)
|
|
44708
|
-
) : 0;
|
|
44714
|
+
const maskX = maskImageData ? Math.min(maskWidth - 1, Math.floor(x / canvasWidth * maskWidth)) : 0;
|
|
44715
|
+
const maskY = maskImageData ? Math.min(maskHeight - 1, Math.floor(y / canvasHeight * maskHeight)) : 0;
|
|
44709
44716
|
const maskAlpha = maskImageData ? maskImageData.data[(maskY * maskWidth + maskX) * 4 + 3] ?? 0 : 0;
|
|
44710
44717
|
const profile = getBoardSurfaceProfile(
|
|
44711
44718
|
data[i] ?? 0,
|
|
@@ -44713,13 +44720,13 @@ var createBoardReliefTextures = (texture, maskedCopperMask) => {
|
|
|
44713
44720
|
data[i + 2] ?? 0,
|
|
44714
44721
|
maskAlpha >= 16
|
|
44715
44722
|
);
|
|
44716
|
-
const salt =
|
|
44723
|
+
const salt = canvasWidth + canvasHeight;
|
|
44717
44724
|
const fineGrain = profile.isExposedCopper ? createCopperDetail(x, y, salt) : profile.isMaskedCopper ? createMaskedTraceDetail(x, y, salt) : 0;
|
|
44718
|
-
const
|
|
44725
|
+
const surfaceHeight = clamp01(
|
|
44719
44726
|
invertSurfaceHeight(profile.height) + fineGrain * profile.microSurfaceWeight
|
|
44720
44727
|
);
|
|
44721
|
-
heights[pixelIndex] =
|
|
44722
|
-
const heightChannel =
|
|
44728
|
+
heights[pixelIndex] = surfaceHeight;
|
|
44729
|
+
const heightChannel = surfaceHeight * 255;
|
|
44723
44730
|
data[i] = data[i + 1] = data[i + 2] = heightChannel;
|
|
44724
44731
|
data[i + 3] = 255;
|
|
44725
44732
|
const roughness = profile.isExposedCopper ? clamp01(
|
|
@@ -44737,31 +44744,28 @@ var createBoardReliefTextures = (texture, maskedCopperMask) => {
|
|
|
44737
44744
|
roughnessCtx.putImageData(roughnessImageData, 0, 0);
|
|
44738
44745
|
metalnessCtx.putImageData(metalnessImageData, 0, 0);
|
|
44739
44746
|
const bumpCanvas = document.createElement("canvas");
|
|
44740
|
-
bumpCanvas.width =
|
|
44741
|
-
bumpCanvas.height =
|
|
44747
|
+
bumpCanvas.width = canvasWidth;
|
|
44748
|
+
bumpCanvas.height = canvasHeight;
|
|
44742
44749
|
const bumpCtx = bumpCanvas.getContext("2d");
|
|
44743
44750
|
if (!bumpCtx) return null;
|
|
44744
44751
|
bumpCtx.putImageData(imageData, 0, 0);
|
|
44745
44752
|
const normalCanvas = document.createElement("canvas");
|
|
44746
|
-
normalCanvas.width =
|
|
44747
|
-
normalCanvas.height =
|
|
44753
|
+
normalCanvas.width = canvasWidth;
|
|
44754
|
+
normalCanvas.height = canvasHeight;
|
|
44748
44755
|
const normalCtx = normalCanvas.getContext("2d");
|
|
44749
44756
|
if (!normalCtx) return null;
|
|
44750
|
-
const normalImageData = normalCtx.createImageData(
|
|
44751
|
-
sourceCanvas.width,
|
|
44752
|
-
sourceCanvas.height
|
|
44753
|
-
);
|
|
44757
|
+
const normalImageData = normalCtx.createImageData(canvasWidth, canvasHeight);
|
|
44754
44758
|
const normalData = normalImageData.data;
|
|
44755
|
-
const getHeight4 = (x, y) => heights[Math.max(0, Math.min(
|
|
44756
|
-
for (let y = 0; y <
|
|
44757
|
-
for (let x = 0; x <
|
|
44759
|
+
const getHeight4 = (x, y) => heights[Math.max(0, Math.min(canvasHeight - 1, y)) * canvasWidth + Math.max(0, Math.min(canvasWidth - 1, x))] ?? 0;
|
|
44760
|
+
for (let y = 0; y < canvasHeight; y++) {
|
|
44761
|
+
for (let x = 0; x < canvasWidth; x++) {
|
|
44758
44762
|
const dx = (getHeight4(x + 1, y) - getHeight4(x - 1, y)) * 4;
|
|
44759
44763
|
const dy = (getHeight4(x, y + 1) - getHeight4(x, y - 1)) * 4;
|
|
44760
|
-
const
|
|
44761
|
-
const i = (y *
|
|
44762
|
-
normalData[i] = (
|
|
44763
|
-
normalData[i + 1] = (
|
|
44764
|
-
normalData[i + 2] = (
|
|
44764
|
+
const inverseLength = 1 / Math.sqrt(dx * dx + dy * dy + 1);
|
|
44765
|
+
const i = (y * canvasWidth + x) * 4;
|
|
44766
|
+
normalData[i] = (-dx * inverseLength * 0.5 + 0.5) * 255;
|
|
44767
|
+
normalData[i + 1] = (-dy * inverseLength * 0.5 + 0.5) * 255;
|
|
44768
|
+
normalData[i + 2] = (inverseLength * 0.5 + 0.5) * 255;
|
|
44765
44769
|
normalData[i + 3] = 255;
|
|
44766
44770
|
}
|
|
44767
44771
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/3d-viewer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.607",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/tscircuit/3d-viewer"
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"troika-three-text": "^0.52.4"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
|
-
"zod": "
|
|
49
|
+
"zod": "*",
|
|
50
50
|
"react": "19.1.0",
|
|
51
51
|
"react-dom": "19.1.0",
|
|
52
52
|
"@tscircuit/core": "*",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"@tscircuit/alphabet": "^0.0.25",
|
|
66
66
|
"@tscircuit/circuit-json-util": "^0.0.116",
|
|
67
67
|
"@tscircuit/copper-pour-solver": "^0.0.29",
|
|
68
|
-
"@tscircuit/core": "^0.0.
|
|
68
|
+
"@tscircuit/core": "^0.0.1972",
|
|
69
69
|
"@tscircuit/props": "^0.0.666",
|
|
70
70
|
"@tscircuit/solver-utils": "^0.0.4",
|
|
71
71
|
"@types/jsdom": "^21.1.7",
|
|
@@ -88,7 +88,9 @@
|
|
|
88
88
|
"typescript": "^5.7.3",
|
|
89
89
|
"vite": "^7.1.5",
|
|
90
90
|
"vite-tsconfig-paths": "^4.3.2",
|
|
91
|
-
"circuit-json-to-gltf": "0.0.129"
|
|
91
|
+
"circuit-json-to-gltf": "0.0.129",
|
|
92
|
+
"modelprinter": "https://jscdn.tscircuit.com/@tscircuit/modelprinter/0.0.4.tgz",
|
|
93
|
+
"zod": "^3.25.67"
|
|
92
94
|
},
|
|
93
95
|
"patchedDependencies": {
|
|
94
96
|
"@tscircuit/fanout-solver@0.0.78": "patches/@tscircuit%2Ffanout-solver@0.0.78.patch"
|