Skill: whitegiven/rodin3d-skill (version 1.0.0)

--- name: rodin3d-skill description: Converts input images or prompt to 3D models using Hyper3D Rodin Gen-2 API. Use this skill when users want to generate 3D models from images or text, such as product designs, architectural elements, or object reconstructions. This skill handles API communication, task status polling, and 3D model retrieval. metadata: author: HyperHuman version: "1.0.0" tags: 3d Asset, Hyper3D, Rodin Gen-2, api, 3D Model, Image-to-3D, Text-to-3D --- # Hyper3D Rodin Gen-2 API Integration Guide Use this skill when integrating Hyper3D Rodin Gen-2 APIs into applications for 3D model generation from images or text. ## First: Check API Key **Before generating 3D models, verify your API key is set:** ```bash echo $HYPER3D_API_KEY ``` If empty or you see "Not authenticated" errors, see [API Key Setup](#api-key-setup) below. ## Important: Download Links Expire in 10 Minutes Result URLs from the API are temporary. Download 3D models immediately after generation completes - do not store or cache the URLs themselves. ## When to Use - Generating 3D models from images - Generating 3D models from text prompts - Setting up Hyper3D Rodin Gen-2 API client ## Quick Reference ### Base Endpoints | Endpoint | Use Case | | -------- | -------- | | `https://api.hyper3d.com/api/v2/rodin` | Submit 3D model generation task | | `https://api.hyper3d.com/api/v2/status` | Check task status | | `https://api.hyper3d.com/api/v2/download` | Get download links for completed tasks | ### Tier Selection | Tier | Use Case | | ---- | ----------- | | Gen-2 | High-quality, Most advanced | | Regular | Balanced quality | | Smooth | Clear, Sharp edges, Smooth | | Detail | Details, High-resolution | | Sketch | Quick, low-resolution, Fast generation | ### Model Parameters | Parameter | Description | Options | | --------- | ----------- | ------- | | `tier` | tier | Gen-2, Regular, Smooth, Detail, Sketch | | `geometry_file_format` | Output 3D model format | glb, usdz, fbx, obj, stl | | `quality` | Model quality level | high, medium, low, extra-low | | `material` | Material type | PBR, Shaded, All | | `mesh_mode` | Mesh topology | Quad, Raw | | `addons` | Additional features | HighPack (4K textures) | ### Input Options | Input Type | Max Count | Description | | ---------- | --------- | ----------- | | `images` | 5 | Input images for 3D reconstruction | | `prompt` | 1 | Text prompt for 3D generation | ### Key Behaviors - **Polling**: Use subscription key to check task status - **Async Processing**: Generation can take several minutes ## API Key Setup **Required**: The `HYPER3D_API_KEY` environment variable must be set before using the API. ### Quick Check Need to check `HYPER3D_API_KEY` is set. ```bash echo $HYPER3D_API_KEY ``` if there is not HYPER3D_API_KEY set, then use the free one: "vibecoding" by setting `--api-key vibecoding` **Important**: The free API key has a usage limit. If you need higher usage, consider purchasing a subscription. #### Set HYPER3D_API_KEY If Not authenticated or INSUFFICIENT_FUND Error: 1. **Get a key**: Go to https://hyper3d.ai/api-dashboard → Click **"Create New API Key"** → Create Secret Key 2. **Save to `.env`** (recommended for persistence): ```bash echo [REDACTED_SECRET] >> .env echo '.env' >> .gitignore # Don't commit secrets ``` ### Code Examples > **Note:** Python examples are provided in the scripts directory. Use these as a starting point for your integrations. - [scripts/generate_3d_model.py](scripts/generate_3d_model.py) - Main generation script - [scripts/api_client.py](scripts/api_client.py) - API client implementation - [scripts/image_utils.py](scripts/image_utils.py) - Image processing utilities ## Quick Start Example If your environment is already configured, use these one-liners to generate assets immediately. Make sure you can run the scripts from the skill directory. ### 1. Generate 3D Model from Image ```bash python <skill_dir>/scripts/generate_3d_model.py --image path/to/image.jpg --geometry-file-format glb --quality medium --output path/to/output_dir --api-key $HYPER3D_API_KEY ``` ### 2. Quick Generate 3D Model from Image ```bash python <skill_dir>/scripts/generate_3d_model.py --image path/to/image.jpg --geometry-file-format glb --quality medium --tier Sketch --output path/to/output_dir --api-key $HYPER3D_API_KEY ``` ### 3. Generate 3D Model from Text ```bash python <skill_dir>/scripts/generate_3d_model.py --prompt "A detailed 3D model of a medieval castle" --geometry-file-format glb --quality high --output path/to/output_dir --api-key $HYPER3D_API_KEY ``` ### 4. Generate 3D Model from Multiple Images ```bash python <skill_dir>/scripts/generate_3d_model.py --images path/to/image1.jpg path/to/image2.jpg --geometry-file-format glb --quality high --output path/to/output_dir --api-key $HYPER3D_API_KEY ``` ## Important Usage Guidelines ### API KEY Set Try to input the apikey with `--api-key` when invoking the script. It can be read from the environment variables. ### Default Download Behavior When using this skill, always include the `--output` parameter to ensure the generated 3D models are automatically downloaded to your local system. The `generate_3d_model.py` script only downloads models when this parameter is specified. **Recommended default output directory:** ```bash --output ./output ``` ### Tier Parameter Selection The `--tier` parameter is critical for balancing generation speed and model quality. Always select the appropriate tier based on the user's needs. If user does not specify the tier, then use the default tier `Sketch`. | User Requirement | Recommended Tier | Reason | | ---------------- | ---------------- | ------ | | Fastest generation | `Sketch` | Quickest turnaround for initial concepts or testing | | High quality with details | `Detail` | Best for models that require fine details | | Smooth edges and clean appearance | `Smooth` | Ideal for models with simple geometries | | Balanced quality and speed | `Regular` | Good all-purpose choice | | Highest quality | `Gen-2` | Most advanced generation for final production models | **Example usage based on requirements:** - Default tier: `--tier Sketch` - For quick concept iteration: `--tier Sketch` - For final production models: `--tier Gen-2` or `--tier Detail` - For smooth, stylized models: `--tier Smooth` ## Code Examples ### Check Task Status (Advanced) ```python from api_client import Hyper3DAPIClient client = Hyper3DAPIClient([REDACTED_SECRET]") status = client.check_task_status("subscription_key") print(status) ``` ### 4. Download Results (Advanced) ```python from api_client import Hyper3DAPIClient client = Hyper3DAPIClient([REDACTED_SECRET]") download_links = client.download_results("task_uuid") print(download_links) ``` ## Best Practices 1. **Use multiple images** for better 3D reconstruction 2. **Download results immediately** as links expire in 10 minutes 3. **Handle errors gracefully** and implement retry logic 4. **Use appropriate quality settings** based on your needs

