Example #1
0
class MapOperations(object):
    """ class that contains operations applied to the entire mesh """
    def __init__(self):
        self.mll = MllInterface()
        self.selection_name = []
        self.ngs_layer_id = -1
        self.ngs_influence = None
        self.ngs_weight_list = []
        self.ngs_vert_count = -1
        self.max_value = -1.0
        self.min_value = -1.0

    def get_data(self):
        self.selection_name = cmds.ls(selection=True)
        self.ngs_layer_id = self.mll.getCurrentLayer()
        self.ngs_influence = self.mll.getCurrentPaintTarget()
        self.ngs_weight_list = self.mll.getInfluenceWeights(
            self.ngs_layer_id, self.ngs_influence)
        self.ngs_vert_count = self.mll.getVertCount()
        self.max_value = max(self.ngs_weight_list)
        self.min_value = min(self.ngs_weight_list)

    def grow_map(self, intensity):
        """ pushes the border of the active weight map outwards """
        self.get_data()
        new_weight_list = []
        for i in range(self.ngs_vert_count):
            vertex_weight = self.ngs_weight_list[i]
            if vertex_weight >= self.max_value:
                new_weight_list.append(vertex_weight)
                continue
            vertex_name = '.'.join([self.selection_name[0], 'vtx[%d]' % i])
            area_vertices = get_surrounding_verts(vertex_name)
            weight_list = [self.ngs_weight_list[int(x)] for x in area_vertices]
            max_avg = max(weight_list)
            if max_avg <= self.min_value:
                new_weight_list.append(vertex_weight)
                continue
            grow_weight = vertex_weight + (abs(vertex_weight - max_avg) *
                                           intensity)
            grow_weight = min(grow_weight, self.max_value)
            new_weight_list.append(grow_weight)
        self.mll.setInfluenceWeights(self.ngs_layer_id, self.ngs_influence,
                                     new_weight_list)

    def shrink_map(self, intensity):
        """ pulls the border of the active weight map inwards """
        self.get_data()
        new_weight_list = []
        for i in range(self.ngs_vert_count):
            vertex_weight = self.ngs_weight_list[i]
            if vertex_weight <= self.min_value:
                new_weight_list.append(vertex_weight)
                continue
            vertex_name = '.'.join([self.selection_name[0], 'vtx[%d]' % i])
            area_vertices = get_surrounding_verts(vertex_name)
            weight_list = [self.ngs_weight_list[int(x)] for x in area_vertices]
            min_avg = min(weight_list)
            if min_avg >= self.max_value:
                new_weight_list.append(vertex_weight)
                continue
            shrink_weight = vertex_weight - (abs(vertex_weight - min_avg) *
                                             intensity)
            shrink_weight = max(shrink_weight, self.min_value)
            new_weight_list.append(shrink_weight)
        self.mll.setInfluenceWeights(self.ngs_layer_id, self.ngs_influence,
                                     new_weight_list)

    def conceal_map(self, intensity):
        """ smooth operation for the active map by only lowering values """
        self.get_data()
        new_weight_list = []
        threshold = 0.01 / (intensity / 0.1)
        for i in range(self.ngs_vert_count):
            vertex_weight = self.ngs_weight_list[i]
            if vertex_weight <= self.min_value:
                new_weight_list.append(vertex_weight)
                continue
            vertex_name = '.'.join([self.selection_name[0], 'vtx[%d]' % i])
            area_vertices = get_surrounding_verts(vertex_name)
            weight_list = [self.ngs_weight_list[int(x)] for x in area_vertices]
            weight_avg = sum(weight_list) / float(len(weight_list))
            min_avg = min(weight_list)
            if weight_avg >= self.max_value and abs(weight_avg -
                                                    vertex_weight) < threshold:
                new_weight_list.append(vertex_weight)
                continue
            weight_diff = abs(weight_avg - vertex_weight)
            conceal_weight = vertex_weight * (1 - (weight_diff * intensity))
            conceal_weight = max(conceal_weight, min_avg)
            new_weight_list.append(conceal_weight)
        self.mll.setInfluenceWeights(self.ngs_layer_id, self.ngs_influence,
                                     new_weight_list)

    def spread_map(self, intensity):
        """ smooth operation for the active map by only increasing values """
        self.get_data()
        new_weight_list = []
        threshold = 0.01 / (intensity / 0.1)
        for i in range(self.ngs_vert_count):
            vertex_weight = self.ngs_weight_list[i]
            if vertex_weight >= self.max_value:
                new_weight_list.append(vertex_weight)
                continue
            vertex_name = '.'.join([self.selection_name[0], 'vtx[%d]' % i])
            area_vertices = get_surrounding_verts(vertex_name)
            weight_list = [self.ngs_weight_list[int(x)] for x in area_vertices]
            weight_avg = sum(weight_list) / float(len(weight_list))
            max_avg = max(weight_list)
            if weight_avg <= self.min_value and abs(weight_avg -
                                                    vertex_weight) < threshold:
                new_weight_list.append(vertex_weight)
                continue
            weight_diff = abs(weight_avg - vertex_weight)
            spread_weight = vertex_weight + weight_diff * intensity
            spread_weight = min(spread_weight, max_avg)
            new_weight_list.append(spread_weight)
        self.mll.setInfluenceWeights(self.ngs_layer_id, self.ngs_influence,
                                     new_weight_list)

    def gain_map(self, intensity):
        """ 'reverse scale' tool that only increases weight values above 0 """
        self.get_data()
        new_weight_list = []
        for i in range(self.ngs_vert_count):
            vertex_weight = self.ngs_weight_list[i]
            if vertex_weight == 0:
                new_weight_list.append(vertex_weight)
                continue
            gain_weight = vertex_weight + (vertex_weight * intensity)
            gain_weight = min(gain_weight, 1)
            new_weight_list.append(gain_weight)
        self.mll.setInfluenceWeights(self.ngs_layer_id, self.ngs_influence,
                                     new_weight_list)

    def contrast_map(self, intensity):
        """ sharpens the edge of the active weight map """
        self.get_data()
        new_weight_list = []
        avg_value = (self.max_value + self.min_value) / 2
        normalized_range = self.max_value - self.min_value
        for i in range(self.ngs_vert_count):
            vertex_weight = self.ngs_weight_list[i]
            if not self.max_value > vertex_weight > self.min_value:
                new_weight_list.append(vertex_weight)
                continue
            dist_value = vertex_weight - avg_value
            modifier = norm.cdf(dist_value,
                                loc=0,
                                scale=(0.1 * normalized_range)) - vertex_weight
            contrast_weight = vertex_weight + modifier * intensity
            contrast_weight = max(self.min_value,
                                  min(contrast_weight, self.max_value))
            new_weight_list.append(contrast_weight)
        self.mll.setInfluenceWeights(self.ngs_layer_id, self.ngs_influence,
                                     new_weight_list)
