def rig_propagate_scale(self, mch, index1, index2, factor, use_y=False):
        handles = self.get_all_mch_handles()

        self.make_constraint(
            mch, 'COPY_SCALE', handles[index1], space='LOCAL',
            use_x=True, use_y=use_y, use_z=True,
            use_offset=True, power=clamp(1-factor)
        )
        self.make_constraint(
            mch, 'COPY_SCALE', handles[index2], space='LOCAL',
            use_x=True, use_y=use_y, use_z=True,
            use_offset=True, power=clamp(factor)
        )
Beispiel #2
0
    def get_node_parent_bones(self, node):
        """Get parent bones and their armature weights for the given control node."""
        self.arrange_child_chains()

        # Choose correct layer bones
        layer = self.chain_to_layer[node.rig]

        top_mch = LazyRef(self.bones.mch, 'top_out', layer)
        bottom_mch = LazyRef(self.bones.mch, 'bottom_out', layer)
        middle_mch = LazyRef(self.bones.mch, 'middle_out', layer)

        # Corners have one input
        corner = self.is_corner_node(node)
        if corner:
            if corner == SideZ.TOP:
                return [top_mch]
            elif corner == SideZ.BOTTOM:
                return [bottom_mch]
            else:
                return [middle_mch]

        # Otherwise blend two
        if node.rig in self.chains_by_side[SideZ.TOP]:
            side_mch = top_mch
        else:
            side_mch = bottom_mch

        pt_x = (self.to_mouth_space @ node.point).x
        side = Side.LEFT if pt_x * self.left_sign >= 0 else Side.RIGHT

        corner_x = (self.to_mouth_space @ self.corners[side][layer].point).x
        factor = math.sqrt(1 - clamp(pt_x / corner_x) ** 2)

        return [(side_mch, factor), (middle_mch, 1-factor)]
 def get_pivot_projection(self, pos, index):
     """Compute the interpolation factor within the chain for a control at pos and index."""
     if self.params.skin_chain_falloff_length:
         # Position along the length of the chain
         return self.chain_lengths[index] / self.chain_lengths[-1]
     else:
         # Position projected on the line connecting chain ends
         return clamp((pos - self.pivot_base).dot(self.pivot_vector) / self.pivot_length)
    def rig_propagate_twist(self, mch, index1, index2, factor):
        handles = self.get_all_mch_handles()
        handles_pre = self.get_all_mch_handles_pre()

        variables = {
            'y1':
            driver_var_transform(self.obj,
                                 handles[index1],
                                 type='ROT_Y',
                                 space='LOCAL',
                                 rotation_mode='SWING_TWIST_Y'),
            'y2':
            driver_var_transform(self.obj,
                                 handles[index2],
                                 type='ROT_Y',
                                 space='LOCAL',
                                 rotation_mode='SWING_TWIST_Y'),
        }

        if handles_pre[index1] != handles[index1]:
            variables['p1'] = driver_var_transform(
                self.obj,
                handles_pre[index1],
                type='ROT_Y',
                space='LOCAL',
                rotation_mode='SWING_TWIST_Y')
            expr1 = 'y1-p1'
        else:
            expr1 = 'y1'

        if handles_pre[index2] != handles[index2]:
            variables['p2'] = driver_var_transform(
                self.obj,
                handles_pre[index2],
                type='ROT_Y',
                space='LOCAL',
                rotation_mode='SWING_TWIST_Y')
            expr2 = 'y2-p2'
        else:
            expr2 = 'y2'

        bone = self.get_bone(mch)
        bone.rotation_mode = 'YXZ'

        self.make_driver(bone,
                         'rotation_euler',
                         index=1,
                         expression='lerp({},{},{})'.format(
                             expr1, expr2, clamp(factor)),
                         variables=variables)
    def extend_control_node_parent(self, parent, node):
        if node.rig != self or node.index in (0, self.num_orgs):
            return parent

        parent = ControlBoneParentOffset(self, node, parent)

        # Add offsets from the end controls to other nodes
        factor = self.get_pivot_projection(node.point, node.index)

        if self.use_falloff_curve(Control.START):
            parent.add_copy_local_location(
                LazyRef(self.control_nodes[0], 'reparent_bone'),
                influence=self.apply_falloff_curve(1 - factor, Control.START),
            )

        if self.use_falloff_curve(Control.END):
            parent.add_copy_local_location(
                LazyRef(self.control_nodes[-1], 'reparent_bone'),
                influence=self.apply_falloff_curve(factor, Control.END),
            )

        # Add offset from the middle pivot
        if self.pivot_pos and node.index != self.pivot_pos:
            if self.use_falloff_curve(Control.MIDDLE):
                if node.index < self.pivot_pos:
                    factor = factor / self.middle_pivot_factor
                else:
                    factor = (1 - factor) / (1 - self.middle_pivot_factor)

                parent.add_copy_local_location(
                    LazyRef(self.control_nodes[self.pivot_pos], 'reparent_bone'),
                    influence=self.apply_falloff_curve(clamp(factor), Control.MIDDLE),
                )

        # If Propagate To Controls is set, add an extra wrapper for twist/scale
        if node.index != self.pivot_pos and self.params.skin_chain_falloff_to_controls:
            if self.params.skin_chain_falloff_twist or self.params.skin_chain_falloff_scale:
                parent = ControlBoneChainPropagate(self, node, parent)

        return parent
    def extend_control_node_parent(self, parent, node):
        if node.rig != self or node.index in (0, self.num_orgs):
            return parent

        parent = ControlBoneParentOffset(self, node, parent)
        factor = self.get_pivot_projection(node.point, node.index)

        if self.use_falloff_curve(0):
            parent.add_copy_local_location(
                LazyRef(self.control_nodes[0], 'reparent_bone'),
                influence=self.apply_falloff_start(1 - factor),
            )

        if self.use_falloff_curve(2):
            parent.add_copy_local_location(
                LazyRef(self.control_nodes[-1], 'reparent_bone'),
                influence=self.apply_falloff_end(factor),
            )

        if self.pivot_pos and node.index != self.pivot_pos and self.use_falloff_curve(
                1):
            if node.index < self.pivot_pos:
                factor = factor / self.middle_pivot_factor
            else:
                factor = (1 - factor) / (1 - self.middle_pivot_factor)

            parent.add_copy_local_location(
                LazyRef(self.control_nodes[self.pivot_pos], 'reparent_bone'),
                influence=self.apply_falloff_middle(clamp(factor)),
            )

        if node.index != self.pivot_pos and self.params.skin_chain_falloff_to_controls:
            if self.params.skin_chain_falloff_twist or self.params.skin_chain_falloff_scale:
                parent = ControlBoneChainPropagate(self, node, parent)

        return parent
