示例#1
0
    def compute(self, plug, dataBlock):
        if plug == arrayTest.output1WgtAttr:
            #calculations here
            #get inputs
            dataHandleInput = dataBlock.inputValue(arrayTest.input1VecAttr)
            inVal = dataHandleInput.asFloat()

            #get ouput array
            arrayDataHandle = OpenMaya.MArrayDataHandle(
                dataBlock.outputArrayValue(arrayTest.output1WgtAttr))
            myBuilder = OpenMaya.MArrayDataBuilder(arrayTest.output1WgtAttr, 0)

            for i in range(arrayDataHandle.elementCount()):
                #arrayDataHandle.next()
                output = inVal / (i + 1)
                #output = inVal + outValue

                myElementHandle = OpenMaya.MDataHandle(myBuilder.addElement(i))
                myElementHandle.setFloat(output)

            arrayDataHandle.set(myBuilder)
            arrayDataHandle.setAllClean()

            dataBlock.setClean(plug)

        else:
            return OpenMaya.kUnknownParameter
    def compute(self, plug, block):
        this_node = self.thisMObject()

        # get input handles
        input_matrix_handle = block.inputValue(self.input_matrix)
        mat = input_matrix_handle.asMatrix()

        # get output plug
        output_elements_plug = om.MPlug(this_node, self.output_elements)

        output_elements_handle = output_elements_plug.constructHandle(block)
        array_handle = om.MArrayDataHandle(output_elements_handle)
        array_builder = array_handle.builder()

        index = 0
        for i in range(4):
            for j in range(4):
                data_handle = array_builder.addElement(index)
                data_handle.setFloat(mat(i, j))

                index += 1

        # refresh connection
        array_handle.set(array_builder)
        output_elements_plug.setMDataHandle(output_elements_handle)
        output_elements_plug.destructHandle(output_elements_handle)

        block.setClean(plug)
示例#3
0
def nodeAttrToFloatArray(DataBlock, NodeAttr):
    dataHandle = DataBlock.inputValue(NodeAttr)
    arrayDataHandle = om.MArrayDataHandle(dataHandle)
    outFloatArray = []
    for i in range(0, arrayDataHandle.elementCount()):
        if not (i == 0): arrayDataHandle.next()
        dataHandle = arrayDataHandle.inputValue()
        outFloatArray.append(dataHandle.asFloat())

    return outFloatArray
示例#4
0
def nodeAttrToMStrings(DataBlock, NodeAttr):
    dataHandle = DataBlock.inputValue(NodeAttr)
    arrayDataHandle = om.MArrayDataHandle(dataHandle)
    outMString = []
    for i in range(0, arrayDataHandle.elementCount()):
        if not (i == 0): arrayDataHandle.next()
        dataHandle = arrayDataHandle.inputValue()
        outMString.append(dataHandle.asString())

    return outMString
示例#5
0
 def compute(self, plug, dataBlock):
     """Compute the arithmetic mean of all the items in input array."""
     if (plug == AR_AverageArrayDoublesNode.outputAttr):
         # get the incoming data
         arrayDataHandle = om.MArrayDataHandle(
             dataBlock.inputValue(AR_AverageArrayDoublesNode.inputAttr))
         # compute output
         output = 0.0
         try:
             output = (arrayDataHandle.inputValue()).asDouble()
         except:
             pass
         for i in range(arrayDataHandle.elementCount() - 1):
             arrayDataHandle.next()
             output += (arrayDataHandle.inputValue()).asDouble()
         try:
             output /= arrayDataHandle.elementCount()
         except:
             pass
         """
         # an alternative approach using an MPlug; less efficient because MPlug is slower
         arrayPlug = om.MPlug(self.thisMObject(), AR_AverageArrayDoublesNode.inputAttr)
         output = 0.0
         for i in range(arrayPlug.numElements()):
             elementPlug = om.MPlug(arrayPlug[i]).asDouble() # index operator works with physical indices
             output += elementPlug.asDouble()
         try: output /= arrayPlug.numElements()
         except: pass
         """
         # set the outgoing plug
         dataHandle = om.MDataHandle(
             dataBlock.outputValue(AR_AverageArrayDoublesNode.outputAttr))
         dataHandle.setDouble(output)
         dataBlock.setClean(plug)
     else:
         return om.kUnknownParameter
示例#6
0
    def rebuild_solver(self, data):
        """recalcule le solver a l'aide de matrixMM
        aucun  input ou output dans ce code"""

		# NOTE 获取 N 和 M 的长度数量
        self.N = data.inputValue(self.NDimension).asInt()
        self.M = data.inputValue(self.MDimension).asInt()

		# NOTE 获取 pose 的数量
        poses_H = data.inputArrayValue(self.poses)
        pose_ids = OpenMaya.MIntArray()
        OpenMaya.MPlug(self.thisMObject(), self.poses).getExistingArrayAttributeIndices(
            pose_ids
        )

        self.poseUsed_ids = []  #   = pose_ids  utilisées

        # trouve les infos necessaires pour creer le system
        self.nKeys = []  # liste (dim  poses_num) 	de liste ( dim N )
        mValues = []  # liste (dim  poses_num) 	de liste ( dim M )
        self.weights = []  # liste (dim  poses_num) 	de floats
        self.only_one_mValue = []

		# NOTE 获取 self.nKeys mValues
        for i in pose_ids:

            poses_H.jumpToElement(i)
            pose_H = poses_H.inputValue()

            state = pose_H.child(self.state).asBool()
            # wgt		= pose_H.child( self.weight ).asFloat()

            # if not (state and wgt>self.epsilon)  :
            # 	continue
            if not state:
                continue

            nKey_H = OpenMaya.MArrayDataHandle(pose_H.child(self.nKey))
            nKey = []
            mValue_H = OpenMaya.MArrayDataHandle(pose_H.child(self.mValue))
            mValue = []

            for n in xrange(self.N):
                # try au cas ou y'aurai rien de branché ...
                try:
                    nKey_H.jumpToElement(n)
                    key = nKey_H.inputValue().asFloat()
                    nKey.append(key)
                except:
                    nKey.append(0.0)

            # ignore les clé deja presentes
            if nKey in self.nKeys:
                OpenMaya.MGlobal.displayWarning(
                    "key[%s] %s  can not be used more than once" % (i, nKey)
                )
                continue

            for m in xrange(self.M):
                try:
                    mValue_H.jumpToElement(m)
                    value = mValue_H.inputValue().asFloat()
                    mValue.append(value)
                except:
                    mValue.append(0.0)

            self.nKeys.append(nKey)
            mValues.append(mValue)
            # self.weights.append( wgt )

            self.poseUsed_ids.append(i)

        #
        poseUsed_num = len(self.poseUsed_ids)

        if poseUsed_num == 0:
            OpenMaya.MGlobal.displayError("RbfSolver failed : No Key")
            return False

        elif poseUsed_num == 1:
            # no interpolation
            self.only_one_mValue = mValues[0]
            return True

        # pour la suite necessite de connaitre les fonctions utilisées :
        # Distance fonction ?
        # RBF fonction ?
        normalize = data.inputValue(self.normalize).asBool()

        distance_id = data.inputValue(self.distanceMode).asInt()
        self.distance_fonction = self.distance_fonctions[distance_id]

        rbf_id = data.inputValue(self.rbfMode).asInt()
        self.rbf_fonction = self.rbf_fonctions[rbf_id]

        # matrixMM pour resoudre les system AX = Y
        # factorize la   et    solve la pour chaque m
        # store les X(m)   dans   self.mX
        distanceMax = 0.0

        mat = MatrixNN()
        mat.setDimension(poseUsed_num)

        # ** pour les poses doublon
        # remove les  [ligne-colonne]  contenant .0 en dehor de la diagonale

        for i in xrange(poseUsed_num):
            for j in xrange(poseUsed_num):

                if i == j:
                    # ici la distance d'une pose sur elle meme
                    mat.rc[i][j] = 0.0
                else:
                    # distance de chaque pose a chaque pose
                    # NOTE 默认使用 欧几里得度量 作为距离计算
                    # NOTE https://baike.baidu.com/item/%E6%AC%A7%E5%87%A0%E9%87%8C%E5%BE%97%E5%BA%A6%E9%87%8F/1274107
                    distance = self.distance_fonction(
                        self.N, self.nKeys[i], self.nKeys[j]
                    )

                    # stock la distance maximale entre 2 poses
                    # ceci servira à la normalisation du system
                    if distance > distanceMax:
                        distanceMax = distance

                    mat.rc[i][j] = distance

        # utilise le scale pour smoother plus ou moins
        # si on veut le system normalisé, il faut disiviser le scale par la distanceMax
        fScale = data.inputValue(self.scale).asFloat()
        # NOTE fscale 不为零
        if fScale < self.epsilon:
            fScale = self.epsilon

        if normalize:
            self.fScale = fScale / distanceMax
        else:
            self.fScale = fScale

        # RBF chaque element
        for i in xrange(poseUsed_num):
            for j in xrange(poseUsed_num):

                # euclidienne ou angulaire ?  ou autre...
                mat.rc[i][j] = self.rbf_fonction(mat.rc[i][j] * self.fScale)

        # factorizeLU  et sauve les ids des lignes permutées
         
        # NOTE 矩阵 LU 分解
        # NOTE https://baike.baidu.com/item/lu%E5%88%86%E8%A7%A3/764245
        LU, Pids = mat.factorize_LU()

        # pour chaque m de chaque pose
        # solv_LU  et store les X(m)   dans   self.mX
        # mX =  m * nVector
        self.mX = []

        for m in xrange(self.M):

            Y = [mValues[i][m] for i in xrange(poseUsed_num)]

            X = mat.solve_LU(LU, Pids, Y)  # nVector des coeff

            self.mX.append(X)

        # *** setClean  indique que le system  est  solved
        solved_H = data.outputValue(self.solved)
        solved_H.setClean()

        OpenMaya.MGlobal.displayInfo(
            "RbfSolver recomputed using poses :  %s" % self.poseUsed_ids
        )
        return True
