示例#1
0
    def command(
            meshes=None,
            name='bulletSoftBodyShape#',
            # Attrs
            generateBendConstraints=None,
            selfCollision=None,
            bendResistance=None,
            linearStiffness=None,
            friction=None,
            damping=None,
            pressure=None,
            collisionMargin=None,
            positionIterations=None,
            #poseMatching=None,
            #enablePoseMatching=None,
            preserveSourceMesh=None,
            singleTransform=None,
            **kwargs):
        '''Create a bulletSoftBody from specified mesh.  
		'''

        # Explicitly list the names of settable attributes iterated over below
        settableAttrs = [
            'generateBendConstraints',
            'selfCollision',
            'bendResistance',
            'linearStiffness',
            'friction',
            'damping',
            'pressure',
            'collisionMargin',
            'positionIterations',
            #'poseMatching',
            #'enablePoseMatching',
        ]

        # Make a boolean value that is easier to read in code
        singleTransform = singleTransform != False

        # Get list of meshes from selection if not passed in
        if (meshes == None):
            maya.cmds.select(maya.cmds.listRelatives(shapes=True,
                                                     fullPath=True),
                             add=True)
            meshes = maya.cmds.ls(sl=True, type='mesh', long=True)

        # Make sure the selection doesn't contain any bullet objects.
        BulletUtils.verifySelectionNotBullet(meshes)

        returnedNodes = []
        # Sanity Checking
        if len(meshes) == 0:
            maya.OpenMaya.MGlobal.displayError(
                maya.stringTable['y_SoftBody.kSelectMesh'])
            return returnedNodes

        # Loop over meshes and create soft bodies
        for mesh in meshes:
            meshT = maya.cmds.listRelatives([mesh], parent=True,
                                            fullPath=True)[0]

            # Duplicate mesh and connect in history
            # Alternate: use a stub func like polyReduce -replaceOriginal 0 -percentage 100 -nodeState 1 -name "stubPolyMod";
            meshCopyT = maya.cmds.polyDuplicateAndConnect(mesh)[0]
            meshCopyShape = maya.cmds.listRelatives(meshCopyT,
                                                    s=True,
                                                    fullPath=True)[0]

            if not singleTransform:
                maya.cmds.setAttr((meshCopyT + ".t"), 0, 0, 0)
                # zero out the transform since get values from WorldSpace
                maya.cmds.setAttr((meshCopyT + ".r"), 0, 0, 0)
                # zero out the transform since get values from WorldSpace
                maya.cmds.setAttr((meshCopyT + ".s"), 1, 1, 1)
                # zero out the transform since get values from WorldSpace
                maya.cmds.setAttr((meshCopyT + ".inheritsTransform"), 0)

            # Create softbody shape
            # NOTE: If plugin not loaded, then sbShape will return unknown nodetype
            #	   and listRelatives will not work as expected
            sbShape = maya.cmds.createNode('bulletSoftBodyShape', name=name)
            sbT = maya.cmds.listRelatives([sbShape],
                                          parent=True,
                                          fullPath=True)[0]

            # Reparent body shape under it
            maya.cmds.parent(sbShape, meshT, r=True, s=True)
            maya.cmds.delete(sbT)
            sbT = meshT

            # Create Solver (proto)
            sol = BulletUtils.getSolver()

            # Connect
            maya.cmds.connectAttr((mesh + ".worldMesh"),
                                  (sbShape + ".inWorldMesh"))
            maya.cmds.connectAttr((sol + ".outSolverInitialized"),
                                  (sbShape + ".solverInitialized"))
            maya.cmds.connectAttr((sbShape + ".outSoftBodyData"),
                                  (sol + ".softBodies"),
                                  na=True)
            maya.cmds.connectAttr((sol + ".outSolverUpdated"),
                                  (sbShape + ".solverUpdated"))
            maya.cmds.connectAttr((sbShape + ".outSolvedMesh"),
                                  (meshCopyShape + ".inMesh"),
                                  f=True)

            # REVISIT: Consider alternatives like a single initSystem bool attr instead of startTime and currentTime.
            #		  Might be able to get around needing it at all
            maya.cmds.connectAttr((sol + ".startTime"),
                                  (sbShape + ".startTime"))
            maya.cmds.connectAttr((sol + ".currentTime"),
                                  (sbShape + ".currentTime"))

            # Set Attrs (optional, set if value != None)
            # Use the settableAttrs list above to qualify kwargs passed into the function
            for k, v in locals().iteritems():
                if k in settableAttrs and v != None:
                    if isinstance(v, list):
                        maya.cmds.setAttr('%s.%s' % (sbShape, k),
                                          *v)  # covers float3 cases
                    else:
                        maya.cmds.setAttr('%s.%s' % (sbShape, k), v)

            # Additional Actions
            if (preserveSourceMesh == False):
                maya.cmds.setAttr((mesh + '.intermediateObject'), True)

            # Alternate: Explicit method
            #if generateBendConstraints != None:
            #	maya.cmds.setAttr((sbShape+'.generateBendConstraints'), generateBendConstraints)
            #if selfCollision != None:
            #	maya.cmds.setAttr((sbShape+'.selfCollision'), selfCollision)
            #...

            if singleTransform:
                # Move the solved mesh under the same transform as the original mesh
                maya.cmds.parent(meshCopyShape,
                                 meshT,
                                 relative=True,
                                 shape=True)
                maya.cmds.reorder(sbShape, back=True)
                maya.cmds.delete(meshCopyT)
                maya.cmds.setAttr(sbShape + '.localSpaceOutput', True)
            else:
                # We will keep the solved mesh under the new transform
                # Rename new transform
                maya.cmds.rename(meshCopyT, meshT + "_Solved")

            # Update list of returned nodes
            returnedNodes.append(sbT)
            returnedNodes.append(sbShape)

        # If command echoing is off, echo this short line.
        if (not maya.cmds.commandEcho(query=True, state=True)):
            print("SoftBody.CreateSoftBody.executeCommandCB()")
            print "// Result: %s //" % string.join(returnedNodes, " ")

        # Select and return
        maya.cmds.select(returnedNodes, add=True)
        return returnedNodes
