# Understanding the Display Record Transform API in cadjs: A Complete Guide

> Master the display record transform API in cadjs to compose effect matrices and offsets. Apply transforms to three.js objects efficiently every frame for stunning visuals.

- Repository: [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad)
- Tags: deep-dive
- Published: 2026-08-01

---

**The display record transform API in cadjs provides pure functions that compose per-part effect matrices and exploded-view offsets, then apply the combined transforms to three.js mesh, edge, and silhouette objects every frame.**

The display record transform API is the low-level runtime engine inside the `earthtojake/text-to-cad` repository that manages how CAD parts move, rotate, and appear in the viewer. Located in the **cadjs** package, this API encapsulates all matrix mathematics into three atomic operations, keeping the rendering pipeline clean of raw three.js boilerplate while handling step-module effects, exploded views, and visibility toggles.

## What the Display Record Transform API Does

At its core, the API transforms abstract **display records**—plain JavaScript objects that store the visual state of individual CAD parts—into updated three.js scene objects. Each display record contains `mesh`, `edges`, and `silhouette` objects, along with optional `effectMatrix` and `explodedViewMatrix` properties that represent temporary visual modifications.

### The Three-Stage Transformation Pipeline

The API processes every visual change through a strict three-stage pipeline:

1.  **Compose Effect Matrix**: Merges any step-module effect matrices with the exploded-view matrix stored on the record.
2.  **Compose Final Object Matrix**: Multiplies the effect matrix with the part’s base transform (derived from STEP or URDF pose data).
3.  **Apply to Scene Objects**: Writes the final calculated matrix directly to the three.js objects and updates visibility flags.

This design ensures that step-module effects, exploded views, and base CAD geometry all converge through a single, consistent mathematical path before hitting the GPU.

## Core Functions and Implementation Details

All functions live in [`packages/cadjs/src/common/displayRecordTransform.js`](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadjs/src/common/displayRecordTransform.js) and operate as pure functions accepting a `THREE` context and a display record.

### composeDisplayRecordEffectMatrix

**`composeDisplayRecordEffectMatrix(THREE, record)`** returns a combined `THREE.Matrix4` representing the accumulation of `record.effectMatrix` and `record.explodedViewMatrix`. If neither matrix exists, the function returns `null`, allowing the pipeline to skip unnecessary calculations.

