Skip to content

EN codex docs viewport api

rkfsociety edited this page Oct 21, 2026 · 1 revision

Shared rendering and viewport API v1

Полный русский перевод

Русский обзор · English reference

Русский обзор

Контракт отображения модели

Viewport API отдаёт read-only сцену, изображения и события для наблюдения за состоянием Core. Агент выбирает проект и камеру через API, не управляя DOM браузера. Координата Z направлена вверх. Точечные облака, треугольные сетки и OCCT B-rep сохраняют разные типы и пределы доказательности. PNG может быть снимком браузера либо серверным fallback; источник обозначается явно. Прогресс и действия должны отражать реальные операции. Полные схемы сцены, события и dashboard-контракт сохранены ниже.

Это обзор, не полный перевод. Полные схемы, примеры и подробности контракта приведены на английском ниже.

English reference

GET /api/v1/projects/{id}/viewport and GET /api/v1/agent/projects/{id}/viewport return identical JSON scenes. Core reads the atomically saved project snapshot, so each response reflects one committed revision. Observation requires no edit lease and does not alter project.json, command history or lease ownership. Read-only routes load the last atomically saved snapshot without waiting on an agent's edit lease, so the viewer can show the latest committed operation while the next command runs. Core checks a stat-only project-file token before loading and validating the full document; unchanged reads reuse the cached scene. On a cache miss, geometry-validation results are keyed by the document revision, which changes atomically with accepted edits. This avoids serializing and hashing large scan meshes just to check the cache. A document edit invalidates the scene, and callers receive copies so they cannot mutate the cache. Missing projects use the existing 404 contract; invalid geometry uses 400. The scene is derived, never persisted; no project/document migration is required.

The matching GET /api/v1/projects/{id}/viewport.png and GET /api/v1/agent/projects/{id}/viewport.png endpoints return the exact image/png frame drawn in the browser's main model canvas when a current browser frame is available. This includes the same camera, wireframe mode, rotation axis, global XYZ axes through the origin with a 0, 0, 0 marker, coordinate gizmo, and grid. The browser publishes frames to POST /api/v1/agent/projects/{id}/viewport/snapshot, tagged with the document revision; this is a read-only observation update, needs no edit lease, and is held in memory only. Frames are refreshed as the viewport renders, with uploads coalesced to at most 2.5 per second. The image's pixel dimensions match the browser canvas backing size. Responses identify their origin through X-CADYX-Viewport-Source (browser or server-fallback) and the source revision through X-CADYX-Document-Revision. If no browser frame has arrived, the API retains the standalone 960×720 isometric server render as a fallback. If a stored browser frame belongs to an older document revision, it is discarded and the endpoint returns the current server-rendered image while the browser catches up. Both read routes return the same bytes for a given request state.

The response has version: 1, document revision, coordinate_system: "XYZ", projection: "orthographic", bounds (min/max XYZ triples, or null when empty), and objects. Each render object has its stable object_id, document type, flat XYZ positions, and zero-based vertex index arrays: triangles (triples), lines (pairs), points (single indices). Empty arrays are explicit. Features, sketches and constraints have no independent visible geometry. OCCT B-rep triangles come from native tessellation, including face location transforms and outward winding. Viewport-only tessellation uses an absolute linear deflection of 0.01 document units to keep curved faces and edge overlays aligned at close zoom; this is a display approximation and does not alter the exact editable B-rep or exports. OCCT B-rep edges are sampled at a 0.01 document-unit deflection and returned as body lines; periodic seams and edges between adjacent faces whose local normals differ by less than 30 degrees are omitted. The browser draws these feature curves against the shaded depth buffer, so rear edges do not draw through front faces. The edge depth tolerance accounts for the combined 0.01 unit display-mesh and edge-sampling deflections; lines farther behind the surface remain hidden. Smooth-surface silhouette contours are derived from triangle facing and checked against the shaded depth buffer; depth is interpolated on the nearest rasterized triangles covering each line sample, including nearby pixel samples when the line falls on a raster coverage boundary. The edge's incident triangles are excluded from occlusion so they do not break their own contour; all other covering faces remain depth-tested. Runs shorter than 1.5 screen pixels are omitted to avoid isolated marks. During pointer orbit, the reduced-resolution frame raises that threshold to three screen pixels; the full-resolution frame restores additional detail when the pointer is released. Triangle tessellation seams are never treated as feature edges. Triangle-mesh bodies have no B-rep feature edges and therefore show only their view-dependent, depth-tested silhouette. Active sketch lines and points remain overlays and are not hidden-line tested. Editable OCCT solids include boxes, closed-profile extrusions and revolutions, swept pipes, Boolean fuses, fillets, and external metric threads. Generated involute spur gears render as ordinary XY sketch linework until extruded through the profile-feature command. Reconstructed imported scans remain validated cadyx-mesh-v1 triangle meshes rather than B-reps. Direct project point-cloud imports use the same validated descriptor with zero triangles and explicit vertex indices; the shared scene and server PNG render them as points. Point clouds are not B-reps or triangle meshes. Sketch elements are located through their saved work-plane frame: default XY points lie at Z=0, legacy XZ sketches map local y to global Z with Y=0, and v12 YZ/custom/face-attached sketches use their persisted three-dimensional frames. See work-plane contract. Circles use 64 closed segments, a display approximation rather than replacement CAD geometry. Coordinates retain document units without inventing a physical unit convention.