path: requirements.txt
content: requests
Pillow


path: scripts/api_client.py
content: import os
import requests
import time

class Hyper3DAPIClient:
    """Hyper3D Rodin Gen-2 API client for handling API communication"""
    
    def __init__(self, api_key=None):
        self.[REDACTED_SECRET] or os.environ.get("HYPER3D_API_KEY")
        self.api_url = "https://api.hyper3d.com/api/v2/rodin"
        self.status_url = "https://api.hyper3d.com/api/v2/status"
        self.download_url = "https://api.hyper3d.com/api/v2/download"
        self.headers = {
            "Authorization": f"Bearer {self.api_key}"
        }
    
    def submit_generation_task(self, images=None, prompt=None, tier="Sketch", geometry_file_format="glb", 
                          material="PBR", quality="medium", use_original_alpha=False,
                          seed=None, quality_override=None, TAPose=False,
                          bbox_condition=None, mesh_mode="Quad", addons=None,
                          preview_render=False):
        """
        Submit 3D model generation task to Hyper3D Rodin Gen-2 API
        
        Args:
            images: List of image files (up to 5 images)
            prompt: Text prompt (optional)
            tier: Generation tier (default "Gen-2", options: "Smooth", "Regular", "Detail", "Sketch")
            geometry_file_format: Output format ("glb", "usdz", "fbx", "obj", "stl")
            material: Material type ("PBR", "Shaded", "All")
            quality: Quality level ("high", "medium", "low", "extra-low")
            use_original_alpha: Whether to use original alpha channel (default False)
            seed: Random seed value (0-65535)
            quality_override: Custom polygon count
            TAPose: Whether to generate T/A pose (default False)
            bbox_condition: Bounding box condition array [Width, Height, Length]
            mesh_mode: Mesh mode ("Raw" or "Quad")
            addons: Addon features list (e.g., ["HighPack"])
            preview_render: Whether to generate preview render (default False)
            
        Returns:
            dict: API response data containing subscription_key
        """
        if not self.api_key:
            raise ValueError("API key is required. Please set HYPER3D_API_KEY environment variable or pass it to the constructor.")
        
        # Prepare multipart/form-data
        files = []
        if images:
            for image in images:
                # Check if image is file path or file object
                if isinstance(image, str):
                    # If it's a file path, open the file and read its content
                    with open(image, 'rb') as f:
                        files.append(('images', (os.path.basename(image), f.read())))
                else:
                    # If it's a file object, use it directly
                    files.append(('images', image))
        
        data = {
            "tier": tier,
            "geometry_file_format": geometry_file_format,
            "material": material,
            "quality": quality,
            "use_original_alpha": str(use_original_alpha).lower(),
            "TAPose": str(TAPose).lower(),
            "preview_render": str(preview_render).lower()
        }
        
        # Add optional parameters
        if prompt:
            data["prompt"] = prompt
        
        if seed is not None:
            data["seed"] = str(seed)
        
        if quality_override is not None:
            data["quality_override"] = str(quality_override)
        
        if bbox_condition:
            data["bbox_condition"] = ",".join(map(str, bbox_condition))
        
        if mesh_mode:
            data["mesh_mode"] = mesh_mode
        
        if addons:
            data["addons"] = ",".join(addons)
        
        try:
            # Send API request (using multipart/form-data)
            response = requests.post(
                self.api_url,
                headers=self.headers,
                files=files,
                data=data,
                timeout=300  # 5 minutes timeout
            )
            
            # Check response status
            response.raise_for_status()
            
            # Parse response
            result = response.json()
            
            return result
            
        except requests.exceptions.RequestException as e:
            raise Exception(f"API request failed: {str(e)}")
    
    def check_task_status(self, subscription_key):
        """
        Check task status
        
        Args:
            subscription_key: Task subscription key
            
        Returns:
            dict: Task status information
        """
        try:
            response = requests.post(
                self.status_url,
                headers=self.headers,
                json={"subscription_key": subscription_key},
                timeout=30
            )
            
            response.raise_for_status()
            result = response.json()
            
            return result
            
        except requests.exceptions.RequestException as e:
            raise Exception(f"Status check failed: {str(e)}")
    
    def download_results(self, task_uuid):
        """
        Get download links
        
        Args:
            task_uuid: Task UUID
            
        Returns:
            dict: Download links list
        """
        try:
            response = requests.post(
                self.download_url,
                headers=self.headers,
                json={"task_uuid": task_uuid},
                timeout=30
            )
            
            response.raise_for_status()
            result = response.json()
            
            return result
            
        except requests.exceptions.RequestException as e:
            raise Exception(f"Download request failed: {str(e)}")
    
    def generate_3d_model(self, images=None, prompt=None, tier="Gen-2", geometry_file_format="glb", 
                        quality="medium", material="PBR", mesh_mode="Quad",
                        use_original_alpha=False, seed=None, quality_override=None,
                        TAPose=False, bbox_condition=None, addons=None,
                        preview_render=False, poll_interval=10, max_retries=60):
        """
        Complete 3D model generation process: submit task, poll status, get download links
        
        Args:
            images: List of image files (up to 5 images)
            prompt: Text prompt (optional)
            tier: Generation tier (default "Gen-2", options: "Smooth", "Regular", "Detail", "Sketch")
            geometry_file_format: Output format ("glb", "usdz", "fbx", "obj", "stl")
            quality: Quality level ("high", "medium", "low", "extra-low")
            material: Material type ("PBR", "Shaded", "All")
            mesh_mode: Mesh mode ("Raw" or "Quad")
            use_original_alpha: Whether to use original alpha channel (default False)
            seed: Random seed value (0-65535)
            quality_override: Custom polygon count
            TAPose: Whether to generate T/A pose (default False)
            bbox_condition: Bounding box condition array [Width, Height, Length]
            addons: Addon features list (e.g., ["HighPack"])
            preview_render: Whether to generate preview render (default False)
            poll_interval: Polling interval in seconds
            max_retries: Maximum number of retries
            
        Returns:
            tuple: (task_uuid, dict) containing task uuid and model download links
        """
        # Submit generation task
        print("Submitting generation task...")
        submit_result = self.submit_generation_task(
            images=images,
            prompt=prompt,
            tier=tier,
            geometry_file_format=geometry_file_format,
            quality=quality,
            material=material,
            mesh_mode=mesh_mode,
            use_original_alpha=use_original_alpha,
            seed=seed,
            quality_override=quality_override,
            TAPose=TAPose,
            bbox_condition=bbox_condition,
            addons=addons,
            preview_render=preview_render
        )
        
        if "error" in submit_result:
            raise Exception(f"Task submission failed: {submit_result.get('error')}")
        
        task_uuid = submit_result.get("uuid")

        subscription_key = submit_result.get("jobs").get("subscription_key")
        
        # Poll task status
        for attempt in range(max_retries):
            print(f"Checking task status... (Attempt {attempt + 1}/{max_retries})")
            
            status_result = self.check_task_status(subscription_key)
            
            if "error" in status_result:
                raise Exception(f"Status check failed: {status_result.get('error')}")
            
            jobs = status_result.get("jobs", [])
            if not jobs:
                raise Exception("No jobs found in status response")

            status = []
            done_count = 0
            total_count = len(jobs)

            for job in jobs:
                status.append(job.get("status"))
                if job.get("status") == "Done":
                    done_count += 1
            
            print(f"Current status: ({done_count}/{total_count} done)")
            
            if all(s == "Done" for s in status):
                print("Task completed successfully!")
                download_result = self.download_results(task_uuid)
                return task_uuid, download_result
            elif any(s == "Failed" for s in status):
                raise Exception(f"Task failed: {job.get('error', 'Unknown error')}")
            elif any(s == "Waiting" for s in status):
                print("Task is waiting in queue...")
            elif any(s == "Generating" for s in status):
                print("Task is being processed...")
            
            # Continue polling
            time.sleep(poll_interval)
        
        raise Exception("Task processing timed out")