示例#2
0
    def command(
        rigidBodyA=None,
        rigidBodyB=None,
        parent=None,
        # Attrs
        constraintType=None,
        useReferenceFrame=None,
        linearDamping=None,
        linearSoftness=None,
        linearRestitution=None,
        angularDamping=None,
        angularSoftness=None,
        angularRestitution=None,
        linearConstraintX=None,
        linearConstraintY=None,
        linearConstraintZ=None,
        linearConstraintMin=None,
        linearConstraintMax=None,
        angularConstraintX=None,
        angularConstraintY=None,
        angularConstraintZ=None,
        angularConstraintMin=None,
        angularConstraintMax=None,
        linearLimitSoftness=None,
        linearLimitBias=None,
        linearLimitRelaxation=None,
        angularLimitSoftness=None,
        angularLimitBias=None,
        angularLimitRelaxation=None,
        linearMotorEnabled=None,
        linearMotorTargetSpeed=None,
        linearMotorMaxForce=None,
        angularMotorEnabled=None,
        angularMotorTargetSpeed=None,
        angularMotorMaxForce=None,
        linearSpringEnabledX=None,
        linearSpringEnabledY=None,
        linearSpringEnabledZ=None,
        linearSpringStiffness=None,
        linearSpringDamping=None,
        angularSpringEnabledX=None,
        angularSpringEnabledY=None,
        angularSpringEnabledZ=None,
        angularSpringStiffness=None,
        angularSpringDamping=None,
        breakable=None,
        breakingThreshold=None,
    ):
        logger.debug( maya.stringTable[ 'y_RigidBodyConstraint.kCreatingRBC'  ] \
                       % (rigidBodyA, rigidBodyB) )
        # List settable attrs (setAttr below)
        settableAttrs = [
            'constraintType',
            'useReferenceFrame',
            'linearDamping',
            'linearSoftness',
            'linearRestitution',
            'angularDamping',
            'angularSoftness',
            'angularRestitution',
            'linearConstraintX',
            'linearConstraintY',
            'linearConstraintZ',
            'linearConstraintMin',
            'linearConstraintMax',
            'angularConstraintX',
            'angularConstraintY',
            'angularConstraintZ',
            'angularConstraintMin',
            'angularConstraintMax',
            'linearLimitSoftness',
            'linearLimitBias',
            'linearLimitRelaxation',
            'angularLimitSoftness',
            'angularLimitBias',
            'angularLimitRelaxation',
            'linearMotorEnabled',
            'linearMotorTargetSpeed',
            'linearMotorMaxForce',
            'angularMotorEnabled',
            'angularMotorTargetSpeed',
            'angularMotorMaxForce',
            'linearSpringEnabledX',
            'linearSpringEnabledY',
            'linearSpringEnabledZ',
            'linearSpringStiffness',
            'linearSpringDamping',
            'angularSpringEnabledX',
            'angularSpringEnabledY',
            'angularSpringEnabledZ',
            'angularSpringStiffness',
            'angularSpringDamping',
            'breakable',
            'breakingThreshold',
        ]
        # Get the rigid body/bodies.
        rigids = [i for i in [rigidBodyA, rigidBodyB]
                  if i != None]  # list of non-None rigid bodies
        if len(rigids) == 0:  # if no rigids specified, then look at selection
            rigids = BulletUtils.getConnectedRigidBodies()
        logger.info(
            maya.stringTable['y_RigidBodyConstraint.kRigidBodiesToConnect'] %
            (rigids, parent))
        if len(rigids) == 0 or len(rigids) > 2:
            # TODO: this produces a pretty difficult to read error for the user.
            maya.OpenMaya.MGlobal.displayError(
                maya.
                stringTable['y_RigidBodyConstraint.kPleaseSelectRigidbodies'])
            return []
        if len(rigids) == 1 and locals()['constraintType'] in (
                eConstraintType.kRBConstraintHinge2,
                eConstraintType.kRBConstraintSixDOF2):
            maya.OpenMaya.MGlobal.displayError(maya.stringTable[
                'y_RigidBodyConstraint.kPleaseSelectTwoRigidbodies'])
            return []

        # Get Solver
        solver = BulletUtils.getSolver()
        # Create Node
        constraint = maya.cmds.createNode('bulletRigidBodyConstraintShape',
                                          parent=parent)
        # Set Attrs (optional, set if value != None)
        # Use the settableAttrs list above to qualify kwargs passed into the
        # function
        for k, v in locals().iteritems():
            if k in settableAttrs and v != None:
                if isinstance(v, list):
                    maya.cmds.setAttr('%s.%s' % (constraint, k),
                                      *v)  # covers float3 cases
                else:
                    maya.cmds.setAttr('%s.%s' % (constraint, k), v)
        # Connect
        maya.cmds.connectAttr((solver + ".outSolverInitialized"),
                              (constraint + ".solverInitialized"))
        maya.cmds.connectAttr((rigids[0] + ".outRigidBodyData"),
                              (constraint + ".rigidBodyA"))
        if len(rigids) > 1:
            maya.cmds.connectAttr((rigids[1] + ".outRigidBodyData"),
                                  (constraint + ".rigidBodyB"))
        maya.cmds.connectAttr((constraint + ".outConstraintData"),
                              (solver + ".rigidBodyConstraints"),
                              na=True)
        # REVISIT: Consider alternatives like a single initSystem bool attr
        #          instead of startTime and currentTime.
        #          Might be able to get around needing it at all
        maya.cmds.connectAttr((solver + ".startTime"),
                              (constraint + ".startTime"))
        maya.cmds.connectAttr((solver + ".currentTime"),
                              (constraint + ".currentTime"))

        # Translate (avg the rigid body positions)
        t = maya.cmds.xform(maya.cmds.listRelatives(rigids[0],
                                                    fullPath=True,
                                                    parent=True),
                            q=True,
                            ws=True,
                            t=True)
        if len(rigids) > 1:
            t2 = maya.cmds.xform(maya.cmds.listRelatives(rigids[1],
                                                         fullPath=True,
                                                         parent=True),
                                 q=True,
                                 ws=True,
                                 t=True)
            t = [(t[0] + t2[0]) * 0.5, (t[1] + t2[1]) * 0.5,
                 (t[2] + t2[2]) * 0.5]

        constraintT = maya.cmds.listRelatives(constraint, parent=True)
        maya.cmds.xform(constraintT, ws=True, t=t)

        ret = [constraint]
        # If command echoing is off, echo this short line.
        if (not maya.cmds.commandEcho(query=True, state=True)):
            print(
                "RigidBodyConstraint.CreateRigidBodyConstraint.executeCommandCB()"
            )
            print "// Result: %s //" % constraint

        return ret