示例#7
0
  def compute(self, plug, data):
  
    # Begin constructing data points and samples from the user inputs. 
    # The user has specified the number of 'sites' so we need to loop through 
    # the dataBlock to see what's actually there an construct some lists. 
    
    dataPoints = list()
    pyFValues = list()  # the function values are our samples
    
    allInputs_mDataArrayHandle = data.inputArrayValue( RbfBlender.allInputs_compound )
    # numInputs = allInputs_mDataArrayHandle.elementCount()
    numInputs = data.inputValue( RbfBlender.numInputGroups ).asInt()
    sampleDimensions = data.inputValue( RbfBlender.sampleDimensions ).asInt()
    
    # get the deleted indices. this is because we can't differentiate between "optimized" 
    # array indices and deleted indices. 
    deletedIndices_mArrayDataHandle = data.inputArrayValue(RbfBlender.deletedIndices)
    deletedIndices = list()
    numDeletedIndices = deletedIndices_mArrayDataHandle.elementCount()
    
    for i in xrange( numDeletedIndices ):
      deletedIndices_mArrayDataHandle.jumpToArrayElement(i)
      di_i_mDataHandle = deletedIndices_mArrayDataHandle.inputValue()
      deletedIndices.append( di_i_mDataHandle.asInt() )
    
    
    for i in xrange( numInputs + numDeletedIndices ):
      if not i in deletedIndices: 
        # jumpToArrayElement handles the sparse array. 
        # for exmaple, create three inputs, and delete the entry at index 1. 
        #i 0,   array element index 0
        #i 1,   array element index 2
        
        # Just like with the individual attrs, if entire compounds with arrays have zero as their values, 
        # maya will "optimize" by ignoring that whole compound. This is harder to detect than with regular values
        # because the elements still show up in the node editor. Can be checked though with mc.getAttr(<theCompoundAttr>, mi=True)
        # the question becomes: how do you differentiate between an index that has been optimized, with one that 
        # has been deleted by the user? you can't just flatly assume zero, like I do with the others because then you might get
        # multiple "zero compounds" which will break the rbf math. 
        # The only way I can think of, is by storing an array of which indices have been deleted by the user. 
        
        elementOptimized = 0
        thisDataPoint = [0.0, 0.0, 0.0]
        thisSampleSite = list()
        for l in xrange(sampleDimensions): 
          thisSampleSite.append(0.0)
        
        try:  # test for optimized
          allInputs_mDataArrayHandle.jumpToElement(i)
                  
        except: 
          elementOptimized = 1  
          
        if not elementOptimized: 
          
          # So now this is the compound! how do I get the children... ???  you just pass in the object type
          # internally. it must be searching the children of the compound for a "type" 
          currentCompound_i_mDataHandle =  allInputs_mDataArrayHandle.inputValue() 
          dataPoint_mDataHandle = currentCompound_i_mDataHandle.child(RbfBlender.dataPoint_array)
          sample_mDataHandle = currentCompound_i_mDataHandle.child(RbfBlender.sample_array)
          # convert the dataHandle to an daraArrayHandle... you'd think it would know its own type when being 
          # returned eh.  nah. 
          dataPoint_mArrayDataHandle = om.MArrayDataHandle(dataPoint_mDataHandle)
          sample_mArrayDataHandle = om.MArrayDataHandle(sample_mDataHandle)
          
          for j in xrange( 3 ):  # we know this is always 3 for this implemenation
          
            # Maya "optimizes" array attrs with values equal to zero, by removing them.  This causes the 
            # plugin to fail until the attribute editor is opened and the data is reset. Highly annoying. 
            # Work around is to catch the jumpToElement and if it can't find the element, we assume a value
            # of zero. 
            dataPointValue = 0.0
            try:
              dataPoint_mArrayDataHandle.jumpToElement(j)
              dataPointValue = dataPoint_mArrayDataHandle.inputValue().asFloat()
            except:
              pass
              
            thisDataPoint[j] = dataPointValue
          
          for k in xrange( sampleDimensions ):   
            # there shouldn't be a sparse array for the samples because I only add/remove from the end
            sampleValue = 0.0
            try:
              sample_mArrayDataHandle.jumpToElement(k)
              sampleValue = sample_mArrayDataHandle.inputValue().asFloat()
            except:
              pass        
            
            thisSampleSite[k] = sampleValue       
        
        dataPoints.append( thisDataPoint )
        pyFValues.append( thisSampleSite )
      
      # ------------- Done building data points / sample site lists  -------------------------------- #
      
      
    R = data.inputValue(RbfBlender.R_input).asFloat()
    lookup_mDataArrayHandle = data.inputArrayValue( RbfBlender.lookup_input )
    
    lookupValues = list()
    for m in xrange( 3 ): # always gonna be 3.. 
      lookupValue = 0.0
      try: 
        lookup_mDataArrayHandle.jumpToElement(m)
        lookupValue = lookup_mDataArrayHandle.inputValue().asFloat()
      except:  
        pass
      lookupValues.append( lookupValue )
    
    # ----------------- do the math here ---------------- #
    typeIndex = data.inputValue(RbfBlender.typeIndex).asInt()

    outValues = computeWeights( pyFValues, dataPoints, lookupValues, RbfBlender.typeDic[typeIndex], R )
    # ----------------- done doing math ----------------- #   lol
    
    output_mArrayDataHandle = data.outputArrayValue( RbfBlender.output )
    sampleDimensions = data.inputValue( RbfBlender.sampleDimensions ).asInt()


    for n in xrange( sampleDimensions ):   # actually read the sample dimensions here to avoid update issues
      output_mArrayDataHandle.jumpToArrayElement( n )
      output_n_mDataHandle = output_mArrayDataHandle.outputValue()

      if outValues[n] > 1.0:
        outValues[n] = 1.0
      elif outValues[n] < 0.0:
        outValues[n] = 0.0

      output_n_mDataHandle.setFloat(outValues[n])
    
    data.setClean(plug)