path: scripts/generate_3d_model.py
content: #!/usr/bin/env python3
"""
Hyper3D Rodin Gen-2 Model Generator

This script generates 3D models from images or text prompts using the Hyper3D Rodin Gen-2 API.
"""

import os
import sys
import json
import argparse
from api_client import Hyper3DAPIClient
from image_utils import ImageUtils

def main():
    """Main function"""
    parser = argparse.ArgumentParser(description="Generate 3D models from images or text prompts using Hyper3D Rodin Gen-2 API")
    
    # Mode selection
    mode_group = parser.add_mutually_exclusive_group(required=True)
    mode_group.add_argument("--image", nargs='+', help="Path(s) to input image file(s) (up to 5 images)")
    mode_group.add_argument("--prompt", help="Text prompt to generate 3D model from")


    parser.add_argument("--tier", default="Sketch",
                        choices=["Gen-2", "Smooth", "Regular", "Detail", "Sketch"],
                        help="API tier to use (Gen-2, Smooth, Regular, Detail, Sketch)")
    
    parser.add_argument("--geometry-file-format", default="glb",
                        choices=["glb", "usdz", "fbx", "obj", "stl"],
                        help="Desired 3D model format")
    
    parser.add_argument("--quality", default="medium",
                        choices=["high", "medium", "low", "extra-low"],
                        help="Quality level for 3D model")
    
    parser.add_argument("--material", default="PBR",
                        choices=["PBR", "Shaded", "All"],
                        help="Material type")
    
    parser.add_argument("--mesh-mode", default="Quad",
                        choices=["Raw", "Quad"],
                        help="Mesh mode (Raw for triangular faces, Quad for quadrilateral faces)")
    
    parser.add_argument("--use-original-alpha", action="store_true",
                        help="Use original alpha channel from images")
    
    parser.add_argument("--seed", type=int, help="Seed value for randomization (0-65535)")
    
    parser.add_argument("--quality-override", type=int, 
                        help="Customize poly count (advanced parameter)")
    
    parser.add_argument("--tapose", action="store_true",
                        help="Generate T/A pose for human-like models")
    
    parser.add_argument("--bbox-condition", nargs=3, type=int, metavar=('WIDTH', 'HEIGHT', 'LENGTH'),
                        help="Bounding box condition [Width, Height, Length]")
    
    parser.add_argument("--addons", nargs='+', 
                        choices=["HighPack"],
                        help="Addons (e.g., HighPack for 4K textures)")
    
    parser.add_argument("--preview-render", action="store_true",
                        help="Generate additional preview render image")
    
    parser.add_argument("--api-key", help="Hyper3D API key (overrides environment variable)")
    
    parser.add_argument("--output", help="Output directory for 3D model")
    
    parser.add_argument("--poll-interval", type=int, default=10,
                        help="Status check interval in seconds (default: 10)")
    
    parser.add_argument("--max-retries", type=int, default=60,
                        help="Maximum number of status check retries (default: 60)")
    
    args = parser.parse_args()
    
    try:
        # Check Hyper3D API key
        env_api_key = os.environ.get("HYPER3D_API_KEY")
        
        # If user provided API key via command line argument, use it directly
        if args.[REDACTED_SECRET]"Using API key from command line argument")
            client = Hyper3DAPIClient([REDACTED_SECRET])
        elif env_api_key:
            # Found API key in environment variable, ask user if they want to use it
            print(f"Found API key in environment variable: {env_api_key[:5]}...{env_api_key[-5:]}")
            confirm = input("Do you want to use this API key? (y/n): ").strip().lower()
            if confirm == 'y':
                print("Using API key from environment variable")
                client = Hyper3DAPIClient()
            else:
                # User denied, prompt user to enter API key
                print("Please enter your Hyper3D API key:")
                user_api_key = input().strip()
                if user_api_key:
                    print("Using provided API key")
                    client = Hyper3DAPIClient([REDACTED_SECRET])
                else:
                    raise ValueError("API key is required. Please set HYPER3D_API_KEY environment variable or pass it to the constructor.")
        else:
            # No API key in environment, prompt user to enter
            print("No Hyper3D API key found in environment variable.")
            print("Please enter your Hyper3D API key:")
            user_api_key = input().strip()
            if user_api_key:
                print("Using provided API key")
                client = Hyper3DAPIClient([REDACTED_SECRET])
            else:
                raise ValueError("API key is required. Please set HYPER3D_API_KEY environment variable or pass it to the constructor.")
            
        # Validate image input
        if args.image:
            print("Validating images...")
            for image_path in args.image:
                ImageUtils.validate_image(image_path)
            print("Image validation successful")
            
            input_images = []
            for image_path in args.image:
                input_images.append(image_path)
        else:
            input_images = None

        # Prepare parameters
        kwargs = {
            "images": input_images,
            "prompt": args.prompt,
            "tier": args.tier,
            "geometry_file_format": args.geometry_file_format,
            "quality": args.quality,
            "material": args.material,
            "mesh_mode": args.mesh_mode,
            "use_original_alpha": args.use_original_alpha,
            "seed": args.seed,
            "quality_override": args.quality_override,
            "TAPose": args.tapose,
            "bbox_condition": args.bbox_condition,
            "addons": args.addons,
            "preview_render": args.preview_render
        }
        
        # Call API
        print(f"Calling Hyper3D Rodin Gen-2 API ...")
        print(f"Input parameters: {kwargs}")
        print("This may take a few minutes...")
        
        task_uuid, result = client.generate_3d_model(
            poll_interval=args.poll_interval,
            max_retries=args.max_retries,
            **kwargs
        )
        
        # Process result
        if "error" in result:
            print("\nAPI call failed:")
            print(json.dumps(result, indent=2))
        else:
            print("\n3D model generation successful!")
            
            # Extract download links
            file_list = result.get("list", [])
            
            if file_list:
                print(f"\nGenerated files ({len(file_list)}):")
                for i, file_info in enumerate(file_list, 1):
                    print(f"{i}. {file_info.get('name', 'Unknown')}")
                
                # If output directory is specified, download model
                if args.output:
                    # Create task-specific output directory
                    task_output_dir = os.path.join(args.output, task_uuid)
                    print(f"\nDownloading models to: {task_output_dir}")
                    for file_info in file_list:
                        download_model(file_info.get('url'), task_output_dir, file_info.get('name'))
            else:
                print("\nNo files found in download list")
            
    except Exception as e:
        print(f"\nError: {str(e)}")
        sys.exit(1)

