"""
Topology Evaluation Tools
Tools for evaluating retopology results with configurable pass/fail criteria.
"""
from mcp.server.fastmcp import Context
import logging
logger = logging.getLogger("BlenderMCPServer")
def evaluate_retopology(
ctx: Context,
blender_connection,
high_poly: str,
low_poly: str,
quad_threshold: float = 0.85,
distance_threshold: float = 0.01,
coverage_threshold: float = 0.95,
valence_threshold: float = 0.80
) -> str:
"""
Evaluate retopology result by comparing low-poly mesh to high-poly reference.
Compares topology quality, surface deviation, and provides pass/fail status
based on configurable thresholds.
Parameters:
- high_poly: Name of the high-poly reference mesh
- low_poly: Name of the low-poly retopology mesh
- quad_threshold: Minimum quad ratio for pass (default: 0.85 = 85%)
- distance_threshold: Maximum surface deviation for pass (default: 0.01 units)
- coverage_threshold: Minimum surface coverage for pass (default: 0.95 = 95%)
- valence_threshold: Minimum valence-4 ratio for pass (default: 0.80 = 80%)
Returns comprehensive evaluation with pass/fail determination.
"""
try:
result = blender_connection.send_command("evaluate_retopology", {
"high_poly": high_poly,
"low_poly": low_poly,
"quad_threshold": quad_threshold,
"distance_threshold": distance_threshold,
"coverage_threshold": coverage_threshold,
"valence_threshold": valence_threshold
})
if "error" in result:
return f"Error: {result['error']}"
# Format the evaluation report
passed = result.get('passed', False)
status_icon = "PASSED" if passed else "FAILED"
output = f"Retopology Evaluation: {status_icon}\n"
output += "=" * 50 + "\n\n"
output += f"High-poly: {result.get('high_poly')} ({result.get('high_face_count', 0):,} faces)\n"
output += f"Low-poly: {result.get('low_poly')} ({result.get('low_face_count', 0):,} faces)\n"
output += f"Reduction: {result.get('polycount_ratio', 0):.2%}\n\n"
# Quality metrics
output += "QUALITY METRICS:\n"
output += f" Quality Grade: {result.get('quality_grade', 'N/A')}\n"
output += f" Quad Ratio: {result.get('quad_ratio', 0):.1%}\n"
output += f" Valence-4 Ratio: {result.get('valence_ratio', 0):.1%}\n\n"
# Distance metrics
output += "SURFACE DEVIATION:\n"
output += f" Max Distance: {result.get('distance_max', 0):.6f}\n"
output += f" Avg Distance: {result.get('distance_avg', 0):.6f}\n"
output += f" Coverage: {result.get('distance_coverage', 0):.1%}\n\n"
# Pass/Fail criteria
output += "CRITERIA STATUS:\n"
criteria = result.get('passed_criteria', {})
thresholds = result.get('thresholds_used', {})
for name, passed_crit in criteria.items():
icon = "PASS" if passed_crit else "FAIL"
threshold = thresholds.get(name.replace('_ratio', '_threshold').replace('distance_max', 'distance_threshold'), 'N/A')
output += f" [{icon}] {name}: threshold {threshold}\n"
output += "\n"
# Issues
issues = result.get('issues', [])
if issues:
output += "ISSUES TO ADDRESS:\n"
for issue in issues:
output += f" - {issue}\n"
output += "\n"
# Final verdict
if passed:
output += "VERDICT: Retopology meets all quality criteria.\n"
else:
output += "VERDICT: Retopology needs improvement. See issues above.\n"
return output
except Exception as e:
logger.error(f"Error evaluating retopology: {str(e)}")
return f"Error evaluating retopology: {str(e)}"