示例#8
0
    def deform(self, dataBlock, geoIterator, local2WorldMatrix, geomIndex):

        inputAttr = ompx.cvar.MPxGeometryFilter_input

        # Envelope
        envelope = ompx.cvar.MPxGeometryFilter_envelope
        dataHandleEnvolope = dataBlock.inputValue(envelope)
        envelopeValue = dataHandleEnvolope.asFloat()

        # damping
        dataHandleDamping = dataBlock.inputValue(JiggleDeformerNode.dampingVal)
        dampMagnitude = dataHandleDamping.asFloat()

        # stiffness
        dataHandleStiff = dataBlock.inputValue(JiggleDeformerNode.stiffVal)
        stiffMagnitude = dataHandleStiff.asFloat()

        # time
        dataHandleTime = dataBlock.inputValue(JiggleDeformerNode.time)
        currentTime = dataHandleTime.asTime()

        # scale
        dataHandleScale = dataBlock.inputValue(JiggleDeformerNode.scale)
        scale = dataHandleScale.asFloat()

        # max velocity
        dataHandleVelocity = dataBlock.inputValue(
            JiggleDeformerNode.maxVelocity)
        maxVelocity = dataHandleVelocity.asFloat() * scale

        # direction bias
        dataHandleDirection = dataBlock.inputValue(
            JiggleDeformerNode.directionBias)
        directionBias = dataHandleDirection.asFloat()

        # normal strength
        dataHandleNormalStrength = dataBlock.inputValue(
            JiggleDeformerNode.normalStrength)
        normalStrength = dataHandleNormalStrength.asFloat()

        # start frame
        dataHandleStartFrame = dataBlock.inputValue(
            JiggleDeformerNode.startFrame)
        startFrame = dataHandleStartFrame.asInt()

        # points' positions in local space
        points = om.MPointArray()
        geoIterator.allPositions(points)

        # INITIALIZE ATTRIBUTES
        if geomIndex not in self.initialFlagDict.keys():
            self.initialFlagDict[geomIndex] = False

        if geomIndex not in self.dirtyMapDict.keys():
            self.dirtyMapDict[geomIndex] = False

        if geomIndex not in self.preTimeDict.keys():
            self.preTimeDict[geomIndex] = om.MTime()

        if geomIndex not in self.curPosDict.keys():
            self.curPosDict[geomIndex] = om.MPointArray()

        if geomIndex not in self.prePosDict.keys():
            self.prePosDict[geomIndex] = om.MPointArray()

        if geomIndex not in self.membershipDict.keys():
            self.membershipDict[geomIndex] = om.MIntArray()

        # Get normalsDict
        normals = om.MFloatVectorArray()
        if directionBias != 0.0 or normalStrength < 1.0:

            inputMesh = self.getInputMesh(dataBlock, geomIndex, inputAttr)

            MFnMesh = om.MFnMesh(inputMesh)

            MFnMesh.getVertexNormals(0, normals)

        # test initialize flag for the first time
        if not self.initialFlagDict[geomIndex]:
            self.preTimeDict[geomIndex] = currentTime

            self.curPosDict[geomIndex].setLength(geoIterator.count())
            self.prePosDict[geomIndex].setLength(geoIterator.count())

            for i in range(points.length()):
                self.curPosDict[geomIndex].set(points[i] * local2WorldMatrix,
                                               i)
                self.prePosDict[geomIndex].set(self.curPosDict[geomIndex][i],
                                               i)

            self.initialFlagDict[geomIndex] = True

            self.dirtyMapDict[geomIndex] = True

        # for stable simulation, check the time difference whether it is 1 frame or not
        # If the current time smaller than the startFrame, jiggling effect will not be performed
        timeDiff = currentTime.value() - self.preTimeDict[geomIndex].value()

        if timeDiff > 1.0 or timeDiff < 0.0 or currentTime.value(
        ) <= startFrame:
            self.initialFlagDict[geomIndex] = False
            self.preTimeDict[geomIndex] = om.MTime(currentTime)
            return

        # perGeometry
        hGeo = dataBlock.inputArrayValue(JiggleDeformerNode.perGeo)

        # jump to each geometry
        self.jump2Element(hGeo, geomIndex)
        hGeo.jumpToElement(geomIndex)

        hPerGeo = hGeo.inputValue()

        # get the different map handle in component attribute
        hJiggleMap = om.MArrayDataHandle(
            hPerGeo.child(JiggleDeformerNode.jiggleMap))
        hStiffMap = om.MArrayDataHandle(
            hPerGeo.child(JiggleDeformerNode.stiffMap))
        hDampMap = om.MArrayDataHandle(
            hPerGeo.child(JiggleDeformerNode.dampMap))

        matrix = hPerGeo.child(JiggleDeformerNode.worldMatrix).asMatrix()

        if geomIndex not in self.weightMapDict.keys():
            self.weightMapDict[geomIndex] = om.MFloatArray()
            # self.weightMapDict[geomIndex].setLength(geoIterator.count())

        if geomIndex not in self.jiggleMapDict.keys():
            self.jiggleMapDict[geomIndex] = om.MFloatArray()
            # self.jiggleMapDict[geomIndex].setLength(geoIterator.count())

        if geomIndex not in self.stiffMapDict.keys():
            self.stiffMapDict[geomIndex] = om.MFloatArray()
            # self.stiffMapDict[geomIndex].setLength(geoIterator.count())

        if geomIndex not in self.dampMapDict.keys():
            self.dampMapDict[geomIndex] = om.MFloatArray()
            # self.dampMapDict[geomIndex].setLength(geoIterator.count())

        if self.dirtyMapDict[geomIndex] or geoIterator.count(
        ) != self.membershipDict[geomIndex].length():
            self.weightMapDict[geomIndex].setLength(geoIterator.count())
            self.jiggleMapDict[geomIndex].setLength(geoIterator.count())
            self.stiffMapDict[geomIndex].setLength(geoIterator.count())
            self.dampMapDict[geomIndex].setLength(geoIterator.count())
            self.membershipDict[geomIndex].setLength(geoIterator.count())

            # loop through the geoIterator.count() (i.e. mesh geometry) for getting the jiggleMap Value.
            ii = 0
            geoIterator.reset()
            while not geoIterator.isDone():
                index = geoIterator.index()

                # JIGGLE MAP
                self.jump2Element(hJiggleMap, index)
                hJiggleMap.jumpToElement(index)
                self.jiggleMapDict[geomIndex].set(
                    hJiggleMap.inputValue().asFloat(), ii)

                # STIFF MAP
                self.jump2Element(hStiffMap, index)
                hStiffMap.jumpToElement(index)
                self.stiffMapDict[geomIndex].set(
                    hStiffMap.inputValue().asFloat(), ii)

                # DAMP MAP
                self.jump2Element(hDampMap, index)
                hDampMap.jumpToElement(index)
                self.dampMapDict[geomIndex].set(
                    hDampMap.inputValue().asFloat(), ii)

                # WEIGHT MAP
                self.weightMapDict[geomIndex].set(
                    self.weightValue(dataBlock, geomIndex,
                                     geoIterator.index()), ii)

                # MEMBERSHIP
                self.membershipDict[geomIndex].set(geoIterator.index(), ii)

                ii += 1
                geoIterator.next()

            self.dirtyMapDict[geomIndex] = False

        #######################
        # CALCULATE POSITIONS #
        #######################

        i = 0
        geoIterator.reset()
        while not geoIterator.isDone():
            goal = points[i] * local2WorldMatrix

            damping = dampMagnitude * self.dampMapDict[geomIndex][i]
            stiff = stiffMagnitude * self.stiffMapDict[geomIndex][i]

            # velocity
            velocity = (self.curPosDict[geomIndex][i] -
                        self.prePosDict[geomIndex][i]) * (1.0 - damping)
            newPos = self.curPosDict[geomIndex][i] + velocity

            goalForce = (goal - newPos) * stiff

            newPos = newPos + goalForce

            # clamp to the MAX velocity
            displacement = newPos - goal
            if displacement.length() > maxVelocity:
                displacement = displacement.normal() * maxVelocity
                newPos = goal + displacement

            # normal strength
            if normalStrength < 1.0:
                normalDot = displacement * om.MVector(
                    normals[self.membershipDict[geomIndex][i]])
                newPos -= om.MVector(
                    normals[self.membershipDict[geomIndex][i]]) * normalDot * (
                        1.0 - normalStrength)

            # direction bias
            membership = self.membershipDict[geomIndex][i]

            # displacement = om.MFloatVector(displacement)
            if directionBias > 0.0:
                normalDot = displacement.normal() * om.MVector(
                    normals[membership])

                if normalDot < 0.0:
                    RESULT = displacement * (
                        (displacement * om.MVector(normals[membership])) *
                        directionBias)
                    newPos = newPos + RESULT

            elif directionBias < 0.0:
                normalDot = displacement.normal() * om.MVector(
                    normals[membership])

                if normalDot > 0.0:
                    RESULT = displacement * (
                        (displacement * om.MVector(normals[membership])) *
                        directionBias)
                    newPos = newPos + RESULT

            # store for next time computing
            self.prePosDict[geomIndex].set(self.curPosDict[geomIndex][i], i)
            self.curPosDict[geomIndex].set(newPos, i)

            # multi with weight map and envelope
            newPosLoc = newPos * local2WorldMatrix.inverse()
            jiggle = self.jiggleMapDict[geomIndex][i]
            weight = self.weightMapDict[geomIndex][i]

            points.set(
                (points[i] +
                 (newPosLoc - points[i]) * weight * envelopeValue * jiggle), i)

            self.preTimeDict[geomIndex] = om.MTime(currentTime)

            i = i + 1
            geoIterator.next()

        # set positions
        geoIterator.setAllPositions(points)