示例#3
0
def createSoftBodyAnchorConstraint(selectedVerts=None):
    '''Create a bulletSoftConstraint to anchor selected SoftBody vertices to a
    RigidBody. If no RigidBody is specified, then one will be created and
    centered on the first selected vertex.
    '''

    # Get list of selected verts
    if selectedVerts == None:
        selectedVerts = maya.cmds.ls(sl=True, flatten=True,
                                     type='float3')  # flattened list
    if len(selectedVerts) == 0:
        maya.OpenMaya.MGlobal.displayError(maya.stringTable[
            'y_SoftBodyConstraint.kPleaseSelectASetOfMeshVertsForTheAnchorConstraint']
                                           )
        return

    # extract out the vertex number
    anchoredVertexIds = BulletUtils.extractVertexIds(selectedVerts)

    # Get center of selected vertices
    origTranslate = centroid(selectedVerts)

    # Get meshshape
    objs = maya.cmds.listRelatives(selectedVerts[0], parent=True, type='mesh')
    if objs == None or len(objs) == 0:
        maya.OpenMaya.MGlobal.displayError(maya.stringTable[
            'y_SoftBodyConstraint.kPleaseSelectMeshVertsForTheAnchorConstraint']
                                           )
        return

    mesh = objs[0]
    # Get $softbody attached to mesh
    # First check if output mesh vert selected, so look for incoming connection
    softbody = ""
    cons = maya.cmds.listConnections(".inMesh",
                                     s=1,
                                     sh=1,
                                     type='bulletSoftBodyShape')
    if cons != None and len(cons) == 1:
        softbody = cons[0]
    else:
        # Otherwise, check input mesh to be connected to a softbody
        cons = maya.cmds.listConnections(".worldMesh[0]",
                                         d=1,
                                         sh=1,
                                         type='bulletSoftBodyShape')
        if cons != None and len(cons) == 1:
            softbody = cons[0]
    if softbody == "":
        maya.OpenMaya.MGlobal.displayError(
            maya.stringTable['y_SoftBodyConstraint.kCouldNotDetermineSBShape'])
        return

    # Get anchor object
    anchorCandidates = maya.cmds.ls(
        sl=True, dag=True, shapes=True)  # list all selected shape nodes
    numCandidates = len(anchorCandidates)
    if numCandidates == 0:
        maya.OpenMaya.MGlobal.displayError(maya.stringTable[
            'y_SoftBodyConstraint.kPleaseSelectOneBulletRigidBodyForAnchorConstraint']
                                           )
        return

    # use first object found or first rigid body found
    anchorConstrError1 = maya.stringTable[
        'y_SoftBodyConstraint.kPleaseSelectOnlyOneObjectForAnchorConstraint1']
    anchorConstrError2 = maya.stringTable[
        'y_SoftBodyConstraint.kPleaseSelectOnlyOneObjectForAnchorConstraint2']
    anchor = None
    shape = None
    rigidbody = None
    for candidate in anchorCandidates:
        if maya.cmds.objectType(candidate, isType='bulletRigidBodyShape'):
            if rigidbody is not None:
                maya.OpenMaya.MGlobal.displayError(anchorConstrError1)
                return
            anchor = candidate
            rigidbody = candidate
        else:
            if shape is not None:
                maya.OpenMaya.MGlobal.displayError(anchorConstrError2)
                return
            anchor = candidate
            shape = candidate

    # allow a geometry shape and rigid body shape to be selected as long as the rigid body
    # shape is connected to the geometry shape and therefore the same 'object'.
    if shape and rigidbody:
        rigidbodies = maya.cmds.listConnections(shape,
                                                sh=True,
                                                type='bulletRigidBodyShape')
        if rigidbodies is None or rigidbodies[0] != rigidbody:
            maya.OpenMaya.MGlobal.displayError(anchorConstrError2)
            return

    # Create SoftConstraint
    shape = maya.cmds.createNode("bulletSoftConstraintShape")
    shapeT = maya.cmds.listRelatives(shape, parent=True)[0]
    # Create Solver
    sol = BulletUtils.getSolver()

    maya.cmds.setAttr((shapeT + ".translate"), *origTranslate)

    # The logical place for the anchors to be stored is on the constraint node,
    # but in order to remap the indices when the topology changes we have to
    # put it on the soft body node and connect it to the constraint node.  This
    # is an array (multi) attribute, one per constraint; each constraint is
    # itself an int32 array.

    # Find the new index for the anchor.
    anchorListAttr = softbody + ".anchors"
    anchorIndices = maya.cmds.getAttr(anchorListAttr, multiIndices=True)
    if anchorIndices:
        anchorNewIndex = anchorIndices[-1] + 1
    else:
        anchorNewIndex = 0
    anchorName = "%s[%d]" % (anchorListAttr, anchorNewIndex)

    # getAttr allocates the new index, then setAttr stores the data,
    # then connectAttr moves the data to where it's used.
    maya.cmds.getAttr(anchorName)
    maya.cmds.setAttr(anchorName, anchoredVertexIds, type='Int32Array')
    maya.cmds.connectAttr(anchorName, shape + ".indexList")

    # Connect the simple attributes.
    maya.cmds.connectAttr((sol + ".startTime"), (shape + ".startTime"))
    maya.cmds.connectAttr((sol + ".currentTime"), (shape + ".currentTime"))
    maya.cmds.connectAttr((softbody + ".outSoftBodyData"),
                          (shape + ".softBody"))

    if (rigidbody):
        maya.cmds.connectAttr((rigidbody + ".outRigidBodyData"),
                              (shape + ".rigidBody"))
    else:
        maya.cmds.connectAttr((anchor + ".worldMatrix"),
                              (shape + ".inWorldMatrix"))

    maya.cmds.connectAttr((shape + ".outConstraintData"),
                          (sol + ".softConstraints"),
                          na=True)
    # Return
    maya.cmds.select(shape)
    ret = [shape]

    # If command echoing is off, echo this short line.
    if (not maya.cmds.commandEcho(query=True, state=True)):
        print("SoftBodyConstraint.createSoftBodyAnchorConstraint()")
        print "// Result: %s //" % shape

    return ret
