"""
Modifier Tools for Retopology
Tools for adding and configuring modifiers that assist in retopology workflows.
"""
from mcp.server.fastmcp import Context
import logging
logger = logging.getLogger("BlenderMCPServer")
def add_mirror_modifier(
ctx: Context,
blender_connection,
axis: str = "X",
use_clip: bool = True,
use_bisect: bool = True,
mirror_object: str = None
) -> str:
"""
Add a Mirror modifier to the active mesh object for symmetrical modeling.
Parameters:
- axis: Mirror axis - "X", "Y", or "Z" (default: "X")
- use_clip: Prevent vertices from crossing the mirror plane (default: True)
- use_bisect: Cut the mesh along the mirror plane (default: True)
- mirror_object: Name of object to use as mirror center (default: None = use object origin)
Returns success status and modifier configuration.
"""
try:
result = blender_connection.send_command("add_mirror_modifier", {
"axis": axis,
"use_clip": use_clip,
"use_bisect": use_bisect,
"mirror_object": mirror_object
})
if "error" in result:
return f"Error: {result['error']}"
output = "Mirror Modifier Added!\n\n"
output += f"Mirror Axis: {result.get('axis', axis)}\n"
output += f"Clipping: {'Enabled' if result.get('use_clip', use_clip) else 'Disabled'}\n"
output += f"Bisect: {'Enabled' if result.get('use_bisect', use_bisect) else 'Disabled'}\n"
if result.get('mirror_object'):
output += f"Mirror Object: {result['mirror_object']}\n"
else:
output += "Mirror Object: Object origin\n"
return output
except Exception as e:
logger.error(f"Error adding mirror modifier: {str(e)}")
return f"Error adding mirror modifier: {str(e)}"
def add_laplacian_smooth_modifier(
ctx: Context,
blender_connection,
iterations: int = 2,
lambda_factor: float = 1.0,
lambda_border: float = 1.0,
preserve_volume: bool = True
) -> str:
"""
Add a Laplacian Smooth modifier to reduce noise while preserving shape.
Useful for smoothing scanned or noisy meshes without losing detail.
Parameters:
- iterations: Number of smoothing iterations (default: 2)
- lambda_factor: Smoothing strength, 0-1000 (default: 1.0)
- lambda_border: Border smoothing strength, 0-1000 (default: 1.0)
- preserve_volume: Try to preserve the original volume (default: True)
Returns success status and modifier configuration.
"""
try:
result = blender_connection.send_command("add_laplacian_smooth_modifier", {
"iterations": iterations,
"lambda_factor": lambda_factor,
"lambda_border": lambda_border,
"preserve_volume": preserve_volume
})
if "error" in result:
return f"Error: {result['error']}"
output = "Laplacian Smooth Modifier Added!\n\n"
output += f"Iterations: {result.get('iterations', iterations)}\n"
output += f"Lambda Factor: {result.get('lambda_factor', lambda_factor)}\n"
output += f"Lambda Border: {result.get('lambda_border', lambda_border)}\n"
output += f"Preserve Volume: {'Yes' if result.get('preserve_volume', preserve_volume) else 'No'}\n"
return output
except Exception as e:
logger.error(f"Error adding Laplacian Smooth modifier: {str(e)}")
return f"Error adding Laplacian Smooth modifier: {str(e)}"
def add_weighted_normal_modifier(
ctx: Context,
blender_connection,
mode: str = "FACE_AREA",
weight: int = 50,
keep_sharp: bool = True,
face_influence: bool = False
) -> str:
"""
Add a Weighted Normal modifier to improve shading on hard-surface models.
Adjusts custom normals based on face area or corner angles.
Parameters:
- mode: Weighting mode (default: "FACE_AREA")
* "FACE_AREA" - Weight by face area
* "CORNER_ANGLE" - Weight by corner angles
* "FACE_AREA_WITH_ANGLE" - Weight by both area and angle
- weight: Weighting factor, 1-100 (default: 50)
- keep_sharp: Don't change sharp edges (default: True)
- face_influence: Use face area influence (default: False)
Returns success status and modifier configuration.
"""
try:
result = blender_connection.send_command("add_weighted_normal_modifier", {
"mode": mode,
"weight": weight,
"keep_sharp": keep_sharp,
"face_influence": face_influence
})
if "error" in result:
return f"Error: {result['error']}"
output = "Weighted Normal Modifier Added!\n\n"
output += f"Mode: {result.get('mode', mode)}\n"
output += f"Weight: {result.get('weight', weight)}\n"
output += f"Keep Sharp: {'Yes' if result.get('keep_sharp', keep_sharp) else 'No'}\n"
output += f"Face Influence: {'Yes' if result.get('face_influence', face_influence) else 'No'}\n"
return output
except Exception as e:
logger.error(f"Error adding Weighted Normal modifier: {str(e)}")
return f"Error adding Weighted Normal modifier: {str(e)}"
def add_data_transfer_modifier(
ctx: Context,
blender_connection,
source: str,
data_types: list,
mapping: str = "NEAREST_FACE",
mix_mode: str = "REPLACE",
mix_factor: float = 1.0
) -> str:
"""
Add a Data Transfer modifier to copy data from a source object.
Useful for transferring normals, UVs, or vertex colors from high-poly to low-poly.
Parameters:
- source: Name of the source object to transfer data from
- data_types: List of data types to transfer. Options:
* "CUSTOM_NORMAL" - Custom split normals
* "VCOL" - Vertex colors
* "UV" - UV coordinates
* "VGROUP" - Vertex groups
- mapping: Mapping method (default: "NEAREST_FACE")
* "NEAREST_FACE" - Nearest face interpolated
* "NEAREST_CORNER" - Nearest corner
* "POLYINTERP_NEAREST" - Nearest poly interpolated
* "POLYINTERP_LNORPROJ" - Projected face interpolated
- mix_mode: How to mix with existing data (default: "REPLACE")
* "REPLACE" - Replace existing data
* "ADD" - Add to existing
* "SUB" - Subtract from existing
* "MUL" - Multiply with existing
- mix_factor: Influence of the transfer, 0-1 (default: 1.0)
Returns success status and modifier configuration.
"""
try:
result = blender_connection.send_command("add_data_transfer_modifier", {
"source": source,
"data_types": data_types,
"mapping": mapping,
"mix_mode": mix_mode,
"mix_factor": mix_factor
})
if "error" in result:
return f"Error: {result['error']}"
output = "Data Transfer Modifier Added!\n\n"
output += f"Source Object: {result.get('source', source)}\n"
output += f"Data Types: {', '.join(result.get('data_types', data_types))}\n"
output += f"Mapping: {result.get('mapping', mapping)}\n"
output += f"Mix Mode: {result.get('mix_mode', mix_mode)}\n"
output += f"Mix Factor: {result.get('mix_factor', mix_factor)}\n"
return output
except Exception as e:
logger.error(f"Error adding Data Transfer modifier: {str(e)}")
return f"Error adding Data Transfer modifier: {str(e)}"