Beispiel #7
0
 def drawBoltGPU(self, lines, pixels, coord, w, h):
     vertexSource = '''
         in vec3 position;
         void main() 
         {
             gl_Position = vec4(position, 1.0);
         }
         '''
     geometrySource = '''
         layout(lines) in;
         layout(triangle_strip, max_vertices = 4) out;
         void main() 
         {
             float width = gl_in[1].gl_Position.z;
             vec2 line = gl_in[1].gl_Position.xy - gl_in[0].gl_Position.xy;
             vec2 normal = normalize(vec2(line.y, -line.x))*(width/2.0);
             for(int i=0; i<4; i++)
             {
                 vec2 coords = gl_in[i/2].gl_Position.xy+(1-2*(i%2))*normal;
                 gl_Position = vec4(coords, 0.0, 1.0);
                 EmitVertex();
             }
             EndPrimitive();
         }
         '''
     fragmentSource = '''
         out vec4 fragColor;
         void main()
         {
             fragColor = vec4(1.0,1.0,1.0,1.0);
         }
         '''
     positions = []
     for segment in lines.segments:
         pts = lines.getCoords(segment)[0]
         ptA = np.divide(pts[0], np.array([w, h])) * 2 - 1.0
         ptB = np.divide(pts[1], np.array([w, h])) * 2 - 1.0
         width = bl_math.clamp(
             self.thickness *
             (1.0 - (segment.level / (self.falloff * lines.getMaxLevel()))),
             0, self.thickness) / w
         positions.append((ptA[0], ptA[1], width))
         positions.append((ptB[0], ptB[1], width))
     offscreen = gpu.types.GPUOffScreen(w, h)
     shaders = gpu.types.GPUShader(vertexSource,
                                   fragmentSource,
                                   geocode=geometrySource)
     batch = batch_for_shader(shaders, 'LINES',
                              {"position": tuple(positions)})
     with offscreen.bind():
         bgl.glClearColor(0.0, 0.0, 0.0, 1.0)
         bgl.glClear(bgl.GL_COLOR_BUFFER_BIT)
         with gpu.matrix.push_pop():
             gpu.matrix.load_matrix(mathutils.Matrix.Identity(4))
             gpu.matrix.load_projection_matrix(mathutils.Matrix.Identity(4))
             shaders.bind()
             batch.draw(shaders)
         buffer = bgl.Buffer(bgl.GL_FLOAT, w * h * 4)
         bgl.glReadBuffer(bgl.GL_BACK)
         bgl.glReadPixels(0, 0, w, h, bgl.GL_RGBA, bgl.GL_FLOAT, buffer)
     pixels.foreach_set(buffer)
     offscreen.free()