Example #2
0
class UseNgBrush(object):
    """ setup for custom brush operations, a new instance is created on every brush stroke """
    def __init__(self, surface_name):
        self.surface = surface_name
        self.stroke_id = None
        self.mode = 1
        self.value = 1
        self.volumeThreshold = -0.1

        self.mll = MllInterface()
        self.selection_name = cmds.ls(selection=True)
        self.mesh = cmds.listRelatives(self.selection_name[0], shapes=True)
        self.ngs_layer_id = self.mll.getCurrentLayer()
        self.ngs_influence = self.mll.getCurrentPaintTarget()
        self.ngs_weight_list = self.mll.getInfluenceWeights(
            self.ngs_layer_id, self.ngs_influence)
        self.max_value = max(self.ngs_weight_list)
        self.min_value = min(self.ngs_weight_list)

    def stroke_initialize(self):
        """ this function is executed before each brush stroke """
        cmds.undoInfo(openChunk=True, undoName="paint stroke")
        get_stroke_id = ngLayerPaintCtxInitialize(self.mesh[0])
        self.stroke_id = int(get_stroke_id.split(" ")[1])
        cmds.ngSkinLayer(paintOperation=self.mode, paintIntensity=self.value)
        self.stroke_update()
        return self.surface, self.stroke_id

    def stroke_finalize(self):
        """ this function is executed after each brush stroke """
        if self.stroke_id:
            cmds.ngLayerPaintCtxFinalize(self.stroke_id)
        self.stroke_id = None
        cmds.undoInfo(closeChunk=True)

    def stroke_update(self):
        """ updates certain attributes for the brush instance """
        # self.mll = MllInterface()
        # self.selection_name = cmds.ls(selection=True)
        # self.mesh = cmds.listRelatives(self.selection_name[0], shapes=True)
        # self.ngs_layer_id = self.mll.getCurrentLayer()
        # self.ngs_influence = self.mll.getCurrentPaintTarget()
        # self.ngs_weight_list = self.mll.getInfluenceWeights(self.ngs_layer_id, self.ngs_influence)
        # self.max_value = max(self.ngs_weight_list)
        # self.min_value = min(self.ngs_weight_list)
        self.volumeThreshold = cmds.floatSlider("volume_slider",
                                                q=True,
                                                value=True)

    def contrast_paint(self, vert_id, value):
        """ sharpens the edge of the active weight map """
        vertex_weight = self.ngs_weight_list[vert_id]
        if not self.max_value > vertex_weight > self.min_value:
            return
        avg_value = (self.max_value + self.min_value) / 2
        normalized_range = self.max_value - self.min_value
        dist_value = vertex_weight - avg_value
        modifier = norm.cdf(dist_value, loc=0,
                            scale=(0.1 * normalized_range)) - vertex_weight
        contrast_weight = vertex_weight + (modifier * value)
        contrast_weight = max(self.min_value,
                              min(contrast_weight, self.max_value))
        cmds.ngSkinLayer(paintIntensity=contrast_weight)
        cmds.ngLayerPaintCtxSetValue(self.stroke_id, vert_id, 1)

    def conceal_paint(self, vert_id, value):
        """ smooth operation that only lowers weight values """
        vertex_weight = self.ngs_weight_list[vert_id]
        if vertex_weight <= self.min_value:
            return
        vertex_name = '{}.vtx[{}]'.format(self.selection_name[0], vert_id)
        area_vertices = get_surrounding_verts(vertex_name)
        weight_list = [self.ngs_weight_list[int(x)] for x in area_vertices]
        weight_avg = sum(weight_list) / float(len(weight_list))
        min_avg = min(weight_list)
        threshold = 0.01 / (value / 0.1)
        if weight_avg >= self.max_value and abs(weight_avg -
                                                vertex_weight) <= threshold:
            return
        weight_diff = abs(weight_avg - vertex_weight)
        conceal_weight = vertex_weight * (1 - (weight_diff * value))
        conceal_weight = max(conceal_weight, min_avg)
        cmds.ngSkinLayer(paintIntensity=conceal_weight)
        cmds.ngLayerPaintCtxSetValue(self.stroke_id, vert_id, 1)

    def spread_paint(self, vert_id, value):
        """ smooth operation that only increases weight values """
        vertex_weight = self.ngs_weight_list[vert_id]
        if vertex_weight >= self.max_value:
            return
        vertex_name = '.'.join([self.selection_name[0], 'vtx[%d]' % vert_id])
        area_vertices = get_surrounding_verts(vertex_name)
        weight_list = [self.ngs_weight_list[int(x)] for x in area_vertices]
        weight_avg = sum(weight_list) / float(len(weight_list))
        max_avg = max(weight_list)
        threshold = 0.01 / (value / 0.1)
        if weight_avg <= self.min_value and abs(weight_avg -
                                                vertex_weight) <= threshold:
            return
        weight_diff = abs(weight_avg - vertex_weight)
        spread_weight = vertex_weight + (weight_diff * value)
        spread_weight = min(spread_weight, max_avg)
        cmds.ngSkinLayer(paintIntensity=spread_weight)
        cmds.ngLayerPaintCtxSetValue(self.stroke_id, vert_id, 1)

    def gain_paint(self, vert_id, value):
        """ increases existing weight values but preserves empty weights """
        vertex_weight = self.ngs_weight_list[vert_id]
        if vertex_weight == 0:
            return
        gain_weight = vertex_weight + (vertex_weight * value)
        gain_weight = min(gain_weight, 1)
        cmds.ngSkinLayer(paintIntensity=gain_weight)
        cmds.ngLayerPaintCtxSetValue(self.stroke_id, vert_id, 1)

    def volume_equalize(self, vert_id, value):
        """
        i.e a volumetric match operation with a falloff.
        applies weight values inside the brush radius onto other vertices inside a spherical volume
        """
        origin_vertex = '.'.join([self.selection_name[0], 'vtx[%s]']) % vert_id
        vertex_weight = self.ngs_weight_list[vert_id]
        v1 = cmds.pointPosition(origin_vertex)
        for i in range(len(self.ngs_weight_list)):
            target_weight = self.ngs_weight_list[i]
            if target_weight == vertex_weight:
                continue
            if i == vert_id:
                continue
            target_vertex = '.'.join([self.selection_name[0], 'vtx[%s]']) % i
            v2 = cmds.pointPosition(target_vertex)
            target_distance = sqrt((pow((v1[0] - v2[0]), 2)) +
                                   (pow((v1[1] - v2[1]), 2)) +
                                   (pow((v1[2] - v2[2]), 2)))
            if target_distance > (self.volumeThreshold * value):
                continue
            falloff = (self.volumeThreshold -
                       target_distance) / self.volumeThreshold
            eq_weight = target_weight - ((
                (target_weight - vertex_weight) * value) * falloff)
            cmds.ngSkinLayer(paintIntensity=eq_weight)
            cmds.ngLayerPaintCtxSetValue(self.stroke_id, i, 1)
