@classcad/mcp 0.1.5 → 0.2.1
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/README.md +21 -3
- package/dist/auth.d.ts +7 -0
- package/dist/auth.js +2 -2
- package/dist/auth.js.map +1 -1
- package/dist/client.d.ts +2 -12
- package/dist/client.js +1 -23
- package/dist/client.js.map +1 -1
- package/dist/mcp-server.d.ts +1 -1
- package/dist/mcp-server.js +9 -3
- package/dist/mcp-server.js.map +1 -1
- package/dist/queue.d.ts +7 -0
- package/dist/queue.js +22 -9
- package/dist/queue.js.map +1 -1
- package/dist/tools/auth.js +1 -1
- package/dist/tools/auth.js.map +1 -1
- package/dist/tools/lifecycle.js +42 -20
- package/dist/tools/lifecycle.js.map +1 -1
- package/dist/tools/viewer.d.ts +6 -0
- package/dist/tools/viewer.js +110 -0
- package/dist/tools/viewer.js.map +1 -0
- package/dist/viewer/scene.d.ts +60 -0
- package/dist/viewer/scene.js +271 -0
- package/dist/viewer/scene.js.map +1 -0
- package/dist/viewer/server.d.ts +27 -0
- package/dist/viewer/server.js +229 -0
- package/dist/viewer/server.js.map +1 -0
- package/dist/viewer-page/cube.svg +15 -0
- package/dist/viewer-page/fonts/LICENSE.txt +3 -0
- package/dist/viewer-page/fonts/jetbrains-mono-latin.woff2 +0 -0
- package/dist/viewer-page/index.html +135 -0
- package/dist/viewer-page/vendor/LICENSE.txt +21 -0
- package/dist/viewer-page/vendor/VERSION.txt +1 -0
- package/dist/viewer-page/vendor/addons/controls/OrbitControls.js +1963 -0
- package/dist/viewer-page/vendor/addons/lines/LineMaterial.js +726 -0
- package/dist/viewer-page/vendor/addons/lines/LineSegments2.js +434 -0
- package/dist/viewer-page/vendor/addons/lines/LineSegmentsGeometry.js +298 -0
- package/dist/viewer-page/vendor/three.core.min.js +6 -0
- package/dist/viewer-page/vendor/three.module.min.js +6 -0
- package/dist/viewer-page/viewer.css +717 -0
- package/dist/viewer-page/viewer.js +530 -0
- package/package.json +4 -3
package/dist/tools/lifecycle.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// Lifecycle tools: clear, save, load.
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { dirname, isAbsolute } from 'node:path';
|
|
5
|
+
import { buildScene, sceneToGlb } from '../viewer/scene.js';
|
|
3
6
|
export function registerLifecycleTools(server, client) {
|
|
4
7
|
server.registerTool('clear', {
|
|
5
8
|
title: 'Clear drawing',
|
|
@@ -20,29 +23,48 @@ export function registerLifecycleTools(server, client) {
|
|
|
20
23
|
});
|
|
21
24
|
server.registerTool('save', {
|
|
22
25
|
title: 'Save drawing',
|
|
23
|
-
description: '
|
|
26
|
+
description: 'Write the current drawing to a file, or return it as base64. Formats: STP (STEP, exact geometry), STL (triangles), GLB (binary glTF: triangles with colours, for 3D viewers and the web), OFB (ClassCAD\'s own format: the model with its features, to open again in ClassCAD or Buerligons), JSON. ' +
|
|
27
|
+
'With `path` the file is written to disk and only its path and size come back — the way to hand the user a model (give them the path); without it the content is returned base64-encoded, which is large. ' +
|
|
28
|
+
'The user can also download STEP, STL and GLB themselves from the live 3D view (`view`).',
|
|
24
29
|
inputSchema: {
|
|
25
|
-
format: z.enum(['STP', 'STL', 'JSON']).describe('Output format.'),
|
|
30
|
+
format: z.enum(['STP', 'STL', 'GLB', 'OFB', 'JSON']).describe('Output format.'),
|
|
31
|
+
path: z.string().optional()
|
|
32
|
+
.describe('Absolute file path to write, e.g. /Users/me/Desktop/flange.stp (folders are created). Omit to get the content back as base64.'),
|
|
26
33
|
},
|
|
27
|
-
}, async ({ format }) => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
34
|
+
}, async ({ format, path }) => {
|
|
35
|
+
let data = null;
|
|
36
|
+
let maxLevel = 0;
|
|
37
|
+
if (format === 'GLB') {
|
|
38
|
+
// The engine has no glTF: packed here from the same graphic the 3D view draws.
|
|
39
|
+
const scene = buildScene((await client.getTree()), (await client.getGraphic()));
|
|
40
|
+
if (scene.bodies.length)
|
|
41
|
+
data = sceneToGlb(scene);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
const args = { format, encoding: 'base64' };
|
|
45
|
+
if (format === 'STP')
|
|
46
|
+
args.stp = { version: 2 };
|
|
47
|
+
if (format === 'STL')
|
|
48
|
+
args.stl = { binary: true, facetingTol: 0.1, angleTol: 6 };
|
|
49
|
+
const r = await client.execute({ 'v1.common.save': [args] });
|
|
50
|
+
maxLevel = r.maxLevel;
|
|
51
|
+
if (r.result?.content)
|
|
52
|
+
data = Buffer.from(r.result.content, 'base64');
|
|
53
|
+
}
|
|
54
|
+
if (!data) {
|
|
55
|
+
return { isError: true, content: [{ type: 'text', text: JSON.stringify({ format, success: false, error: 'Nothing to save: the drawing has no geometry in this format.', maxLevel }) }] };
|
|
56
|
+
}
|
|
57
|
+
if (path) {
|
|
58
|
+
if (!isAbsolute(path))
|
|
59
|
+
return { isError: true, content: [{ type: 'text', text: JSON.stringify({ format, success: false, error: `path must be absolute: ${path}` }) }] };
|
|
60
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
61
|
+
writeFileSync(path, data);
|
|
62
|
+
return { content: [{ type: 'text', text: JSON.stringify({ format, success: true, path, bytes: data.length, maxLevel }) }] };
|
|
63
|
+
}
|
|
36
64
|
return {
|
|
37
65
|
content: [{
|
|
38
66
|
type: 'text',
|
|
39
|
-
text: JSON.stringify({
|
|
40
|
-
format,
|
|
41
|
-
success: r.result?.success ?? false,
|
|
42
|
-
bytes: r.result?.content ? Buffer.from(r.result.content, 'base64').length : 0,
|
|
43
|
-
content: r.result?.content ?? null,
|
|
44
|
-
maxLevel: r.maxLevel,
|
|
45
|
-
}),
|
|
67
|
+
text: JSON.stringify({ format, success: true, bytes: data.length, content: data.toString('base64'), maxLevel }),
|
|
46
68
|
}],
|
|
47
69
|
};
|
|
48
70
|
});
|
|
@@ -94,10 +116,10 @@ export function registerLifecycleTools(server, client) {
|
|
|
94
116
|
},
|
|
95
117
|
}, async ({ label }) => {
|
|
96
118
|
const name = (label || 'checkpoint').trim().slice(0, 60) || 'checkpoint';
|
|
97
|
-
//
|
|
119
|
+
// An OFB save, held in this process.
|
|
98
120
|
const r = await client.execute({
|
|
99
121
|
'v1.common.save': [{ format: 'OFB', encoding: 'base64' }],
|
|
100
|
-
}
|
|
122
|
+
});
|
|
101
123
|
if (!r.result?.content) {
|
|
102
124
|
return { isError: true, content: [{ type: 'text', text: JSON.stringify({ error: 'Checkpoint failed: the engine returned no OFB data.', maxLevel: r.maxLevel }) }] };
|
|
103
125
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/tools/lifecycle.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/tools/lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { Client } from '../client.js';
|
|
3
|
+
import { type ViewerSession } from '../viewer/server.js';
|
|
4
|
+
export declare const VIEWER_NOTE = "3D VIEW: every session has a live 3D view in the user's browser. It opens by itself with the first model and follows every change. Results carry its link (\"3D view: \u2026\"): give the user that link, as a clickable link on its own line, when you present a model \u2014 once, and again when they ask to see it. `view` returns the link and brings the view up; it also offers STEP, STL and glTF downloads to the user.";
|
|
5
|
+
export declare function attachViewer(server: McpServer, client: Client, log?: (msg: string) => void): Promise<ViewerSession | null>;
|
|
6
|
+
export declare function registerViewerTool(server: McpServer, viewer: ViewerSession | null): void;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// tools/viewer.ts — the session's live 3D view, wired into its tools.
|
|
2
|
+
//
|
|
3
|
+
// Every session has a view of its own (viewer/server.ts): a link that shows
|
|
4
|
+
// the model in 3D and follows it. attachViewer() patches registerTool (like
|
|
5
|
+
// serializeTools and requireSignIn) so that after a tool that may have changed
|
|
6
|
+
// the model the view is told, and so that results which show a model carry
|
|
7
|
+
// the link. The first model of a session opens the view in the browser.
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { hostName } from '../auth.js';
|
|
10
|
+
import { enqueue } from '../queue.js';
|
|
11
|
+
import { openViewerSession } from '../viewer/server.js';
|
|
12
|
+
/** Tools after which the model may be another one. */
|
|
13
|
+
const CHANGES_MODEL = new Set(['run_script', 'clear', 'load', 'restore', 'use_session']);
|
|
14
|
+
/** Results that show or change a model end with the link of its view. */
|
|
15
|
+
const OFFERS_LINK = new Set(['run_script', 'snapshot', 'load', 'restore']);
|
|
16
|
+
export const VIEWER_NOTE = '3D VIEW: every session has a live 3D view in the user\'s browser. It opens by itself with the first model and follows every change. Results carry its link ("3D view: …"): give the user that link, as a clickable link on its own line, when you present a model — once, and again when they ask to see it. `view` returns the link and brings the view up; it also offers STEP, STL and glTF downloads to the user.';
|
|
17
|
+
const engineLabel = (client) => {
|
|
18
|
+
if (client.transport === 'wasm')
|
|
19
|
+
return 'WebAssembly · this machine';
|
|
20
|
+
if (client.transport === 'bridge')
|
|
21
|
+
return 'in an app';
|
|
22
|
+
try {
|
|
23
|
+
return `worker · ${new URL(client.url).host}`;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return 'worker';
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
export async function attachViewer(server, client, log) {
|
|
30
|
+
if (process.env.CLASSCAD_VIEWER === 'off')
|
|
31
|
+
return null;
|
|
32
|
+
let viewer;
|
|
33
|
+
try {
|
|
34
|
+
viewer = await openViewerSession({
|
|
35
|
+
// Read in the session's tool queue, never in the middle of a script. An
|
|
36
|
+
// engine nobody used is not started for a look at an empty stage.
|
|
37
|
+
load: () => enqueue(server, async () => {
|
|
38
|
+
if (!client.connected && !client.localEngine)
|
|
39
|
+
return null;
|
|
40
|
+
const tree = (await client.getTree());
|
|
41
|
+
const graphic = (await client.getGraphic());
|
|
42
|
+
return { tree, graphic };
|
|
43
|
+
}),
|
|
44
|
+
exportModel: format => enqueue(server, async () => {
|
|
45
|
+
const args = { format, encoding: 'base64' };
|
|
46
|
+
if (format === 'STP')
|
|
47
|
+
args.stp = { version: 2 };
|
|
48
|
+
if (format === 'STL')
|
|
49
|
+
args.stl = { binary: true, facetingTol: 0.05, angleTol: 6 };
|
|
50
|
+
const r = await client.execute({ 'v1.common.save': [args] });
|
|
51
|
+
if (!r.result?.content)
|
|
52
|
+
throw new Error(`the engine returned no ${format} data`);
|
|
53
|
+
return Buffer.from(r.result.content, 'base64');
|
|
54
|
+
}),
|
|
55
|
+
host: () => {
|
|
56
|
+
const name = server.server.getClientVersion()?.name;
|
|
57
|
+
return name ? hostName(name) : undefined;
|
|
58
|
+
},
|
|
59
|
+
engine: () => engineLabel(client),
|
|
60
|
+
log,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
// No view is no reason to have no MCP.
|
|
65
|
+
log?.(`3D viewer not available: ${err?.message ?? err}`);
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const original = server.registerTool.bind(server);
|
|
69
|
+
server.registerTool = (name, config, handler) => {
|
|
70
|
+
if (!CHANGES_MODEL.has(name) && !OFFERS_LINK.has(name))
|
|
71
|
+
return original(name, config, handler);
|
|
72
|
+
const watched = async (...args) => {
|
|
73
|
+
const result = await handler(...args);
|
|
74
|
+
if (CHANGES_MODEL.has(name))
|
|
75
|
+
viewer.touch();
|
|
76
|
+
if (OFFERS_LINK.has(name) && result && !result.isError && Array.isArray(result.content)) {
|
|
77
|
+
result.content.push({ type: 'text', text: `3D view (live, opens in the user's browser): ${viewer.url}` });
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
};
|
|
81
|
+
return original(name, config, watched);
|
|
82
|
+
};
|
|
83
|
+
// The view ends with its session.
|
|
84
|
+
const close = client.close.bind(client);
|
|
85
|
+
client.close = () => {
|
|
86
|
+
viewer.close();
|
|
87
|
+
close();
|
|
88
|
+
};
|
|
89
|
+
return viewer;
|
|
90
|
+
}
|
|
91
|
+
export function registerViewerTool(server, viewer) {
|
|
92
|
+
server.registerTool('view', {
|
|
93
|
+
title: 'Open the 3D view',
|
|
94
|
+
description: 'The live 3D view of this session\'s model: returns its link and brings it up in the user\'s browser. The view follows every change, turns and zooms, has light and dark, and lets the user download STEP, STL or glTF. Call it when the user wants to see or turn the model; hand them the link as a clickable link on its own line. open: false only returns the link.',
|
|
95
|
+
inputSchema: {
|
|
96
|
+
open: z.boolean().optional().describe('Bring the view up in the browser (default true).'),
|
|
97
|
+
},
|
|
98
|
+
}, async ({ open }) => {
|
|
99
|
+
if (!viewer)
|
|
100
|
+
return { isError: true, content: [{ type: 'text', text: 'The 3D view is not available in this MCP (CLASSCAD_VIEWER=off, or its local listener could not start).' }] };
|
|
101
|
+
const opened = open === false ? false : viewer.open();
|
|
102
|
+
return {
|
|
103
|
+
content: [{
|
|
104
|
+
type: 'text',
|
|
105
|
+
text: `3D view of this session: ${viewer.url}\n${opened ? 'It has been opened in the user\'s browser.' : 'Give the user this link to open it.'} It follows the model live.`,
|
|
106
|
+
}],
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=viewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewer.js","sourceRoot":"","sources":["../../src/tools/viewer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
type Tree = Record<string, any>;
|
|
2
|
+
export type SceneFace = {
|
|
3
|
+
/** positions, flat xyz */
|
|
4
|
+
p: number[];
|
|
5
|
+
/** normals, flat xyz (same length as p), or null: the viewer computes them */
|
|
6
|
+
n: number[] | null;
|
|
7
|
+
/** triangle indices */
|
|
8
|
+
i: number[];
|
|
9
|
+
/** a planar face has no silhouette */
|
|
10
|
+
flat: boolean;
|
|
11
|
+
/** the face's own colour, when it differs from its body's */
|
|
12
|
+
c?: [number, number, number];
|
|
13
|
+
};
|
|
14
|
+
export type SceneBody = {
|
|
15
|
+
/** the solid's id in the structure tree */
|
|
16
|
+
id: number;
|
|
17
|
+
name: string;
|
|
18
|
+
/** the colour the model gave the body, or null: it takes the paper's */
|
|
19
|
+
color: [number, number, number] | null;
|
|
20
|
+
opacity: number;
|
|
21
|
+
faces: SceneFace[];
|
|
22
|
+
/** B-rep edges as polylines, flat xyz */
|
|
23
|
+
edges: number[][];
|
|
24
|
+
};
|
|
25
|
+
export type Scene = {
|
|
26
|
+
kind: 'PART' | 'ASSEMBLY' | 'EMPTY';
|
|
27
|
+
name: string;
|
|
28
|
+
bodies: SceneBody[];
|
|
29
|
+
/** where each body is drawn: a row-major 4×4 per placement (identity in a part) */
|
|
30
|
+
placements: {
|
|
31
|
+
body: number;
|
|
32
|
+
m: number[];
|
|
33
|
+
}[];
|
|
34
|
+
features: {
|
|
35
|
+
no: number;
|
|
36
|
+
name: string;
|
|
37
|
+
kind: string;
|
|
38
|
+
}[];
|
|
39
|
+
stats: {
|
|
40
|
+
bodies: number;
|
|
41
|
+
faces: number;
|
|
42
|
+
triangles: number;
|
|
43
|
+
edges: number;
|
|
44
|
+
};
|
|
45
|
+
/** world bounds of everything placed, or null when empty */
|
|
46
|
+
bounds: {
|
|
47
|
+
min: [number, number, number];
|
|
48
|
+
max: [number, number, number];
|
|
49
|
+
} | null;
|
|
50
|
+
};
|
|
51
|
+
export declare function buildScene(tree: Tree | null | undefined, graphic: {
|
|
52
|
+
containers?: any[];
|
|
53
|
+
} | null | undefined): Scene;
|
|
54
|
+
/**
|
|
55
|
+
* The scene as binary glTF 2.0: one mesh per body, one node per placement,
|
|
56
|
+
* Z up turned to glTF's Y up at the root. Bodies without a colour of their
|
|
57
|
+
* own are white. Edges are not part of it (glTF viewers draw faces).
|
|
58
|
+
*/
|
|
59
|
+
export declare function sceneToGlb(scene: Scene): Buffer;
|
|
60
|
+
export {};
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
// viewer/scene.ts — what the 3D viewer draws, built from a session's
|
|
2
|
+
// structure tree and graphic exactly as the PNG renderer reads them: live
|
|
3
|
+
// solids only (a consumed body's container is stale), and in an assembly one
|
|
4
|
+
// placement per part instance.
|
|
5
|
+
import { extractAssemblyInstances, graphicWithEdges, isConsumedSolid } from '@classcad/renderer';
|
|
6
|
+
const IDENTITY = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
|
7
|
+
/** The engine's colour for a body nobody coloured: such a body is drawn as paper. */
|
|
8
|
+
const ENGINE_DEFAULT = [[128, 128, 128]];
|
|
9
|
+
const rgb = (c) => {
|
|
10
|
+
if (!Array.isArray(c) || c.length < 3)
|
|
11
|
+
return null;
|
|
12
|
+
// the engine sends 0–255; tolerate 0–1
|
|
13
|
+
const scale = c.every(v => typeof v === 'number' && v <= 1) ? 255 : 1;
|
|
14
|
+
return [Math.round(c[0] * scale), Math.round(c[1] * scale), Math.round(c[2] * scale)];
|
|
15
|
+
};
|
|
16
|
+
const ownColor = (c) => {
|
|
17
|
+
const v = rgb(c);
|
|
18
|
+
if (!v)
|
|
19
|
+
return null;
|
|
20
|
+
return ENGINE_DEFAULT.some(d => d[0] === v[0] && d[1] === v[1] && d[2] === v[2]) ? null : v;
|
|
21
|
+
};
|
|
22
|
+
const same = (a, b) => (a && b ? a[0] === b[0] && a[1] === b[1] && a[2] === b[2] : a === b);
|
|
23
|
+
/** 4 decimals: a tenth of a micron, and a third less JSON. */
|
|
24
|
+
const round = (a) => {
|
|
25
|
+
const out = new Array(a.length);
|
|
26
|
+
for (let i = 0; i < a.length; i++)
|
|
27
|
+
out[i] = Math.round(a[i] * 1e4) / 1e4;
|
|
28
|
+
return out;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Features in build order. The operation sequence holds references
|
|
32
|
+
* (`refObj` → the feature); the datums' references and the rollback bar are
|
|
33
|
+
* not features.
|
|
34
|
+
*/
|
|
35
|
+
function features(tree) {
|
|
36
|
+
const out = [];
|
|
37
|
+
const seq = Object.values(tree).find(n => n?.class === 'CC_OperationSequence');
|
|
38
|
+
for (const id of seq?.children ?? []) {
|
|
39
|
+
const ref = tree[String(id)];
|
|
40
|
+
const target = tree[String(ref?.members?.refObj?.value)];
|
|
41
|
+
if (!target || /^CC_(Work|RollbackBar)/.test(String(target.class ?? '')))
|
|
42
|
+
continue;
|
|
43
|
+
out.push({ no: out.length + 1, name: String(target.name ?? ''), kind: String(target.class ?? '').replace(/^CC_/, '') });
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
export function buildScene(tree, graphic) {
|
|
48
|
+
const t = tree ?? {};
|
|
49
|
+
// Analytic edges arrive as lines and arcs; as the renderer does, draw them as edges too.
|
|
50
|
+
const containers = (graphicWithEdges(graphic)?.containers ?? []).filter((c) => (c?.meshes?.length ?? 0) > 0 && !isConsumedSolid(t, c.owner));
|
|
51
|
+
const root = Object.values(t).find(n => n?.class === 'CC_AssemblyRoot') ?? Object.values(t).find(n => n?.class === 'CC_Part');
|
|
52
|
+
const kind = !root ? 'EMPTY' : root.class === 'CC_AssemblyRoot' ? 'ASSEMBLY' : 'PART';
|
|
53
|
+
const bodies = [];
|
|
54
|
+
const bodyOfOwner = new Map();
|
|
55
|
+
let faces = 0;
|
|
56
|
+
let triangles = 0;
|
|
57
|
+
let edges = 0;
|
|
58
|
+
for (const c of containers) {
|
|
59
|
+
const color = ownColor(c.properties?.material?.color);
|
|
60
|
+
const body = {
|
|
61
|
+
id: Number(c.owner ?? c.id),
|
|
62
|
+
name: String(t[String(c.owner)]?.name ?? t[String(c.id)]?.name ?? 'Body'),
|
|
63
|
+
color,
|
|
64
|
+
opacity: typeof c.properties?.material?.opacity === 'number' ? c.properties.material.opacity : 1,
|
|
65
|
+
faces: [],
|
|
66
|
+
edges: [],
|
|
67
|
+
};
|
|
68
|
+
for (const m of c.meshes) {
|
|
69
|
+
if (!m?.vertices?.length || !m?.indices?.length)
|
|
70
|
+
continue;
|
|
71
|
+
const fc = ownColor(m.properties?.material?.color);
|
|
72
|
+
body.faces.push({
|
|
73
|
+
p: round(m.vertices),
|
|
74
|
+
n: m.normals?.length === m.vertices.length ? round(m.normals) : null,
|
|
75
|
+
i: Array.from(m.indices),
|
|
76
|
+
flat: m.properties?.surface?.type === 'plane',
|
|
77
|
+
...(fc && !same(fc, color) ? { c: fc } : {}),
|
|
78
|
+
});
|
|
79
|
+
faces++;
|
|
80
|
+
triangles += m.indices.length / 3;
|
|
81
|
+
}
|
|
82
|
+
// A seam is not a line of the part: it is where one curved face closes on
|
|
83
|
+
// itself. An edge of a solid lies between two faces; a seam borders one.
|
|
84
|
+
const borders = new Map();
|
|
85
|
+
for (const m of c.meshes) {
|
|
86
|
+
for (const loop of m.loops ?? []) {
|
|
87
|
+
for (const id of loop) {
|
|
88
|
+
const faces = borders.get(id) ?? new Set();
|
|
89
|
+
faces.add(m.id);
|
|
90
|
+
borders.set(id, faces);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const isSeam = (id) => borders.size > 0 && (borders.get(id)?.size ?? 0) < 2;
|
|
95
|
+
for (const e of c.edges ?? []) {
|
|
96
|
+
if (e?.points?.length >= 6 && !isSeam(e.id)) {
|
|
97
|
+
body.edges.push(round(e.points));
|
|
98
|
+
edges++;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (!body.faces.length)
|
|
102
|
+
continue;
|
|
103
|
+
bodyOfOwner.set(body.id, bodies.length);
|
|
104
|
+
bodies.push(body);
|
|
105
|
+
}
|
|
106
|
+
// An assembly draws each part's bodies once per instance; a part draws them where they are.
|
|
107
|
+
const instances = kind === 'ASSEMBLY' ? extractAssemblyInstances(t) : null;
|
|
108
|
+
const placements = [];
|
|
109
|
+
if (instances?.length) {
|
|
110
|
+
for (const inst of instances) {
|
|
111
|
+
const body = bodyOfOwner.get(Number(inst.ownerSolidId));
|
|
112
|
+
if (body != null)
|
|
113
|
+
placements.push({ body, m: inst.transform.map(Number) });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
bodies.forEach((_, body) => placements.push({ body, m: IDENTITY }));
|
|
118
|
+
}
|
|
119
|
+
// world bounds
|
|
120
|
+
let bounds = null;
|
|
121
|
+
const min = [Infinity, Infinity, Infinity];
|
|
122
|
+
const max = [-Infinity, -Infinity, -Infinity];
|
|
123
|
+
for (const pl of placements) {
|
|
124
|
+
const m = pl.m;
|
|
125
|
+
for (const f of bodies[pl.body].faces) {
|
|
126
|
+
for (let k = 0; k < f.p.length; k += 3) {
|
|
127
|
+
const x = f.p[k], y = f.p[k + 1], z = f.p[k + 2];
|
|
128
|
+
const w = [m[0] * x + m[1] * y + m[2] * z + m[3], m[4] * x + m[5] * y + m[6] * z + m[7], m[8] * x + m[9] * y + m[10] * z + m[11]];
|
|
129
|
+
for (let a = 0; a < 3; a++) {
|
|
130
|
+
if (w[a] < min[a])
|
|
131
|
+
min[a] = w[a];
|
|
132
|
+
if (w[a] > max[a])
|
|
133
|
+
max[a] = w[a];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (placements.length && Number.isFinite(min[0]))
|
|
139
|
+
bounds = { min, max };
|
|
140
|
+
return {
|
|
141
|
+
kind: bodies.length || kind !== 'EMPTY' ? kind : 'EMPTY',
|
|
142
|
+
name: String(root?.name ?? ''),
|
|
143
|
+
bodies,
|
|
144
|
+
placements,
|
|
145
|
+
features: kind === 'PART' ? features(t) : [],
|
|
146
|
+
stats: { bodies: placements.length, faces, triangles, edges },
|
|
147
|
+
bounds,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
// ─── GLB ───────────────────────────────────────────────────────────────────
|
|
151
|
+
/**
|
|
152
|
+
* The scene as binary glTF 2.0: one mesh per body, one node per placement,
|
|
153
|
+
* Z up turned to glTF's Y up at the root. Bodies without a colour of their
|
|
154
|
+
* own are white. Edges are not part of it (glTF viewers draw faces).
|
|
155
|
+
*/
|
|
156
|
+
export function sceneToGlb(scene) {
|
|
157
|
+
const chunks = [];
|
|
158
|
+
let offset = 0;
|
|
159
|
+
const bufferViews = [];
|
|
160
|
+
const accessors = [];
|
|
161
|
+
const push = (buf, target) => {
|
|
162
|
+
const pad = (4 - (buf.length % 4)) % 4;
|
|
163
|
+
bufferViews.push({ buffer: 0, byteOffset: offset, byteLength: buf.length, target });
|
|
164
|
+
chunks.push(buf, Buffer.alloc(pad));
|
|
165
|
+
offset += buf.length + pad;
|
|
166
|
+
return bufferViews.length - 1;
|
|
167
|
+
};
|
|
168
|
+
const materials = [];
|
|
169
|
+
const materialOf = (c, opacity) => {
|
|
170
|
+
const col = c ?? [255, 255, 255];
|
|
171
|
+
const key = `${col.join(',')}|${opacity}`;
|
|
172
|
+
let i = materials.findIndex(m => m.extras.key === key);
|
|
173
|
+
if (i < 0) {
|
|
174
|
+
const lin = (v) => Math.pow(v / 255, 2.2);
|
|
175
|
+
materials.push({
|
|
176
|
+
pbrMetallicRoughness: { baseColorFactor: [lin(col[0]), lin(col[1]), lin(col[2]), opacity], metallicFactor: 0, roughnessFactor: 0.8 },
|
|
177
|
+
doubleSided: true,
|
|
178
|
+
...(opacity < 1 ? { alphaMode: 'BLEND' } : {}),
|
|
179
|
+
extras: { key },
|
|
180
|
+
});
|
|
181
|
+
i = materials.length - 1;
|
|
182
|
+
}
|
|
183
|
+
return i;
|
|
184
|
+
};
|
|
185
|
+
const meshes = scene.bodies.map(body => {
|
|
186
|
+
// one primitive per colour
|
|
187
|
+
const groups = new Map();
|
|
188
|
+
for (const f of body.faces) {
|
|
189
|
+
const color = f.c ?? body.color;
|
|
190
|
+
const key = color ? color.join(',') : '-';
|
|
191
|
+
const g = groups.get(key) ?? { color, faces: [] };
|
|
192
|
+
g.faces.push(f);
|
|
193
|
+
groups.set(key, g);
|
|
194
|
+
}
|
|
195
|
+
const primitives = [...groups.values()].map(g => {
|
|
196
|
+
let nv = 0;
|
|
197
|
+
let ni = 0;
|
|
198
|
+
for (const f of g.faces) {
|
|
199
|
+
nv += f.p.length / 3;
|
|
200
|
+
ni += f.i.length;
|
|
201
|
+
}
|
|
202
|
+
const pos = new Float32Array(nv * 3);
|
|
203
|
+
const nor = new Float32Array(nv * 3);
|
|
204
|
+
const idx = new Uint32Array(ni);
|
|
205
|
+
const lo = [Infinity, Infinity, Infinity];
|
|
206
|
+
const hi = [-Infinity, -Infinity, -Infinity];
|
|
207
|
+
let vo = 0;
|
|
208
|
+
let io = 0;
|
|
209
|
+
let normals = true;
|
|
210
|
+
for (const f of g.faces) {
|
|
211
|
+
pos.set(f.p, vo * 3);
|
|
212
|
+
if (f.n)
|
|
213
|
+
nor.set(f.n, vo * 3);
|
|
214
|
+
else
|
|
215
|
+
normals = false;
|
|
216
|
+
for (let k = 0; k < f.i.length; k++)
|
|
217
|
+
idx[io + k] = f.i[k] + vo;
|
|
218
|
+
for (let k = 0; k < f.p.length; k += 3) {
|
|
219
|
+
for (let a = 0; a < 3; a++) {
|
|
220
|
+
if (f.p[k + a] < lo[a])
|
|
221
|
+
lo[a] = f.p[k + a];
|
|
222
|
+
if (f.p[k + a] > hi[a])
|
|
223
|
+
hi[a] = f.p[k + a];
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
vo += f.p.length / 3;
|
|
227
|
+
io += f.i.length;
|
|
228
|
+
}
|
|
229
|
+
const attributes = {};
|
|
230
|
+
accessors.push({ bufferView: push(Buffer.from(pos.buffer), 34962), componentType: 5126, count: nv, type: 'VEC3', min: lo, max: hi });
|
|
231
|
+
attributes.POSITION = accessors.length - 1;
|
|
232
|
+
if (normals) {
|
|
233
|
+
accessors.push({ bufferView: push(Buffer.from(nor.buffer), 34962), componentType: 5126, count: nv, type: 'VEC3' });
|
|
234
|
+
attributes.NORMAL = accessors.length - 1;
|
|
235
|
+
}
|
|
236
|
+
accessors.push({ bufferView: push(Buffer.from(idx.buffer), 34963), componentType: 5125, count: ni, type: 'SCALAR' });
|
|
237
|
+
return { attributes, indices: accessors.length - 1, material: materialOf(g.color, body.opacity), mode: 4 };
|
|
238
|
+
});
|
|
239
|
+
return { name: body.name, primitives };
|
|
240
|
+
});
|
|
241
|
+
// glTF matrices are column-major; ours are row-major. The root turns Z up into Y up, in metres.
|
|
242
|
+
const columnMajor = (m) => [m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13], m[2], m[6], m[10], m[14], m[3], m[7], m[11], m[15]];
|
|
243
|
+
const nodes = scene.placements.map(pl => ({ name: scene.bodies[pl.body].name, mesh: pl.body, matrix: columnMajor(pl.m) }));
|
|
244
|
+
nodes.push({ name: scene.name || 'ClassCAD', children: nodes.map((_, i) => i), matrix: [0.001, 0, 0, 0, 0, 0, -0.001, 0, 0, 0.001, 0, 0, 0, 0, 0, 1] });
|
|
245
|
+
const bin = Buffer.concat(chunks);
|
|
246
|
+
const json = {
|
|
247
|
+
asset: { version: '2.0', generator: 'ClassCAD MCP' },
|
|
248
|
+
scene: 0,
|
|
249
|
+
scenes: [{ nodes: [nodes.length - 1] }],
|
|
250
|
+
nodes,
|
|
251
|
+
meshes,
|
|
252
|
+
materials: materials.map(({ extras, ...m }) => m),
|
|
253
|
+
accessors,
|
|
254
|
+
bufferViews,
|
|
255
|
+
buffers: [{ byteLength: bin.length }],
|
|
256
|
+
};
|
|
257
|
+
let jsonBuf = Buffer.from(JSON.stringify(json), 'utf8');
|
|
258
|
+
jsonBuf = Buffer.concat([jsonBuf, Buffer.alloc((4 - (jsonBuf.length % 4)) % 4, 0x20)]);
|
|
259
|
+
const header = Buffer.alloc(12);
|
|
260
|
+
header.writeUInt32LE(0x46546c67, 0);
|
|
261
|
+
header.writeUInt32LE(2, 4);
|
|
262
|
+
header.writeUInt32LE(12 + 8 + jsonBuf.length + 8 + bin.length, 8);
|
|
263
|
+
const jsonHead = Buffer.alloc(8);
|
|
264
|
+
jsonHead.writeUInt32LE(jsonBuf.length, 0);
|
|
265
|
+
jsonHead.writeUInt32LE(0x4e4f534a, 4);
|
|
266
|
+
const binHead = Buffer.alloc(8);
|
|
267
|
+
binHead.writeUInt32LE(bin.length, 0);
|
|
268
|
+
binHead.writeUInt32LE(0x004e4942, 4);
|
|
269
|
+
return Buffer.concat([header, jsonHead, jsonBuf, binHead, bin]);
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=scene.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene.js","sourceRoot":"","sources":["../../src/viewer/scene.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type ViewerSource = {
|
|
2
|
+
/** Structure tree and graphic of the session, read in its tool queue. null: the engine was never used. */
|
|
3
|
+
load: () => Promise<{
|
|
4
|
+
tree: Record<string, any>;
|
|
5
|
+
graphic: {
|
|
6
|
+
containers?: any[];
|
|
7
|
+
} | null;
|
|
8
|
+
} | null>;
|
|
9
|
+
/** The model in an engine format, read in the session's tool queue. */
|
|
10
|
+
exportModel: (format: 'STP' | 'STL') => Promise<Buffer>;
|
|
11
|
+
/** The host as people know it ("Claude Code"), and where the engine runs. */
|
|
12
|
+
host: () => string | undefined;
|
|
13
|
+
engine: () => string;
|
|
14
|
+
log?: (msg: string) => void;
|
|
15
|
+
};
|
|
16
|
+
export type ViewerSession = {
|
|
17
|
+
/** The link of this session's view. */
|
|
18
|
+
readonly url: string;
|
|
19
|
+
/** The model may have changed: watchers are told, and the first model opens the view. */
|
|
20
|
+
touch: () => void;
|
|
21
|
+
/** Opens the view in the user's browser now. False where there is no browser to open. */
|
|
22
|
+
open: () => boolean;
|
|
23
|
+
/** The session is over: its watchers are told and the link stops working. */
|
|
24
|
+
close: () => void;
|
|
25
|
+
};
|
|
26
|
+
/** A session's view. The listener starts with the first one. */
|
|
27
|
+
export declare function openViewerSession(source: ViewerSource): Promise<ViewerSession>;
|