示例#4
0
	def doCommand(name='bulletRigidBodyShape#',
				transformName = None,
				bAttachSelected = True,
				ignoreShape = False,
				hideShape = False,
				# Attrs
				colliderShapeType = None,
				axis = None,
				length = None,
				radius = None,
				extents = None,
				bodyType = None,
				initiallySleeping = None,
				neverSleeps = None,
				mass = None,
				linearDamping = None,
				angularDamping = None,
				friction = None,
				restitution = None,
				initialVelocity = None,
				initialAngularVelocity = None,
				impulse = None,
				torqueImpulse = None,
				centerOfMass = None,
				autoFit = None,
				colliderShapeOffset = None,
				colliderShapeMargin = None,
				**kwargs ):
		'''Create a bulletRigidBody 
		'''
		# Explicitly list the names of settable attributes iterated over below

		# Check for selection being a rigid body already
		if ( bAttachSelected ):
			selectedObjs = _getSelectedTransforms()
			selectedObj = selectedObjs[0] if len(selectedObjs) else None

			# don't attach a rigid body underneath another one during
			# creation, it's more likely that the user is invoking
			# this command multiple times, and the selection is
			# leftover from a previous invocation. 
			if ( BulletUtils.getRigidBodyFromTransform(selectedObj) is not None ):
				selectedObj = None
			else:
				transformName = selectedObj
		else:
			selectedObj = None

		if not transformName:
			transformName=''

		# Create from scratch
		rbShape = maya.cmds.createNode( "bulletRigidBodyShape", name=name, parent=transformName )
		rbXform = _firstParent(rbShape)

		if not rbXform:
			OpenMaya.MGlobal.displayError(maya.stringTable[ 'y_RigidBody.kErrorRigidBodyNotCreated' ])
			return [ None, None ]

		# Performance: if we're attaching to an object 
		# make rbShape an visibility so it doesn't draw by default.
		# NOTE: since the rigid body is not a MPxShape it doesn't
		# support an intermediateObject attribute.
		if transformName and hideShape:
			_setAttr(rbShape, 'visibility', 0)

		# Create Solver (proto)
		solver = BulletUtils.getSolver()

		# Set Attrs (optional, set if value != None)
		# Use the settableAttrs list above to qualify kwargs passed into the function
		for k,v in locals().iteritems():
			if k in CreateRigidBody.settableAttrs and v != None:
				_setAttr( rbShape, k, v )

		# Additional Actions

		# ******* TODO: Need to enable local transform instead of just worldSpace.  Pass in parentMatrix to rigidbody

		# Store t and r (used below)
		origTranslate = _getAttr(rbXform, 'translate')[0]
		origRotate = _getAttr(rbXform,'rotate')[0]

		# Connect
		_connectAttr( _attr(rbXform,'worldMatrix'), _attr(rbShape,'inWorldMatrix') )
		_connectAttr( _attr(rbXform,'parentInverseMatrix'), _attr(rbShape,'inParentInverseMatrix') )

		_connectAttr( _attr(solver,'outSolverInitialized'), _attr(rbShape,'solverInitialized') )
		_connectAttr( _attr(solver,'outSolverUpdated'), _attr(rbShape,'solverUpdated') )
		_connectAttr( _attr(rbShape,'outRigidBodyData'), _attr(solver,'rigidBodies'), nextAvailable=True )
		# REVISIT: Consider alternatives like a single initSystem bool
		#		  attr instead of startTime and currentTime. 
		#		  Might be able to get around needing it at all
		_connectAttr( _attr(solver,'startTime'), _attr(rbShape,'startTime') )
		_connectAttr( _attr(solver,'currentTime'), _attr(rbShape,'currentTime') )
		_setAttr(rbShape, 'initialTranslate', origTranslate)
		deg2Rad = 3.14159 / 180
		_setAttr(rbShape, 'initialRotateX', origRotate[0] * deg2Rad)
		_setAttr(rbShape, 'initialRotateY', origRotate[1] * deg2Rad)
		_setAttr(rbShape, 'initialRotateZ', origRotate[2] * deg2Rad)
		pairBlend = maya.cmds.createNode( "pairBlend", name= "translateRotate")
		_setAttr(pairBlend, 'inTranslate1', origTranslate)
		_setAttr(pairBlend, 'inRotate1', origRotate)
		_connectAttr( _attr(rbShape, 'outSolvedTranslate'), _attr(pairBlend, 'inTranslate2') )
		_connectAttr( _attr(rbShape, 'outSolvedRotate'), _attr(pairBlend, 'inRotate2') )
		_connectAttr(_attr(pairBlend, 'outTranslateX'), _attr(rbXform, 'translateX'), force=True) 
		_connectAttr(_attr(pairBlend, 'outTranslateY'), _attr(rbXform, 'translateY'), force=True) 
		_connectAttr(_attr(pairBlend, 'outTranslateZ'), _attr(rbXform, 'translateZ'), force=True) 
		_connectAttr(_attr(pairBlend, 'outRotateX'),	_attr(rbXform, 'rotateX'),	force=True) 
		_connectAttr(_attr(pairBlend, 'outRotateY'),	_attr(rbXform, 'rotateY'),	force=True) 
		_connectAttr(_attr(pairBlend, 'outRotateZ'),	_attr(rbXform, 'rotateZ'),	force=True) 
		_connectAttr(_attr(rbXform, 'isDrivenBySimulation'), _attr(pairBlend,'weight'), force=True)

		_connectAttr(_attr(rbXform, 'rotatePivot'), _attr(rbShape,'pivotTranslate') )

		# ****** TODO: Remove the unused pairBlend weight attrs

		# Select the rigidBody transform and return the resulting values
		maya.cmds.select( rbXform, replace=True )

		return [ rbXform, rbShape ]