Blender Integration Module
Low-level Blender mesh operations for terrain visualization.
This module contains Blender-specific code for creating and configuring terrain meshes,
applying vertex colors, and managing mesh data. Uses Blender’s high-performance bulk
operations (foreach_set, foreach_get) for ~100x faster vertex manipulation.
Vertex Colors
- src.terrain.blender_integration.apply_vertex_colors(mesh_obj, vertex_colors, y_valid=None, x_valid=None, n_surface_vertices=None, logger=None)[source]
Apply colors to an existing Blender mesh.
Accepts colors in either vertex-space (n_vertices, 3/4) or grid-space (height, width, 3/4). When grid-space colors are provided with y_valid/x_valid indices, colors are extracted for each vertex using those coordinates.
Uses Blender’s foreach_set for ~100x faster bulk operations.
- Parameters:
mesh_obj (bpy.types.Object) – The Blender mesh object to apply colors to
vertex_colors (np.ndarray) – Colors in one of two formats: - Vertex-space: shape (n_vertices, 3) or (n_vertices, 4) - Grid-space: shape (height, width, 3) or (height, width, 4)
y_valid (np.ndarray, optional) – Y indices for grid-space colors
x_valid (np.ndarray, optional) – X indices for grid-space colors
n_surface_vertices (int, optional) – Number of surface vertices. If provided, boundary vertices (index >= n_surface_vertices) will be skipped to preserve their existing colors (e.g., two-tier edge colors). Default: None (apply to all)
logger (logging.Logger, optional) – Logger for progress messages
Apply colors to mesh vertices with automatic grid-to-vertex mapping. Used in Combined Render: Full-Featured Example.
Supports two color formats:
Vertex-space colors: shape
(n_vertices, 3)or(n_vertices, 4)- One color per vertex - Direct application (fastest)Grid-space colors: shape
(height, width, 3)or(height, width, 4)- Colors in DEM grid coordinates - Requiresy_valid/x_validindices to extract per-vertex colors - Handles downsampled meshes automatically
Preserves boundary colors:
Use
n_surface_verticesparameter to preserve edge colors when applying terrain colors (used with two-tier edges).Example:
from src.terrain.blender_integration import apply_vertex_colors # Vertex-space colors (simple) apply_vertex_colors(mesh_obj, vertex_colors) # Grid-space colors (with mapping) apply_vertex_colors( mesh_obj, grid_colors, y_valid=terrain.y_valid, x_valid=terrain.x_valid ) # Preserve edge colors (two-tier mode) apply_vertex_colors( mesh_obj, terrain_colors, y_valid=terrain.y_valid, x_valid=terrain.x_valid, n_surface_vertices=len(terrain.y_valid) )
- src.terrain.blender_integration.apply_ring_colors(mesh_obj, ring_mask, y_valid, x_valid, ring_color=(0.15, 0.15, 0.15), logger=None)[source]
Apply a solid color to vertices within a ring mask.
Modifies the existing TerrainColors vertex color layer, setting RGB values for vertices that fall within the ring mask to the specified color. This creates a dark outline around areas of interest (e.g., park zones).
Uses Blender’s foreach_get/foreach_set for efficient bulk operations.
- Parameters:
mesh_obj (bpy.types.Object) – The Blender mesh object
ring_mask (np.ndarray) – 2D boolean array (height, width) where True = apply ring color
y_valid (np.ndarray) – Y indices mapping vertices to grid positions
x_valid (np.ndarray) – X indices mapping vertices to grid positions
ring_color (tuple) – RGB color (0-1 range) to apply to ring vertices. Default: dark gray.
logger (logging.Logger, optional) – Logger for progress messages
Apply solid color to ring/boundary vertices.
Used to color two-tier edge extrusions with base materials.
Example:
apply_ring_colors( mesh_obj, ring_mask, y_valid, x_valid, ring_color=(0.5, 0.48, 0.45) # Clay )
- src.terrain.blender_integration.apply_road_mask(mesh_obj, road_mask, y_valid, x_valid, logger=None)[source]
Apply a road mask as a separate vertex color layer for material detection.
Creates a “RoadMask” vertex color layer where road vertices have R=1.0 and non-road vertices have R=0.0. This allows the material shader to detect roads without changing the terrain colors.
Uses Blender’s foreach_set for ~100x faster bulk operations.
- Parameters:
mesh_obj (bpy.types.Object) – The Blender mesh object
road_mask (np.ndarray) – 2D boolean or float array (height, width) where >0.5 = road
y_valid (np.ndarray) – Y indices mapping vertices to grid positions
x_valid (np.ndarray) – X indices mapping vertices to grid positions
logger (logging.Logger, optional) – Logger for progress messages
Apply road mask to color road vertices.
Marks road vertices with a distinctive color for shader-based material detection.
Example:
apply_road_mask( mesh_obj, road_mask, y_valid, x_valid )
Vertex Positions
- src.terrain.blender_integration.apply_vertex_positions(mesh_obj, new_positions, logger=None)[source]
Apply new 3D positions to mesh vertices.
Useful for applying smoothed vertex coordinates to an existing mesh, e.g., after road smoothing or terrain filtering.
- Parameters:
mesh_obj – Blender mesh object to modify
new_positions (ndarray) – Array of shape (n_vertices, 3) with new [x, y, z] positions
logger – Optional logger for progress messages
- Raises:
ValueError – If new_positions shape doesn’t match mesh vertex count
- Return type:
None
Example
>>> # Smooth road vertices and apply to mesh >>> from src.terrain.roads import smooth_road_vertices >>> >>> vertices = np.array([v.co[:] for v in mesh.data.vertices]) >>> smoothed = smooth_road_vertices(vertices, road_mask, y_valid, x_valid) >>> apply_vertex_positions(mesh, smoothed)
Update mesh vertex positions in place.
Used for modifying terrain geometry after mesh creation (smoothing, offsetting, etc.).
Example:
# Offset vertices by height new_positions = old_positions.copy() new_positions[:, 2] += height_offset apply_vertex_positions(mesh_obj, new_positions)
Mesh Creation
- src.terrain.blender_integration.create_blender_mesh(vertices, faces, colors=None, y_valid=None, x_valid=None, boundary_colors=None, name='TerrainMesh', logger=None)[source]
Create a Blender mesh object from vertices and faces.
Creates a new Blender mesh datablock, populates it with geometry data, optionally applies vertex colors, and creates a material with colormap shader.
- Parameters:
vertices (np.ndarray) – Array of (n, 3) vertex positions
faces (list) – List of tuples defining face connectivity
colors (np.ndarray, optional) – Array of RGB/RGBA colors (height, width, channels) for surface vertices
y_valid (np.ndarray, optional) – Array of y indices for vertex colors
x_valid (np.ndarray, optional) – Array of x indices for vertex colors
boundary_colors (np.ndarray, optional) – Array of RGB colors (n_boundary, 3) for boundary vertices in two-tier mode
name (str) – Name for the mesh and object (default: “TerrainMesh”)
logger (logging.Logger, optional) – Logger for progress messages
- Returns:
The created terrain mesh object
- Return type:
bpy.types.Object
- Raises:
RuntimeError – If Blender is not available or mesh creation fails
Create Blender mesh object from vertices and faces.
Low-level mesh creation. Most users should use
create_mesh()instead.Example:
mesh_obj = create_blender_mesh( vertices, faces, name="Terrain" )
Performance Notes
This module uses Blender’s bulk operations for maximum performance:
foreach_set/foreach_get: ~100x faster than Python loopsFlat numpy arrays: Direct memory access without Python overhead
Vectorized operations: Process all vertices simultaneously
Typical performance:
Applying colors to 1M vertices: ~0.1 seconds (vs 10+ seconds with loops)
Creating mesh with 1M faces: ~0.5 seconds