For 360 capture, the current frame uses a transient preview in the same canvas. After the completed preview PLY is imported as a point-cloud body, the project view restores the saved server scene and disables the duplicate file preview. The viewport API and server PNG then render the persisted body; its source units and physical scale remain unverified unless a known reference dimension is used.

The browser checks inspection and scene revisions before presenting a snapshot; if a command commits between requests, it refreshes again. SSE refreshes the scene immediately after local agent/human commands. A lightweight update snapshot also checks workspace, project, file, activity, and UI asset versions every five seconds, so changes made by another cooperating host appear automatically. Changed HTML, CSS, JavaScript assets, or browser/API compatibility version trigger a page reload; the selected project is restored. Returning to a hidden tab or reconnecting also triggers a sync. The browser keeps the read-only model viewport dominant, with section navigation on the left and an inspection column on the right. The column shows a single progress block with current status, progress and elapsed duration, the current or last actual agent action, and its current or most recently finished task. The browser does not show planned phases or future queue entries; agents continue to receive the full plan and queue through the Agent API. The column also shows front/right/top projections of the same validated viewport geometry. Orthographic wireframes include view-dependent silhouette edges so smooth revolved walls remain outlined in front and side views. Scene geometry metrics remain in the viewport footer. Object selection remains available in the Geometry view; selecting a feature shows its dimensions without overlaying tessellation edges. When the document revision changes, tree selection follows the latest visible feature so its result dimensions stay attached to the current modeling action; manual selection remains in effect until the next revision. For solid B-rep features, the Geometry inspector estimates mass from the saved CAD volume and a selected reference material density in g/cm³. The built-in values are PLA 1.24, PETG 1.27, ABS 1.04, ASA 1.07, aluminum 2.70, steel 7.80, stainless steel 8.00, and copper 8.94. They are indicative material values; the inspector also accepts a custom density. The calculation is mass_g = volume_mm3 * density_g_cm3 / 1000. Triangle meshes do not show this calculation because they do not provide a validated solid volume. The estimate assumes a solid part; 3D-print infill is not included. Reference values come from Prusament PLA, Prusament PETG, Prusament ASA, Protolabs ABS data, the Aluminum Association, Outokumpu steel data, and the Copper Development Association. Clicking empty space in the feature tree clears the tree selection, viewport highlight, and selected-item properties. Object properties are not shown in a separate panel. Files is navigation item 06 and lists direct user files in the active project through GET /api/v1/projects/{id}/files; selected files are served from the corresponding /files/{name} route. The tab is enabled only when GET /api/v1/updates?project_id={id} reports project_lock.state: FREE and the activity snapshot has no running operation. Unknown or busy lock/activity state disables the tab. Lock changes arrive over SSE and are also polled for cooperating hosts. The file view never changes the active project. Body geometry renders with only the currently edited sketch. Inactive sketches, their points/lines, and sketches already referenced by a solid feature are omitted from both the viewport and the user-facing object tree. A previously used sketch may reappear only while its profile is actively being edited, then is hidden when that edit finishes. Agent operation events animate each new sketch stroke and apply eased visual transitions to profile extrusions/revolutions, metric-thread construction, path sweeps, Boolean fuses, and edge fillets; consuming a sketch removes its overlay as the solid feature appears. Additive sketch pads and ribs use a separate transition along the source sketch plane normal and section offset; an XZ sketch grows along Y while the base below its profile remains fixed. This keeps a pad's preview consistent with its extrusion direction instead of treating every fused result as a Z-axis growth. Sweep animation precomputes each mesh vertex's progress along its nearest path segment using a segment AABB hierarchy, so it avoids scanning the entire path for every vertex. Boolean fuse hides its consumed source bodies and eases the newly connected B-rep into the scene. Sketch lines and points overlay solid shading only while that sketch is active (no hidden-line removal or viewport picking). The progress card shows the current action/result, a distinct current or most recently finished task, and a compact history of completed or failed agent actions in newest-first order. Action rows include local completion time derived from the API snapshot timestamp; the full API journal remains available to agents and is not rendered as a transcript.