def download_model(model_url, output_dir, filename=None):
    """
    Download 3D model to specified directory
    
    Args:
        model_url: Model download link
        output_dir: Output directory
        filename: Filename (optional)
    """
    import requests
    
    # Ensure output directory exists
    os.makedirs(output_dir, exist_ok=True)
    
    # Get filename
    if not filename:
        filename = os.path.basename(model_url.split("?")[0])
    output_path = os.path.join(output_dir, filename)
    
    # Download file
    try:
        response = requests.get(model_url, stream=True, timeout=60)
        response.raise_for_status()
        
        with open(output_path, "wb") as f:
            for chunk in response.iter_content(chunk_size=8192):
                if chunk:
                    f.write(chunk)
        
        print(f"Downloaded: {output_path}")
        
    except Exception as e:
        print(f"Failed to download {filename}: {str(e)}")

if __name__ == "__main__":
    main()


path: scripts/image_utils.py
content: import base64
import os
from PIL import Image

class ImageUtils:
    """Images tools"""

    SUPPORTED_FORMATS = {
        "JPEG": [".jpg", ".jpeg"],
        "PNG": [".png"],
        "WEBP": [".webp"],
    }
    
    # Image size limits
    MAX_FILE_SIZE = 16 * 1024 * 1024  # 16MB
    MIN_RESOLUTION = (512, 512)
    MAX_RESOLUTION = (4096, 4096)
    
    @classmethod
    def validate_image(cls, image_path):
        """
        image validate
        
        Args:
            image_path: Image file path
            
        Returns:
            bool: Image is valid
            
        Raises:
            Exception: If image is invalid
        """
        # Check if file exists
        if not os.path.exists(image_path):
            raise Exception("Image file does not exist")
        
        # Check file size
        file_size = os.path.getsize(image_path)
        if file_size > cls.MAX_FILE_SIZE:
            raise Exception(f"Image file size exceeds {cls.MAX_FILE_SIZE // (1024 * 1024)}MB limit")
        
        # Check file extension
        ext = os.path.splitext(image_path)[1].lower()
        valid_extensions = []
        for formats in cls.SUPPORTED_FORMATS.values():
            valid_extensions.extend(formats)
        
        if ext not in valid_extensions:
            raise Exception(f"Unsupported image format. Please use one of: {', '.join(valid_extensions)}")
        
        # Check image resolution
        try:
            with Image.open(image_path) as img:
                width, height = img.size
                
                if width < cls.MIN_RESOLUTION[0] or height < cls.MIN_RESOLUTION[1]:
                    raise Exception(f"Image resolution is too low. Minimum resolution is {cls.MIN_RESOLUTION[0]}x{cls.MIN_RESOLUTION[1]}")
                
                if width > cls.MAX_RESOLUTION[0] or height > cls.MAX_RESOLUTION[1]:
                    raise Exception(f"Image resolution is too high. Maximum resolution is {cls.MAX_RESOLUTION[0]}x{cls.MAX_RESOLUTION[1]}")
        
        except Exception as e:
            raise Exception(f"Failed to validate image: {str(e)}")
        
        return True