示例#9
0
	def rebuild_solver(self, data):
		'''recalculate the solver using matrixNN no input or output in this code '''
		
		self.N = data.inputValue(self.NDimension).asInt()
		self.M = data.inputValue(self.MDimension).asInt()
		
		poses_H	= data.inputArrayValue(self.poses)
		pose_ids = OpenMaya.MIntArray()
		OpenMaya.MPlug(self.thisMObject(), self.poses).getExistingArrayAttributeIndices(pose_ids)
	
		self.poseUsed_ids = []
		
		# find the necessary information to create the system
		self.nKeys   = []
		mValues      = []
		self.weights = []
		
		for i in pose_ids:
			
			poses_H.jumpToElement(i)
			pose_H = poses_H.inputValue()
			
			state = pose_H.child(self.state).asBool()
			#wgt = pose_H.child(self.weight).asFloat()
			
			#if not (state and wgt>self.epsilon):
			#	continue
			if not state:
				continue

			nKey_H = OpenMaya.MArrayDataHandle(pose_H.child(self.nKey))
			nKey = []
			mValue_H = OpenMaya.MArrayDataHandle(pose_H.child(self.mValue))
			mValue = []
			
			for n in range(self.N):
				# try in case there is nothing connected ...
				try:
					nKey_H.jumpToElement(n)
					key	= nKey_H.inputValue().asFloat()
					nKey.append(key)
				except:
					nKey.append(0.0)
			
			# ignore the keys already present
			if nKey in self.nKeys:
				OpenMaya.MGlobal.displayWarning('key[%s] %s  can not be used more than once' %(i, nKey))
				continue
			
			for m in range(self.M):
				try:
					mValue_H.jumpToElement(m)
					value = mValue_H.inputValue().asFloat()
					mValue.append(value)
				except: 
					mValue.append(0.0)
			
			self.nKeys.append(nKey)
			mValues.append(mValue)
			#self.weights.append(wgt)
			
			self.poseUsed_ids.append(i)
		
		poseUsed_num = len(self.poseUsed_ids)
		
		if poseUsed_num in (0, 1):
			OpenMaya.MGlobal.displayError('RbfSolver failed: valid poses number is less than 2')
			return False
		
		# for the continuation need to know the functions used:
		# Distance function ?
		# RBF function ?
		normalize = data.inputValue(self.normalize).asBool()
		distance_id = data.inputValue(self.distanceMode).asInt()
		self.distance_function = self.distance_functions[distance_id]
		rbf_id = data.inputValue(self.rbfMode).asInt()
		self.rbf_function = self.rbf_functions[rbf_id]
	
		# matrixNN to solve systems AX = Y
		# factorize la and solve la for each m
		# store the X (m) in self.mX
		distanceMax	= 0.0
		mat = MatrixNN()
		mat.setDimension(poseUsed_num)
		
		for i in range(poseUsed_num):
			for j in range(poseUsed_num):
				
				if i == j:
					# Here the distance of a pose on itself
					mat.rc[i][j] = 0.0
				else:
					# Distance from each pose to each pose
					distance = self.distance_function(self.N, self.nKeys[i], self.nKeys[j])
					
					# Stores the maximum distance between 2 poses, this will be used to standardize the system
					if distance > distanceMax:
						distanceMax = distance
					
					mat.rc[i][j] = distance
		
		# Use the scale for smoother more or less
		# If you want the standardized system, you have to divide the scale by the distanceMax
		fScale = data.inputValue(self.scale).asFloat()
		if fScale < self.epsilon:
			fScale = self.epsilon
		
		if normalize:
			self.fScale	= fScale / distanceMax
		else:
			self.fScale	= fScale
		
		# RBF each element
		for i in range(poseUsed_num):
			for j in range(poseUsed_num):
				mat.rc[i][j] = self.rbf_function(mat.rc[i][j] * self.fScale)
	
		# factorizeLU and save the ids of the swapped lines
		LU, Pids = mat.factorize_LU()

		# for each m of each pose
		# solv_LU and store the X (m) in self.mX
		# mX =  m * nVector
		self.mX	= []
		
		for m in range(self.M):
			
			Y = [mValues[i][m]  for i in range(poseUsed_num)]
			X = mat.solve_LU(LU, Pids, Y)  # nVector coeff
			self.mX.append(X)
		
		#*** setClean indicates that the system is solved
		solved_H = data.outputValue(self.solved)
		solved_H.setClean()
		
		OpenMaya.MGlobal.displayInfo("RbfSolver recomputed using poses:  %s" %self.poseUsed_ids)
		return True
示例#10
0
    def doIt(self, args):
        """
		This method is called from script when this command is called.
		It should set up any class data necessary for redo/undo,
		parse any given arguments, and then call redoIt.
		"""
        argData = OpenMaya.MArgDatabase(self.syntax(), args)

        if argData.isFlagSet(kIndexFlag):
            self.__isIndex = True

        # Get the plug specified on the command line.
        slist = OpenMaya.MSelectionList()
        argData.getObjects(slist)
        if slist.length() == 0:
            print "Must specify an array plug in the form <nodeName>.<multiPlugName>."
            return

        plug = OpenMaya.MPlug()
        slist.getPlug(0, plug)
        if plug.isNull():
            print "Must specify an array plug in the form <nodeName>.<multiPlugName>."
            return

        # Construct a data handle containing the data stored in the plug.
        dh = plug.asMDataHandle()
        adh = None
        try:
            adh = OpenMaya.MArrayDataHandle(dh)
        except:
            print "Could not create the array data handle."
            plug.destructHandle(dh)
            return

        # Iterate over the values in the multiPlug.  If the index flag has been used, just return
        # the logical indices of the child plugs.  Otherwise, return the plug values.
        for i in range(adh.elementCount()):
            try:
                indx = adh.elementIndex()
            except:
                advance(adh)
                continue

            if self.__isIndex:
                self.appendToResult(indx)
            else:
                h = adh.outputValue()
                if h.isNumeric():
                    if h.numericType() == OpenMaya.MFnNumericData.kBoolean:
                        self.appendToResult(h.asBool())
                    elif h.numericType() == OpenMaya.MFnNumericData.kShort:
                        self.appendToResult(h.asShort())
                    elif h.numericType() == OpenMaya.MFnNumericData.kInt:
                        self.appendToResult(h.asInt())
                    elif h.numericType() == OpenMaya.MFnNumericData.kFloat:
                        self.appendToResult(h.asFloat())
                    elif h.numericType() == OpenMaya.MFnNumericData.kDouble:
                        self.appendToResult(h.asDouble())
                    else:
                        print "This sample command only supports boolean, integer, and floating point values."
            advance(adh)

        plug.destructHandle(dh)
