Esempio n. 1
0
def getUVFaceNormal( facepath ):
	uvs = getWindingOrder(facepath)

	if len(uvs) < 3: return (1,0,0) #if there are less than 3 uvs we have no uv area so bail

	#get edge vectors and cross them to get the uv face normal
	uvAPos = cmd.polyEditUV(uvs[0], query=True, uValue=True, vValue=True)
	uvBPos = cmd.polyEditUV(uvs[1], query=True, uValue=True, vValue=True)
	uvCPos = cmd.polyEditUV(uvs[2], query=True, uValue=True, vValue=True)
	uvAB = Vector( [uvBPos[0]-uvAPos[0], uvBPos[1]-uvAPos[1], 0] )
	uvBC = Vector( [uvCPos[0]-uvBPos[0], uvCPos[1]-uvBPos[1], 0] )
	uvNormal = uvAB.cross( uvBC ).normalize()

	return uvNormal
Esempio n. 2
0
def getJointSizeAndCentre( joints, threshold=0.65, space=SPACE_OBJECT ):
	'''
	minor modification to the getJointSize function in rigging.utils - uses the
	child of the joint[ 0 ] (if any exist) to determine the size of the joint in
	the axis aiming toward
	'''

	centre = Vector.Zero( 3 )
	if not isinstance( joints, (list, tuple) ):
		joints = [ joints ]

	joints = [ str( j ) for j in joints if j is not None ]
	if not joints:
		return Vector( (1, 1, 1) )

	size, centre = rigUtils.getJointSizeAndCentre( joints, threshold, space )
	if size.within( Vector.Zero( 3 ), 1e-2 ):
		while threshold > 1e-2:
			threshold *= 0.9
			size, centre = rigUtils.getJointSizeAndCentre( joints, threshold )

		if size.within( Vector.Zero( 3 ), 1e-2 ):
			size = Vector( (1, 1, 1) )

	children = listRelatives( joints[ 0 ], pa=True, type='transform' )
	if children:
		childPos = Vector( [ 0.0, 0.0, 0.0 ] )
		childPosMag = childPos.get_magnitude()
		for child in children:
			curChildPos = Vector( xform( child, q=True, ws=True, rp=True ) ) - Vector( xform( joints[ 0 ], q=True, ws=True, rp=True ) )
			curChildPosMag = curChildPos.get_magnitude()
			if curChildPosMag > childPosMag:
				childPos = curChildPos
				childPosMag = curChildPosMag

		axis = rigUtils.getObjectAxisInDirection( joints[ 0 ], childPos, DEFAULT_AXIS )
		axisValue = getAttr( '%s.t%s' % (children[ 0 ], axis.asCleanName()) )

		if space == SPACE_WORLD:
			axis = Axis.FromVector( childPos )

		size[ axis % 3 ] = abs( axisValue )
		centre[ axis % 3 ] = axisValue / 2.0


	return size, centre
