def TryLoadExternalBaseMeshBodyMorph(): with mayaUtils.DebugTimer('TryLoadExternalBaseMeshBodyMorph'): mainMesh = mayaUtils.FindMeshByWildcard('Genesis8Female*', checkForMatWithName='Torso') if mainMesh is None: print 'Error! Can`t find body(Torso) mesh' return #Mesh unskinned on this stage so we can safely delete all history cmds.delete(mainMesh, constructionHistory=True) bodyMorphFile = os.path.join(env.GetIntermediateFullPath(), env.PROCESSED_BASE_MESH_NAME + '.obj') bodyMorphExist = os.path.exists(bodyMorphFile) print 'Body morph file: {} Exist: {}'.format(bodyMorphFile, bodyMorphExist) if not bodyMorphExist: print 'ABORTED: no body morph file found' return morphMesh = cmds.file(bodyMorphFile, i=True, returnNewNodes=True)[0] morphMesh = cmds.rename(morphMesh, 'BodyMorph') cmds.xform(morphMesh, absolute=True, translation=[0, 0, 100]) bs = cmds.blendShape([morphMesh, mainMesh]) cmds.blendShape(bs, edit=True, weight=[0, 1.0]) cmds.delete(mainMesh, constructionHistory=True) cmds.delete(morphMesh)
def SetVertexColorForBorderVertices(): with mayaUtils.DebugTimer('SetVertexColorForBorderVertices'): skinList = cmds.ls(type='skinCluster') cmds.select(clear=True) for s in skinList: cmds.select(clear=True) mesh = mayaUtils.GetMeshFromSkinCluster(s) cmds.select(mesh) cmds.selectType(polymeshFace=True) cmds.polySelectConstraint(mode=3, type=8, where=1) # to get border vertices borderVerts = cmds.polyListComponentConversion(tv=True) cmds.polySelectConstraint(mode=0, sh=0, bo=0) cmds.select(clear=True) allVerts = cmds.polyListComponentConversion(mesh, tv=True) mayaUtils.SetVertexColors(allVerts, (1, 1, 1)) mayaUtils.SetVertexColors(borderVerts, (0, 1, 1)) cmds.select(clear=True) shape = mayaUtils.FindMeshByWildcard( 'FemaleBody*', checkForMatWithName='Body') #new name is 'Body' if shape: MaskShellsEdgesForTesselation(shape, 0) MaskShellsEdgesForTesselation(shape, 1) MaskShellsEdgesForTesselation(shape, 2) MaskShellsEdgesForTesselation(shape, 3) MaskShellsEdgesForTesselation(shape, 4)
def TryLoadExternalUVs(): with mayaUtils.DebugTimer('TryLoadExternalUVs'): mainMesh = mayaUtils.FindMeshByWildcard('Genesis8Female*', checkForMatWithName='Torso') if mainMesh is None: print 'Error! Can`t find body(Torso) mesh' return cmds.delete(mainMesh, constructionHistory=True) uvMeshFile = os.path.join(env.GetIntermediateFullPath(), env.BASE_FEMALE_MESH_WITH_UV1_NAME + '.obj') uvMeshFileExist = os.path.exists(uvMeshFile) print 'UV mesh file: {} Exist: {}'.format(uvMeshFile, uvMeshFileExist) if not uvMeshFileExist: print 'ABORTED: no uv mesh file found' return uvMesh = cmds.file(uvMeshFile, i=True, returnNewNodes=True)[0] uvMesh = cmds.rename(uvMesh, 'UV_Source') cmds.xform(uvMesh, absolute=True, translation=[0, 0, 100]) cmds.polyUVSet(mainMesh, create=True, uvSet='Tesselation_UV') cmds.transferAttributes(uvMesh, mainMesh, transferPositions=0, transferNormals=0, transferUVs=1, sourceUvSet='map1', targetUvSet='Tesselation_UV', sampleSpace=5) cmds.delete(mainMesh, constructionHistory=True) cmds.delete(uvMesh)
def CollapseUVTiles(): cmds.select(clear=True) shape = mayaUtils.FindMeshByWildcard( 'FemaleBody*', checkForMatWithName='Body') #new name is 'Body' if shape: #CollapseUVTile(shape, 0) CollapseUVTile(shape, 1) CollapseUVTile(shape, 2) CollapseUVTile(shape, 3) CollapseUVTile(shape, 4)
def TryLoadExternalMorphTargets(): with mayaUtils.DebugTimer('TryLoadExternalMorphTargets'): mainMesh = mayaUtils.FindMeshByWildcard('Genesis8Female*', checkForMatWithName='Torso') if mainMesh is None: print 'Error! Can`t find body(Torso) mesh' return subDirs = fileUtils.GetSubdirNames(env.GetIntermediateFullPath()) blendShapeDeformer = None for subDir in subDirs: if not fileUtils.IsDirStartWithPrefixes(subDir, env.MORPH_TARGET_PREFIXES): print 'SKIPPING directory {}. Reason - unresolved name (should starts with \'{}\')'.format( subDir, env.MORPH_TARGET_PREFIXES) continue fullSubdirPath = os.path.join(env.GetIntermediateFullPath(), subDir) morphMeshFile = os.path.join(fullSubdirPath, env.PROCESSED_BASE_MESH_NAME + '.obj') morphMeshExist = os.path.exists(morphMeshFile) print 'Dir: {} SubD mesh: {} Exist: {}'.format( subDir, morphMeshFile, morphMeshExist) if not morphMeshExist: print 'SKIPPING...' continue morphMesh = cmds.file(morphMeshFile, i=True, returnNewNodes=True)[0] morphMesh = cmds.rename(morphMesh, subDir) # name new blendshape as it folder cmds.xform(morphMesh, absolute=True, translation=[0, 0, 100]) blendShapeDeformer = mayaUtils.GetBlendShape(mainMesh) if blendShapeDeformer is None: blendShapeDeformer = cmds.blendShape(mainMesh)[0] weightsCount = cmds.blendShape( blendShapeDeformer, q=True, weightCount=True) # Index for next added blendshape cmds.blendShape(blendShapeDeformer, edit=True, target=(mainMesh, weightsCount, morphMesh, 1.0)) cmds.delete(morphMesh)
def OptimizeBodyMaterials(): with mayaUtils.DebugTimer('OptimizeBodyMaterials'): shape = mayaUtils.FindMeshByWildcard('Genesis8Female*', checkForMatWithName='Torso') if shape is None: print 'Error! Can`t find body(Torso) shape' return mayaUtils.AppendShadingGroupByMat(shape, 'Face', 'Lips') mayaUtils.AppendShadingGroupByMat(shape, 'Face', 'Ears') mayaUtils.AppendShadingGroupByMat(shape, 'Face', 'EyeSocket') mayaUtils.AppendShadingGroupByMat(shape, 'Legs', 'Toenails') mayaUtils.AppendShadingGroupByMat(shape, 'Arms', 'Fingernails') mayaUtils.AppendShadingGroupByMat(shape, 'Torso', 'Legs') mayaUtils.AppendShadingGroupByMat(shape, 'Torso', 'Arms') mayaUtils.AppendShadingGroupByMat(shape, 'Torso', 'Face') mayaUtils.AppendShadingGroupByMat(shape, 'Mouth', 'Teeth') mayaUtils.AppendShadingGroupByMat(shape, 'EyeMoisture', 'Cornea') # useful eyes mayaUtils.AppendShadingGroupByMat(shape, 'Pupils', 'Irises') # not used mayaUtils.AppendShadingGroupByMat(shape, 'Pupils', 'Sclera') # not used eyesShape = mayaUtils.DetachSkinnedMeshByMat(shape, ['EyeMoisture', 'Pupils'], '_Eyes') mayaUtils.DeleteFacesByMat(eyesShape, ['Pupils']) unusedEyesFaces = selUtils.GetFacesOutsideCenterUVRange(eyesShape) cmds.delete(unusedEyesFaces) mayaUtils.RenameMaterial('Torso', 'Body') mayaUtils.RenameMaterial('EyeMoisture', 'Eyes') mayaUtils.RenameMaterial('EyeLashes*', 'FemaleEyeLashes') SafeBakePartialHistoryKeepBlendShapes(shape) if eyesShape: cmds.bakePartialHistory(eyesShape, prePostDeformers=True) mayaUtils.CleanUnusedInfluensesOnAllSkinClusters()
def PerformFullBatchProcessing(pForceFullRebuild=True): with DebugTimer( 'PerformFullBatchProcessing: Processing directory: {}'.format( env.GetSrcFullPath())): #process morphs PreprocessMorphTargets(pForceFullRebuild=pForceFullRebuild, inBeepAfterComplete=False) #create output directory fileUtils.MakeDirectoryIfNotExist(env.GetOutputFullPath()) #process animations subDirs = fileUtils.GetSubdirNames(env.GetSrcFullPath()) for subDir in subDirs: if not fileUtils.IsDirStartWithPrefixes(subDir, env.ANIM_PREFIXES): print 'PerformFullBatchProcessing: Skipping Dir: {} as it not ANIMATION directory (checked for prefixes: {})'.format( subDir, env.ANIM_PREFIXES) continue ProcessAnimDir(subDir) #end animations processing #finally process main meshes baseFile = os.path.join(env.GetSrcFullPath(), 'Base.fbx') baseFileExist = os.path.exists(baseFile) print 'PerformFullBatchProcessing: Final Mesh processing Dir: {} Anim File: {} Exist: {}'.format( env.GetSrcFullPath(), baseFile, baseFileExist) if not baseFileExist: print 'SKIPPING...' return cmds.file(newFile=True, force=True) cmds.file(baseFile, pr=1, rpr="Animation", ignoreVersion=1, i=1, type="FBX", importFrameRate=True,\ importTimeRange="override", ra=True, rdn=1, mergeNamespacesOnClash=False, options="groups=1;ptgroups=1;materials=1;smoothing=1;normals=1") dazToUe.OptimizeSkeleton(pbCollapseToes=False, pLoadExternalBaseMesh=True, pLoadExternalMorphs=True,\ pLoadExternalUVs=True, pCreateIKConstraints=True, inBeepAfterComplete=False) #recognize gender baseMeshName = 'Generic' if libHazardMayaUtils.FindMeshByWildcard('Female*'): baseMeshName = 'Female' elif libHazardMayaUtils.FindMeshByWildcard('Male*'): baseMeshName = ('Male') #export rig for 3ds max, motionbuilder etc (with end bones) cmds.select(all=True, hierarchy=True) fileUtils.ExportSelectionFBX(pDir=env.GetOutputFullPath(), pFileNameWithoutExtension='RIG_' + baseMeshName, pBakeAnimation=False) cmds.select(clear=True) #export mesh(meshes) for ue4 (without end bones) body = libHazardMayaUtils.FindMeshByWildcard(baseMeshName + 'Body') eyelashes = libHazardMayaUtils.FindMeshByWildcard(baseMeshName + 'Eyelashes') eyes = libHazardMayaUtils.FindMeshByWildcard(baseMeshName + 'Eyes') meshesToExport = [] if body: meshesToExport.append(body) if eyes: meshesToExport.append(eyes) if eyelashes: meshesToExport.append(eyelashes) cmds.select(clear=True) if meshesToExport: cmds.select(meshesToExport) skelUtils.SelectJointsForSelectedMeshes(bKeepSelection=True, bIncludeSpecialJoints=True, bIncludeIKJoints=True) fileUtils.ExportSelectionFBX(pDir=env.GetOutputFullPath(), pFileNameWithoutExtension='SK_' + baseMeshName, pBakeAnimation=True) else: print 'ERROR: Nothing to export as {}'.format(baseMeshName) cmds.select(clear=True) #save maya file for later use saveFilePath = os.path.join(env.GetIntermediateFullPath(), 'BaseProcessed.mb') cmds.file(rename=saveFilePath) cmds.file(save=1, options="v=0;", f=1) #end mesh processing libHazardMayaUtils.NotifyWithSound()
def CreateOptimizedSkeletonOnlyAndRetargetAnim(bFilterCurves=True, inBeepAfterComplete=True): print 'Starting skeleton optimization' start = time.clock() cmds.currentTime(0, edit=True) #set skeleton to 'reference' position dazUtils.RemoveObjectsByWildcard(['Fingernails_*'], 'transform') dazUtils.RemoveObjectsByWildcard(['HazardFemaleGenitalia_*Shape'], 'transform') mayaUtils.ParentAllGeometryToWorld() primaryMesh = mayaUtils.FindMeshByWildcard('Genesis8*', preferShapeWithMaxVertices=True, checkForMatWithName='Torso') if primaryMesh: cmds.select(primaryMesh) else: cmds.select(all=True) mel.eval('gotoBindPose') cmds.select(clear=True) #delete all meshes shapesToDelete = mayaUtils.GetMultipleShapesTransforms( cmds.ls(geometry=True, objectsOnly=True)) if shapesToDelete: for s in shapesToDelete: cmds.delete(s) print 'Deleting {0}'.format(s) dazUtils.RenameSkeletonJoints() oldJoints = mayaUtils.GetHierarchy('root') dazUtils.DuplicateSkeletonJoints('root', 'DAZ_') dazUtils.FixNewJointsOrientation() dazUtils.RecreateHierarchy('root', 'DAZ_') dazUtils.JointOrientToRotation('DAZ_root') #delete twist joints for animation retargetting/ they are procedurally animated in engine unusedJoints = cmds.ls('DAZ_*twist*') for j in unusedJoints: cmds.delete(j) print '\tDeleting {0}'.format(j) print 'Renaming OLD skeleton' oldJoints = mayaUtils.GetHierarchy('root') for j in oldJoints: mayaUtils.RenameJoint(j, 'OLD_' + j) dazUtils.RenameNewSkeleton() #remove DAZ_ prefix dazUtils.AddNippleJointsAndAimBreast() cmds.select(clear=True) #create constraint from old skeleton to new print 'Creating constraints' newJoints = mayaUtils.GetHierarchy('root') for j in newJoints: oldJoint = 'OLD_' + j print '\tCreating parentConstraint from {0} to {1}'.format(oldJoint, j) #not all joints can exist on old skeleton (e.g. nipples) if cmds.objExists(oldJoint) and cmds.nodeType(oldJoint) == 'joint': cmds.parentConstraint(oldJoint, j, maintainOffset=True) dazUtils.CreateIkJoints() #create AFTER constraining new skeleton to old # No need to bake IK joints, they are auto baked during exporting to fbx print '\n' print "\t\t******** BAKING ANIMATION ********" print '\n' attributesToBake = ['tx', 'ty', 'tz', 'rx', 'ry', 'rz'] timeRange = (cmds.playbackOptions(animationStartTime=True, query=True), cmds.playbackOptions(animationEndTime=True, query=True)) print 'timeRange = {0}'.format(timeRange) cmds.bakeResults(newJoints, attribute=attributesToBake, time=timeRange, minimizeRotation=True, preserveOutsideKeys=True, simulation=True, disableImplicitControl=True) print '\n' print "\t\t******** Filtering curves ********" print '\n' if bFilterCurves: animNodes = cmds.listConnections(newJoints, type="animCurve") if animNodes: print 'Performing filtering for {0} anim curves'.format( len(animNodes)) oldKeysCount = cmds.keyframe(animNodes, q=True, keyframeCount=True) cmds.filterCurve(animNodes, filter='simplify', timeTolerance=0.01, tolerance=0.01) newKeysCount = cmds.keyframe(animNodes, q=True, keyframeCount=True) percent = float(newKeysCount) / float(oldKeysCount) * 100.0 print '{0} keys filtered to {1} keys ({2:.1f}%)'.format( oldKeysCount, newKeysCount, percent) else: print 'Filtering NOT requested' #clean scene after finishing print 'Deleting old skeleton' cmds.select(clear=True) cmds.select(mayaUtils.GetHierarchy('OLD_root')) cmds.delete() print 'FINISHED animation retargeting: time taken %.02f seconds' % ( time.clock() - start) if inBeepAfterComplete: mayaUtils.NotifyWithSound()
def ReplaceEyesWithExternalMeshes(): oldEyes = mayaUtils.FindMeshByWildcard('FemaleEyes') jointLeft = cmds.ls('eye_l', type='joint')[0] jointRight = cmds.ls('eye_r', type='joint')[0] print oldEyes print jointLeft print jointRight #get old eyes mesh vertical (Y) size oldSizeY = mayaUtils.GetBoundingBox(oldEyes)[1] print oldSizeY cmds.delete(oldEyes) mayaUtils.CleanUnusedMaterials() print GetSharedResourcesPath() leftEyeFilePath = os.path.join(GetSharedResourcesPath(), 'Eye_Left.obj') print leftEyeFilePath leftEyeMesh = cmds.ls(cmds.file(leftEyeFilePath, i=True, returnNewNodes=True), transforms=True)[0] externalSizeY = mayaUtils.GetBoundingBox(leftEyeMesh)[1] print externalSizeY rightEyeFilePath = os.path.join(GetSharedResourcesPath(), 'Eye_Right.obj') rightEyeMesh = cmds.ls(cmds.file(rightEyeFilePath, i=True, returnNewNodes=True), transforms=True)[0] scaleFactor = oldSizeY / externalSizeY print 'Scale factor = {}'.format(scaleFactor) #scale and move new eyes cmds.scale(scaleFactor, scaleFactor, scaleFactor, leftEyeMesh, relative=True) cmds.matchTransform(leftEyeMesh, jointLeft, position=True, rotation=True) cmds.rotate(0, '90deg', 0, leftEyeMesh, relative=True) cmds.makeIdentity(leftEyeMesh, apply=True, translate=True, rotate=True, scale=True, normal=1) cmds.delete(leftEyeMesh, constructionHistory=True) cmds.scale(scaleFactor, scaleFactor, scaleFactor, rightEyeMesh, relative=True) cmds.matchTransform(rightEyeMesh, jointRight, position=True, rotation=True) cmds.rotate(0, '90deg', 0, rightEyeMesh, relative=True) cmds.makeIdentity(rightEyeMesh, apply=True, translate=True, rotate=True, scale=True, normal=1) cmds.delete(rightEyeMesh, constructionHistory=True) #binding cmds.skinCluster(jointLeft, leftEyeMesh, tsb=True) cmds.select(clear=True) cmds.skinCluster(jointRight, rightEyeMesh, tsb=True) cmds.select(clear=True) cmds.polyUniteSkinned([leftEyeMesh, rightEyeMesh], ch=False) cmds.rename('FemaleEyes') cmds.select(clear=True) sha = cmds.shadingNode('lambert', asShader=True, name='Eyes') sg = cmds.sets(empty=True, renderable=True, noSurfaceShader=True, name='Eyes_sg') cmds.connectAttr(sha + '.outColor', sg + '.surfaceShader', f=True) cmds.sets('FemaleEyes', e=True, forceElement=sg)
def PostprocessGenitaliaObject(genitaliaMeshWildcard): with mayaUtils.DebugTimer( 'PostprocessGenitaliaObject(genitaliaMeshWildcard={0})'.format( genitaliaMeshWildcard)): genitaliaMesh = mayaUtils.FindMeshByWildcard(genitaliaMeshWildcard) if not genitaliaMesh: print 'Genitalia mesh not found. Aborted' return print 'Processing {0}'.format(genitaliaMesh) genitaliaMesh = cmds.rename(genitaliaMesh, 'FemaleGenitalia') #rename to proper name #replace material with original torso mat facesWithTorsoMat = mayaUtils.GetFacesByMatsWildcard( genitaliaMesh, 'Torso*') mayaUtils.AssignObjectListToShader(facesWithTorsoMat, 'Body') #use new material name # mayaUtils.ArrangeUVByMat(genitaliaMesh, 'Body', su=0.5, sv=0.5, u=0.5, v=0.5) mayaUtils.AppendShadingGroupByMat(genitaliaMesh, 'Anus', 'V****a') mayaUtils.RenameMaterial('Anus', 'BodyGenitalia') cmds.bakePartialHistory(genitaliaMesh, prePostDeformers=True) bodyMesh = mayaUtils.FindMeshByWildcard('FemaleBody' + '*', checkForMatWithName='Body') if not bodyMesh: print '{0} mesh not found. Aborted' return cmds.select(clear=True) borderVertsList = mayaUtils.GetBorderVertices(genitaliaMesh) borderVertsList = cmds.filterExpand(borderVertsList, sm=31, expand=True) bodySkinCluster = mayaUtils.GetSkinCluster(bodyMesh) genitaliaSkinCluster = mayaUtils.GetSkinCluster(genitaliaMesh) #transfer attributes manually for v in borderVertsList: pos = cmds.pointPosition(v, world=True) #print pos closestVert = mayaUtils.GetClosestVertex(bodyMesh, pos) closestVertPos = cmds.xform(closestVert, t=True, ws=True, q=True) closestVertNormal = cmds.polyNormalPerVertex(closestVert, query=True, xyz=True) # set position cmds.move(closestVertPos[0], closestVertPos[1], closestVertPos[2], v, absolute=True, worldSpace=True) # set normal cmds.polyNormalPerVertex(v, xyz=(closestVertNormal[0], closestVertNormal[1], closestVertNormal[2])) referenceVertInfluences = cmds.skinPercent(bodySkinCluster, closestVert, query=True, transform=None, ignoreBelow=0.00001) targetInfluences = cmds.skinCluster(genitaliaSkinCluster, query=True, influence=True) targetTransformValues = [] for i in referenceVertInfluences: if i not in targetInfluences: cmds.skinCluster(genitaliaSkinCluster, e=True, addInfluence=i, weight=0.0) #print i referenceInfluenceValuePerVertex = cmds.skinPercent( bodySkinCluster, closestVert, query=True, transform=i, transformValue=True) targetTransformValues.append( (i, referenceInfluenceValuePerVertex)) #print targetTransformValues # set weight cmds.skinPercent(genitaliaSkinCluster, v, transformValue=targetTransformValues) cmds.bakePartialHistory(genitaliaMesh, prePostDeformers=True)