Thursday, August 17, 2023

doodle python check if mesh is symmetric in Blender 2.79

doodle for checking if a mesh is symmetric in x-axis tested in Blender 2.79 (useful for checking mesh before trying to mirror skin deformations).  there may be bugs so please modify use at your own risk.

"""how to test in Blender text editor
import bpy
import imp
testTool = imp.load_source("tool","/Users/Nathaniel/Documents/src_blender/python/snippets/deformation_snippets.py") #change to path to python file
testTool.isMeshSymmetric(mesh="notsymmetricPlane")
"""

import bpy

def isMeshSymmetric(mesh = None):
    """return bool true if mesh is symmetric false otherwise. tested in blender 2.79
    i dont think it requires mesh to be at origin
    @param mesh - string data object name of mesh to check
    """
    if not mesh:
        raise RuntimeError("requires a mesh the data object name")
        
    """
    save all +x vert ids
    save all -x vert ids
    
    if number +x and -v verts dont match break mesh not symmetric
    
    for each +x vert loop through all -x verts
        if found a -x vert closer than 0.000001 go to next +x vert
        else break mesh not symmetric    
    """
    plusxVertIds = []
    negxVertIds = []
    howClose = 0.00001
    if mesh not in bpy.data.objects:
        raise RuntimeError("requires {0} to exist in data objects".format(mesh))
        
    meshObj = bpy.data.objects[mesh]
    
    plusxVertIds = [ vert.index for vert in meshObj.data.vertices if vert.co.x > 0]
    negxVertIds = [ vert.index for vert in meshObj.data.vertices if vert.co.x < 0]
    
    numPlusx = len(plusxVertIds)
    numNegx = len(negxVertIds)
    if numPlusx != numNegx:
        print("couldnt find symmetry number left side vertices {0} and right side vertices {1} dont match".format(numPlusx,numNegx))
        return False
        
    for plusVertId in plusxVertIds:
        plusPos = meshObj.data.vertices[plusVertId].co
        isSymmetric = False
        for negVertId in negxVertIds:
            negPos = meshObj.data.vertices[negVertId].co
            #print("plusPos:",plusPos)
            #print("negPos:",negPos)
            if (abs(plusPos.x + negPos.x) <= howClose) and (abs(plusPos.y - negPos.y) <= howClose) and (abs(plusPos.z - negPos.z) <= howClose):
                isSymmetric = True
                break
        if not isSymmetric: #if cant find symmetric for a single vertex exit
            print("couldnt find symmetry for at least vertex id:"+str(plusVertId))
            return False
    print("great :) mesh is symmetric")
    return True #all mesh must be symmetric - i think dont need to check center verts