Agent dashboard reports

GET /api/v1/projects/{id}/dashboard (also available under /api/v1/agent/projects/{id}/dashboard) returns the latest persisted dashboard snapshot:

{
  "workflow": {
    "title": "Проектирование детали",
    "progress_percent": 68,
    "eta_seconds": 252,
    "phases": [
      {"id": "concept", "title": "Подготовка модели", "state": "completed"},
      {"id": "design", "title": "Уточнение конструкции", "state": "in_progress"}
    ]
  },
  "tasks": [
    {"id": "042", "title": "Уточнение крепёжных элементов", "state": "running"}
  ],
  "revision": 1,
  "updated_at": "2026-10-14T12:00:00+00:00",
  "started_at": "2026-10-14T11:55:48+00:00",
  "elapsed_seconds": null
}

Agents replace the current report with POST /api/v1/agent/projects/{id}/dashboard, using workflow: null when no plan is available and tasks: [] when the queue is empty. A workflow contains 1–24 ordered phases (pending, in_progress, completed, or failed), an agent-reported progress estimate from 0 to 100, and an optional ETA in seconds. 100% is accepted only when every phase and queued task is completed; an active report cannot be cleared with workflow: null. Mark verification phases completed only after the model and its deliverables have been inspected. The queue accepts at most 100 tasks with running, pending, completed, or failed state. revision and updated_at are assigned by Core. Reports do not edit the CAD document or require an edit lease. External agent integrations publish workflow and queue updates through this Agent API endpoint. Core publishes each snapshot as agent.dashboard over SSE; /api/v1/updates includes dashboard_revision so the browser can recover missed events. Dashboard reports and their monotonic global work revision are saved together in one SQLite transaction that updates only the reported project row and the global revision, so an unfinished workflow remains active after a host restart. A legacy JSON state is imported when the SQLite store is first created. /api/v1/updates exposes agent_work_active and agent_work_revision plus the active project IDs, and the host publishes workspace.agent-work over SSE for informational status. Browser edit controls are gated by the selected project's authoritative lease/recovery snapshot and running-operation activity snapshot, not by the dashboard report. A persisted or stale unfinished workflow therefore cannot keep an otherwise-free project locked; server-side commands still enforce leases and revision checks. Unknown project availability remains fail-closed until both snapshots arrive. Hardware telemetry is not currently reported, so the UI does not display invented CPU/GPU/memory values.

Core adds started_at and elapsed_seconds to persisted dashboard snapshots; agents must not send these fields. started_at is set at the first phase in_progress or task running report. The browser counts up from this UTC timestamp and displays elapsed time in the progress strip. On verified 100% completion or a failed phase/task, Core freezes the whole-second duration in elapsed_seconds, which remains available after host or page restarts. Legacy dashboard snapshots without timer fields remain readable. The API retains the agent-reported eta_seconds for integrations, while the browser shows elapsed time in this location. Workflow titles, phase names, task titles, and agent.activity.action values are shown as received; send them in Russian to keep the localized browser interface consistent. Project names, object names, and file names remain as entered by the user or supplied by their source files.

For a modeling request, the agent should inspect the project and references, then publish a concrete ordered plan before its first model command. Use 3–7 request-specific phases with observable outcomes, initially all pending, and report 0% progress. Set ETA only when it can be estimated honestly; use null otherwise, and leave the task queue empty unless work is actually queued. Update phase states, progress, and ETA as work advances; publish a revised plan before continuing if findings change the steps. Mark phases complete only after verification, and mark failed work explicitly. Publish the plan before model changes so the agent has a stable execution sequence; the browser displays the latest actual action, current or most recently finished task, and the timestamped history of completed/failed actions without exposing future steps. When the latest action has completed and no action or agent lease is active, the progress strip appends · завершено to its action text so present-tense action names cannot be mistaken for work that is still running.

