forgecad 0.9.2 → 0.9.3
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/LICENSE +7 -5
- package/README.md +1 -1
- package/README.public.md +24 -2
- package/dist/assets/{AdminPage-Bs4PiK00.js → AdminPage-4jihcEk_.js} +1 -1
- package/dist/assets/{BlogPage-DVmgN0ma.js → BlogPage-BvzruKtw.js} +1 -1
- package/dist/assets/{DocsPage-BP6wlsBN.js → DocsPage-DHbd-WS-.js} +13 -13
- package/dist/assets/{EditorApp-Arw2NnGJ.js → EditorApp-C5P2rBfh.js} +433 -84
- package/dist/assets/{EditorApp-VY9lXx0N.css → EditorApp-DS0AIUrZ.css} +25 -0
- package/dist/assets/{EmbedViewer-qgQiOahL.js → EmbedViewer-B70wQwlE.js} +2 -2
- package/dist/assets/{LandingPageProofDriven-DvhtmWOz.js → LandingPageProofDriven-DIsYTnep.js} +1 -1
- package/dist/assets/{PricingPage-Ck3CP2ti.css → PricingPage-BMedqFef.css} +48 -0
- package/dist/assets/{PricingPage-657oLvWh.js → PricingPage-YPOr12pP.js} +34 -6
- package/dist/assets/{SettingsPage-wNy3_2yn.js → SettingsPage-rntoyJ3b.js} +10 -13
- package/dist/assets/{app-BdBoMQeO.js → app-CWucmnLZ.js} +801 -1208
- package/dist/assets/cli/{render-Ci3jjyT1.js → render-DZHmUySW.js} +214 -23
- package/dist/assets/copy-CQKQppF-.js +8 -0
- package/dist/assets/{evalWorker-CMCAbK8r.js → evalWorker-C3dKxi9Y.js} +1117 -95
- package/dist/assets/{manifold-BMn-8Vf8.js → manifold-CQ3FhfWB.js} +1 -1
- package/dist/assets/{manifold-jlYQ6E5R.js → manifold-CU0G1yYL.js} +1 -1
- package/dist/assets/{manifold-DbyILno4.js → manifold-CYWZMfjB.js} +2 -2
- package/dist/assets/{renderSceneState-DAnqvxSt.js → renderSceneState-BBUrnsUN.js} +1 -1
- package/dist/assets/{reportWorker-BcRVMHK-.js → reportWorker-BhZ7DjxQ.js} +1091 -95
- package/dist/assets/{sectionPlaneMath-DXJ_TdIW.js → sectionPlaneMath-BxfokaJE.js} +1091 -95
- package/dist/cli/render.html +1 -1
- package/dist/docs/index.html +2 -2
- package/dist/docs-raw/AI/usage.md +182 -89
- package/dist/docs-raw/API/core/concepts.md +26 -0
- package/dist/docs-raw/CLI.md +58 -37
- package/dist/docs-raw/INDEX.md +81 -64
- package/dist/docs-raw/cli-monetization.md +9 -8
- package/dist/docs-raw/generated/concepts.md +111 -4
- package/dist/docs-raw/generated/core.md +2 -0
- package/dist/docs-raw/generated/curves.md +480 -1
- package/dist/docs-raw/generated/output.md +1 -0
- package/dist/docs-raw/generated/sketch.md +2 -0
- package/dist/docs-raw/generated/viewport.md +81 -3
- package/dist/docs-raw/product/user-outreach-email-templates.md +159 -0
- package/dist/docs-raw/skills/forgecad-image-replicator.md +1 -1
- package/dist/docs-raw/skills/forgecad-make-a-model.md +33 -4
- package/dist/docs-raw/skills/forgecad-prepare-prompt.md +1 -1
- package/dist/docs-raw/skills/forgecad-project.md +1 -1
- package/dist/docs-raw/skills/forgecad-render-inspect.md +1 -1
- package/dist/docs-raw/skills/forgecad.md +2 -1
- package/dist/docs-raw/welcome.md +85 -137
- package/dist/index.html +1 -1
- package/dist/llms.txt +4 -3
- package/dist/sitemap.xml +6 -6
- package/dist-cli/forgecad.js +1413 -219
- package/dist-cli/forgecad.js.map +1 -1
- package/dist-skill/CONTEXT.md +594 -5
- package/dist-skill/SKILL-dev.md +2 -1
- package/dist-skill/SKILL.md +2 -1
- package/dist-skill/docs/API/core/concepts.md +26 -0
- package/dist-skill/docs/CLI.md +58 -37
- package/dist-skill/docs/generated/core.md +2 -0
- package/dist-skill/docs/generated/curves.md +480 -1
- package/dist-skill/docs/generated/output.md +1 -0
- package/dist-skill/docs/generated/sketch.md +2 -0
- package/dist-skill/docs/generated/viewport.md +81 -3
- package/dist-skill/docs-dev/API/core/concepts.md +26 -0
- package/dist-skill/docs-dev/CLI.md +58 -37
- package/dist-skill/docs-dev/generated/core.md +2 -0
- package/dist-skill/docs-dev/generated/curves.md +480 -1
- package/dist-skill/docs-dev/generated/output.md +1 -0
- package/dist-skill/docs-dev/generated/sketch.md +2 -0
- package/dist-skill/docs-dev/generated/viewport.md +81 -3
- package/dist-skill/library/README.md +0 -1
- package/dist-skill/library/forgecad-image-replicator/SKILL.md +1 -1
- package/dist-skill/library/forgecad-make-a-model/SKILL.md +33 -4
- package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +1 -1
- package/dist-skill/library/forgecad-project/SKILL.md +1 -1
- package/dist-skill/library/forgecad-render-inspect/SKILL.md +1 -1
- package/examples/api/conformal-product-ribbon.forge.js +77 -0
- package/examples/api/render-labels.forge.js +33 -0
- package/examples/api/text2d-basics.forge.js +6 -3
- package/package.json +1 -1
- package/dist-skill/library/forgecad-deep-dive/SKILL.md +0 -120
- package/dist-skill/library/forgecad-deep-dive/agents/openai.yaml +0 -4
- package/dist-skill/library/forgecad-deep-dive/references/output-shape.md +0 -64
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import { D as DoubleSide, bF as initSolverWasm, bE as initKernel, S as Scene, bG as BoxGeometry, bc as MeshStandardMaterial, a4 as BackSide, a$ as PointLight, M as Mesh, aa as MeshBasicMaterial, bH as localAabbPlaneRelation, h as Vector2, bI as ShapeUtils, g as Vector3, e as Color, aB as resolveForgeRenderStyle, b8 as getRenderStylePreset, ax as setParamOverrides, b5 as runScript, a0 as MathUtils, G as Box3, bJ as Group, b2 as shapeToGeometry, b6 as MeshPhysicalMaterial, b9 as AdditiveBlending, aG as LineBasicMaterial, b7 as LineSegments, aF as BufferGeometry, P as PerspectiveCamera, k as ShaderMaterial, bK as intersectWithPlane, W as WebGLRenderer, A as ACESFilmicToneMapping, c as SRGBColorSpace, bL as parseCameraCliSpec, bM as PMREMGenerator, aU as CanvasTexture, aV as Object3D, aW as FogExp2, aX as Fog, aY as AmbientLight, b0 as DirectionalLight, aZ as HemisphereLight, by as findJointAnimationClip, p as Plane, Y as Vector4, $ as Matrix4, bf as SDF_RAYMARCH_PROXY_VERTEX_SHADER, be as buildSdfRaymarchFragmentShader, O as OrthographicCamera, bz as resolveJointAnimation, bA as resolveJointViewValues, R as Raycaster, aT as BufferAttribute, bN as worldAuthorPlaneToLocal, a_ as SpotLight } from "../sectionPlaneMath-
|
|
5
|
-
import { m as mergeViewportRenderSceneStates, p as parseRenderSceneCliSpec } from "../renderSceneState-
|
|
4
|
+
import { D as DoubleSide, bF as initSolverWasm, bE as initKernel, S as Scene, bG as BoxGeometry, bc as MeshStandardMaterial, a4 as BackSide, a$ as PointLight, M as Mesh, aa as MeshBasicMaterial, bH as localAabbPlaneRelation, h as Vector2, bI as ShapeUtils, g as Vector3, e as Color, aB as resolveForgeRenderStyle, b8 as getRenderStylePreset, ax as setParamOverrides, b5 as runScript, a0 as MathUtils, G as Box3, bJ as Group, b2 as shapeToGeometry, b6 as MeshPhysicalMaterial, b9 as AdditiveBlending, aG as LineBasicMaterial, b7 as LineSegments, aF as BufferGeometry, P as PerspectiveCamera, k as ShaderMaterial, bK as intersectWithPlane, W as WebGLRenderer, A as ACESFilmicToneMapping, c as SRGBColorSpace, bL as parseCameraCliSpec, bM as PMREMGenerator, aU as CanvasTexture, aV as Object3D, aW as FogExp2, aX as Fog, aY as AmbientLight, b0 as DirectionalLight, aZ as HemisphereLight, by as findJointAnimationClip, p as Plane, Y as Vector4, $ as Matrix4, bf as SDF_RAYMARCH_PROXY_VERTEX_SHADER, be as buildSdfRaymarchFragmentShader, O as OrthographicCamera, bz as resolveJointAnimation, bA as resolveJointViewValues, R as Raycaster, aT as BufferAttribute, bN as worldAuthorPlaneToLocal, a_ as SpotLight } from "../sectionPlaneMath-BxfokaJE.js";
|
|
5
|
+
import { m as mergeViewportRenderSceneStates, p as parseRenderSceneCliSpec } from "../renderSceneState-BBUrnsUN.js";
|
|
6
6
|
const CAD_MATERIAL_PROPS = {
|
|
7
7
|
color: 6003669,
|
|
8
8
|
metalness: 0.05,
|
|
@@ -1069,6 +1069,34 @@ function analyzeDistanceInspection(entries, rawOptions = {}) {
|
|
|
1069
1069
|
warnings: [...connectivity.warnings]
|
|
1070
1070
|
};
|
|
1071
1071
|
}
|
|
1072
|
+
function formatAvailableViews(views) {
|
|
1073
|
+
const names = Object.keys(views ?? {}).sort();
|
|
1074
|
+
if (names.length === 0) {
|
|
1075
|
+
return "No named render views are declared with scene({ views }).";
|
|
1076
|
+
}
|
|
1077
|
+
return `Available views: ${names.join(", ")}.`;
|
|
1078
|
+
}
|
|
1079
|
+
function sceneViewCameraToViewportCameraState(camera) {
|
|
1080
|
+
return {
|
|
1081
|
+
projectionMode: camera.type ?? "perspective",
|
|
1082
|
+
position: camera.position,
|
|
1083
|
+
target: camera.target,
|
|
1084
|
+
up: camera.up ?? [0, 0, 1],
|
|
1085
|
+
...camera.fov !== void 0 ? { fov: camera.fov } : {}
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
function resolveNamedSceneViewCamera(sceneConfig, viewName) {
|
|
1089
|
+
const normalizedName = viewName.trim();
|
|
1090
|
+
if (!normalizedName) {
|
|
1091
|
+
throw new Error("Named render view cannot be empty.");
|
|
1092
|
+
}
|
|
1093
|
+
const views = (sceneConfig == null ? void 0 : sceneConfig.views) ?? null;
|
|
1094
|
+
const view = views == null ? void 0 : views[normalizedName];
|
|
1095
|
+
if (!view) {
|
|
1096
|
+
throw new Error(`Named render view "${normalizedName}" was not found. ${formatAvailableViews(views)}`);
|
|
1097
|
+
}
|
|
1098
|
+
return sceneViewCameraToViewportCameraState(view.camera);
|
|
1099
|
+
}
|
|
1072
1100
|
function edgesStrokeAttrs(preset) {
|
|
1073
1101
|
switch (preset) {
|
|
1074
1102
|
case "off":
|
|
@@ -1290,6 +1318,24 @@ let rendererPixelRatio = 1;
|
|
|
1290
1318
|
let rendererContextKey = "";
|
|
1291
1319
|
let captureSession = null;
|
|
1292
1320
|
let studioEnvTexture = null;
|
|
1321
|
+
function createCaptureDebugLogger(enabled) {
|
|
1322
|
+
const start = performance.now();
|
|
1323
|
+
let previous = start;
|
|
1324
|
+
return (phase, detail = {}) => {
|
|
1325
|
+
if (!enabled) return;
|
|
1326
|
+
const now = performance.now();
|
|
1327
|
+
const sinceStart = (now - start).toFixed(1);
|
|
1328
|
+
const delta = (now - previous).toFixed(1);
|
|
1329
|
+
previous = now;
|
|
1330
|
+
let detailText = "";
|
|
1331
|
+
try {
|
|
1332
|
+
detailText = Object.keys(detail).length > 0 ? ` ${JSON.stringify(detail)}` : "";
|
|
1333
|
+
} catch {
|
|
1334
|
+
detailText = " [detail-unserializable]";
|
|
1335
|
+
}
|
|
1336
|
+
console.info(`[forge-capture:debug] +${sinceStart}ms Δ${delta}ms ${phase}${detailText}`);
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1293
1339
|
const COLLISION_SOURCE_OPACITY = 0.22;
|
|
1294
1340
|
const COLLISION_SOURCE_COLOR = [180, 200, 220];
|
|
1295
1341
|
const COLLISION_HIGHLIGHT_COLOR = [255, 68, 16];
|
|
@@ -2429,11 +2475,19 @@ function parseColor(input, fallback) {
|
|
|
2429
2475
|
return new Color(fallback);
|
|
2430
2476
|
}
|
|
2431
2477
|
}
|
|
2432
|
-
function buildSectionMeshPayload(objectId, shape) {
|
|
2478
|
+
function buildSectionMeshPayload(objectId, shape, debug, objectName) {
|
|
2433
2479
|
try {
|
|
2480
|
+
const start = performance.now();
|
|
2434
2481
|
const mesh = shape.getMesh();
|
|
2435
2482
|
const bb = shape.boundingBox();
|
|
2436
2483
|
if (!mesh.triVerts.length || !mesh.vertProperties.length) return null;
|
|
2484
|
+
debug == null ? void 0 : debug("sectionMesh:built", {
|
|
2485
|
+
objectId,
|
|
2486
|
+
name: objectName,
|
|
2487
|
+
ms: Number((performance.now() - start).toFixed(1)),
|
|
2488
|
+
triangles: Math.floor(mesh.triVerts.length / 3),
|
|
2489
|
+
vertices: Math.floor(mesh.vertProperties.length / Math.max(1, mesh.numProp))
|
|
2490
|
+
});
|
|
2437
2491
|
return {
|
|
2438
2492
|
meshId: `capture:${objectId}`,
|
|
2439
2493
|
numProp: mesh.numProp,
|
|
@@ -2444,7 +2498,12 @@ function buildSectionMeshPayload(objectId, shape) {
|
|
|
2444
2498
|
max: [bb.max[0], bb.max[1], bb.max[2]]
|
|
2445
2499
|
}
|
|
2446
2500
|
};
|
|
2447
|
-
} catch {
|
|
2501
|
+
} catch (err) {
|
|
2502
|
+
debug == null ? void 0 : debug("sectionMesh:error", {
|
|
2503
|
+
objectId,
|
|
2504
|
+
name: objectName,
|
|
2505
|
+
error: err instanceof Error ? err.message : String(err)
|
|
2506
|
+
});
|
|
2448
2507
|
return null;
|
|
2449
2508
|
}
|
|
2450
2509
|
}
|
|
@@ -2842,23 +2901,51 @@ function applyObjectTransforms(session, animationProgress) {
|
|
|
2842
2901
|
});
|
|
2843
2902
|
session.collisionReport = null;
|
|
2844
2903
|
}
|
|
2845
|
-
function updateSectionSweepCaps(session, progress, mode) {
|
|
2846
|
-
var _a;
|
|
2904
|
+
function updateSectionSweepCaps(session, progress, mode, debug) {
|
|
2905
|
+
var _a, _b;
|
|
2847
2906
|
const sweep = session.sweep;
|
|
2848
2907
|
if (!sweep) return;
|
|
2849
2908
|
const t = easedSweepProgress(progress, sweep.ease);
|
|
2850
2909
|
const offset = sweep.from + (sweep.to - sweep.from) * t;
|
|
2910
|
+
debug == null ? void 0 : debug("frame:caps:start", {
|
|
2911
|
+
progress: Number(progress.toFixed(4)),
|
|
2912
|
+
offset: Number(offset.toFixed(4)),
|
|
2913
|
+
mode
|
|
2914
|
+
});
|
|
2851
2915
|
sweep.clippingPlane.constant = offset;
|
|
2852
2916
|
clearSectionCapGroups(session);
|
|
2853
|
-
if (mode === "wireframe")
|
|
2917
|
+
if (mode === "wireframe") {
|
|
2918
|
+
debug == null ? void 0 : debug("frame:caps:skip-wireframe");
|
|
2919
|
+
return;
|
|
2920
|
+
}
|
|
2854
2921
|
session.scene.updateMatrixWorld(true);
|
|
2855
|
-
|
|
2922
|
+
let computed = 0;
|
|
2923
|
+
let emitted = 0;
|
|
2924
|
+
for (let index = 0; index < session.renderables.length; index += 1) {
|
|
2925
|
+
const renderable = session.renderables[index];
|
|
2856
2926
|
if (!renderable.sectionMesh) continue;
|
|
2857
2927
|
const localPlane = worldAuthorPlaneToLocal({ normal: sweep.normal, offset }, renderable.root.matrixWorld);
|
|
2858
2928
|
if (!localPlane) continue;
|
|
2929
|
+
const capStart = performance.now();
|
|
2930
|
+
debug == null ? void 0 : debug("frame:cap:start", {
|
|
2931
|
+
index: index + 1,
|
|
2932
|
+
id: renderable.id,
|
|
2933
|
+
name: renderable.name
|
|
2934
|
+
});
|
|
2859
2935
|
const payload = computeMeshSectionCap(renderable.sectionMesh, localPlane);
|
|
2860
|
-
|
|
2936
|
+
computed += 1;
|
|
2937
|
+
debug == null ? void 0 : debug("frame:cap:end", {
|
|
2938
|
+
index: index + 1,
|
|
2939
|
+
id: renderable.id,
|
|
2940
|
+
name: renderable.name,
|
|
2941
|
+
ms: Number((performance.now() - capStart).toFixed(1)),
|
|
2942
|
+
positions: payload.positions.length / 3,
|
|
2943
|
+
triangles: payload.indices.length / 3,
|
|
2944
|
+
warnings: ((_a = payload.warnings) == null ? void 0 : _a.join(",")) ?? ""
|
|
2945
|
+
});
|
|
2946
|
+
(_b = payload.warnings) == null ? void 0 : _b.forEach((warning) => sweep.warnings.add(warning));
|
|
2861
2947
|
if (payload.positions.length === 0 || payload.indices.length === 0) continue;
|
|
2948
|
+
emitted += 1;
|
|
2862
2949
|
const clippingPlanes = (renderable.solidMaterial.clippingPlanes ?? []).filter((plane) => plane !== sweep.clippingPlane);
|
|
2863
2950
|
const geometry = createSectionCapGeometry(payload);
|
|
2864
2951
|
const material = createSectionCapMaterial({
|
|
@@ -2889,11 +2976,21 @@ function updateSectionSweepCaps(session, progress, mode) {
|
|
|
2889
2976
|
renderable.sectionCapGroup.add(outline);
|
|
2890
2977
|
}
|
|
2891
2978
|
}
|
|
2979
|
+
debug == null ? void 0 : debug("frame:caps:end", { computed, emitted });
|
|
2892
2980
|
}
|
|
2893
2981
|
function renderCaptureFrame(session, opts) {
|
|
2894
2982
|
const mode = (opts == null ? void 0 : opts.mode) ?? "solid";
|
|
2895
2983
|
const cameraMotion = (opts == null ? void 0 : opts.cameraMotion) ?? "orbit";
|
|
2896
2984
|
const shouldProfile = (opts == null ? void 0 : opts.profile) === true;
|
|
2985
|
+
const debug = createCaptureDebugLogger(opts == null ? void 0 : opts.debug);
|
|
2986
|
+
debug("frame:start", {
|
|
2987
|
+
mode,
|
|
2988
|
+
cameraMotion,
|
|
2989
|
+
turn: opts == null ? void 0 : opts.turn,
|
|
2990
|
+
animationProgress: opts == null ? void 0 : opts.animationProgress,
|
|
2991
|
+
sweepProgress: opts == null ? void 0 : opts.sweepProgress,
|
|
2992
|
+
imageFormat: (opts == null ? void 0 : opts.imageFormat) ?? "png"
|
|
2993
|
+
});
|
|
2897
2994
|
const start = shouldProfile ? performance.now() : 0;
|
|
2898
2995
|
let mark = start;
|
|
2899
2996
|
const timings = {
|
|
@@ -2921,7 +3018,7 @@ function renderCaptureFrame(session, opts) {
|
|
|
2921
3018
|
applyOrbitPose(session, (opts == null ? void 0 : opts.turn) ?? 0, opts == null ? void 0 : opts.pitchDeg);
|
|
2922
3019
|
}
|
|
2923
3020
|
captureMark("cameraMs");
|
|
2924
|
-
updateSectionSweepCaps(session, (opts == null ? void 0 : opts.sweepProgress) ?? 0, mode);
|
|
3021
|
+
updateSectionSweepCaps(session, (opts == null ? void 0 : opts.sweepProgress) ?? 0, mode, debug);
|
|
2925
3022
|
captureMark("capsMs");
|
|
2926
3023
|
const r = getRenderer(session.size, session.pixelRatio);
|
|
2927
3024
|
session.scene.updateMatrixWorld(true);
|
|
@@ -2930,6 +3027,7 @@ function renderCaptureFrame(session, opts) {
|
|
|
2930
3027
|
captureMark("renderMs");
|
|
2931
3028
|
const png = captureRenderedImage(session.size, (opts == null ? void 0 : opts.imageFormat) === "jpeg" ? "jpeg" : "png", (opts == null ? void 0 : opts.jpegQuality) ?? 0.96);
|
|
2932
3029
|
captureMark("pngMs");
|
|
3030
|
+
debug("frame:end");
|
|
2933
3031
|
if (shouldProfile) {
|
|
2934
3032
|
timings.totalMs = performance.now() - start;
|
|
2935
3033
|
return { png, timings };
|
|
@@ -2982,9 +3080,17 @@ function isFocusVisible(obj, focus, hide) {
|
|
|
2982
3080
|
return true;
|
|
2983
3081
|
}
|
|
2984
3082
|
function createSession(code, opts) {
|
|
2985
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
3083
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
2986
3084
|
const size = (opts == null ? void 0 : opts.size) ?? 1024;
|
|
2987
3085
|
const pixelRatio = (opts == null ? void 0 : opts.pixelRatio) ?? 1;
|
|
3086
|
+
const debug = createCaptureDebugLogger(opts == null ? void 0 : opts.debug);
|
|
3087
|
+
debug("session:start", {
|
|
3088
|
+
capture: (opts == null ? void 0 : opts.capture) ?? "orbit",
|
|
3089
|
+
size,
|
|
3090
|
+
pixelRatio,
|
|
3091
|
+
quality: (opts == null ? void 0 : opts.quality) ?? "high",
|
|
3092
|
+
fileName: (opts == null ? void 0 : opts.fileName) ?? "main.forge.js"
|
|
3093
|
+
});
|
|
2988
3094
|
const r = getRenderer(size, pixelRatio);
|
|
2989
3095
|
const renderStyle = resolveForgeRenderStyle(opts == null ? void 0 : opts.renderStyle);
|
|
2990
3096
|
const renderStylePreset = getRenderStylePreset(renderStyle);
|
|
@@ -2995,8 +3101,20 @@ function createSession(code, opts) {
|
|
|
2995
3101
|
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
2996
3102
|
}
|
|
2997
3103
|
setParamOverrides((opts == null ? void 0 : opts.paramOverrides) ?? {});
|
|
2998
|
-
|
|
3104
|
+
debug("session:runScript:start");
|
|
3105
|
+
const runStart = performance.now();
|
|
3106
|
+
const result = runScript(code, (opts == null ? void 0 : opts.fileName) || "main.forge.js", (opts == null ? void 0 : opts.allFiles) || {}, {
|
|
3107
|
+
quality: (opts == null ? void 0 : opts.quality) ?? "high",
|
|
3108
|
+
debug: (opts == null ? void 0 : opts.debug) ? (phase, detail) => debug(`runScript:${phase}`, detail) : void 0
|
|
3109
|
+
});
|
|
3110
|
+
debug("session:runScript:end", {
|
|
3111
|
+
ms: Number((performance.now() - runStart).toFixed(1)),
|
|
3112
|
+
objects: ((_a = result.objects) == null ? void 0 : _a.length) ?? 0,
|
|
3113
|
+
cutPlanes: ((_b = result.cutPlanes) == null ? void 0 : _b.length) ?? 0,
|
|
3114
|
+
hasError: Boolean(result.error)
|
|
3115
|
+
});
|
|
2999
3116
|
if (result.error) {
|
|
3117
|
+
debug("session:error", { error: String(result.error) });
|
|
3000
3118
|
return { ok: false, error: String(result.error) };
|
|
3001
3119
|
}
|
|
3002
3120
|
const focus = (opts == null ? void 0 : opts.focus) ?? null;
|
|
@@ -3017,6 +3135,13 @@ function createSession(code, opts) {
|
|
|
3017
3135
|
return { ok: false, error: "No renderable shape or SDF returned" };
|
|
3018
3136
|
}
|
|
3019
3137
|
const visibleObjs = objs.filter((entry) => entry.visible);
|
|
3138
|
+
debug("session:objects", {
|
|
3139
|
+
totalObjects: result.objects.length,
|
|
3140
|
+
renderableObjects: objs.length,
|
|
3141
|
+
visibleObjects: visibleObjs.length,
|
|
3142
|
+
shapeObjects: visibleObjs.filter((entry) => entry.shape != null).length,
|
|
3143
|
+
sdfObjects: visibleObjs.filter((entry) => entry.sdf != null).length
|
|
3144
|
+
});
|
|
3020
3145
|
const boundsObjs = visibleObjs.length > 0 ? visibleObjs : objs;
|
|
3021
3146
|
const objectVisibility = new Map(objs.map((entry) => [entry.source.id, entry.visible]));
|
|
3022
3147
|
const objectRenderability = new Set(objs.map((entry) => entry.source.id));
|
|
@@ -3065,6 +3190,21 @@ function createSession(code, opts) {
|
|
|
3065
3190
|
}) : [];
|
|
3066
3191
|
const scene = new Scene();
|
|
3067
3192
|
const sceneConfig = result.sceneConfig ?? null;
|
|
3193
|
+
try {
|
|
3194
|
+
if (opts == null ? void 0 : opts.viewName) {
|
|
3195
|
+
if (requestedSceneState == null ? void 0 : requestedSceneState.camera) {
|
|
3196
|
+
return {
|
|
3197
|
+
ok: false,
|
|
3198
|
+
error: "Cannot use --view with an explicit render camera. Remove --camera or the camera field from --scene."
|
|
3199
|
+
};
|
|
3200
|
+
}
|
|
3201
|
+
requestedSceneState = mergeViewportRenderSceneStates(requestedSceneState, {
|
|
3202
|
+
camera: resolveNamedSceneViewCamera(sceneConfig, opts.viewName)
|
|
3203
|
+
});
|
|
3204
|
+
}
|
|
3205
|
+
} catch (err) {
|
|
3206
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
3207
|
+
}
|
|
3068
3208
|
scene.background = parseColor((opts == null ? void 0 : opts.background) ?? renderStylePreset.background, DEFAULT_BACKGROUND);
|
|
3069
3209
|
scene.environment = (opts == null ? void 0 : opts.capture) === "section-sweep" ? null : getStudioEnvironment(r);
|
|
3070
3210
|
r.toneMappingExposure = renderStylePreset.toneMappingExposure;
|
|
@@ -3074,6 +3214,10 @@ function createSession(code, opts) {
|
|
|
3074
3214
|
addRenderStyleLights(scene, renderStyle);
|
|
3075
3215
|
}
|
|
3076
3216
|
const sceneSummary = summarizeSceneGeometry(boundsObjs);
|
|
3217
|
+
debug("session:summary", {
|
|
3218
|
+
bbox: sceneSummary.bbox,
|
|
3219
|
+
volume: Number(sceneSummary.volume.toFixed(1))
|
|
3220
|
+
});
|
|
3077
3221
|
const { bbox } = sceneSummary;
|
|
3078
3222
|
const bb = new Box3(new Vector3(...bbox.min), new Vector3(...bbox.max));
|
|
3079
3223
|
const center = new Vector3();
|
|
@@ -3083,19 +3227,29 @@ function createSession(code, opts) {
|
|
|
3083
3227
|
const maxDim = Math.max(1, bsize.x, bsize.y, bsize.z);
|
|
3084
3228
|
const fov = 45;
|
|
3085
3229
|
const distance = maxDim / (2 * Math.tan(fov * Math.PI / 360)) * 1.6;
|
|
3086
|
-
const cameraFov = ((
|
|
3087
|
-
const joints = ((
|
|
3088
|
-
const jointCouplings = ((
|
|
3089
|
-
const animationClips = ((
|
|
3090
|
-
const defaultAnimation = ((
|
|
3230
|
+
const cameraFov = ((_c = requestedSceneState == null ? void 0 : requestedSceneState.camera) == null ? void 0 : _c.fov) ?? ((_d = sceneConfig == null ? void 0 : sceneConfig.camera) == null ? void 0 : _d.fov) ?? fov;
|
|
3231
|
+
const joints = ((_e = result.jointsView) == null ? void 0 : _e.enabled) === false ? [] : ((_f = result.jointsView) == null ? void 0 : _f.joints) ?? [];
|
|
3232
|
+
const jointCouplings = ((_g = result.jointsView) == null ? void 0 : _g.enabled) === false ? [] : ((_h = result.jointsView) == null ? void 0 : _h.couplings) ?? [];
|
|
3233
|
+
const animationClips = ((_i = result.jointsView) == null ? void 0 : _i.enabled) === false ? [] : ((_j = result.jointsView) == null ? void 0 : _j.animations) ?? [];
|
|
3234
|
+
const defaultAnimation = ((_k = result.jointsView) == null ? void 0 : _k.defaultAnimation) ?? null;
|
|
3091
3235
|
let selectedAnimation;
|
|
3092
3236
|
let sweep = null;
|
|
3093
3237
|
try {
|
|
3094
3238
|
selectedAnimation = resolveSelectedAnimation(animationClips, (opts == null ? void 0 : opts.capture) ?? "orbit", defaultAnimation, opts == null ? void 0 : opts.animationName);
|
|
3095
3239
|
sweep = (opts == null ? void 0 : opts.capture) === "section-sweep" ? createSectionSweepState((opts == null ? void 0 : opts.sweep) ?? {}, bbox) : null;
|
|
3096
3240
|
} catch (err) {
|
|
3241
|
+
debug("session:sweep:error", { error: err instanceof Error ? err.message : String(err) });
|
|
3097
3242
|
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
3098
3243
|
}
|
|
3244
|
+
if (sweep) {
|
|
3245
|
+
debug("session:sweep", {
|
|
3246
|
+
normal: sweep.normal,
|
|
3247
|
+
from: Number(sweep.from.toFixed(4)),
|
|
3248
|
+
to: Number(sweep.to.toFixed(4)),
|
|
3249
|
+
padding: Number(sweep.padding.toFixed(4)),
|
|
3250
|
+
style: sweep.style
|
|
3251
|
+
});
|
|
3252
|
+
}
|
|
3099
3253
|
const enabledCutPlanes = new Set((opts == null ? void 0 : opts.enabledCutPlanes) ?? []);
|
|
3100
3254
|
const availableCutPlanes = result.cutPlanes.filter((cp) => new Vector3(cp.normal[0], cp.normal[1], cp.normal[2]).lengthSq() > 1e-8);
|
|
3101
3255
|
if (enabledCutPlanes.size > 0) {
|
|
@@ -3110,8 +3264,23 @@ function createSession(code, opts) {
|
|
|
3110
3264
|
}
|
|
3111
3265
|
const activeCutPlanes = availableCutPlanes.filter((cp) => enabledCutPlanes.has(cp.name));
|
|
3112
3266
|
const renderables = [];
|
|
3113
|
-
|
|
3267
|
+
debug("session:renderables:start", {
|
|
3268
|
+
visibleObjects: visibleObjs.length,
|
|
3269
|
+
activeCutPlanes: activeCutPlanes.length,
|
|
3270
|
+
sectionSweep: Boolean(sweep)
|
|
3271
|
+
});
|
|
3272
|
+
for (let renderableIndex = 0; renderableIndex < visibleObjs.length; renderableIndex += 1) {
|
|
3273
|
+
const obj = visibleObjs[renderableIndex];
|
|
3114
3274
|
const mp = obj.materialProps;
|
|
3275
|
+
const objectLabel = obj.source.name || obj.source.id;
|
|
3276
|
+
debug("renderable:start", {
|
|
3277
|
+
index: renderableIndex + 1,
|
|
3278
|
+
total: visibleObjs.length,
|
|
3279
|
+
id: obj.source.id,
|
|
3280
|
+
name: objectLabel,
|
|
3281
|
+
hasShape: Boolean(obj.shape),
|
|
3282
|
+
hasSdf: Boolean(obj.sdf)
|
|
3283
|
+
});
|
|
3115
3284
|
const applicableCutPlanes = activeCutPlanes.filter((cutPlane) => !isObjectExcludedFromCutPlane(obj.source, cutPlane)).map(toClippingPlane);
|
|
3116
3285
|
if (sweep && !isObjectExcludedFromCutPlane(obj.source, { normal: sweep.normal, offset: sweep.from })) {
|
|
3117
3286
|
applicableCutPlanes.push(sweep.clippingPlane);
|
|
@@ -3127,7 +3296,16 @@ function createSession(code, opts) {
|
|
|
3127
3296
|
let sdfRaymarch;
|
|
3128
3297
|
let sectionMesh = null;
|
|
3129
3298
|
if (obj.shape) {
|
|
3299
|
+
const geometryStart = performance.now();
|
|
3130
3300
|
const geo = shapeToGeometry(obj.shape);
|
|
3301
|
+
debug("renderable:geometry", {
|
|
3302
|
+
index: renderableIndex + 1,
|
|
3303
|
+
id: obj.source.id,
|
|
3304
|
+
name: objectLabel,
|
|
3305
|
+
ms: Number((performance.now() - geometryStart).toFixed(1)),
|
|
3306
|
+
triangles: Math.floor((((_l = geo.solid.getAttribute("position")) == null ? void 0 : _l.count) ?? 0) / 3),
|
|
3307
|
+
edgeSegments: Math.floor((((_m = geo.edges.getAttribute("position")) == null ? void 0 : _m.count) ?? 0) / 2)
|
|
3308
|
+
});
|
|
3131
3309
|
const materialDefaults = renderStylePreset.material;
|
|
3132
3310
|
const authoredMaterialOpacity = mp == null ? void 0 : mp.opacity;
|
|
3133
3311
|
const authoredMaterialTransmission = mp == null ? void 0 : mp.transmission;
|
|
@@ -3185,9 +3363,16 @@ function createSession(code, opts) {
|
|
|
3185
3363
|
clippingPlanes: applicableCutPlanes
|
|
3186
3364
|
});
|
|
3187
3365
|
wire = new LineSegments(geo.edges, wireMaterial);
|
|
3188
|
-
sectionMesh = sweep ? buildSectionMeshPayload(obj.source.id, obj.shape) : null;
|
|
3366
|
+
sectionMesh = sweep ? buildSectionMeshPayload(obj.source.id, obj.shape, debug, objectLabel) : null;
|
|
3189
3367
|
} else if (obj.sdf) {
|
|
3368
|
+
const sdfStart = performance.now();
|
|
3190
3369
|
const sdfRenderable = createSdfRaymarchRuntime(obj, applicableCutPlanes);
|
|
3370
|
+
debug("renderable:sdf", {
|
|
3371
|
+
index: renderableIndex + 1,
|
|
3372
|
+
id: obj.source.id,
|
|
3373
|
+
name: objectLabel,
|
|
3374
|
+
ms: Number((performance.now() - sdfStart).toFixed(1))
|
|
3375
|
+
});
|
|
3191
3376
|
solid = sdfRenderable.mesh;
|
|
3192
3377
|
solidMaterial = sdfRenderable.material;
|
|
3193
3378
|
sdfRaymarch = sdfRenderable.runtime;
|
|
@@ -3241,7 +3426,7 @@ function createSession(code, opts) {
|
|
|
3241
3426
|
}
|
|
3242
3427
|
const cameraSpec = sceneConfigCameraState && (opts == null ? void 0 : opts.capture) === "section-sweep" ? fitCameraStateToBounds(sceneConfigCameraState, bbox, cameraFov) : (requestedSceneState == null ? void 0 : requestedSceneState.camera) ?? sceneConfigCameraState;
|
|
3243
3428
|
const cameraRig = buildCameraRig(center, distance, maxDim, cameraSpec, cameraFov);
|
|
3244
|
-
const explicitCameraFov = (cameraSpec == null ? void 0 : cameraSpec.fov) ?? ((
|
|
3429
|
+
const explicitCameraFov = (cameraSpec == null ? void 0 : cameraSpec.fov) ?? ((_n = sceneConfig == null ? void 0 : sceneConfig.camera) == null ? void 0 : _n.fov);
|
|
3245
3430
|
if (explicitCameraFov && cameraRig.camera instanceof PerspectiveCamera) {
|
|
3246
3431
|
cameraRig.camera.fov = explicitCameraFov;
|
|
3247
3432
|
cameraRig.camera.updateProjectionMatrix();
|
|
@@ -3282,9 +3467,11 @@ function createSession(code, opts) {
|
|
|
3282
3467
|
captureDefaults: (sceneConfig == null ? void 0 : sceneConfig.capture) ?? null,
|
|
3283
3468
|
renderStyle
|
|
3284
3469
|
};
|
|
3470
|
+
debug("session:renderables:end", { renderables: renderables.length });
|
|
3285
3471
|
setSessionMode(session, "solid");
|
|
3286
3472
|
applyObjectTransforms(session, 0);
|
|
3287
3473
|
applyCameraPose(session.camera, session.fixedCameraState);
|
|
3474
|
+
debug("session:ready");
|
|
3288
3475
|
return { ok: true, session };
|
|
3289
3476
|
}
|
|
3290
3477
|
async function setup() {
|
|
@@ -3302,10 +3489,13 @@ async function emitInspectProgress(opts, event) {
|
|
|
3302
3489
|
}
|
|
3303
3490
|
}
|
|
3304
3491
|
window.__forgeRender = async (code, opts) => {
|
|
3305
|
-
var _a;
|
|
3492
|
+
var _a, _b;
|
|
3306
3493
|
const requestedCameraTokens = (opts == null ? void 0 : opts.cameras) ?? (opts == null ? void 0 : opts.angles);
|
|
3307
3494
|
const hasDirectionalCameraTokens = Array.isArray(requestedCameraTokens) && requestedCameraTokens.length > 0;
|
|
3308
|
-
|
|
3495
|
+
if ((opts == null ? void 0 : opts.viewName) && hasDirectionalCameraTokens) {
|
|
3496
|
+
return { ok: false, error: "Cannot use --view with --camera or --angles. Choose either a model-declared view or an explicit camera." };
|
|
3497
|
+
}
|
|
3498
|
+
const hasExplicitFixedCamera = Boolean((opts == null ? void 0 : opts.camera) || (opts == null ? void 0 : opts.cameraSpec) || ((_a = opts == null ? void 0 : opts.sceneState) == null ? void 0 : _a.camera) || (opts == null ? void 0 : opts.sceneSpec) || (opts == null ? void 0 : opts.viewName));
|
|
3309
3499
|
const cameraTokens = hasDirectionalCameraTokens ? requestedCameraTokens : hasExplicitFixedCamera ? ["__fixed"] : ["iso"];
|
|
3310
3500
|
const requestedChannelList = (opts == null ? void 0 : opts.channels) ?? ["rgb"];
|
|
3311
3501
|
const requestedChannels = new Set(requestedChannelList);
|
|
@@ -3319,6 +3509,7 @@ window.__forgeRender = async (code, opts) => {
|
|
|
3319
3509
|
background: opts == null ? void 0 : opts.background,
|
|
3320
3510
|
camera: opts == null ? void 0 : opts.camera,
|
|
3321
3511
|
cameraSpec: opts == null ? void 0 : opts.cameraSpec,
|
|
3512
|
+
viewName: opts == null ? void 0 : opts.viewName,
|
|
3322
3513
|
sceneState: opts == null ? void 0 : opts.sceneState,
|
|
3323
3514
|
sceneSpec: opts == null ? void 0 : opts.sceneSpec,
|
|
3324
3515
|
focus: opts == null ? void 0 : opts.focus,
|
|
@@ -3380,7 +3571,7 @@ window.__forgeRender = async (code, opts) => {
|
|
|
3380
3571
|
try {
|
|
3381
3572
|
let label;
|
|
3382
3573
|
if (token === "__fixed") {
|
|
3383
|
-
label = "camera";
|
|
3574
|
+
label = ((_b = opts == null ? void 0 : opts.viewName) == null ? void 0 : _b.trim()) || "camera";
|
|
3384
3575
|
applyCameraPose(session.camera, session.fixedCameraState);
|
|
3385
3576
|
} else {
|
|
3386
3577
|
const parsed = parseCameraToken(token);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const COMMERCIAL_USE_CASES = "client, employer, sale, funded product, or closed commercial IP";
|
|
2
|
+
const PRODUCTION_EXPORT_COPY = `Free to export. For ${COMMERCIAL_USE_CASES} work, Pro covers commercial use and support.`;
|
|
3
|
+
const PRO_STORAGE_UPGRADE_COPY = "Upgrade for 500 MB and commercial coverage.";
|
|
4
|
+
export {
|
|
5
|
+
COMMERCIAL_USE_CASES as C,
|
|
6
|
+
PRO_STORAGE_UPGRADE_COPY as P,
|
|
7
|
+
PRODUCTION_EXPORT_COPY as a
|
|
8
|
+
};
|