Esempio n. 3
0
def getAlignedBoundsForJoint( joint, threshold=0.65, onlyVisibleMeshes=True ):
	'''
	looks at the verts the given joint/s and determines a local space (local to the first joint
	in the list if multiple are given) bounding box of the verts, and positions the hitbox
	accordingly

	if onlyVisibleMeshes is True, then only meshes that are visible in the viewport will
	contribute to the bounds
	'''
	theJoint = joint
	verts = []

	#so this is just to deal with the input arg being a tuple, list or string.  you can pass in a list
	#of joint names and the verts affected just get accumulated into a list, and the resulting bound
	#should be the inclusive bounding box for the given joints
	if isinstance( joint, (tuple,list) ):
		theJoint = joint[0]
		for joint in joint:
			verts += jointVertsForMaya( joint, threshold, onlyVisibleMeshes )
	else:
		verts += jointVertsForMaya( joint, threshold, onlyVisibleMeshes )

	jointDag = apiExtensions.asMDagPath( theJoint )
	jointMatrix = jointDag.inclusiveMatrix()
	vJointPos = OpenMaya.MTransformationMatrix( jointMatrix ).rotatePivot( OpenMaya.MSpace.kWorld ) + OpenMaya.MTransformationMatrix( jointMatrix ).getTranslation( OpenMaya.MSpace.kWorld )
	vJointPos = Vector( [vJointPos.x, vJointPos.y, vJointPos.z] )
	vJointBasisX = OpenMaya.MVector(-1,0,0) * jointMatrix
	vJointBasisY = OpenMaya.MVector(0,-1,0) * jointMatrix
	vJointBasisZ = OpenMaya.MVector(0,0,-1) * jointMatrix

	bbox = OpenMaya.MBoundingBox()
	for vert in verts:
		#get the position relative to the joint in question
		vPos = Vector( xform(vert, query=True, ws=True, t=True) )
		vPos = vJointPos - vPos

		#now transform the joint relative position into the coordinate space of that joint
		#we do this so we can get the width, height and depth of the bounds of the verts
		#in the space oriented along the joint
		vPosInJointSpace = Vector( (vPos.x, vPos.y, vPos.z) )
		vPosInJointSpace = vPosInJointSpace.change_space( vJointBasisX, vJointBasisY, vJointBasisZ )
		bbox.expand( OpenMaya.MPoint( *vPosInJointSpace ) )

	minB, maxB = bbox.min(), bbox.max()

	return minB[0], minB[1], minB[2], maxB[0], maxB[1], maxB[2]
Esempio n. 4
0
	def setup( self, axis=None ):
		'''
		sets up the initial state of the pair node
		'''

		if axis:
			axis = abs( Axis( axis ) )
			setAttr( '%s.axis' % self.node, axis )

		#if we have two controls try to auto determine the orientAxis and the flipAxes
		if self.controlA and self.controlB:
			worldMatrixA = getWorldRotMatrix( self.controlA )
			worldMatrixB = getWorldRotMatrix( self.controlB )

			#so restPoseB = restPoseA * offsetMatrix
			#restPoseAInv * restPoseB = restPoseAInv * restPoseA * offsetMatrix
			#restPoseAInv * restPoseB = I * offsetMatrix
			#thus offsetMatrix = restPoseAInv * restPoseB
			offsetMatrix = worldMatrixA.inverse() * worldMatrixB

			AXES = AX_X.asVector(), AX_Y.asVector(), AX_Z.asVector()
			flippedAxes = []
			for n in range( 3 ):
				axisNVector = Vector( offsetMatrix[ n ][ :3 ] )

				#if the axes are close to being opposite, then consider it a flipped axis...
				if axisNVector.dot( AXES[n] ) < -0.8:
					flippedAxes.append( n )

			for n, flipAxes in enumerate( self.FLIP_AXES ):
				if tuple( flippedAxes ) == flipAxes:
					setAttr( '%s.flipAxes' % self.node, n )
					break

		#this is a bit of a hack - and not always true, but generally singular controls built by skeleton builder will work with this value
		elif self.controlA:
			setAttr( '%s.flipAxes' % self.node, 0 )
			self.setWorldSpace( False )
Esempio n. 5
0
		def __init__( self, x, y, z, vertIdx=None ):
			Vector.__init__(self, [x, y, z])
			self.id = vertIdx