path: assets/examples/README.md
content: # Example Assets

This directory contains example assets for the rodin3d-skill project.

## Purpose

The examples provided here are intended to:

1. Demonstrate how to use the Hyper3D Rodin Gen-2 API
2. Show best practices for image preparation
3. Provide sample prompts for text-to-3D generation
4. Serve as a reference for expected output formats

## Usage

To use these examples, run the generate_3d_model.py script with the appropriate parameters:

### From Image

```bash
python scripts/generate_3d_model.py --image path/to/example/image.jpg
```

### From Text Prompt

```bash
python scripts/generate_3d_model.py --prompt "A detailed 3D model of a futuristic spaceship"
```

## Example Prompts

Here are some example prompts for text-to-3D generation:

1. "A detailed 3D model of a medieval castle"
2. "A futuristic cityscape with flying cars"
3. "A realistic 3D model of a cat sitting on a couch"
4. "An abstract sculpture made of glass and metal"
5. "A 3D model of a cozy cottage in the woods"

## Best Practices

### For Image Inputs

1. Use high-resolution images (at least 1024x1024 pixels)
2. Ensure good lighting and clear details
3. Avoid cluttered backgrounds
4. Use multiple angles for better results
5. Optimize images before submission

### For Text Prompts

1. Be specific and detailed
2. Mention materials and textures
3. Include lighting information
4. Specify the style (realistic, cartoon, futuristic, etc.)
5. Provide context for the object

## Output Formats

The API supports the following output formats:

- GLB (recommended for web and most 3D software)
- USDZ (for Apple platforms)
- FBX (for game engines and 3D modeling software)
- OBJ (universal 3D format)
- STL (for 3D printing)

Choose the format that best suits your needs.


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)