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