Esempio n. 6
0
def findVertsInVolume(meshes, volume):
    '''
	returns a dict containing meshes and the list of vert attributes contained
	within the given <volume>
	'''

    #define a super simple vector class to additionally record vert id with position...
    class VertPos(Vector):
        def __init__(self, x, y, z, vertIdx=None):
            Vector.__init__(self, [x, y, z])
            self.id = vertIdx

    #this dict provides the functions used to determine whether a point is inside a volume or not
    insideDeterminationMethod = {
        ExportManager.kVOLUME_SPHERE: isPointInSphere,
        ExportManager.kVOLUME_CUBE: isPointInCube
    }

    #if there are any uniform overrides for the contained method (called if the volume's scale is
    #unity) it can be registered here
    insideDeterminationIfUniform = {
        ExportManager.kVOLUME_SPHERE: isPointInUniformSphere,
        ExportManager.kVOLUME_CUBE: isPointInCube
    }

    #grab any data we're interested in for the volume
    volumePos = Vector(cmd.xform(volume, q=True, ws=True, rp=True))
    volumeScale = map(abs, cmd.getAttr('%s.s' % volume)[0])
    volumeBasis = rigUtils.getObjectBasisVectors(volume)

    #make sure the basis is normalized
    volumeBasis = [v.normalize() for v in volumeBasis]

    #now lets determine the volume type
    type = ExportManager.kVOLUME_SPHERE
    try:
        type = int(cmd.getAttr('%s.exportVolume' % volume))
    except TypeError:
        pass

    isContainedMethod = insideDeterminationMethod[type]
    print 'method for interior volume determination', isContainedMethod.__name__
    sx = volumeScale[0]
    if Vector(volumeScale).within((sx, sx, sx)):
        try:
            isContainedMethod = insideDeterminationIfUniform[type]
        except KeyError:
            pass

    #now lets iterate over the geometry
    meshVertsWithin = {}
    for mesh in meshes:
        #its possible to pass not a mesh but a component in - this is totally valid, as the polyListComponentConversion
        #should make sure we're always dealing with verts no matter what, but we still need to make sure the dict key is
        #the actual name of the mesh - hence this bit of jiggery pokery
        dotIdx = mesh.rfind('.')
        meshName = mesh if dotIdx == -1 else mesh[:dotIdx]

        meshPositions = []
        meshVertsWithin[meshName] = meshPositions

        #this gives us a huge list of floats - each sequential triple is the position of a vert
        try:
            #if this complains its most likely coz the geo is bad - so skip it...
            vertPosList = cmd.xform(cmd.ls(cmd.polyListComponentConversion(
                mesh, toVertex=True),
                                           fl=True),
                                    q=True,
                                    t=True,
                                    ws=True)
        except TypeError:
            continue
        count = len(vertPosList) / 3

        for idx in xrange(count):
            pos = VertPos(vertPosList.pop(0), vertPosList.pop(0),
                          vertPosList.pop(0), idx)
            contained = isContainedMethod(pos, volumePos, volumeScale,
                                          volumeBasis)
            if contained:
                pos.weight = contained[1]
                meshPositions.append(pos)

    return meshVertsWithin
Esempio n. 7
0
def _asPy( self ):
	return Vector( (self.x, self.y, self.z) )
Esempio n. 8
0
def __asNice( self ):
	return Vector( [self.x, self.y, self.z] )
Esempio n. 9
0
    def mirrorMatrix(self, matrix):
        matrix = mirrorMatrix(matrix, self.getAxis())
        for flipAxis in self.getFlips():
            matrix.setRow(flipAxis, -Vector(matrix.getRow(flipAxis)))

        return matrix