示例#11
0
    def compute(self, plug, data):

        # Input plug filter
        if plug != vmMultiGeometryConstraint.outTranslate_attr:
            return OpenMaya.kUnknownParameter

        # GET : meshes
        in_meshes = OpenMaya.MArrayDataHandle(
            data.inputValue(vmMultiGeometryConstraint.inputMeshes))
        meshes = [in_meshes.inputValue().asMesh()]
        for i in xrange(in_meshes.elementCount() - 1):
            in_meshes.next()
            meshes.append(in_meshes.inputValue().asMesh())

        # GET : Matrices
        in_matrices = OpenMaya.MArrayDataHandle(
            data.inputValue(vmMultiGeometryConstraint.inputMatrices))
        matrices = [in_matrices.inputValue().asMatrix()]
        for i in xrange(in_matrices.elementCount() - 1):
            in_matrices.next()
            matrices.append(in_matrices.inputValue().asMatrix())

        # GET : Input position
        mtx = data.inputValue(
            vmMultiGeometryConstraint.inputMatrix_attr).asMatrix()
        this_position = OpenMaya.MPoint(mtx(3, 0), mtx(3, 1), mtx(3, 2))

        closest_delta = self.max_distance
        closest_point = OpenMaya.MFloatPoint()

        # Get input meshes count
        # mesh_plug.getExistingArrayAttributeIndices(self.indices_list)

        # Main loop
        for m, mat in zip(meshes, matrices):

            # # Get Mesh and closestPoint
            # mfnmesh = OpenMaya.MFnMesh(m)
            # this_closest_point = OpenMaya.MPoint()
            # mfnmesh.getClosestPoint(this_position, this_closest_point)

            # # Compare with before
            # this_delta = this_closest_point.distanceTo(this_position)
            # if this_delta < closest_delta:
            #     closest_point = this_closest_point
            #     closest_delta = this_delta

            # Get Mesh and closestPoint
            intersector = OpenMaya.MMeshIntersector()
            intersector.create(m, mat)
            this_closest_point = OpenMaya.MPointOnMesh()
            intersector.getClosestPoint(this_position, this_closest_point)
            this_closest_point = OpenMaya.MPoint(this_closest_point.getPoint())

            # Compare with before
            this_delta = this_closest_point.distanceTo(this_position)
            if this_delta < closest_delta:
                closest_point = this_closest_point
                closest_delta = this_delta

        # Remember, remember, the fifth of November
        self.prev_pos = closest_point

        # for k in xrange(self.indices_list.length()):
        #     mesh_handle.jumpToArrayElement(k)
        #     temp_msh = OpenMaya.MFnMesh(mesh_handle.inputValue().asMesh())

        # Set output rotate
        out_translate_dh = data.outputValue(
            vmMultiGeometryConstraint.outTranslate_attr)
        out_translate_dh.set3Float(closest_point.x, closest_point.y,
                                   closest_point.z)
        data.setClean(plug)
示例#12
0
    def deform(self, dataBlock, geoIterator, local2WorldMatrix, geomIndex):

        input = ompx.cvar.MPxGeometryFilter_input

        dataHandleInputArray = dataBlock.outputArrayValue(input)

        dataHandleInputArray.jumpToElement(geomIndex)

        dataHandleInputElement = dataHandleInputArray.outputValue()

        # inputMesh
        inputGeom = ompx.cvar.MPxGeometryFilter_inputGeom
        dataHandleInputGeom = dataHandleInputElement.child(inputGeom)
        inputMesh = dataHandleInputGeom.asMesh()

        # MFnMesh
        inputMFnMesh = om.MFnMesh(inputMesh)

        # Envelope
        envelope = ompx.cvar.MPxGeometryFilter_envelope
        dataHandleEnvolope = dataBlock.inputValue(envelope)
        envelopeValue = dataHandleEnvolope.asFloat()

        # damping
        dataHandleDamping = dataBlock.inputValue(JiggleDeformerNode.dampingVal)
        dampMagnitude = dataHandleDamping.asFloat()

        # stiffness
        dataHandleStiff = dataBlock.inputValue(JiggleDeformerNode.stiffVal)
        stiffMagnitude = dataHandleStiff.asFloat()

        # time
        dataHandleTime = dataBlock.inputValue(JiggleDeformerNode.time)
        currentTime = dataHandleTime.asTime()

        # points' positions in local space
        points = om.MPointArray()
        geoIterator.allPositions(points)

        # INITIALIZE ATTRIBUTES
        if geomIndex not in self.initialFlagDict.keys():
            self.initialFlagDict[geomIndex] = False

        if geomIndex not in self.preTimeDict.keys():
            self.preTimeDict[geomIndex] = om.MTime()

        if geomIndex not in self.curPosDict.keys():
            self.curPosDict[geomIndex] = om.MPointArray()

        if geomIndex not in self.prePosDict.keys():
            self.prePosDict[geomIndex] = om.MPointArray()

        # test initialize flag for the first time
        if not self.initialFlagDict[geomIndex]:
            self.preTimeDict[geomIndex] = currentTime

            self.curPosDict[geomIndex].setLength(geoIterator.count())
            self.prePosDict[geomIndex].setLength(geoIterator.count())

            for i in range(points.length()):
                self.curPosDict[geomIndex].set(points[i] * local2WorldMatrix,
                                               i)
                self.prePosDict[geomIndex].set(self.curPosDict[geomIndex][i],
                                               i)

            self.preTimeDict[geomIndex] = currentTime

            self.initialFlagDict[geomIndex] = True

        # for stable simulation, check the time difference whether it is 1 frame or not
        timeDiff = currentTime.value() - self.preTimeDict[geomIndex].value()

        if timeDiff > 1.0 or timeDiff < 0.0:
            self.initialFlagDict[geomIndex] = False
            self.preTimeDict[geomIndex] = om.MTime(currentTime)
            return

        # perGeometry
        hGeo = dataBlock.inputArrayValue(JiggleDeformerNode.perGeo)

        self.jump2Element(hGeo, geomIndex)
        hGeo.jumpToElement(geomIndex)

        hPerGeo = hGeo.inputValue()

        hJiggleMap = om.MArrayDataHandle(
            hPerGeo.child(JiggleDeformerNode.jiggleMap))
        hStiffMap = om.MArrayDataHandle(
            hPerGeo.child(JiggleDeformerNode.stiffMap))
        hDampMap = om.MArrayDataHandle(
            hPerGeo.child(JiggleDeformerNode.dampMap))

        matrix = hPerGeo.child(JiggleDeformerNode.worldMatrix).asMatrix()

        if geomIndex not in self.weightMapDict.keys():
            self.weightMapDict[geomIndex] = om.MFloatArray()
            self.weightMapDict[geomIndex].setLength(geoIterator.count())

        if geomIndex not in self.jiggleMapDict.keys():
            self.jiggleMapDict[geomIndex] = om.MFloatArray()
            self.jiggleMapDict[geomIndex].setLength(geoIterator.count())

        if geomIndex not in self.stiffMapDict.keys():
            self.stiffMapDict[geomIndex] = om.MFloatArray()
            self.stiffMapDict[geomIndex].setLength(geoIterator.count())

        if geomIndex not in self.dampMapDict.keys():
            self.dampMapDict[geomIndex] = om.MFloatArray()
            self.dampMapDict[geomIndex].setLength(geoIterator.count())

        # loop through the geoIterator.count() (i.e. mesh geometry) for getting the jiggleMap Value.
        ii = 0
        geoIterator.reset()
        while not geoIterator.isDone():
            index = geoIterator.index()

            self.jump2Element(hJiggleMap, index)
            hJiggleMap.jumpToElement(index)
            self.jiggleMapDict[geomIndex].set(
                hJiggleMap.inputValue().asFloat(), ii)

            self.jump2Element(hStiffMap, index)
            hStiffMap.jumpToElement(index)
            self.stiffMapDict[geomIndex].set(hStiffMap.inputValue().asFloat(),
                                             ii)

            self.jump2Element(hDampMap, index)
            hDampMap.jumpToElement(index)
            self.dampMapDict[geomIndex].set(hDampMap.inputValue().asFloat(),
                                            ii)

            self.weightMapDict[geomIndex].set(
                self.weightValue(dataBlock, geomIndex, geoIterator.index()),
                ii)

            ii += 1
            geoIterator.next()

        # calculate positions
        i = 0
        geoIterator.reset()
        while not geoIterator.isDone():
            goal = points[i] * local2WorldMatrix

            damping = dampMagnitude * self.dampMapDict[geomIndex][i]
            stiff = stiffMagnitude * self.stiffMapDict[geomIndex][i]

            # velocity
            velocity = (self.curPosDict[geomIndex][i] -
                        self.prePosDict[geomIndex][i]) * (1.0 - damping)
            newPos = self.curPosDict[geomIndex][i] + velocity

            goalForce = (goal - newPos) * stiff

            newPos = newPos + goalForce

            # store for next time computing
            self.prePosDict[geomIndex].set(self.curPosDict[geomIndex][i], i)
            self.curPosDict[geomIndex].set(newPos, i)

            # multi with weight map and envelope
            newPosLoc = newPos * local2WorldMatrix.inverse()
            jiggle = self.jiggleMapDict[geomIndex][i]
            weight = self.weightMapDict[geomIndex][i]

            points.set(
                (points[i] +
                 (newPosLoc - points[i]) * weight * envelopeValue * jiggle), i)

            self.preTimeDict[geomIndex] = om.MTime(currentTime)

            i = i + 1
            geoIterator.next()

        # set positions
        geoIterator.setAllPositions(points)
示例#13
0
    def deform(self, block, iterator, localToWorldMatrix, multiIndex):
        thisNode = self.thisMObject()
        if not block.inputValue(self.enabled).asBool():
            return

        envelope = block.inputValue(self.envelope).asFloat()
        if envelope == 0.0:
            return

        if not block.inputValue(self.maxDistanceEnabled).asBool():
            maxDistance = 0.0
        else:
            maxDistance = block.inputValue(
                self.maxDistance).asDistance().value()
        maxDistanceUScaleEnabled = block.inputValue(
            self.maxDistanceUScaleEnabled).asBool()
        maxDistanceVScaleEnabled = block.inputValue(
            self.maxDistanceVScaleEnabled).asBool()
        if maxDistanceUScaleEnabled or maxDistanceVScaleEnabled:
            float2PtrUtil = om.MScriptUtil()
            float2PtrUtil.createFromList([0.0, 0.0], 2)
            float2Ptr = float2PtrUtil.asFloat2Ptr()
        if maxDistanceUScaleEnabled:
            maxDistanceUScaleAttr = om.MRampAttribute(thisNode,
                                                      self.maxDistanceUScale)
            uValues = {}
        if maxDistanceVScaleEnabled:
            maxDistanceVScaleAttr = om.MRampAttribute(thisNode,
                                                      self.maxDistanceVScale)
            vValues = {}

        falloffEnabled = block.inputValue(self.falloffEnabled).asBool()
        if falloffEnabled:
            falloffRampAttr = om.MRampAttribute(thisNode, self.falloff)
        if falloffEnabled or maxDistanceUScaleEnabled or maxDistanceVScaleEnabled:
            floatPtrUtil = om.MScriptUtil()
            floatPtrUtil.createFromDouble(0.0)
            floatPtr = floatPtrUtil.asFloatPtr()

        iteratorCount = iterator.count()
        if iteratorCount == 0:
            return

        if len(self.__membership__[multiIndex]) != iteratorCount:
            self.__membership__[multiIndex] = []
            while not iterator.isDone():
                index = iterator.index()
                self.__membership__[multiIndex].append(index)
                iterator.next()
            iterator.reset()
        indices = self.__membership__[multiIndex]

        if self.__weightsDirty__[multiIndex]:
            self.__weights__[multiIndex] = []
            for index in self.__membership__[multiIndex]:
                self.__weights__[multiIndex].append(
                    self.weightValue(block, multiIndex, index))
            self.__weightsDirty__[multiIndex] = False
        weights = self.__weights__[multiIndex]

        if self.__maxDistanceWeightsDirty__[multiIndex]:
            maxDistanceWeightListArrayHandle = block.inputArrayValue(
                self.maxDistanceWeightList)
            JumpToElement(maxDistanceWeightListArrayHandle, multiIndex)
            maxDistanceWeightListHandle = maxDistanceWeightListArrayHandle.inputValue(
            )
            maxDistanceWeightsArrayHandle = om.MArrayDataHandle(
                maxDistanceWeightListHandle.child(self.maxDistanceWeights))
            self.__maxDistanceWeights__[multiIndex] = []
            for index in self.__membership__[multiIndex]:
                JumpToElement(maxDistanceWeightsArrayHandle, index)
                self.__maxDistanceWeights__[multiIndex].append(
                    maxDistanceWeightsArrayHandle.inputValue().asFloat())
            self.__maxDistanceWeightsDirty__[multiIndex] = False
        maxDistanceWeights = self.__maxDistanceWeights__[multiIndex]

        pointsWorldSpace = []
        while not iterator.isDone():
            pointsWorldSpace.append(iterator.position() * localToWorldMatrix)
            iterator.next()

        # loop ptr vars
        intUtil = om.MScriptUtil()
        intUtil.createFromInt(0)
        intPtr = intUtil.asIntPtr()
        doublePtrUtil = om.MScriptUtil()
        doublePtrUtil.createFromDouble(0.0)
        doublePtr = doublePtrUtil.asDoublePtr()
        doublePtrUtil2 = om.MScriptUtil()
        doublePtrUtil2.createFromDouble(0.0)
        doublePtr2 = doublePtrUtil2.asDoublePtr()

        deltas = {}
        inputTargetArrayHandle = block.inputArrayValue(self.inputTarget)
        for i in range(inputTargetArrayHandle.elementCount()):
            inputTargetArrayHandle.jumpToArrayElement(i)
            inputTargetHandle = inputTargetArrayHandle.inputValue()
            if not inputTargetHandle.child(self.targetEnabled).asBool():
                continue
            targetHandle = inputTargetHandle.child(self.target)
            targetData = targetHandle.data()
            if targetData.isNull():
                continue
            targetType = targetHandle.type()
            targetPoint = om.MPoint()

            if targetType == om.MFnMeshData.kMesh:
                meshFn = om.MFnMesh(targetData)
                closestVertex = inputTargetHandle.child(
                    self.closestVertex).asFloat()
                if closestVertex:
                    tempPoint = om.MPoint()
                    faceVertices = om.MIntArray()

                def getClosestPoint(startPoint):
                    meshFn.getClosestPoint(startPoint, targetPoint,
                                           om.MSpace.kWorld, intPtr)
                    if closestVertex:
                        meshFn.getPolygonVertices(
                            om.MScriptUtil(intPtr).asInt(), faceVertices)
                        shortestDistance = None
                        for vertexId in faceVertices:
                            meshFn.getPoint(vertexId, tempPoint,
                                            om.MSpace.kWorld)
                            vertexDistance = (startPoint - tempPoint).length()
                            if shortestDistance is None or vertexDistance < shortestDistance:
                                shortestDistance = vertexDistance
                                closestVertexPoint = om.MPoint(tempPoint)
                        return targetPoint * (
                            1.0 - closestVertex) + om.MVector(
                                closestVertexPoint * closestVertex)
                    return targetPoint

                def setMaxDistanceUvScaleValues(uvPoint):
                    if maxDistanceUScaleEnabled or maxDistanceVScaleEnabled:
                        meshFn.getUVAtPoint(uvPoint, float2Ptr,
                                            om.MSpace.kWorld)
                        if maxDistanceUScaleEnabled:
                            uValues[index] = float2PtrUtil.getFloat2ArrayItem(
                                float2Ptr, 0, 0)
                        if maxDistanceVScaleEnabled:
                            vValues[index] = float2PtrUtil.getFloat2ArrayItem(
                                float2Ptr, 0, 1)

            elif targetType == om.MFnNurbsCurveData.kNurbsCurve:
                curveFn = om.MFnNurbsCurve(targetData)

                def getClosestPoint(startPoint):
                    return curveFn.closestPoint(startPoint, doublePtr, 0.00001,
                                                om.MSpace.kWorld)

                def setMaxDistanceUvScaleValues(*args):
                    if maxDistanceUScaleEnabled:
                        uValues[index] = om.MScriptUtil.getDouble(
                            doublePtr) / curveFn.numSpans()
                    if maxDistanceVScaleEnabled and index in vValues:
                        del vValues[index]

            elif targetType == om.MFnNurbsSurfaceData.kNurbsSurface:
                surfaceFn = om.MFnNurbsSurface(targetData)

                def getClosestPoint(startPoint):
                    return surfaceFn.closestPoint(startPoint, doublePtr,
                                                  doublePtr2, False, 0.00001,
                                                  om.MSpace.kWorld)

                def setMaxDistanceUvScaleValues(*args):
                    if maxDistanceUScaleEnabled:
                        uValues[index] = om.MScriptUtil.getDouble(
                            doublePtr) / surfaceFn.numSpansInU()
                    if maxDistanceVScaleEnabled:
                        vValues[index] = om.MScriptUtil.getDouble(
                            doublePtr2) / surfaceFn.numSpansInV()

            elif targetType == om.MFnMatrixData.kMatrix:
                position = om.MPoint(
                    om.MFnMatrixData(
                        targetData).transformation().getTranslation(
                            om.MSpace.kWorld))

                def getClosestPoint(*args):
                    return position

                def setMaxDistanceUvScaleValues(*args):
                    if maxDistanceUScaleEnabled and index in uValues:
                        del uValues[index]
                    if maxDistanceVScaleEnabled and index in vValues:
                        del vValues[index]
            else:
                raise ValueError('can never happen?')

            for index, weight, point in izip(indices, weights,
                                             pointsWorldSpace):
                if not weight:
                    continue
                targetPoint = getClosestPoint(point)
                delta = targetPoint - point
                if index in deltas and deltas[index].length() < delta.length():
                    continue
                deltas[index] = targetPoint - point
                setMaxDistanceUvScaleValues(targetPoint)

        # maxDistance / falloff
        for vertexId, delta in deltas.iteritems():
            listIndex = indices.index(vertexId)
            if maxDistance:
                deltaLength = delta.length()
                vertexMaxDistance = maxDistance * maxDistanceWeights[listIndex]
                if maxDistanceUScaleEnabled and vertexId in uValues:
                    maxDistanceUScaleAttr.getValueAtPosition(
                        uValues[vertexId], floatPtr)
                    vertexMaxDistance *= om.MScriptUtil.getFloat(floatPtr)
                if maxDistanceVScaleEnabled and vertexId in vValues:
                    maxDistanceVScaleAttr.getValueAtPosition(
                        vValues[vertexId], floatPtr)
                    vertexMaxDistance *= om.MScriptUtil.getFloat(floatPtr)
                if deltaLength > vertexMaxDistance:
                    continue
                if falloffEnabled:
                    lengthMaxDistancePercent = deltaLength / vertexMaxDistance
                    falloffRampAttr.getValueAtPosition(
                        float(1.0 - lengthMaxDistancePercent), floatPtr)
                    falloff = om.MScriptUtil.getFloat(floatPtr)
                    delta *= falloff

            pointsWorldSpace[
                listIndex] += delta * weights[listIndex] * envelope

        pointsObjectSpace = om.MPointArray()
        worldToLocalMatrix = localToWorldMatrix.inverse()
        for point in pointsWorldSpace:
            pointsObjectSpace.append(point * worldToLocalMatrix)
        iterator.setAllPositions(pointsObjectSpace)
示例#14
0
    def compute(self, plug, dataBlock):

        outsAttr = [self.outputTAttr, self.outputRAttr, self.outputSAttr]
        if not (plug in outsAttr):
            return om.kUnknownParameter

        trsObj = trsClass.trsClass()
        # _________________________________ IN MATRIX
        masterTrs = []

        arrayDataHandle = om.MArrayDataHandle(
            dataBlock.inputValue(self.inputMatrixAttr))

        for i in range(arrayDataHandle.elementCount() - 1):
            arrayDataHandle.next()
            floatMatrix = (arrayDataHandle.inputValue()).asFloatMatrix()
            masterTrs.append(
                trsObj.createFromFloatMatrix(MMatrixToNum(floatMatrix)))

        # _________________________________ IN DYN ATTR

        dataHandle = dataBlock.inputValue(self.inputTimeAttr)
        intime = dataHandle.asFloat()

        dataHandle = dataBlock.inputValue(self.inputActivateAttr)
        activate = dataHandle.asFloat()

        dataHandle = dataBlock.inputValue(self.input1Attr)
        mass = dataHandle.asFloat()

        dataHandle = dataBlock.inputValue(self.input2Attr)
        elasticity = dataHandle.asFloat()

        dataHandle = dataBlock.inputValue(self.input3Attr)
        damping = dataHandle.asFloat()

        dataHandle = dataBlock.inputValue(self.input4Attr)
        gravity = dataHandle.asFloat()

        # _________________________________ SAVE NEXT EVAL

        dataHandle = dataBlock.inputValue(self.inputNext1Attr)
        self.nbrEval = dataHandle.asFloat()

        dataHandle = dataBlock.inputValue(self.inputNext2Attr)
        self.lastTime = dataHandle.asFloat()

        dataHandle = dataBlock.inputValue(self.inputNext3Attr)
        self.lastSpeed = dataHandle.asFloat3()
        self.lastSpeed = [
            self.lastSpeed[0], self.lastSpeed[1], self.lastSpeed[2]
        ]

        self.slavesValues = []

        arrayDataHandle = om.MArrayDataHandle(
            dataBlock.inputValue(self.inputNext4Attr))

        for i in range(arrayDataHandle.elementCount() - 1):
            arrayDataHandle.next()
            slaveValue = (arrayDataHandle.inputValue()).asFloat3()
            self.slavesValues.append(
                [slaveValue[0], slaveValue[1], slaveValue[2]])

        #_____________________________________________________________________________________COMPUTE

        gravityVector = [0, gravity, 0]

        #_______________ DELTA TIME
        incrEval = 0.04
        self.nbrEval += incrEval

        curTime = self.nbrEval
        deltaTime = curTime - self.lastTime
        self.lastTime = curTime

        #_______________ DYNAMIC
        curentFrame = mc.currentTime(query=True)
        startFrame = mc.playbackOptions(query=True, minTime=True)

        if (activate == 0) or (curentFrame == startFrame):

            self.nbrEval = 0
            self.lastTime = 0
            self.lastSpeed = [0, 0, 0]

            self.slavesValues = []
            for i in range(0, len(masterTrs)):
                self.slavesValues.append(masterTrs[i][0:3])

            for i in range(1, len(masterTrs)):
                leadPos = masterTrs[i - 1]
                slavePos = masterTrs[i]
                baseLengths[i] = ompy.MVector(
                    slavePos[0] - leadPos[0], slavePos[1] - leadPos[1],
                    slavePos[2] - leadPos[2]).length()

        else:

            # FOLLOW DYN
            self.slaveValue[0] = inMatrices[0][0:3]

            for i in range(1, len(masterTrs)):
                leadPos = self.slavesValues[i - 1]
                slavePos = self.slavesValues[i]

                vLeadSlave = ompy.MVector(slavePos[0] - leadPos[0],
                                          slavePos[1] - leadPos[1],
                                          slavePos[2] - leadPos[2])
                vLeadSlaveAdjust = vLeadSlave * (baseLengths[i] /
                                                 vLeadSlave.length())
                slavePosNew = [
                    leadPos[0] + vLeadSlaveAdjust.x,
                    leadPos[1] + vLeadSlaveAdjust.y,
                    leadPos[2] + vLeadSlaveAdjust.z
                ]

                self.slavesValues[i] = slavePosNew

        translate = self.slaveValue
        rotate = [0, 0, 0]
        scale = [1, 1, 1]

        #_____________________________________________________________________________________ OUT NEXT

        nodeName = self.name()
        mc.undoInfo(swf=0)

        mc.setAttr(nodeName + '.' + self.kInputNext1AttrName, self.nbrEval)
        mc.setAttr(nodeName + '.' + self.kInputNext2AttrName, self.lastTime)
        #mc.setAttr( nodeName +'.'+ self.kInputNext3AttrName  , self.lastSpeed[0] ,  self.lastSpeed[1] ,  self.lastSpeed[2] , type = 'double3')

        for i in range(0, len(self.slavesValues)):
            mc.setAttr(nodeName + '.' + self.kInputNext4AttrName +
                       '[{0}]'.format(i),
                       self.slavesValues[i][0],
                       self.slavesValues[i][1],
                       self.slavesValues[i][2],
                       type='double3')

        mc.undoInfo(swf=1)

        #_____________________________________________________________________________________COMPUTE OUT

        dataHandle = dataBlock.outputValue(self.outputTAttr)
        dataHandle.set3Double(translate[0], translate[1], translate[2])
        dataHandle.setClean()

        dataHandle = dataBlock.outputValue(self.outputRAttr)
        dataHandle.set3Double(math.radians(rotate[0]), math.radians(rotate[1]),
                              math.radians(rotate[2]))
        dataHandle.setClean()

        dataHandle = dataBlock.outputValue(self.outputSAttr)
        dataHandle.set3Double(scale[0], scale[1], scale[2])
        dataHandle.setClean()

        dataBlock.setClean(plug)
