Go to: Synopsis. Return value. Keywords. Related. Flags. Python examples.

Synopsis

skeletonEmbed([mergedMesh=boolean], [segmentationMethod=uint], [segmentationResolution=uint])

Note: Strings representing object names and arguments must be separated by commas. This is not depicted in the synopsis.

skeletonEmbed is undoable, queryable, and NOT editable.

This command is used to embed a skeleton inside meshes.

Return value

None

In query mode, return type is based on queried flag.

Keywords

geomBind

Related

geomBind

Flags

mergedMesh, segmentationMethod, segmentationResolution
Long name (short name) Argument types Properties
mergedMesh(mm) boolean query
When specified, the query command merges selected meshes together and returns a Python object representing the merged mesh.
segmentationMethod(sm) uint create
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.
segmentationResolution(sr) uint create
Specifies which segmentation resolution to use for the voxel grid. By default, 256x256x256 voxels will be used.

Flag can appear in Create mode of command Flag can appear in Edit mode of command
Flag can appear in Query mode of command Flag can have multiple arguments, passed either as a tuple or a list.

Python examples

import maya.cmds as cmds

# First select the shape, not the transform.
cmds.select( 'characterShape' , r=True )
# Embed skeleton using default parameter.
cmds.skeletonEmbed( )
# Result: u'{ [...] (A JSON dictionary with the description of the embedding. }' #
# For debugging: get the merged mesh that will be used
cmds.skeletonEmbed( query=True , mergedMesh=True )
# Result: u'{ [...] (A JSON dictionary with the description of the merged mesh. }' #
# Embed skeleton using polygon soup and 512 resolution.
cmds.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 = cmds.createNode( 'joint' , name=name )
        cmds.xform( joint , worldSpace=True , translation=position )
result = cmds.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()
    cmds.sets( nodeName , e=True , fe='initialShadingGroup' )
    return nodeName
result = cmds.skeletonEmbed( query=True , mergedMesh=True )
createMeshFromDescription( result )