Esempio n. 10
0
def buildControl( name,
                  placementDesc=DEFAULT_PLACE_DESC,
                  pivotModeDesc=PivotModeDesc.MID,
                  shapeDesc=DEFAULT_SHAPE_DESC,
                  colour=DEFAULT_COLOUR,
                  constrain=True,
                  oriented=True,
                  offset=Vector( (0, 0, 0) ), offsetSpace=SPACE_OBJECT,
                  size=Vector( (1, 1, 1) ), scale=1.0, autoScale=False,
                  parent=None, qss=None,
                  asJoint=False, freeze=True,
                  lockAttrs=( 'scale', ), hideAttrs=DEFAULT_HIDE_ATTRS,
                  niceName=None,
                  displayLayer=None ):
	'''
	this rather verbosely called function deals with creating control objects in
	a variety of ways.

	the following args take "struct" like instances of the classes defined above,
	so look to them for more detail on defining those options

	displayLayer (int) will create layers (if doesn't exist) and add control shape to that layer.
	layer None or zero doesn't create.
	'''

	select( cl=True )

	#sanity checks...
	if not isinstance( placementDesc, PlaceDesc ):
		if isinstance( placementDesc, (list, tuple) ):
			placementDesc = PlaceDesc( *placementDesc )
		else:
			placementDesc = PlaceDesc( placementDesc )

	if not isinstance( shapeDesc, ShapeDesc ):
		if isinstance( shapeDesc, (list, tuple) ):
			shapeDesc = ShapeDesc( *shapeDesc )
		else:
			shapeDesc = ShapeDesc( shapeDesc )

	offset = Vector( offset )


	#if we've been given a parent, cast it to be an MObject so that if its name path changes (for example if
	#parent='aNode' and we create a control called 'aNode' then the parent's name path will change to '|aNode' - yay!)
	if parent:
		parent = asMObject( parent )


	#unpack placement objects
	place, align, pivot = placementDesc.place, placementDesc.align, placementDesc.pivot

	if shapeDesc.surfaceType == ShapeDesc.SKIN:
		shapeDesc.curveType = ShapeDesc.NULL_SHAPE  #never build curve shapes if the surface type is skin
		if shapeDesc.joints is None:
			shapeDesc.joints = [ str( place ) ]

		shapeDesc.expand *= scale


	#determine auto scale/size - if nessecary
	if autoScale:
		_scale = list( getJointSize( [ place ] + (shapeDesc.joints or []) ) )
		_scale = sorted( _scale )[ -1 ]
		if abs( _scale ) < 1e-2:
			print 'AUTO SCALE FAILED', _scale, name, place
			_scale = scale

		scale = _scale

	if size is AUTO_SIZE:
		tmpKw = {} if oriented else { 'space': SPACE_WORLD }
		size = getJointSize( [ place ] + (shapeDesc.joints or []), **tmpKw )
		for n, v in enumerate( size ):
			if abs( v ) < 1e-2:
				size[ n ] = scale

		scale = 1.0


	#if we're doing a SKIN shape, ensure there is actually geometry skinned to the joints, otherwise bail on the skin and change to the default type
	if shapeDesc.surfaceType == ShapeDesc.SKIN:
		try:
			#loop over all joints and see if there is geo skinned to it
			for j in shapeDesc.joints:
				verts = meshUtils.jointVerts( j, tolerance=DEFAULT_SKIN_EXTRACTION_TOLERANCE )

				#if so throw a breakException to bail out of the loop
				if verts:
					raise BreakException

			#if we get this far that means none of the joints have geo skinned to them - so set the surface and curve types to their default values
			shapeDesc.surfaceType = shapeDesc.curveType = ShapeDesc.DEFAULT_TYPE
			print 'WARNING - surface type was set to SKIN, but no geometry is skinned to the joints: %s' % shapeDesc.joints
		except BreakException: pass


	#build the curve shapes first
	if shapeDesc.curveType != ShapeDesc.NULL_SHAPE \
	   and shapeDesc.curveType != ShapeDesc.SKIN:
		curveShapeFile = getFileForShapeName( shapeDesc.curveType )
		assert curveShapeFile is not None, "cannot find shape %s" % shapeDesc.curveType

		createCmd = ''.join( curveShapeFile.read() )
		mel.eval( createCmd )
	else:
		select( group( em=True ) )

	sel = ls( sl=True )
	obj = asMObject( sel[ 0 ] )

	#now to deal with the surface - if its different from the curve, then build it
	if shapeDesc.surfaceType != shapeDesc.curveType \
	   and shapeDesc.surfaceType != ShapeDesc.NULL_SHAPE \
	   and shapeDesc.surfaceType != ShapeDesc.SKIN:

		#if the typesurface is different from the typecurve, then first delete all existing surface shapes under the control
		shapesTemp = listRelatives( obj, s=True, pa=True )
		for s in shapesTemp:
			if nodeType( s ) == "nurbsSurface":
				delete( s )

		#now build the temporary control
		surfaceShapeFile = getFileForShapeName( shapeDesc.surfaceType )
		assert surfaceShapeFile is not None, "cannot find shape %s" % shapeDesc.surfaceType

		createCmd = ''.join( surfaceShapeFile.read() )
		mel.eval( createCmd )

		#and parent its surface shape nodes to the actual control, and then delete it
		tempSel = ls( sl=True )
		shapesTemp = listRelatives( tempSel[0], s=True, pa=True ) or []
		for s in shapesTemp:
			if nodeType(s) == "nurbsSurface":
				cmd.parent( s, obj, add=True, s=True )

		delete( tempSel[ 0 ] )
		select( sel )


	#if the joint flag is true, parent the object shapes under a joint instead of a transform node
	if asJoint:
		select( cl=True )
		j = joint()
		for s in listRelatives( obj, s=True, pa=True ) or []:
			cmd.parent( s, j, add=True, s=True )

		setAttr( '%s.radius' % j, keyable=False )
		setAttr( '%s.radius' % j, cb=False )
		delete( obj )
		obj = asMObject( j )

	setAttr( '%s.s' % obj, scale, scale, scale )


	#rename the object - if no name has been given, call it "control".  if there is a node with the name already, get maya to uniquify it
	if not name:
		name = 'control'

	if objExists( name ):
		name = '%s#' % name

	rename( obj, name )


	#move the pivot - if needed
	makeIdentity( obj, a=1, s=1 )
	shapeStrs = getShapeStrs( obj )
	if pivotModeDesc == PivotModeDesc.TOP:
		for s in shapeStrs:
			move(  0, -scale/2.0, 0, s, r=True )
	elif pivotModeDesc == PivotModeDesc.BASE:
		for s in shapeStrs:
			move(  0, scale/2.0, 0, s, r=True )


	#rotate it accordingly
	rot = AXIS_ROTATIONS[ shapeDesc.axis ]
	rotate( rot[0], rot[1], rot[2], obj, os=True )
	makeIdentity( obj, a=1, r=1 )


	#if the user wants the control oriented, create the orientation group and parent the control
	grp = obj
	if oriented:
		grp = group( em=True, n="%s_space#" % obj )
		cmd.parent( obj, grp )
		attrState( grp, ['s', 'v'], *LOCK_HIDE )
		if align is not None:
			delete( parentConstraint( align, grp ) )


	#place and align
	if place:
		delete( pointConstraint( place, grp ) )

	if align:
		delete( orientConstraint( align, grp ) )
	else:
		rotate( 0, 0, 0, grp, a=True, ws=True )


	#do the size scaling...
	if shapeDesc.surfaceType != ShapeDesc.SKIN:
		for s in getShapeStrs( obj ):
			cmd.scale( size[0], size[1], size[2], s )


	#if the parent exists - parent the new control to the given parent
	if parent is not None:
		grp = cmd.parent( grp, parent )[0]


	#do offset
	for s in getShapeStrs( obj ):
		mkw = { 'r': True }
		if offsetSpace == SPACE_OBJECT: mkw[ 'os' ] = True
		elif offsetSpace == SPACE_LOCAL: mkw[ 'ls' ] = True
		elif offsetSpace == SPACE_WORLD: mkw[ 'ws' ] = True
		if offset:
			move( offset[0], offset[1], offset[2], s, **mkw )

	if freeze:
		makeIdentity( obj, a=1, r=1 )

	makeIdentity( obj, a=1, t=1 )  #always freeze translations


	#delete shape data that we don't want
	if shapeDesc.curveType is None:
		for s in listRelatives( obj, s=True, pa=True ) or []:
			if nodeType(s) == "nurbsCurve":
				delete(s)

	if shapeDesc.surfaceType is None:
		for s in listRelatives( obj, s=True, pa=True ) or []:
			if nodeType(s) == "nurbsSurface":
				delete(s)


	#now snap the pivot to alignpivot object if it exists
	if pivot is not None and objExists( pivot ):
		p = placementDesc.pivotPos
		move( p[0], p[1], p[2], '%s.rp' % obj, '%s.sp' % obj, a=True, ws=True, rpr=True )


	#constrain the target object to this control?
	if constrain:
		#check to see if the transform is constrained already - if so, bail.  buildControl doesn't do multi constraints
		if not listConnections( pivot, d=0, type='constraint' ):
			if place:
				parentConstraint( obj, pivot, mo=True )
				setItemRigControl( pivot, obj )


	#if the user has specified skin geometry as the representation type, then build the geo
	#NOTE: this really needs to happen after ALL the placement has happened otherwise the extracted
	#will be offset from the surface its supposed to be representing
	if shapeDesc.surfaceType == ShapeDesc.SKIN:

		#extract the surface geometry
		geo = meshUtils.extractMeshForJoints( shapeDesc.joints, expand=shapeDesc.expand )

		#if the geo is None, use the default control representation instead
		writeTrigger = True
		if geo is None:
			writeTrigger = False
			curveShapeFile = getFileForShapeName( ShapeDesc.DEFAULT_TYPE )
			createCmd = ''.join( curveShapeFile.read() )
			mel.eval( createCmd )
			geo = ls( sl=True )[ 0 ]

		geo = cmd.parent( geo, obj )[0]
		makeIdentity( geo, a=True, s=True, r=True, t=True )

		cmd.parent( listRelatives( geo, s=True, pa=True ), obj, add=True, s=True )
		delete( geo )

		#when selected, turn the mesh display off, and only highlight edges
		if writeTrigger:
			triggered.Trigger.CreateTrigger( str( obj ), cmdStr="for( $s in `listRelatives -s -pa #` ) setAttr ( $s +\".displayEdges\" ) 2;" )


	#build a shader for the control
	if colour is not None:
		colours.setObjShader( obj, colours.getShader( colour, True ) )


	#add to a selection set if desired
	if qss is not None:
		sets( obj, add=qss )


	#hide and lock attributes
	attrState( obj, lockAttrs, lock=True )
	attrState( obj, hideAttrs, show=False )

	if niceName:
		setNiceName( obj, niceName )

	# display layer
	if displayLayer and not int( displayLayer ) <= 0 :
		layerName = 'ctrl_%d' % int( displayLayer )
		allLayers = ls( type='displayLayer' )

		layer = ''
		if layerName in allLayers:
			layer = layerName
		else:
			layer = createDisplayLayer( n=layerName, number=1, empty=True )
			setAttr( '%s.color' % layer,  24 + int( displayLayer ) )

		for s in listRelatives( obj, s=True, pa=True ) or []:
			connectAttr( '%s.drawInfo.visibility' % layer, '%s.v' % s )
			connectAttr( '%s.drawInfo.displayType' % layer, '%s.overrideDisplayType' % s )

	return obj