Beispiel #8
0
    def drawBolt(self, lines, pixels, coord, w, h):
        bitmap = [0.0, 0.0, 0.0, 1.0] * (w * h)

        def drawLine(start, end, thickness):
            def scaleRadius(radius, point, start, end, scale):
                if (scale == 1.0):
                    return radius
                maxDistMultiplier = 1.0
                maxDist = math.dist((coord[0], coord[1]),
                                    (coord[2], coord[3])) * maxDistMultiplier
                currentDist = math.dist(point, (coord[0], coord[1]))
                if (currentDist == 0.0):
                    return radius
                return int(
                    round((currentDist / maxDist) * scale * radius + radius))

            def setPixel(x, y):
                if (0 <= x < w) and (0 <= y < h):
                    offset = (x + int(y * w)) * 4
                    for i in range(4):
                        try:
                            bitmap[offset + i] = 1.0
                        except:
                            {}

            def drawPoint(x, y, thickness):
                radius = scaleRadius(thickness, [x, y], start, end,
                                     self.perspectiveScale)
                for X in range(-radius, radius + 1):
                    for Y in range(-radius, radius + 1):
                        if (X * X + Y * Y <= radius * radius):
                            setPixel(X + x, Y + y)

            # Bressenham
            dx = abs(end[0] - start[0])
            dy = abs(end[1] - start[1])
            x, y = start[0], start[1]
            sx = -1 if start[0] > end[0] else 1
            sy = -1 if start[1] > end[1] else 1
            if dx > dy:
                err = dx / 2.0
                while x != end[0] and (0 <= x < w):
                    drawPoint(x, y, thickness)
                    err -= dy
                    if err < 0:
                        y += sy
                        err += dx
                    x += sx
            else:
                err = dy / 2.0
                while y != end[1] and (0 <= y < h):
                    drawPoint(x, y, thickness)

                    err -= dx
                    if err < 0:
                        x += sx
                        err += dy
                    y += sy
            drawPoint(x, y, thickness)

        for segment in lines.segments:
            pts = lines.getCoords(segment)[0]
            width = int(
                bl_math.clamp(
                    self.thickness * (1.0 -
                                      (segment.level /
                                       (self.falloff * lines.getMaxLevel()))),
                    0, self.thickness))
            drawLine((int(pts[0][0]), int(pts[0][1])),
                     (int(pts[1][0]), int(pts[1][1])), width)
        pixels.foreach_set(bitmap)
 def get_pivot_projection(self, pos, index):
     if self.params.skin_chain_falloff_length:
         return self.chain_lengths[index] / self.chain_lengths[-1]
     else:
         return clamp((pos - self.pivot_base).dot(self.pivot_vector) /
                      self.pivot_length)