window.CadyxViewport.createViewer(canvas) is shared with PLY preview and returns:

  • load({positions, triangles, bounds, lines?, points?, bodyTriangleRanges?, featureTriangleRanges?}, {reset = true, transition?}); omit lines/points for a PLY point cloud. Use reset: false on document refresh. Agent-created sketch and profile transitions are eased in the shared viewer; regular loads and PLY previews remain static unless a transition is supplied.
  • setSelectedBody(bodyId) highlights the visible faces of that body in the shared preview. bodyTriangleRanges maps body IDs to triangle-index ranges; highlight tint is depth-tested, so hidden faces are not drawn through the model. Pass null to clear the highlight.
  • setSelectedFeature(featureId) highlights only OCCT-generated faces associated with the selected fillet or chamfer feature. featureTriangleRanges maps feature IDs to triangle-index ranges. Consumed edge-feature faces can be supplied through overlayTriangleRanges; the renderer depth-tests them against the visible mesh and keeps them out of the normal shaded pass.
  • render() redraws after resize/visibility changes.
  • fit() resets orientation and zoom to fit all scene bounds.
  • getCamera() returns {orientation, zoom, projection: "orthographic"}; orientation is a row-major 3×3 camera rotation matrix.
  • setCamera(camera) accepts that orientation matrix or the legacy {yaw, pitch} form, along with zoom within 0.25–5 and the orthographic projection. Pitch is not clamped, so legacy callers can select orientations beyond either pole.
  • orbitBy(yawDelta, pitchDelta, zoomFactor = 1) applies relative camera rotations and zoom without changing the document.

Camera drag and wheel events update camera state immediately and coalesce canvas rendering to one animation-frame callback. CAD body shading averages adjacent triangle normals at shared vertices so the lighter viewport mesh keeps a smooth surface appearance.

The browser uses a broad two-sided key light with a weaker fill light. Imported triangle-mesh bodies render as shaded surfaces in the main preview, without the bright automatically inferred boundary, crease and silhouette overlay. Holes remain visible as real geometry. Client-side surfaceTriangleRanges mark these faces in a combined scene; mixed scenes retain explicit CAD body curves and CAD edge styling. Unshaded orthographic views retain mesh wireframes. This affects presentation only and does not modify saved geometry or the viewport API scene.

Camera orientation maps world XYZ into camera [right, depth, up] coordinates. Dragging uses a virtual trackball, allowing unrestricted rotation around all three axes, including complete turns and roll. The camera triad and view cube follow the complete orientation. Wheel zooms; double-click or Вписать restores the fitted isometric view. API camera events apply incremental yaw and pitch rotations without clamping the accumulated pitch. Unless a modeling request specifies another datum, new geometry starts at global Z=0. When a scene has a shared revolution axis, the camera orbits around that axis at the body's Z midpoint; an asymmetric handle therefore cannot shift the camera pivot away from the mug centerline. Fit size accounts for the full scene bounds relative to that pivot. A compact XYZ triad tracks camera orientation; revolved bodies show a dashed Z-axis line through their rotation axis. Camera stays local to the viewer, requires no document mutation and is retained across revisions of the same project. New projects/files reset it.

Agents can animate a camera change without synthesizing browser input by posting to POST /api/v1/agent/projects/{id}/viewport/camera:

{
  "yaw_delta": 1.2,
  "pitch_delta": 0.1,
  "zoom_factor": 1.0,
  "duration_ms": 1200
}

yaw_delta is limited to ±2π, pitch_delta to ±0.5 radians, zoom_factor to 0.5–2, and duration_ms to 0–5000. The Core records a visual camera operation and publishes viewport.camera over SSE. The browser animates the change only when that project is selected. Camera state remains local to each viewer; this endpoint needs no edit lease and never changes the saved document. Events are not replayed after an SSE reconnect.

Validation: tests/test_rendering.py checks kernel mesh winding/volume/bounds, sketch rendering, parameter refresh and read-only persistence; tests/test_web_api.py checks both endpoints and unchanged inspection state; tests/test_viewport.cjs checks Z-up projection, trackball turns, camera orientation, top view, coordinate axes, zoom, validation, fit and camera preservation. See run/check commands.

Source comparison

GET /api/v1/agent/projects/{id}/comparison (also available under the read-only projects API) returns an aligned source/result mesh overlay and original, modified and delta volumes. Optional original_body_id and modified_body_id select an ancestor and descendant; defaults use the first and last saved body. Rigid transforms along the source chain are applied to the reference mesh. The panel automatically displays available comparisons: cyan reference wireframe and green result. This is a tessellated overlay, not a Boolean added/removed-material analysis. Independent assemblies return available=false by default. No project document is modified.

Clone this wiki locally