Esempio n. 11
0
def getJointSizeAndCentre( joints, threshold=0.65, space=SPACE_OBJECT ):
	'''
	minor modification to the getJointSize function in rigging.utils - uses the
	child of the joint[ 0 ] (if any exist) to determine the size of the joint in
	the axis aiming toward
	'''

	centre = Vector.Zero( 3 )
	if not isinstance( joints, (list, tuple) ):
		joints = [ joints ]

	joints = [ str( j ) for j in joints if j is not None ]
	if not joints:
		return Vector( (1, 1, 1) )

	size, centre = rigUtils.getJointSizeAndCentre( joints, threshold, space )
	if size.within( Vector.Zero( 3 ), 1e-2 ):
		while threshold > 1e-2:
			threshold *= 0.9
			size, centre = rigUtils.getJointSizeAndCentre( joints, threshold )

		if size.within( Vector.Zero( 3 ), 1e-2 ):
			size = Vector( (1, 1, 1) )

	children = listRelatives( joints[ 0 ], pa=True, type='transform' )
	if children:
		childPos = Vector( [ 0.0, 0.0, 0.0 ] )
		childPosMag = childPos.get_magnitude()
		for child in children:
			curChildPos = Vector( xform( child, q=True, ws=True, rp=True ) ) - Vector( xform( joints[ 0 ], q=True, ws=True, rp=True ) )
			curChildPosMag = curChildPos.get_magnitude()
			if curChildPosMag > childPosMag:
				childPos = curChildPos
				childPosMag = curChildPosMag

		axis = rigUtils.getObjectAxisInDirection( joints[ 0 ], childPos, DEFAULT_AXIS )
		axisValue = getAttr( '%s.t%s' % (children[ 0 ], axis.asCleanName()) )

		if space == SPACE_WORLD:
			axis = Axis.FromVector( childPos )

		size[ axis % 3 ] = abs( axisValue )
		centre[ axis % 3 ] = axisValue / 2.0


	return size, centre
Esempio n. 12
0
	def getLocation( self, obj ):
		if obj is None:
			return Vector()

		return xform( obj, q=True, ws=True, rp=True )