# Blender Export Scripts

Python scripts for generating textures and heightmaps from Blender terrain meshes.

## Prerequisites

- Blender 5.0+
- Terrain mesh object (default name: "TerrainPlane")

## Scripts

### generate_heightmap.py

Bakes EXR heightmap from terrain mesh using Blender's render system.

**Output:** `textures/terrain_heightmap.exr` (R32Float single-channel)

**Usage:**
```python
# In Blender's Scripting workspace - just run the script!
# It will automatically find TerrainPlane and bake to textures/terrain_heightmap.exr
```

**Or run from command line:**
```bash
blender terrain.blend --background --python scripts/generate_heightmap.py
```

**Custom parameters:**
```python
from generate_heightmap import bake_heightmap

bake_heightmap(
    terrain_obj=bpy.data.objects["TerrainPlane"],
    resolution=1000,
    output_path="path/to/output.exr"
)
```

### generate_normal_map.py

Generates normal map from terrain mesh for neighbor sampling in shaders.

**Output:** `textures/terrain_normals.png` (RGB encoded normals)

**Usage:**
```python
from generate_normal_map import save_normal_map

save_normal_map(
    output_path=project_root / "textures" / "terrain_normals.png",
    resolution=1024,
    blur_iterations=2,
    terrain_name="TerrainPlane"
)
```

### generate_flowmap.py

Generates flowmap for water/snow flow effects.

**Output:** `textures/terrain_flowmap.png`

## Terrain Export Workflow

1. **Model terrain in Blender 5.0**
   - Create/sculpt terrain mesh
   - Add modifiers (Subdivision, Displacement, etc.)
   - Ensure terrain has UV mapping

2. **Bake heightmap**
   - Run `generate_heightmap.py` script
   - Uses Blender's baking system (like baking a texture)
   - Creates `textures/terrain_heightmap.exr`
   - Automatically applies all modifiers

3. **Export glTF with baked heights**
   - Select terrain mesh
   - File → Export → glTF 2.0
   - Save as `meshes/terrain.gltf`
   - Heights are baked in vertex positions

4. **Both files in sync**
   - glTF: rendering (vertices with baked heights)
   - EXR: physics (rapier3d heightfield collider)
   - Both from same source = guaranteed match

## Resolution Guidelines

- **Heightmap (EXR):** 512×512, 1000×1000, or 1024×1024
  - Higher = more accurate collision
  - Lower = faster loading
  - Default: 1000×1000
  - Uses Blender's render sampling (no gaps!)

- **Normal Map:** 1024×1024 or 2048×2048
  - For shader neighbor sampling
  - Higher quality for detailed terrain

## Customization

Change parameters by editing the script or calling directly:

```python
from generate_heightmap import bake_heightmap

bake_heightmap(
    terrain_obj=bpy.data.objects["MyTerrain"],
    resolution=1024,
    output_path="custom/path.exr"
)
```

## Output Files

```
project_root/
├── meshes/
│   └── terrain.gltf        # Mesh with baked heights (manual export)
└── textures/
    ├── terrain.exr         # Heightmap for physics (generated)
    ├── terrain_normals.png # Normal map (generated)
    └── terrain_flowmap.png # Flow map (generated)
```

## Troubleshooting

**"Object not found":**
- Ensure terrain object exists
- Check object name matches parameter
- Script will auto-detect objects with "terrain" or "plane" in name

**"Mesh has no vertices":**
- Apply all modifiers before running script
- Check mesh is not empty

**EXR export fails:**
- Ensure Blender has EXR support enabled
- Check output directory exists and is writable
