Skip to content

orhun/rotating_terminal

 
 

Repository files navigation

rotating_terminal

Bevy 0.18.1 project that loads a vintage_terminal 3D model and drives its screen with a ratatui UI rendered through soft_ratatui.

The vintage_terminal asset is from Sketchfab: Vintage Terminal.

Previews

Rotation

Rotating terminal preview

Zoom

Zoom terminal preview

Intermission

Intermission preview

Shutdown

Shutdown preview

Current project surface:

  • orbiting hero shot
  • stationary zoom-in intro
  • intermission/standby loop
  • shutdown/outro loop
  • PNG exporters for every scene
  • render scripts that generate both H.264 MP4 loops and animated WebP previews

Requirements

  • Rust and Cargo
  • ffmpeg and img2webp for the render scripts

Install / Verify

cargo check --bins

Interactive Binaries

rotating_terminal

Orbiting hero shot around the terminal.

cargo run --bin rotating_terminal

stationary_terminal

Stationary intro shot with a one-way zoom in that settles on the final framing.

cargo run --bin stationary_terminal

intermission

Standby/intermission scene with the same low camera height and radius envelope as the orbit scene, plus a faster waiting-pattern spinner on the terminal screen.

cargo run --bin intermission

shutdown_outro

Shutdown/outro scene with friendly flashing farewell copy on the terminal screen.

cargo run --bin shutdown_outro

Export Binaries

All exporters render numbered PNGs with bevy_image_export.

Shared export settings:

  • internal Bevy render resolution: 3840x2160
  • final encoded MP4 resolution: 1920x1080 by default
  • output cadence: 60 fps
  • warmup before capture: 60 frames

export_rotation

cargo run --release --bin export_rotation

Custom output directory:

cargo run --release --bin export_rotation -- /path/to/output_dir

Settings:

  • frame count: 420
  • duration: 7.0s
  • motion: one seamless full orbit loop

export_zoom

cargo run --release --bin export_zoom

Custom output directory:

cargo run --release --bin export_zoom -- /path/to/output_dir

Settings:

  • frame count: 720
  • duration: 12.0s
  • motion: slow eased zoom in, then hold on the zoomed-in framing

export_intermission

cargo run --release --bin export_intermission

Custom output directory:

cargo run --release --bin export_intermission -- /path/to/output_dir

Settings:

  • frame count: 384
  • duration: 6.4s
  • motion: seamless intermission loop

export_shutdown

cargo run --release --bin export_shutdown

Custom output directory:

cargo run --release --bin export_shutdown -- /path/to/output_dir

Settings:

  • frame count: 960
  • duration: 16.0s
  • motion: seamless shutdown ping-pong loop based on the shutdown camera and screen text cycle

Render Scripts

The scripts below are executable and can be run directly with ./scripts/....

./scripts/render_rotation_loop.sh

Default outputs:

  • frames: renders/rotation_frames
  • video: renders/rotating_terminal_loop.mp4
  • preview: rotating_terminal_loop.webp

Usage:

./scripts/render_rotation_loop.sh
./scripts/render_rotation_loop.sh /path/to/frames /path/to/output.mp4
./scripts/render_rotation_loop.sh /path/to/frames /path/to/output.mp4 /path/to/output.webp

./scripts/render_zoom_in.sh

Default outputs:

  • frames: renders/zoom_frames
  • video: renders/terminal_zoom_loop.mp4
  • preview: terminal_zoom_loop.webp

Usage:

./scripts/render_zoom_in.sh
./scripts/render_zoom_in.sh /path/to/frames /path/to/output.mp4
./scripts/render_zoom_in.sh /path/to/frames /path/to/output.mp4 /path/to/output.webp

./scripts/render_intermission_loop.sh

Default outputs:

  • frames: renders/intermission_frames
  • video: renders/intermission_loop.mp4
  • preview: intermission_loop.webp

Usage:

./scripts/render_intermission_loop.sh
./scripts/render_intermission_loop.sh /path/to/frames /path/to/output.mp4
./scripts/render_intermission_loop.sh /path/to/frames /path/to/output.mp4 /path/to/output.webp

./scripts/render_outro_loop.sh

Default outputs:

  • frames: renders/shutdown_frames
  • video: renders/shutdown_loop.mp4
  • preview: shutdown_loop.webp

Usage:

./scripts/render_outro_loop.sh
./scripts/render_outro_loop.sh /path/to/frames /path/to/output.mp4
./scripts/render_outro_loop.sh /path/to/frames /path/to/output.mp4 /path/to/output.webp

./scripts/render_all_media.sh

Runs the four scene-specific render scripts.

Default outputs:

  • videos: renders/*.mp4
  • WebPs:
    • rotating_terminal_loop.webp
    • terminal_zoom_loop.webp
    • intermission_loop.webp
    • shutdown_loop.webp

Usage:

./scripts/render_all_media.sh
./scripts/render_all_media.sh /path/to/renders_dir

Shared script options

Override the encoded playback framerate:

FPS=30 ./scripts/render_rotation_loop.sh

Override the final encoded MP4 size:

FINAL_WIDTH=1920 FINAL_HEIGHT=1080 ./scripts/render_rotation_loop.sh

WebP conversion options:

WEBP_FPS=30 WEBP_SCALE_WIDTH=320 WEBP_DELAY_MS=33 WEBP_QUALITY=90 ./scripts/render_rotation_loop.sh

The render scripts keep Bevy's internal frame export at 3840x2160 and downscale to the final MP4 size in ffmpeg using Lanczos filtering.

Final MP4 output size:

FINAL_WIDTH=1920 FINAL_HEIGHT=1080 ./scripts/render_rotation_loop.sh

Each script:

  1. deletes the existing frame directory
  2. runs the matching export_* binary
  3. encodes the PNG sequence to an H.264 MP4 with ffmpeg
  4. converts the MP4 to an animated WebP with img2webp

Encoding settings:

  • codec: libx264
  • preset: veryslow
  • quality: crf 10
  • pixel format: yuv420p

WebP defaults:

  • frame rate: 30 fps
  • width: 320 px
  • quality: 90

MP4 default:

  • final encoded size: 1920x1080
  • source frames: rendered internally at 3840x2160 and downscaled in ffmpeg

Common Commands

Check everything:

cargo check --bins

Run the scenes:

cargo run --bin rotating_terminal
cargo run --bin stationary_terminal
cargo run --bin intermission
cargo run --bin shutdown_outro

Render looping MP4s:

./scripts/render_rotation_loop.sh
./scripts/render_zoom_in.sh
./scripts/render_intermission_loop.sh
./scripts/render_outro_loop.sh
./scripts/render_all_media.sh

Project Layout

Notes

  • The terminal screen is a 14x7 soft_ratatui surface composited back into the model's screen texture atlas.
  • TUI content updates at 15 fps; the live scene runs at 30 fps; exports render at 60 fps.
  • The export/live TUI clock advances using the accumulated render interval so intermission and shutdown text timing matches the final renders.
  • The terminal body materials are intentionally matte and bloom is kept low to avoid blown-out highlights on the shell.
  • Exporters write PNG sequences first, which makes re-encoding with different ffmpeg settings straightforward.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Rust 94.2%
  • Shell 5.8%