CoolFace
Datasetpublic

hz6666/3d-wm-atomic-v2

3d-wm-atomic-v2 — Synthetic CAD construction videos Per-op animated frame sequences for CadQuery construction programs, with per-frame atomic op labels in continuous raw mm. Designed as training data for video → action (IDM) and image → next frame (video-gen) models. Format version: v2-continuous-mm (2026-05-29 onward). One clip = one (case, view) pair data_*/{bNNNN}/train/shard-NNNNNN.tar └── {case_uid}_v{NN}/ ├── 0000.png .. NNNN.png # 256x256 rendered… See the full description on the dataset page: https://huggingface.co/datasets/hz6666/3d-wm-atomic-v2.

sourceHugging Facecc-by-4.0updated 4mo agoView on Hugging Face
0likes284downloads
Dataset Card

3d-wm-atomic-v2 — Synthetic CAD construction videos

Per-op animated frame sequences for CadQuery construction programs, with per-frame atomic op labels in continuous raw mm. Designed as training data for video → action (IDM) and image → next frame (video-gen) models.

Format version: `v2-continuous-mm` (2026-05-29 onward).

One clip = one (case, view) pair

data_*/{bNNNN}/train/shard-NNNNNN.tar
└── {case_uid}_v{NN}/
    ├── 0000.png .. NNNN.png   # 256x256 rendered frames
    ├── meta.json              # all metadata + per-frame op_spans
    ├── ops.json               # full atomic op sequence
    └── frame_codes.json       # per-frame partial CadQuery code

A case is one CAD program rendered from 5 sibling views (iso, front, side, top, random) sharing the same anchor — physical mm/pixel identical across the 5 views, only the camera angle changes.

Atomic op vocabulary (continuous mm, no quantization)

op_idnameparams (schema order)
8SKETCH_BEGINplaneidx (int), originxyz (3×float mm), start_xy (2×float mm)
9SEGMENTx, y (2×float mm)
10ARCmidxy, endxy (4×float mm)
11LOOP_BREAKstart_xy (2×float mm) — open a new sketch loop
12SKETCH_CLOSE— (no params)
13SKETCH_EXTRUDEh (float mm), kind (int: 0=fresh, 1=union, 2=cut)
14END_SKETCH— terminal marker
15SKETCH_CIRCLEr (float mm)
3FILLETedge_idx (int: 0=\Z, 1=\X, 2=\Y), r (float mm)
4CHAMFERedge_idx (int), r (float mm)

Op IDs are STABLE. Sparse IDs (0, 1, 2, 5, 6, 7) are reserved.

Categorical alphabets

  • plane_idx["XY", "YZ", "ZX"]
  • extrude_kind["fresh", "union", "cut"]
  • edge_idx["|Z", "|X", "|Y"]

Example op tuple (from a real clip)

python
[8, 1, -30.0, 0.0, 0.0, 16.0, -20.0]   # SKETCH_BEGIN plane=YZ origin=(-30,0,0) start=(16,-20)
[15, 30.0]                              # SKETCH_CIRCLE r=30.0
[12]                                    # SKETCH_CLOSE
[13, 32.0, 0]                           # SKETCH_EXTRUDE h=32.0 kind=fresh
[14]                                    # END_SKETCH

meta.json key fields

fieldtypemeaning
format_versionstralways "v2-continuous-mm"
uid / base_uid / view_idx / view_nameidentifiersclip id, case id, view 0..N-1, name (iso etc.)
n_framesintnumber of PNGs in this clip
frame_sizeintpx (square)
cam_elev_azim_deg[elev, azim]spherical camera angle in degrees
camera_zoomfloatconstant 0.62 (Open3D set_zoom value)
world_bbox_min / world_bbox_max[x,y,z] mmscene-anchor bbox (final mesh + sketch ribbon overlays) after canonicalization
world_bbox_padded_*[x,y,z] mmscene-anchor bbox after 15%/5mm padding
world_diag_mmfloat mmpadded-bbox 3D diagonal
approx_mm_per_pixelfloat mm/pxworld_diag_mm × camera_zoom / frame_size
canonicalize_offset_mm[x,y,z] mmoriginal = canonical + offset (translation undo)
op_spansarrayone entry per PNG frame, see below
codestrfull CadQuery program for this clip (canonical frame)
exec_okbooltrue if the final-state CadQuery program executed (intermediate per-frame meshes are not separately validated; a tessellation failure on an animation frame falls back to a light-gray placeholder PNG)

op_spans per-frame entry

Each frame has exactly one span. For animated extrude frames, action_op contains SKETCH_EXTRUDE with h = full_h × op_progress so each frame carries a distinct numeric target.

json
{
  "frame_idx": 5,
  "op_idx": 4,
  "op_type": "SKETCH_EXTRUDE",
  "op_progress": 0.864,
  "kind": "extrude",
  "keyframe": false,
  "action_op": [13, 27.65, 0],
  "action_op_human": "SKETCH_EXTRUDE(h=27.65, kind=fresh)"
}

op_progress is the fraction of the full extrude already drawn at this frame. Mostly in (0, 1.0]. With probability ~30% the second-to-last extrude frame overshoots to (1.0, 1.3] — explicitly trained-on negative-feedback signal for inverse-dynamics models.

Translation canonicalization

The renderer shifts each case so the final-mesh bbox is centered at world (0, 0, 0) before generating PNGs and actionop. Two cases that differ only by world translation produce identical PNGs + identical ops.json + identical actionop tuples, with the difference recorded ONLY in canonicalize_offset_mm. Recover original world coords with:

python
original_world_xyz = canonical_xyz + meta["canonicalize_offset_mm"]

No rotation / scale canonicalization is applied — those would be lossy or brittle.

Coordinate frames

  • Continuous params (length / coord) are in canonical-frame mm (canonicalization above).
  • world_bbox_* fields are also in canonical frame.
  • cam_elev_azim_deg is spherical: elev measured from XY plane, azim from +X axis CCW around +Z. front_dir = (cos·elev·cos·azim, cos·elev·sin·azim, sin·elev). Camera position = bbox_center + camera_distance × front_dir, looking back at bbox_center.

Per-clip vs dataset-wide normalization

Default: per-clip auto-fit (each clip fills ~62% of the frame). To recover physical mm from a PNG pixel:

python
mm_per_px = meta["approx_mm_per_pixel"]
mm_offset_from_image_center = pixel_offset × mm_per_px

If meta["reference_bbox_diag"] is non-null, the renderer forced a constant world_diag_mm across the dataset → constant mm/pixel.

Sibling views share scale

For each base_uid, all sibling clips {base_uid}_v00..vNN share exactly the same world_bbox_*, world_diag_mm, and approx_mm_per_pixel. Only cam_elev_azim_deg differs. Use this contract to train view-invariant features.

Recommended downstream normalization recipe

python
# IDM training (predict action_op given video frames):
half_extent = max(
    max(abs(c) for c in meta["world_bbox_min"]),
    max(abs(c) for c in meta["world_bbox_max"]),
)
def normalize_coord(mm): return mm / half_extent          # -> [-1, 1]
def normalize_length(mm): return mm / (half_extent * 2)   # -> [0, 1]

Apply the inverse at sampling / inference time.

For video frames: standard (x / 255 - mean) / std with ImageNet stats or per-dataset stats.

Format transition note

This dataset was migrated to v2-continuous-mm on 2026-05-29. Earlier flat prefixes have been removed. The data_hula_b01..b06 prefixes are being progressively re-rendered and overwritten to v2; until that chain finishes, a minority of bNNNN shards may still carry the older bin-quantized integer encoding (length [0,60] mm @ 128 bins, coord [-30,30] mm @ 128 bins). Always branch on meta["format_version"]: trust only shards whose meta/ops report "v2-continuous-mm".

Source

Cases are parsed from `filapro/cad-recode` training splits and re-rendered with per-op animation.