Example #3
0
class Equalize(object):
    def __init__(self):
        self.mll = MllInterface()
        self.ngs_vert_count = -1
        self.ngs_layer_id = -1
        self.intensity = -1
        self.ngs_influence = None
        self.vert_weight_dict = {}
        self.vert_weight_list = []
        self.ngs_weight_dict = {}
        self.ngs_weight_list = []
        self.new_weight_list = []
        self.selection_vert = []
        self.vertex_list = []
        self.id_list = []

        self.modes = {
            "max": self.vert_max,
            "min": self.vert_min,
            "avg": self.vert_avg,
            "first": self.vert_first,
            "last": self.vert_last
        }

    def get_data(self, check):
        self.ngs_weight_dict = {}
        self.vert_weight_dict = {}
        self.selection_vert = cmds.ls(os=True)
        if not self.selection_vert:
            return False
        if not check:
            self.ngs_influence = [("selected influence:",
                                   self.mll.getCurrentPaintTarget())]
        else:
            self.ngs_influence = self.mll.listLayerInfluences(
                layerId=None, activeInfluences=True)
        self.mll = MllInterface()
        self.ngs_layer_id = self.mll.getCurrentLayer()
        self.ngs_vert_count = self.mll.getVertCount()
        self.vertex_list = cmds.ls(self.selection_vert, flatten=True)
        self.id_list = list(
            map(lambda x: x[x.find("[") + 1:x.find("]")], self.vertex_list))
        for influences in self.ngs_influence:
            influence_weights = self.mll.getInfluenceWeights(
                self.ngs_layer_id, influences[1])
            vert_weights = [influence_weights[int(i)] for i in self.id_list]
            self.ngs_weight_dict[influences] = influence_weights
            self.vert_weight_dict[influences] = vert_weights
        return True

    def set_vert(self, mode, intensity):
        self.intensity = intensity
        for influences in self.ngs_influence:
            self.new_weight_list = []
            self.ngs_weight_list = self.ngs_weight_dict[influences]
            self.vert_weight_list = self.vert_weight_dict[influences]
            self.modes[mode]()
            self.mll.setInfluenceWeights(self.ngs_layer_id, influences[1],
                                         self.new_weight_list)

    def vert_max(self):
        for i in range(self.ngs_vert_count):
            vertex_weight = self.ngs_weight_list[i]
            if str(i) not in self.id_list or vertex_weight == max(
                    self.vert_weight_list):
                self.new_weight_list.append(vertex_weight)
                continue
            new_weight = vertex_weight + (
                (max(self.vert_weight_list) - vertex_weight) * self.intensity)
            self.new_weight_list.append(new_weight)

    def vert_min(self):
        for i in range(self.ngs_vert_count):
            vertex_weight = self.ngs_weight_list[i]
            if str(i) not in self.id_list or vertex_weight == min(
                    self.vert_weight_list):
                self.new_weight_list.append(vertex_weight)
                continue
            new_weight = vertex_weight - (
                (vertex_weight - min(self.vert_weight_list)) * self.intensity)
            self.new_weight_list.append(new_weight)

    def vert_avg(self):
        average = sum(self.vert_weight_list) / float(len(
            self.vert_weight_list))
        for i in range(self.ngs_vert_count):
            vertex_weight = self.ngs_weight_list[i]
            if str(i) not in self.id_list or vertex_weight == average:
                self.new_weight_list.append(vertex_weight)
                continue
            new_weight = vertex_weight - (
                (vertex_weight - average) * self.intensity)
            self.new_weight_list.append(new_weight)

    def vert_first(self):
        first = self.vert_weight_list[0]
        for i in range(self.ngs_vert_count):
            vertex_weight = self.ngs_weight_list[i]
            if str(i) not in self.id_list or vertex_weight == first:
                self.new_weight_list.append(vertex_weight)
                continue
            new_weight = vertex_weight - (
                (vertex_weight - first) * self.intensity)
            self.new_weight_list.append(new_weight)

    def vert_last(self):
        last = self.vert_weight_list[-1]
        for i in range(self.ngs_vert_count):
            vertex_weight = self.ngs_weight_list[i]
            if str(i) not in self.id_list or vertex_weight == last:
                self.new_weight_list.append(vertex_weight)
                continue
            new_weight = vertex_weight - (
                (vertex_weight - last) * self.intensity)
            self.new_weight_list.append(new_weight)