Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ThreeDSViewer

ThreeDSViewer is an experimental native CAD client and GLB viewer for the Nintendo 3DS. It connects directly to Zoo, lets you create and edit cloud CAD projects from the touchscreen, and renders the resulting models locally with Citro3D.

This project was made for the zoo.dev Makeathon.

A small apology: sorry about the code and engineering quality in places. This was built quickly for a Makeathon, on unusual hardware, while the CAD workflow was still evolving. It works, but some modules are larger, stranger, and less polished than they should be.

This project also made heavy use of AI-assisted development for implementation, debugging, emulator testing, and documentation. That helped move quickly during the Makeathon, but it also contributed to the uneven code style and engineering quality noted above.

ThreeDSViewer running in the Azahar emulator

seq.kittycad.mp4

What works

  • OAuth device login with refresh credentials stored on the SD card
  • Browsing, creating, opening, and refreshing Zoo projects
  • Touch-first sketching with lines, points, circles, and rectangles
  • Sketch constraints and dimensions
  • Extrude with New Body, Join, Cut, and Intersect operations
  • Extrude start offsets and signed distances
  • Revolve, Fillet, and Chamfer creation
  • Basic feature editing, selection, deletion, Undo, and Redo
  • Cloud-generated Preview followed by explicit Apply
  • Fresh project reopen from canonical Zoo state
  • Local stereoscopic GLB rendering on the top screen
  • Fourteen bundled offline renderer scenes
  • Touch-draggable lists and inline 3DS button prompts

ThreeDSViewer is still a prototype. CAD actions can modify real Zoo projects; use a disposable project while experimenting.

Setup

Install the following first:

  • Rust through rustup
  • devkitPro with devkitARM, libctru, Citro3D, Citro2D, and Picasso
  • cargo-3ds, which teaches Cargo how to build and package Nintendo 3DS homebrew

The included rust-toolchain.toml selects nightly and installs rust-src. The repository's .cargo/config.toml selects the devkitARM C compiler for the custom Nintendo 3DS target.

Install cargo-3ds and verify that its Cargo subcommand is available:

cargo install cargo-3ds
cargo 3ds --version

Then expose the devkitPro paths in your shell:

export DEVKITPRO=/opt/devkitpro
export DEVKITARM="$DEVKITPRO/devkitARM"

The exact devkitPro installation path can differ by operating system; update those variables if yours is not under /opt/devkitpro.

Build

export DEVKITPRO=/opt/devkitpro
export DEVKITARM="$DEVKITPRO/devkitARM"

cargo 3ds build --release

The application is written to:

target/armv6k-nintendo-3ds/release/threedsviewer.3dsx

Copy the .3dsx to the SD card under 3ds/threedsviewer/, or send it to a console running the Homebrew Launcher:

cargo 3ds run --release

Testing with Azahar

ThreeDSViewer was developed and tested with the Azahar Nintendo 3DS emulator. After building, open this file in Azahar:

target/armv6k-nintendo-3ds/release/threedsviewer.3dsx

Use the emulator's bottom-screen pointer for touch input. Zoo login and CAD operations require working network access inside the emulator. Complete the displayed device-login flow in a regular browser, then return to Azahar.

For repository work, tools/azahar-smoke.sh and tools/azahar-interact.sh provide repeatable smoke and interaction harnesses. They use workstation-specific emulator paths by default, so inspect their environment-variable overrides before running them elsewhere.

Azahar is excellent for iteration and screenshots, but emulator success is not a substitute for testing timing, networking, touch, and rendering on a physical Nintendo 3DS.

First run

  1. Launch ThreeDSViewer and touch CAD.
  2. Choose Sign In.
  3. Open the displayed Zoo verification address on another device and enter the user code.
  4. Return to the 3DS. The project list refreshes after authorization succeeds.
  5. Create a new project or open an existing disposable project.

OAuth credentials are stored at sdmc:/3ds/threedsviewer/oauth. The app uses Zoo's device flow and does not require an API key to be embedded in the ROM.

Controls

The touchscreen is the primary input surface. On-screen action labels include sprites for the corresponding physical buttons.

Input Typical action
Touch Select, draw, drag controls, and scroll lists
A Open, confirm, Preview, or Apply
B Back or cancel
X New, tools, exact input, or retry
Y Context action such as Delete
L / R Undo / Redo or previous / next choice
D-pad Move focus and adjust values
Circle Pad Orbit or move the local cursor where available
START Exit the application

Exact actions are shown on each screen; the same button can have a different contextual action in another workspace.

Typical CAD journey

CAD → New project → Create → Sketch → choose plane
    → draw profile → Finish Sketch
    → select Sketch → Extrude → choose profile and operation
    → Preview → Apply

Preview geometry is transient. Apply is the explicit mutation step, and a successful reopen reloads the canonical project from Zoo.

Project layout

src/                 Nintendo 3DS application, UI, cloud worker, and renderer
crates/cad-model/    Semantic CAD document and Zoo command compiler
crates/cad-core/     Input reducers and editing workspaces
crates/cad-runtime/  Preview, Apply, replay, and runtime composition
crates/cad-store/    Bounded local recovery storage
crates/glb-model/    Bounded GLB/glTF loader
crates/manul/        Blocking Zoo HTTP, OAuth, and Modeling client
crates/citro2d*/     Safe and raw Citro2D bindings
crates/ui-core/      Host-testable layout, pointer, and list state
crates/viewport-pick Host-testable trackpad and body picking
romfs/               Files bundled into the final 3DSX
tools/               Build, emulator, fixture, and focused proof utilities

The main thread owns input, application state, Citro3D/Citro2D, and frame rendering. A bounded worker owns Zoo HTTP and Modeling operations. The renderer never depends on video streaming or WebRTC: Zoo returns GLB data, and the 3DS renders it locally.

Useful development commands

Check the production 3DS target:

cargo 3ds check --release --locked

Build a commit-labelled emulator ROM with provenance metadata:

tools/build-emulator-rom.sh

Run the local debug WebSocket model server:

cargo run -p ws-test-server -- 127.0.0.1:9001 path/to/model.glb

The debug stream is disabled at startup and must be explicitly enabled in the application. It is separate from the normal Zoo CAD path.

GLB support

The renderer supports GLB 2.0 triangle meshes, indexed and non-indexed primitives, float positions and normals, generated flat normals, scene/node transforms, mesh instancing, basic metallic-roughness material factors, alpha modes, and double-sided materials.

Textures, animation, skinning, morph targets, sparse accessors, Draco, Meshopt, KTX2/Basis, and advanced PBR extensions are not currently supported.

Third-party assets

Controller prompt sprites come from Kenney's CC0 Input Prompts Pixel pack. The exact source URL, license note, retained tile mapping, PNGs, and generated 3DS atlas are in romfs/input-prompts-pixel/.

About

A zoo.dev viewer/client for the 3ds

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages