Пример #1
0
def applyMatricesToTransformBlendShapeNodeOffsets(
        blendShapeNode,
        matrices,
        shapeData=None,
        targets=None,
        optionalData=None,
        matrixOp=matrixOp_makeLinearCorrective):
    applyShapeData = bs.getEmptyShapeData()
    for target in targets:
        shape = bs.getEmptyShape()
        applyShapeData['shapes'][target] = shape

    applyMatricesResult = applyMatricesToTransformShapeDataOffsets(
        applyShapeData,
        matrices,
        targets=targets,
        optionalData=optionalData,
        matrixOp=matrixOp)

    return applyMatricesResult
Пример #2
0
    def apply_pose(self,
                   pose_index,
                   training_type='differential',
                   ground_truth=False):
        """
        apply the pose to rigs in the scene
        :param int pose_index: the index of the pose to apply
        :param str training_type: the type of training. Valid options are differential and local_offset
        :param bool ground_truth: if True, read ground truth data instead
        """
        if self.pose_data is None:
            self.read_pose_data()
        if training_type not in self.prediction_data:
            training_types = [training_type]
            if training_type == 'differential':
                training_types.append('anchor')
            self.read_prediction_data(training_types,
                                      ground_truth=ground_truth)

        cur_pose_data = self.pose_data.iloc[pose_index]

        for mover in cur_pose_data.index:

            value = cur_pose_data[mover]

            all_movers = mc.ls(mover, recursive=True)
            for m in all_movers:
                try:
                    mc.setAttr(m, value)
                except RuntimeError as error_msg:
                    pass

        shape_data = bs.getEmptyShapeData()
        shape_data['shapes'][self.TARGET] = bs.getEmptyShape()

        if training_type == 'local_offset':
            cur_offset_data = self.prediction_data[training_type].loc[
                pose_index]

            shape_data['shapes'][self.TARGET] = bs.getEmptyShape()

            exclude_list = []

            for vtx_id in cur_offset_data.index:
                if int(vtx_id) in exclude_list:
                    continue
                shape_data['shapes'][self.TARGET]['offsets'][int(
                    vtx_id)] = cur_offset_data[vtx_id]

        elif training_type == 'differential':
            cur_differential_data = self.prediction_data[training_type].loc[
                pose_index]
            cur_anchor_data = self.prediction_data['anchor'].loc[pose_index]

            if self._laplacian_matrix is None:
                self._cal_matrices()

            col_ct = len(self.vertex_ids['differential'])
            diff_coord = numpy.ndarray(shape=(col_ct +
                                              len(self.vertex_ids['anchor']),
                                              1))

            real_coords = []
            for axis in range(3):
                test_index = []
                test_coord = []
                for i, di in enumerate(self.vertex_ids['differential']):
                    test_index.append(di)
                    test_coord.append(cur_differential_data[di][axis])
                    diff_coord[i] = self._valences[i] * cur_differential_data[
                        di][axis]
                for j, anchor in enumerate(self.vertex_ids['anchor']):
                    if cur_anchor_data is not None:
                        test_coord.append(cur_anchor_data[anchor][axis])
                        diff_coord[
                            j + col_ct] = self.anchor_weight * cur_anchor_data[
                                anchor][axis]
                    else:
                        test_coord.append(0.0)
                        diff_coord[j + col_ct] = 0.0

                # calculates (L*) * d, where D* is the transpose of the laplacian matrix,
                # d is the differential coordinates scaled with valence
                morphed_diff_coord = self._laplacian_matrix.transpose(
                ) * diff_coord

                # reorder the coordinates based on reverse cuthill mckee reordering
                reordered_diff_coord = numpy.ndarray(shape=(col_ct, 1))
                for i in range(col_ct):
                    reordered_diff_coord[i] = morphed_diff_coord[
                        self._reverse_cuthill_mckee_order[i]]

                # back substitution to solve two trianglar matrices
                theta_coord = scipy.linalg.solve_triangular(
                    self._cholesky_matrix,
                    reordered_diff_coord,
                    lower=True,
                    overwrite_b=True,
                    check_finite=False)
                reordered_real_coord = scipy.linalg.solve_triangular(
                    self._cholesky_matrix.T,
                    theta_coord,
                    lower=False,
                    overwrite_b=True,
                    check_finite=False)

                # reorder the coordinates to the original order

                real_coord = []
                for i in range(col_ct):
                    real_coord.append(
                        reordered_real_coord[self._inverse_cmo[i]][0])

                real_coords.append(real_coord)

            for i, di in enumerate(self.vertex_ids[training_type]):
                offset = [
                    real_coords[0][i], real_coords[1][i], real_coords[2][i]
                ]
                shape_data['shapes'][self.TARGET]['offsets'][di] = offset

        else:
            raise NotImplementedError(
                "The training_type %s is not implemented" % training_type)

        bs.setShapeData(self.blendshape, shape_data, shapes=[self.TARGET])
        mc.setAttr(self.blendshape + '.' + self.TARGET, 1.0)
Пример #3
0
def genMatrix(blendShapeNode,
              deformedGeometry=None,
              resultPos=None,
              resultInd=None,
              targetName=None):
    """
    This procedure is meant to return transform matrices which describe 
    how a 1-unit offset in each X, Y, Z direction actually 
    transforms to an offset at the end of the subsequent deformer stack.
    
    :param str blendShapeNode:  the blendShape node whose offsets are in question
    :param str deformedGeometry: the name of the mesh that's deformed by blendShapeNode
    :param str targetName: the name of the blendShape target
    :param list resultPos:  the default positions of the points in resultCmp
    :param list resultInd:  the indices of the points in resultCmp.  For resultCmp element "<mesh>.vtx[5]", its resultInd element would be 5, for example. 
    """
    removeTarget = False

    if not targetName:
        targetName = 'CORRECTIVE_DUMMY_TARGET'
        removeTarget = True
    # initialize empty shape data
    shapeData = bs.getEmptyShapeData()
    shape = bs.getEmptyShape()
    shapeData['shapes'][targetName] = shape
    shape['offsets'] = {}

    if not mc.objExists('%s.%s' % (blendShapeNode, targetName)):
        shapeIndex = 0
        weightIndices = mc.getAttr(blendShapeNode + ".weight",
                                   multiIndices=True)
        if weightIndices:
            shapeIndex = weightIndices[-1] + 1
        attr = '%s.weight[%i]' % (blendShapeNode, shapeIndex)
        mc.getAttr(attr)
        mc.aliasAttr(targetName, attr)
        mc.setAttr(attr, 1.0)

    # get the x, y and z basis vectors for each point
    perAxisUnitOffsetVectors = [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0),
                                (0.0, 0.0, 1.0)]  # X, Y, Z.
    axes = []

    for ii in range(3):
        for ind in resultInd:
            shape['offsets'][ind] = perAxisUnitOffsetVectors[ii]

        bs.setBlendShapeData(blendShapeNode, shapeData)
        currentAxisOffsetPos = getPositions(deformedGeometry)

        newCurrentAxisOffsetPos = [currentAxisOffsetPos[j] for j in resultInd]
        currentAxes = [
            e[0] - e[1] for e in zip(newCurrentAxisOffsetPos, resultPos)
        ]
        axes.append(currentAxes)

    if removeTarget:
        mc.aliasAttr(blendShapeNode + '.' + targetName, remove=True)
        mc.removeMultiInstance(blendShapeNode + '.weight[' + str(shapeIndex) +
                               ']',
                               b=True)
        mc.removeMultiInstance(blendShapeNode +
                               '.inputTarget[0].inputTargetGroup[' +
                               str(shapeIndex) + '].inputTargetItem[6000]')
        mc.removeMultiInstance(blendShapeNode +
                               '.inputTarget[0].inputTargetGroup[' +
                               str(shapeIndex) + ']')

    xAxes = axes[0]
    yAxes = axes[1]
    zAxes = axes[2]

    nonInvertablePoints = []
    nonInvertablePointsSet = set()

    # use the basis vectors to compute the final position

    # calculate the shapeMatrix first:
    matrices = {}
    for index, xAxis, yAxis, zAxis in itertools.izip(resultInd, xAxes, yAxes,
                                                     zAxes):

        shapeMatrix = numpy.array([[xAxis[0], xAxis[1], xAxis[2], 0],
                                   [yAxis[0], yAxis[1], yAxis[2], 0],
                                   [zAxis[0], zAxis[1], zAxis[2], 0],
                                   [0, 0, 0, 1]])
        matrices[index] = shapeMatrix

    result = {}
    result['matrices'] = matrices

    invShapeMatrices = {}
    # calculate the invShapeMatrix first:
    invShapeMatrices, nonInvertablePointsSet, nonInvertablePoints = invertMatrices(
        matrices)

    result['invShapeMatrices'] = invShapeMatrices
    result['nonInvertablePoints'] = nonInvertablePoints
    result['nonInvertablePointsSet'] = nonInvertablePointsSet
    return result