"""
Retopology Workflow Tools
Tools for setting up proper retopology workflow.
"""
from mcp.server.fastmcp import Context
import logging
logger = logging.getLogger("BlenderMCPServer")
def create_retopo_setup(
ctx: Context,
blender_connection,
source_object: str,
retopo_name: str = None,
initial_mesh: str = "PLANE"
) -> str:
"""
Create a proper retopology setup with new low-poly object.
Creates a new object for retopology work with shrinkwrap modifier
and snapping configured. Leaves the high-poly source untouched.
Parameters:
- source_object: Name of the high-poly source mesh to retopologize
- retopo_name: Name for the new retopo object (default: source_object + "_retopo")
- initial_mesh: Starting mesh type - "PLANE", "CUBE", "SPHERE", "EMPTY"
Returns setup confirmation with the new object name.
"""
try:
params = {
"source_object": source_object,
"initial_mesh": initial_mesh
}
if retopo_name:
params["retopo_name"] = retopo_name
result = blender_connection.send_command("create_retopo_setup", params)
if "error" in result:
return f"Error: {result['error']}"
output = "Retopology Setup Created\n"
output += "=" * 40 + "\n\n"
output += f"Source (high-poly): {result.get('source_object')}\n"
output += f"Retopo (low-poly): {result.get('retopo_object')}\n"
output += f"Initial mesh: {result.get('initial_mesh')}\n\n"
output += "Settings Applied:\n"
for setting in result.get('settings_applied', []):
output += f" - {setting}\n"
output += "\nNEXT STEPS:\n"
output += " 1. Enter Edit Mode on the retopo object\n"
output += " 2. Use extrude (E) and loop cuts (Ctrl+R) to build topology\n"
output += " 3. Vertices will snap to the source surface automatically\n"
output += " 4. Use get_topology_quality to check progress\n"
return output
except Exception as e:
logger.error(f"Error creating retopo setup: {str(e)}")
return f"Error creating retopo setup: {str(e)}"
def project_vertices(
ctx: Context,
blender_connection,
object_name: str,
target_object: str,
method: str = "NEAREST_SURFACEPOINT"
) -> str:
"""
Project vertices of an object onto target surface.
Parameters:
- object_name: Name of object whose vertices to project
- target_object: Name of target surface object
- method: Projection method - "NEAREST_SURFACEPOINT", "PROJECT", "NEAREST_VERTEX"
Returns success status and number of vertices projected.
"""
try:
result = blender_connection.send_command("project_vertices", {
"object_name": object_name,
"target_object": target_object,
"method": method
})
if "error" in result:
return f"Error: {result['error']}"
return (f"Projected {result.get('vertices_projected', 0)} vertices "
f"from '{result.get('object')}' onto '{result.get('target')}' "
f"using {result.get('method')} method")
except Exception as e:
logger.error(f"Error projecting vertices: {str(e)}")
return f"Error projecting vertices: {str(e)}"