Source: [`displayRecordTransform.js:16-31`](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadjs/src/common/displayRecordTransform.js#L16-L31)

### composeDisplayRecordObjectMatrix

**`composeDisplayRecordObjectMatrix(THREE, record)`** builds the final transformation by first generating the base part matrix via `buildPartTransformMatrix` (defined in [`stepModuleEffects.js`](https://github.com/earthtojake/text-to-cad/blob/main/stepModuleEffects.js)), then multiplying it with the effect matrix from the previous step.

Source: [`displayRecordTransform.js:34-38`](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadjs/src/common/displayRecordTransform.js#L34-L38)

### applyDisplayRecordTransform

**`applyDisplayRecordTransform(THREE, record)`** performs the actual scene update. It takes the composed matrix and applies it to `record.mesh`, `record.edges`, and `record.silhouette`, then forces three.js to recalculate the world matrix via `updateMatrixWorld()`. This is the function called every frame by the viewer.

Source: [`displayRecordTransform.js:40-48`](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadjs/src/common/displayRecordTransform.js#L40-L48)

### Helper: buildPartTransformMatrix

The pipeline relies on **`buildPartTransformMatrix(THREE, transform)`** from [`packages/cadjs/src/common/stepModuleEffects.js`](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadjs/src/common/stepModuleEffects.js) to convert raw 16-element array data into proper `THREE.Matrix4` instances. This utility bridges the gap between STEP/URDF geometric data and three.js math objects.

Source: [`stepModuleEffects.js:18-43`](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadjs/src/common/stepModuleEffects.js#L18-L43)

## Integration with the Rendering Pipeline

Understanding where the API sits in the data flow clarifies why it remains stateless and pure:

1.  **Model Loading**: `cadjs/lib/cadScene` initializes a `displayRecord` for every part, attaching the three.js objects and a `baseTransform` derived from the original CAD file.
2.  **Effect Injection**: The Step-Module Effects API (`createStepModuleEffectsApi`) writes to `effectsByPartId`, storing temporary `effectMatrix` values on specific records.
3.  **Exploded View**: The exploded-view controller writes translation matrices directly to `record.explodedViewMatrix`.
4.  **Frame Rendering**: Before each render, [`CadViewer.js`](https://github.com/earthtojake/text-to-cad/blob/main/CadViewer.js) (line 842) iterates through `runtime.displayRecords` and calls `applyDisplayRecordTransform(THREE, record)`, ensuring every visual modification appears in the final frame.

Edge-line objects reuse this same pipeline via `applyRecordEffectMatrix` in [`topologyDisplayEdgeLine.js`](https://github.com/earthtojake/text-to-cad/blob/main/topologyDisplayEdgeLine.js), guaranteeing that topology highlights and wireframes move in perfect sync with their parent meshes.

## Working Code Examples

### Applying a Step-Module Effect

Use the Step-Module Effects API to rotate a specific part, then apply the transform:

```javascript
import { createStepModuleEffectsApi } from 'cadjs/lib/stepModuleEffects';
import { applyDisplayRecordTransform } from 'cadjs/lib/viewer/modelRuntime';

const api = createStepModuleEffectsApi(runtime.THREE, {
  meshData,
  features,
  runtime,
  effectsByPartId: new Map(),
  onTransformEffect: ({ target, matrix }) => {
    console.log('Effect applied to', target);
  },
});

// Apply 45-degree rotation around Z-axis to part "001"
api.transform('001', { rotate: { axis: [0, 0, 1], angleDeg: 45 } });

// Update the scene (normally called per frame by the viewer)
runtime.displayRecords.forEach(record => {
  applyDisplayRecordTransform(runtime.THREE, record);
});

```

This stores the rotation in `record.effectMatrix`, which `applyDisplayRecordTransform` composites with the base transform before updating the three.js mesh.

### Implementing Exploded-View Translations

Apply a uniform translation to all parts to simulate an exploded assembly view:

```javascript
import { applyDisplayRecordTransform } from 'cadjs/lib/viewer/modelRuntime';

// Create a translation matrix (20mm along X-axis)
const translation = new runtime.THREE.Matrix4().makeTranslation(20, 0, 0);

// Assign to each record and immediately apply
runtime.displayRecords.forEach(record => {
  record.explodedViewMatrix = translation.clone();
  applyDisplayRecordTransform(runtime.THREE, record);
});

```

The `explodedViewMatrix` integrates seamlessly with any existing `effectMatrix`, demonstrating how the API composes multiple transform sources into a single final matrix.

## Key Source Files

| File | Role | Direct Link |
|------|------|-------------|
| [`packages/cadjs/src/common/displayRecordTransform.js`](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadjs/src/common/displayRecordTransform.js) | Core API implementation (compose & apply functions) | [displayRecordTransform.js](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadjs/src/common/displayRecordTransform.js) |
| [`packages/cadjs/src/common/stepModuleEffects.js`](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadjs/src/common/stepModuleEffects.js) | Matrix builders and effect composition helpers | [stepModuleEffects.js](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadjs/src/common/stepModuleEffects.js) |
| [`viewer/src/client/components/CadViewer.js`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/src/client/components/CadViewer.js) | Frame loop caller at line 842 | [CadViewer.js](https://github.com/earthtojake/text-to-cad/blob/main/viewer/src/client/components/CadViewer.js#L842) |
| [`viewer/packages/cadjs/src/lib/viewer/modelRuntime.js`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/cadjs/src/lib/viewer/modelRuntime.js) | Public API exposure to runtime | [modelRuntime.js](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/cadjs/src/lib/viewer/modelRuntime.js) |
| [`viewer/packages/cadjs/src/lib/viewer/topologyDisplayEdgeLine.js`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/cadjs/src/lib/viewer/topologyDisplayEdgeLine.js) | Edge-line transform reuse | [topologyDisplayEdgeLine.js](https://github.com/earthtojake/text-to-cad/blob/main/viewer/packages/cadjs/src/lib/viewer/topologyDisplayEdgeLine.js) |

## Summary

- The **display record transform API** in cadjs abstracts three.js matrix math into three pure functions: `composeDisplayRecordEffectMatrix`, `composeDisplayRecordObjectMatrix`, and `applyDisplayRecordTransform`.
- It processes **effect matrices** (from step modules) and **exploded-view matrices** separately, then composites them with base CAD transforms before writing to the scene.
- The API is invoked every frame by [`CadViewer.js`](https://github.com/earthtojake/text-to-cad/blob/main/CadViewer.js) (line 842) to ensure all visual states remain synchronized with the underlying three.js objects.
- Edge lines and topology highlights reuse the same transformation logic, maintaining visual consistency across the entire viewport.

## Frequently Asked Questions

### What is a display record in cadjs?

A **display record** is a plain JavaScript object that represents the runtime visual state of a single CAD part. It stores references to the three.js `mesh`, `edges`, and `silhouette` objects, along with `baseTransform` (the original pose from the CAD file), and optional `effectMatrix` or `explodedViewMatrix` properties for temporary visual modifications.

### How does the display record transform API handle step-module effects?

Step-module effects call `createStepModuleEffectsApi`, which writes transformation matrices into `effectsByPartId`. These matrices are stored on the relevant display record's `effectMatrix` property. When `applyDisplayRecordTransform` runs, it calls `composeDisplayRecordEffectMatrix` to merge this effect matrix with any exploded-view matrix before applying the result to the three.js objects.

### What is the difference between effectMatrix and explodedViewMatrix?

The **`effectMatrix`** stores temporary transformations generated by step-module interactions (such as highlighting, rotation, or translation effects), while the **`explodedViewMatrix`** stores offsets used specifically for exploded-view assemblies. Both matrices are optional; the API composites them together with the base transform, allowing both effects to operate simultaneously without interfering with each other.

### Where does applyDisplayRecordTransform get called in the rendering loop?

According to the source in [`viewer/src/client/components/CadViewer.js`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/src/client/components/CadViewer.js) at line 842, `applyDisplayRecordTransform` is invoked once per display record during every animation frame. This ensures that any changes to effect matrices or exploded-view states are immediately reflected in the three.js scene before the next render pass.