示例#15
0
    def compute(self, plug, dataBlock):
        if (plug == self.weight):
            # print "============%s===============" % self.name()
            # NOTE 获取输出阈值
            envelope = dataBlock.inputValue(self.envelope).asFloat()
            thersold = dataBlock.inputValue(self.thersold).asFloat()
            border = dataBlock.inputValue(self.border).asFloat()

            jntMatrix = dataBlock.inputValue(self.jntMatrix).asMatrix()
            jointPoint = OpenMaya.MPoint(jntMatrix(3, 0), jntMatrix(3, 1),
                                         jntMatrix(3, 2))

            # ! -------------------------------------------
            # !         获取骨骼位置和表情点的位置
            # ! -------------------------------------------
            expGrpPlugs = OpenMaya.MPlug(self.thisMObject(), self.expGrp)
            expGrpArrayHandle = dataBlock.inputArrayValue(self.expGrp)

            weight_list = []
            samll_list = []

            data_list = []
            index_list = OpenMaya.MIntArray()
            expGrpPlugs.getExistingArrayAttributeIndices(index_list)

            # NOTE 获取最后的序号值
            last_idx = index_list[index_list.length() - 1]
            el_count = expGrpPlugs.elementByLogicalIndex(last_idx).child(
                self.expPt).numElements()

            # NOTE 如果最后的序号没有元素 去掉最后一个元素
            index_list = list(index_list) if el_count else list(
                index_list)[:-1]
            weight_list = [0 for j in range(index_list[-1])]
            exp_pt_list = []
            for idx in (index_list):
                expGrpPlug = expGrpPlugs.elementByLogicalIndex(idx)
                expGrpArrayHandle.jumpToElement(idx)
                expGrpHandle = expGrpArrayHandle.inputValue()

                expPtArrayHandle = OpenMaya.MArrayDataHandle(
                    expGrpHandle.child(self.expPt))
                expPtArrayHandle.jumpToElement(0)

                expPoint = OpenMaya.MPoint(
                    *expPtArrayHandle.inputValue().asFloat3())

                length = (jointPoint - expPoint).length()

                data = {
                    "idx": idx,
                    "len": length,
                    "expPoint": expPoint,
                    "expGrpPlug": expGrpPlug,
                }
                # print data["expGrpPlug"].child(self.expPt)[0].source().name().replace("editPoints","cv"),round(data["len"],2)
                data_list.append(data)

                # NOTE 添加 基准 的数据计算 base_weight
                if idx == 0:
                    samll_list.append(data)

            # ! -------------------------------------------
            # !         过滤出最相近的两个点
            # ! -------------------------------------------
            # NOTE 取出长度最小的三个表情点
            for data in heapq.nsmallest(3, data_list, key=lambda s: s['len']):
                # print data["expGrpPlug"].child(self.expPt)[0].source().name().replace("editPoints","cv"),round(data["len"],2)

                # NOTE 判断 idx 是否有重复的 避免重复添加 基准data
                for _data in samll_list:
                    if data["idx"] == _data["idx"]:
                        break
                else:
                    samll_list.append(data)

            length_list = [data['len'] for data in samll_list]
            min_value = min(length_list)

            remap_list = self.minMaxNorm(
                length_list,
                min_val=0 if min_value > 0.1 else min_value,
                max_val=max(length_list))

            base_weight = 1
            for data, remap in zip(samll_list, remap_list):
                idx = data['idx']

                weight = 1 if remap < thersold else 1 - remap
                # print "weight",weight
                if idx == 0:
                    base_weight = remap
                    basePoint = data['expPoint']
                else:
                    expPoint = data['expPoint']

                    info = self.calcPtInfo(basePoint, jointPoint, expPoint)

                    jnt_len = info["vec_1_len"]
                    exp_len = info["vec_2_len"]

                    weight *= base_weight
                    if jnt_len < thersold:
                        weight = 0
                    elif data['len'] < thersold:
                        weight = 1
                    # else:
                    #     angle = info["vec_1"]*info["vec_2"]/(jnt_len*exp_len)
                    #     reflect_len = jnt_len * math.cos(angle)
                    #     _weight = reflect_len / exp_len
                    #     _weight = _weight if _weight <= 1 else 1/_weight
                    #     weight *= _weight
                    #     # print self.name(),math.cos(angle),weight

                    weight_list[idx - 1] = 0 if weight < border else (
                        weight - border) / (1 - border)

            weight_list = [
                weight * envelope if weight * envelope < 1 else 1
                for weight in self.rangeValueFilter(weight_list, 2)
            ]

            # NOTE 只保留最大值
            max_value = max(weight_list)
            weight_list = [
                0 if weight < max_value else weight for weight in weight_list
            ]

            # NOTE 遍历输出权重值
            weightArrayHandle = dataBlock.outputArrayValue(self.weight)
            weightBuilder = weightArrayHandle.builder()
            for j, weight in enumerate(weight_list):
                weightHandle = weightBuilder.addElement(j)
                weightHandle.setFloat(weight)
                weightHandle.setClean()

            # NOTE 设置输出数值
            weightArrayHandle.set(weightBuilder)
            weightArrayHandle.setAllClean()
            dataBlock.setClean(plug)

        else:
            return OpenMaya.kUnknownParameter