pymel.core.animation.skeletonEmbed¶
- skeletonEmbed(*args, **kwargs)¶
This command is used to embed a skeleton inside meshes. In query mode, return type is based on queried flag.
Flags:
Long Name / Short Name Argument Types Properties mergedMesh / mm bool When specified, the query command merges selected meshes together and returns a Python object representing the merged mesh. segmentationMethod / sm int Specifies which segmentation algorithm to use to determine what is inside the mesh and what is outside the mesh. By default, boundary-and-fill-and-grow voxelization will be used. Available algorithms are: 0 : Perfect mesh (no voxelization). This method works for perfect meshes, i.e. meshes that are closed, watertight, 2-manifold and without self-intersection or interior/hidden geometry. It segments the interior region of the mesh from the exterior using a pseudo- normal test. It does not use voxelization. If mesh conditions are not respected, the segmentation is likely to be wrong. This can make the segmentation process significantly longer and prevent successful skeleton embedding. 1 : Watertight mesh (flood fill). This method works for watertight meshes, i.e. meshes for which faces completely separate the interior region of the mesh from the exterior. The mesh can have degenerated faces, wrong face orientation, self-intersection, etc. The method uses surface voxelization to classify as part of the interior region all voxels intersecting with a mesh face. It then performs flood-filling from the outside, marking all reached voxels as part of the exterior region of the model. Finally, all unreached voxels are marked as part of the interior region. This method works so long as the mesh is watertight, i.e. without holes up to the voxelization resolution. Otherwise, flood-filling reaches the interior region and creates inaccurate segmentation. 2 : Imperfect mesh (flood fill + growing). This method works for meshes where holes could make the flood-filling step reach the interior region of the mesh, but that have face orientation consistent enough so filling them is possible. First, it uses surface voxelization to classify as part of the interior region all voxels intersecting with a mesh face. It then alternates flood-filling and growing steps. The flood-filling tries to reach all voxels from the outside so that unreached voxels are marked as part of the interior region. The growing step uses a relatively computation-intensive process to check for interior voxels in all neighbors to those already identified. Any voxel identified as interior is likely to fill holes, allowing subsequent flood- filling steps to identify more interior voxels. 3 : Polygon soup (repair). This method has no manifold or face orientation requirements. It reconstructs a mesh that wraps the input mesh with a given offset (3 times the voxel size) and uses this perfect 2-manifold mesh to segment the interior region from the exterior region of the model. Because of the offset, it might lose some of the details and merge parts that are proximal. However, this usually is not an issue with common models where body parts are not too close to one another. 99 : Direct skeleton (no embedding). This method does not try to perform embedding. It simply returns the skeleton in its initial pose without any attempt at embedding inside the meshes, other than placing it in the meshes bounding box. segmentationResolution / sr int Specifies which segmentation resolution to use for the voxel grid. By default, 256x256x256 voxels will be used. Flag can have multiple arguments, passed either as a tuple or a list. Derived from mel command maya.cmds.skeletonEmbed
Example:
- ::
import pymel.core as pm
# First select the shape, not the transform. pm.select( ‘characterShape’ , r=True )
# Embed skeleton using default parameter. pm.skeletonEmbed( ) u’{ [...] (A JSON dictionary with the description of the embedding. }’
# For debugging: get the merged mesh that will be used pm.skeletonEmbed( query=True , mergedMesh=True ) u’{ [...] (A JSON dictionary with the description of the merged mesh. }’
# Embed skeleton using polygon soup and 512 resolution. pm.skeletonEmbed( segmentationMethod=3 , segmentationResolution=512 )
# This method creates a few joints to see the embedding. import json def createJointsFromEmbedding( embeddingString ):
embedding = json.loads( embeddingString ) for name , position in embedding[ ‘joints’ ].iteritems( ):
joint = pm.createNode( ‘joint’ , name=name ) pm.xform( joint , worldSpace=True , translation=position )result = pm.skeletonEmbed( ) createJointsFromEmbedding( result )
# This method creates a mesh from the merged mesh to see it. import json import maya.OpenMaya as OpenMaya def createMeshFromDescription( meshString ):
mesh = json.loads( meshString )
meshPoints = mesh[ ‘points’ ] meshFaces = mesh[ ‘faces’ ] factor = 1.0 / mesh[ ‘conversionFactor’ ]
# Vertices vertexArray = OpenMaya.MFloatPointArray() for i in range( 0 , len( meshPoints ) , 3 ):
vertex = OpenMaya.MFloatPoint( meshPoints[ i ] * factor , meshPoints[ i + 1 ] * factor , meshPoints[ i + 2 ] * factor ) vertexArray.append( vertex )numVertices = vertexArray.length()
# Faces polygonCounts = OpenMaya.MIntArray() polygonConnects = OpenMaya.MIntArray() for face in meshFaces:
- for i in face:
- polygonConnects.append( i )
polygonCounts.append( len( face ) )
numPolygons = polygonCounts.length()
fnMesh = OpenMaya.MFnMesh() newMesh = fnMesh.create( numVertices , numPolygons , vertexArray , polygonCounts , polygonConnects ) fnMesh.updateSurface()
# Assign new mesh to default shading group nodeName = fnMesh.name() pm.sets( nodeName , e=True , fe=’initialShadingGroup’ )
return nodeName
result = pm.skeletonEmbed( query=True , mergedMesh=True ) createMeshFromDescription( result )