Roblox Cube

repository·main·Indexed 22 days ago

https://github.com/roblox/cube

A generative AI system for 3D intelligence designed to accelerate the creation of 3D assets, accessories, and experiences. Cube enables the generation of 3D objects and scenes from text prompts using a shape tokenizer and an auto-regressive model. The system includes the CubePart package for multi-part mesh decomposition and a Python API for text-to-shape generation via the Engine and EngineFast classes.

Tokens
3.8K
Snippets
14
Records
15
Agent score
79%

What's inside cube

  1. Install Cube requirements

    main

    To use Cube, clone the repository and install it in a virtual environment. You can optionally install [meshlab] for mesh simplification support. If you are on Windows, you may need the CUDA toolkit and torch with CUDA support.

    git clone https://github.com/Roblox/cube.git
    cd cube
    pip install -e .[meshlab]
  2. Install CubePart

    main

    Install the CubePart package using pip. You can install it in editable mode or via the requirements file.

    To install for use with the Gradio demo, use the [demo] extra.

    pip install -e .
    # or
    pip install -r requirements.txt
    
    # For Gradio demo support
    pip install ".[demo]"
  3. Download Cube model weights

    main

    Download the model weights from Hugging Face. You can use the huggingface-cli to download the Roblox/cube3d-v0.5 weights into a local directory.

    huggingface-cli download Roblox/cube3d-v0.5 --local-dir ./model_weights
  4. Download CubePart model weights

    main

    CubePart requires pretrained checkpoints (multi-part DiT and shape VAE) from the Hugging Face Hub at Roblox/cubepart.

    By default, the code expects weights to be located in a weights/ directory with the following structure:

    • weights/multi_part_dit.safetensors (~8.6 GB)
    • weights/vae.safetensors (~1.3 GB)

    If you store weights elsewhere, you must pass the paths via --checkpoint and --vae-checkpoint in the CLI, or via the corresponding arguments in the Python API.

    # Using huggingface-cli
    huggingface-cli download Roblox/cubepart --local-dir weights
    # Using Python
    from huggingface_hub import snapshot_download
    
    snapshot_download(repo_id="Roblox/cubepart", local_dir="weights")
  5. Setup Cube 3D

    main

    To set up Cube 3D in a Colab environment, clone the repository, download the model weights from Hugging Face, and install the required dependencies (trimesh, omegaconf, warp-lang, and transformers).

    !git clone https://github.com/Roblox/cube
    %cd /content/cube
    !huggingface-cli download Roblox/cube3d-v0.1 --local-dir ./model_weights
    !pip install trimesh omegaconf warp-lang transformers
  6. Launch the Gradio demo UI

    main

    A Gradio-based web interface is available to interact with the multi-mesh denoiser. It allows you to drag-and-drop a .glb file, specify part names, and visualize the resulting parts in 3D.

    # Ensure demo dependencies are installed
    pip install ".[demo]"
    
    # Run the demo
    python examples/gradio_demo.py \
        --config configs/shape_denoiser_multimesh.yaml \
        --checkpoint weights/multi_part_dit.safetensors \
        --vae-checkpoint weights/vae.safetensors
  7. Perform multi-part mesh decomposition via Python API

    main

    The multi-part decomposition pipeline takes a pre-encoded shape latent and a list of part names to return individual meshes for each part.

    Workflow:

    1. Initialize PartShapeDenoiserPipeline with your config and checkpoint paths.
    2. Load an existing mesh and sample its surface using sample_surface.
    3. Convert the surface to a torch tensor and use parts_pipe.encode_shape(surface) to obtain latents.
    4. Call parts_pipe.input_to_part_shape with a ShapeInput object containing your part prompts and latents.

    Best Practices for Input Meshes:

    • Ensure the mesh is canonically aligned (+Y up, +Z forward).
    • Use a watertight, single-surface mesh. Avoid meshes with duplicated inner/outer shells.
    import torch
    import trimesh
    
    from cube_part.pipelines import PartShapeDenoiserPipeline, ShapeInput
    from cube_part.utils.mesh import load_mesh, sample_surface
    
    parts_pipe = PartShapeDenoiserPipeline(
        config_path="configs/shape_denoiser_multimesh.yaml",
        checkpoint_path="weights/multi_part_dit.safetensors",
        vae_checkpoint_path="weights/vae.safetensors",
        extract_geometry_fn_name="extract_geometry_coarse_to_fine",
    )
    
    mesh, _, _ = load_mesh("examples/inputs/jellyfish_car.glb")
    surface = sample_surface(mesh, num_samples=128_000)
    surface = (
        torch.from_numpy(surface).to(parts_pipe.device).unsqueeze(0).float()
    )
    latents, _ = parts_pipe.encode_shape(surface)
    
    part_meshes = parts_pipe.input_to_part_shape(
        ShapeInput(prompt=[["body", "wheels"]], latents=latents),
        guidance_scale=7.5,
        num_inference_steps=50,
    )
    
    for i, (vertices, faces) in enumerate(part_meshes):
        if vertices is not None:
            trimesh.Trimesh(vertices, faces).export(f"part_{i:02d}.glb")
  8. Use the Cube Python API for shape generation

    main

    Integrate Cube into your Python applications using the Engine or EngineFast classes.

    • EngineFast: Optimized for CUDA devices. Use Engine for other devices.
    • t2s(prompts, ...): The text-to-shape method.
      • use_kv_cache: Boolean to enable caching.
      • resolution_base: Float to control quality/speed.
      • top_p: Float (< 1) to control randomness (None is deterministic).

    Returns a list containing [vertices, faces] for each prompt.

    import torch
    import trimesh
    from cube3d.inference.engine import Engine, EngineFast
    
    # load ckpt
    config_path = "cube3d/configs/open_model.yaml"
    gpt_ckpt_path = "model_weights/shape_gpt.safetensors"
    shape_ckpt_path = "model_weights/shape_tokenizer.safetensors"
    engine_fast = EngineFast( # only supported on CUDA devices, replace with Engine otherwise
        config_path, 
        gpt_ckpt_path, 
        shape_ckpt_path, 
        device=torch.device("cuda"), # Replace with "mps" on Metal-compatible devices
    )
    
    # inference
    input_prompt = "A pair of noise-canceling headphones"
    # NOTE: Reduce `resolution_base` for faster inference and lower VRAM usage
    # The `top_p` parameter controls randomness between inferences:
    #   Float < 1: Keep smallest set of tokens with cumulative probability ≥ top_p. Default None: deterministic generation.
    mesh_v_f = engine_fast.t2s([input_prompt], use_kv_cache=True, resolution_base=8.0, top_p=0.9)
    
    # save output
    vertices, faces = mesh_v_f[0][0], mesh_v_f[0][1]
    _ = trimesh.Trimesh(vertices=vertices, faces=faces).export("output.obj")
  9. Hardware requirements for Cube

    main

    Cube is computationally intensive.

    • Recommended VRAM: 24GB+ when using --fast-inference (or EngineFast).
    • Minimum VRAM: 16GB for standard inference.
    • Supported Hardware: Nvidia L40S, H100, A100, and Apple Silicon (M2-4 chips via MPS).
  10. Visualize the generated mesh

    main

    The output from engine.t2s can be visualized using plotly.graph_objects.Mesh3d. The mesh data is structured as a tuple where the first element contains the vertices and the second contains the faces.

    import plotly.graph_objects as go
    
    # mesh_v_f is the output from engine.t2s
    vertices = mesh_v_f[0][0]
    faces = mesh_v_f[0][1]
    
    fig = go.Figure(
        data=[
            go.Mesh3d(
                x=vertices[:,0],
                y=vertices[:,1],
                z=vertices[:,2],
                i=faces[:,0],
                j=faces[:,1],
                k=faces[:,2],
                opacity=1.0)
        ],
        layout=dict(
            scene=dict(
                xaxis=dict(visible=False),
                yaxis=dict(visible=False),
                zaxis=dict(visible=False)
            )
        )
    )
    fig.show()
  11. Generate 3D models via CLI

    main

    You can generate 3D models from text prompts using the cube3d.generate module.

    Key Arguments:

    • --gpt-ckpt-path: Path to shape_gpt.safetensors.
    • --shape-ckpt-path: Path to shape_tokenizer.safetensors.
    • --prompt: The text description of the object.
    • --bounding-box-xyz: (v0.5+) Specifies the bounding box dimensions.
    • --fast-inference: Optional flag for faster generation (not supported on MacOS or low-VRAM GPUs).
    • --render-gif: Optional flag to render a turntable GIF (requires Blender >= 4.3 in PATH).
    • --resolution-base: Controls output quality (4.0 to 9.0 recommended). Lower values are faster but coarser.
    # Basic generation
    python -m cube3d.generate \
                --gpt-ckpt-path model_weights/shape_gpt.safetensors \
                --shape-ckpt-path model_weights/shape_tokenizer.safetensors \
                --fast-inference \
                --prompt "A tall pagoda" \
                --bounding-box-xyz 1.0 2.0 1.5
  12. Run multi-part decomposition via CLI

    main

    You can run the inference pipeline from the command line using the examples/run_inference.py script.

    Ensure you set your PYTHONPATH to the current directory so the package can be found.

    export PYTHONPATH=.
    
    python examples/run_inference.py \
        --config configs/shape_denoiser_multimesh.yaml \
        --checkpoint weights/multi_part_dit.safetensors \
        --vae-checkpoint weights/vae.safetensors \
        --mesh examples/inputs/jellyfish_car.glb \
        --parts "body, front right wheel, front left wheel, rear right wheel, rear left wheel, exhaust pipe, headlights, gun" \
        --output outputs/jellyfish_car_parts