CameraMotionNode
Turn a trajectory into a fly-through video of your point cloud
- pointcloud
- trajectory
- motion_frames
- mask_frames
CameraMotionNode is where your 3D work finally becomes a video. You've got a point cloud (from DepthToPointCloud), you've got a trajectory (from CameraInterpolationNode or a recorded path), and this node renders the cloud from every pose along that path into a sequence of frames - plus a matching mask that tells you exactly which pixels are "real" 3D geometry and which are empty holes you'll need to fill.
It's the renderer behind the pack's pointcloud_walker.json fly-through demo and the driving engine of pointcloud_inpaint.json, where those mask frames get fed to an inpainter so the disoccluded areas (the gaps behind the geometry as the camera moves) get plausibly filled before you keep flying.
What you feed it
The pointcloud is a (N,7) tensor - XYZ plus RGBA per point, the format every cloud node in this pack speaks. trajectory is a (K,4,4) pose stack. Then the fun starts:
n_points(default 10) is frames per trajectory segment, not total frames. A 20-pose trajectory atn_points=10gives you 200 output frames. That's the input people consistently underestimate - a big number here is a big render.output_projectionis your pick of PINHOLE, FISHEYE, or EQUIRECTANGULAR, withoutput_horizontal_fov(default 90°) andoutput_width/output_height(default 512², up to 16384) controlling the virtual lens. This is how you get a 180° VR-compatible fly-through out of a pinhole pipeline: switch the projection, widen the FOV.point_size(default 1) sets the splat radius of each point. Crank it up for a denser-looking, filled render; keep it low for a crisp point cloud look.points_to_mask(default off) controls whether the mask output marks where points landed. Leave it on when you're doing inpaint-driven disocclusion filling - that's the whole point of thepointcloud_inpaintworkflow.
Two mask controls worth knowing: widen_mask (default 0) dilates the mask edges by up to 64 pixels, and invert_mask flips it. When you're inpaining, the mask convention mismatch between this node and your inpainter is the most common fix-it - hit invert_mask before you blame the model.
Outputs
Two things come out: motion_frames (an IMAGE batch, one frame per trajectory step) and mask_frames (a MASK batch, 1.0 where points projected). They're both is_list=false, so a video model or an image-to-video upscaler can eat the frame batch directly - the WAN VACE video_camera.json workflow builds on exactly that.
Install and requirements
It's a camera-comfyUI node, so the shared install applies: Manager → search "camera-comfyUI" → Install, or clone into custom_nodes/ and run python install.py for the optional heavy deps. This node itself is CPU-friendly math - no models to download, no gsplat needed - which makes it the cheapest way in this pack to preview whether a camera move is worth committing to.
Troubleshooting
- Frames are full of holes: normal. That's what the mask + inpainting stage is for. For a cleaner preview, raise
point_size. - It renders forever: your
n_points × trajectory lengthgot away from you, and/or you're at 4K. Render previews at 512 and 30 frames. - Warped geometry at the edges: if your cloud was built from depth, make sure the depth went through ZDepthToRayDepthNode first - Z-depth straight into the cloud lifts geometry wrong at wide FOVs, and no camera move will look right after that.
The workflow loop to remember: CameraInterpolationNode for the path → CameraMotionNode for frames + masks → an inpainter fills the holes → you've got a camera move.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| pointcloud | TENSOR | — | |
| trajectory | TENSOR | — | |
| n_points | INT | 10 | — |
| output_projection | COMBO | 3 options: PINHOLE, FISHEYE, EQUIRECTANGULAR | |
| output_horizontal_fov | FLOAT | 90.00 | — |
| output_width | INT | 5128–16384 | — |
| output_height | INT | 5128–16384 | — |
| point_size | INT | 1 | — |
| widen_mask | INT | 00–64 | — |
| invert_mask | BOOLEAN | false | — |
| points_to_mask | BOOLEAN | false | Output mask frames of projected points |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| motion_frames | IMAGE | — |
| mask_frames | MASK | — |