Example #1
0
class Eyes:

    def __init__(self, cross_eye=0.0, default_look_distance=200, eye_fov=40):
        self.default_look_target = Vector((0, default_look_distance, 0))
        self.look_target = self.default_look_target
        self.rotation = Quaternion((1, 0, 0, 0))
        self.position = Vector((0, 0, 0))
        self.leye_pos = Vector((-5.96898, 6.09201, 3.69949))
        self.reye_pos = Vector((5.96898, 6.09201, 3.69949))
        self.leye_norm = Vector((cross_eye, 1, 0))
        self.reye_norm = Vector((-cross_eye, 1, 0))
        self.pupil_pos = np.zeros(4)  # lx ly rx ry
        self.eye_fov = eye_fov

    def set_rotation(self, rotation):
        self.rotation = rotation

    def update(self):
        self.update_pupil_pos()
        new_look_target = self.update_look_target()

        if new_look_target:
            print("blonk")
            self.look_target = new_look_target
            self.update()
        else:
            print(self.pupil_pos)

    def update_pupil_pos(self):

        leye_pos = self.leye_pos.copy()
        leye_pos.rotate(self.rotation)
        leye_pos += self.position

        reye_pos = self.reye_pos.copy()
        reye_pos.rotate(self.rotation)
        reye_pos += self.position

        leye_beam = self.look_target.copy() - leye_pos
        reye_beam = self.look_target.copy() - reye_pos

        leye_beam.rotate(self.rotation.inverted())
        leye_beam_angle = self.leye_norm.rotation_difference(leye_beam)

        reye_beam.rotate(self.rotation.inverted())
        reye_beam_angle = self.reye_norm.rotation_difference(reye_beam)

        self.pupil_pos = -1*np.degrees([leye_beam_angle.z, leye_beam_angle.x, reye_beam_angle.z, reye_beam_angle.x])

    def update_look_target(self, forced=False):
        fov = np.full(4, self.eye_fov) / np.array([2, 4, 2, 4])

        if forced or np.any(self.pupil_pos < -1*fov) or np.any(self.pupil_pos > fov):
            new_look_target = self.default_look_target.copy()
            new_look_target.rotate(self.rotation)
            new_look_target += self.position
            return new_look_target
        else:
            return False
Example #2
0
    def compute_translation_rotation_bone_bond(self, old_bone, new_bond):
        # Translation
        v_old_atom_0, v_old_atom_1 = Vector([
            old_bone.head.x, old_bone.head.y, old_bone.head.z
        ]), Vector([old_bone.tail.x, old_bone.tail.y, old_bone.tail.z])
        center_old_bond = (v_old_atom_1 + v_old_atom_0) / 2

        v_new_atom_0, v_new_atom_1 = Vector([
            new_bond.atoms[0].x, new_bond.atoms[0].y, new_bond.atoms[0].z
        ]), Vector(
            [new_bond.atoms[1].x, new_bond.atoms[1].y, new_bond.atoms[1].z])
        center_new_bond = (v_new_atom_1 + v_new_atom_0) / 2

        translation = center_new_bond - center_old_bond

        # Rotation
        old_bond_vec = Vector([
            old_bone.tail.x - old_bone.head.x,
            old_bone.tail.y - old_bone.head.y,
            old_bone.tail.z - old_bone.head.z
        ])
        new_bond_vec = Vector([
            new_bond.atoms[1].x - new_bond.atoms[0].x,
            new_bond.atoms[1].y - new_bond.atoms[0].y,
            new_bond.atoms[1].z - new_bond.atoms[0].z
        ])

        rotation = old_bond_vec.rotation_difference(new_bond_vec).to_euler()
        return translation, rotation
    def invoke(self, context, event):

        scene = context.scene
        active_object = bpy.context.view_layer.objects.active

        if active_object is None or active_object.mode != "SCULPT":
            return {'FINISHED'}

        to_object()
        
        mouse_pos = [event.mouse_region_x, event.mouse_region_y]

        region = context.region
        region3D = context.space_data.region_3d

        # Get intersection and create objects at this location if possible
        view_vector = view3d_utils.region_2d_to_vector_3d(region,   region3D, mouse_pos)
        origin      = view3d_utils.region_2d_to_origin_3d(region,   region3D, mouse_pos)
        loc         = view3d_utils.region_2d_to_location_3d(region, region3D, mouse_pos, view_vector)
        rot         = (0,0,0)  

        hit, loc_hit, norm, face, *_ = scene.ray_cast(context.view_layer, origin, view_vector)
        if hit:
            loc = loc_hit
            z = Vector((0,0,1))
            rot = z.rotation_difference( norm ).to_euler()

        obj_type = context.scene.add_object_type
      
        # TODO: Add more init options here
        if obj_type == "Sphere":
            bpy.ops.mesh.primitive_uv_sphere_add(radius=1, enter_editmode=False, location=loc)
        elif obj_type == "Cube":  
            bpy.ops.mesh.primitive_cube_add(enter_editmode=False, location=loc, rotation=rot)
        elif obj_type == "Cylinder":
            bpy.ops.mesh.primitive_cylinder_add(radius=1, depth=2, enter_editmode=False, location=loc, rotation=rot)
        elif obj_type == "Torus":
            bpy.ops.mesh.primitive_torus_add(align='WORLD', location=loc, rotation=rot, major_radius=1, minor_radius=0.25, abso_major_rad=1.25, abso_minor_rad=0.75)
        
        elif obj_type == "Scene":
            custom_obj = context.scene.add_scene_object
            if custom_obj:

                deselect_all()
                make_active(custom_obj)

                bpy.ops.object.duplicate(linked=True)
                clone_custom = bpy.context.view_layer.objects.active
                bpy.ops.object.make_single_user(object=True, obdata=True)

                clone_custom.location = loc
                clone_custom.rotation_euler = rot

                deselect_all()
                make_active(clone_custom)


        to_sculpt()
 
        return {'FINISHED'}
Example #4
0
    def execute(self, context):
        obj = bpy.context.edit_object
        me = obj.data

        # Get a BMesh representation
        bm = bmesh.from_edit_mesh(me)
        ef = bm.select_history.active

        aim = None
        cent = None
        if isinstance(ef, bmesh.types.BMFace):
            aim = ef.normal
            cent = ef.calc_center_bounds()
        elif isinstance(ef, bmesh.types.BMEdge):
            aim = Vector(ef.verts[1].co) - Vector(ef.verts[0].co)
            cent = .5 * (Vector(ef.verts[1].co) + Vector(ef.verts[0].co))

        diff = aim.rotation_difference(self.p_axis_to_vector()).to_matrix()
        bmesh.ops.rotate(bm,
                         cent=cent,
                         matrix=diff,
                         verts=[v for v in bm.verts if v.select])

        # finalize
        bmesh.update_edit_mesh(me, True)
        return {'FINISHED'}
Example #5
0
def _apply_planer_map(bm, uv_layer, size, offset, rotation, tex_aspect):
    scale = 1.0 / size

    sx = 1.0 * scale
    sy = 1.0 * scale
    ofx = offset[0]
    ofy = offset[1]
    rz = rotation * pi / 180.0
    aspect = tex_aspect

    sel_faces = [f for f in bm.faces if f.select]

    # calculate average of normal
    n_ave = Vector((0.0, 0.0, 0.0))
    for f in sel_faces:
        n_ave = n_ave + f.normal
    q = n_ave.rotation_difference(Vector((0.0, 0.0, 1.0)))

    # update UV coordinate
    for f in sel_faces:
        for l in f.loops:
            co = compat.matmul(q, l.vert.co)
            x = co.x * sx
            y = co.y * sy

            u = x * cos(rz) - y * sin(rz) + ofx
            v = -x * aspect * sin(rz) - y * aspect * cos(rz) + ofy

            l[uv_layer].uv = Vector((u, v))
Example #6
0
def apply_planer_map(bm, uv_layer, size, offset, rotation, tex_aspect):
    scale = 1.0 / size

    sx = 1.0 * scale
    sy = 1.0 * scale
    ofx = offset[0]
    ofy = offset[1]
    rz = rotation * pi / 180.0
    aspect = tex_aspect

    sel_faces = [f for f in bm.faces if f.select]

    # calculate average of normal
    n_ave = Vector((0.0, 0.0, 0.0))
    for f in sel_faces:
        n_ave = n_ave + f.normal
    q = n_ave.rotation_difference(Vector((0.0, 0.0, 1.0)))

    # update UV coordinate
    for f in sel_faces:
        for l in f.loops:
            if common.check_version(2, 80, 0) >= 0:
                # pylint: disable=E0001
                co = q @ l.vert.co
            else:
                co = q * l.vert.co
            x = co.x * sx
            y = co.y * sy

            u = x * cos(rz) - y * sin(rz) + ofx
            v = -x * aspect * sin(rz) - y * aspect * cos(rz) + ofy

            l[uv_layer].uv = Vector((u, v))
Example #7
0
def _apply_planer_map(bm, uv_layer, size, offset, rotation, tex_aspect):
    scale = 1.0 / size

    sx = 1.0 * scale
    sy = 1.0 * scale
    ofx = offset[0]
    ofy = offset[1]
    rz = rotation * pi / 180.0
    aspect = tex_aspect

    sel_faces = [f for f in bm.faces if f.select]

    # calculate average of normal
    n_ave = Vector((0.0, 0.0, 0.0))
    for f in sel_faces:
        n_ave = n_ave + f.normal
    q = n_ave.rotation_difference(Vector((0.0, 0.0, 1.0)))

    # update UV coordinate
    for f in sel_faces:
        for l in f.loops:
            co = compat.matmul(q, l.vert.co)
            x = co.x * sx
            y = co.y * sy

            u = x * cos(rz) - y * sin(rz) + ofx
            v = -x * aspect * sin(rz) - y * aspect * cos(rz) + ofy

            l[uv_layer].uv = Vector((u, v))
Example #8
0
    def vecscorrect(vecs, mats):
        out = []
        lengthve = len(vecs)-1
        for i, m in enumerate(mats):
            out_ = []
            k = i
            if k > lengthve:
                k = lengthve
            vec_c = Vector((0, 0, 0))
            for v in vecs[k]:
                vec = v*m
                out_.append(vec)
                vec_c += vec

            vec_c = vec_c / len(vecs[k])

            v = out_[1]-out_[0]
            w = out_[2]-out_[0]
            A = v.y*w.z - v.z*w.y
            B = -v.x*w.z + v.z*w.x
            C = v.x*w.y - v.y*w.x
            #D = -out_[0].x*A - out_[0].y*B - out_[0].z*C

            norm = Vector((A, B, C)).normalized()
            vec0 = Vector((0, 0, 1))

            mat_rot_norm = vec0.rotation_difference(norm).to_matrix().to_4x4()
            out_pre = []
            for v in out_:
                v_out = (v-vec_c) * mat_rot_norm
                out_pre.append(v_out[:])

            out.append(out_pre)

        return out
def createDimOffsetGiz(group,dim,objIndex):
    #Set Matrix
    k = Vector((0,0,1))
    basisMatrix = Matrix.Translation(Vector((0,0,0)))
    rot = k.rotation_difference(dim.gizRotDir)
    rotMatrix = rot.to_matrix()
    rotMatrix.resize_4x4()
    basisMatrix = basisMatrix @ rotMatrix
    basisMatrix.translation = Vector(dim.gizLoc)+(Vector(dim.gizRotDir)*0.1)
    
    #Offset Gizmo
    dimOffsetGiz = group.gizmos.new("GIZMO_GT_arrow_3d")
    dimOffsetGiz.target_set_prop("offset", dim, "dimOffset")
    dimOffsetGiz.draw_style = "NORMAL"

    dimOffsetGiz.length = 0
    dimOffsetGiz.matrix_basis = basisMatrix

    dimOffsetGiz.scale_basis = 0.8
    dimOffsetGiz.color = (pow(dim.color[0],(1/2.2)),pow(dim.color[1],(1/2.2)),pow(dim.color[2],(1/2.2)))
    dimOffsetGiz.alpha = 0.3

    dimOffsetGiz.color_highlight = (pow(dim.color[0],(1/2.2)),pow(dim.color[1],(1/2.2)),pow(dim.color[2],(1/2.2)))
    dimOffsetGiz.alpha_highlight = 1

    #Button Gizmo
    #dimButton = group.gizmos.new("GIZMO_GT_button_2d")
    #dimButton.icon = 'PREFERENCES'
    #dimButton.scale_basis = 0.2
    #dimButton.matrix_basis = basisMatrix

    # Add Gizmos to group
    group.offset_widget = dimOffsetGiz
Example #10
0
    def draw(self, context):
        selected_archetype = get_selected_archetype(context)
        selected_portal = get_selected_portal(context)
        portal = self.linked_portal
        asset = selected_archetype.asset

        self.color = 0, 0.6, 1

        if selected_portal != portal:
            self.alpha = 0

        if selected_portal == portal:
            self.alpha = 0.3

            if portal and asset:
                corners = [
                    portal.corner1, portal.corner2, portal.corner3,
                    portal.corner4
                ]
                x = [p[0] for p in corners]
                y = [p[1] for p in corners]
                z = [p[2] for p in corners]
                centroid = Vector(
                    (sum(x) / len(corners), sum(y) / len(corners),
                     sum(z) / len(corners)))
                normal = -(corners[2] - corners[0]
                           ).cross(corners[1] - corners[0]).normalized()
                default_axis = Vector((0, 0, 1))
                rot = default_axis.rotation_difference(normal)
                arrow_mat = Matrix.LocRotScale(centroid, rot,
                                               Vector((0.3, 0.3, 0.3)))
                self.draw_preset_arrow(matrix=asset.matrix_world @ arrow_mat)
Example #11
0
    def vecscorrect(vecs, mats):
        out = []
        lengthve = len(vecs) - 1
        for i, m in enumerate(mats):
            out_ = []
            k = i
            if k > lengthve:
                k = lengthve
            vec_c = Vector((0, 0, 0))
            for v in vecs[k]:
                vec = v @ m
                out_.append(vec)
                vec_c += vec

            vec_c = vec_c / len(vecs[k])

            v = out_[1] - out_[0]
            w = out_[2] - out_[0]
            A = v.y * w.z - v.z * w.y
            B = -v.x * w.z + v.z * w.x
            C = v.x * w.y - v.y * w.x
            #D = -out_[0].x*A - out_[0].y*B - out_[0].z*C

            norm = Vector((A, B, C)).normalized()
            vec0 = Vector((0, 0, 1))

            mat_rot_norm = vec0.rotation_difference(norm).to_matrix().to_4x4()
            out_pre = []
            for v in out_:
                v_out = (v - vec_c) @ mat_rot_norm
                out_pre.append(v_out[:])

            out.append(out_pre)

        return out
Example #12
0
def Comp(shape_type, param, name):
    # TODO use param
    global curr_obj
    ob = curr_obj

    if shape_type == "faces":
        # Check that it is indeed a mesh
        if not ob or ob.type != 'MESH':
            print(ob)
            assert (False)
        # If we are in edit mode, return to object mode
        bpy.ops.object.mode_set(mode='OBJECT')
        # Retrieve the mesh data
        mesh = ob.data
        polys = mesh.polygons

        for poly in polys:
            n = poly.normal
            verts = [mesh.vertices[i] for i in poly.vertices]
            # TODO use

            c = poly.center
            Push()
            state["location"] = cpy(c)
            up = Vector((0, 0, 1))
            rdiff = up.rotation_difference(n)
            state["rotation"] = cpy(rdiff)
            Size((state["size"].x, state["size"].y, 0))
            Symbol(name)
            Pop()
    if shape_type == "sideedges":
        if not ob or ob.type != 'MESH':
            print(ob)
            assert (False)
        # If we are in edit mode, return to object mode
        bpy.ops.object.mode_set(mode='OBJECT')
        mesh = ob.data
        edges = mesh.edges

        for edge in edges:
            v1 = Vector(mesh.vertices[edge.vertices[0]].co)
            v2 = Vector(mesh.vertices[edge.vertices[1]].co)

            # Assuming flat
            direction = Vector(v2) - Vector(v1)
            angle = Vector(
                (1, 0)).angle_signed(Vector((direction.x, direction.y)))
            rot = Quaternion((0, 0, 1), -angle)
            #rot = .rotation_difference(direction)
            print("RDIFF: ", rot, rot.angle, rot.axis)
            c = v1 / 2 + v2 / 2

            Push()
            state["location"] = cpy(c)
            state["rotation"] = cpy(rot)
            Size((direction.magnitude, 0, 0))
            Symbol(name)
            Pop()
Example #13
0
    def execute(self, context):
        # FIXME: Undo is inconsistent.
        # FIXME: Would be nicer if rotate could pick some object-local axis.

        from mathutils import Vector

        print_3d = context.scene.print_3d
        face_areas = print_3d.use_alignxy_face_area

        self.context = context
        mode_orig = context.mode
        skip_invalid = []

        for obj in context.selected_objects:
            orig_loc = obj.location.copy()
            orig_scale = obj.scale.copy()

            # When in edit mode, do as the edit mode does.
            if mode_orig == 'EDIT_MESH':
                bm = bmesh.from_edit_mesh(obj.data)
                faces = [f for f in bm.faces if f.select]
            else:
                faces = [p for p in obj.data.polygons if p.select]

            if not faces:
                skip_invalid.append(obj.name)
                continue

            # Rotate object so average normal of selected faces points down.
            normal = Vector((0.0, 0.0, 0.0))
            if face_areas:
                for face in faces:
                    normal += (face.normal * face.calc_area())
            else:
                for face in faces:
                    normal += face.normal
            normal = normal.normalized()
            normal.rotate(obj.matrix_world)  # local -> world.
            offset = normal.rotation_difference(Vector((0.0, 0.0, -1.0)))
            offset = offset.to_matrix().to_4x4()
            obj.matrix_world = offset @ obj.matrix_world
            obj.scale = orig_scale
            obj.location = orig_loc

        if len(skip_invalid) > 0:
            for name in skip_invalid:
                print(
                    f"Align to XY: Skipping object {name}. No faces selected.")
            if len(skip_invalid) == 1:
                self.report(
                    {'WARNING'},
                    f"Skipping object {skip_invalid[0]}. No faces selected.")
            else:
                self.report(
                    {'WARNING'},
                    f"Skipping some objects. No faces selected. See terminal.")
        return {'FINISHED'}
Example #14
0
def create_bond(pt1: Vector, pt2: Vector, atom_size):
    dir = pt2 - pt1
    length = dir.length
    origin = (pt1 + dir / 2).to_tuple()
    up = Vector((0, 0, 1))
    rotation = up.rotation_difference(dir).to_euler()
    bpy.ops.mesh.primitive_cylinder_add(radius=atom_size / 2,
                                        location=origin,
                                        depth=length,
                                        rotation=rotation,
                                        vertices=QUALITY)
    return bpy.context.object
def doodads(object1, mesh1, dmin, dmax):
    """function to generate the doodads"""
    global dVerts
    global dPolygons
    i = 0
    # on parcoure cette boucle pour ajouter des doodads a toutes les polygons
    # english translation: this loops adds doodads to all polygons
    while(i < len(object1.data.polygons)):
        if object1.data.polygons[i].select is False:
            continue

        doods_nbr = random.randint(dmin, dmax)
        j = 0

        while(j <= doods_nbr):
            origin_dood = randVertex(object1.data.polygons[i].vertices[0], object1.data.polygons[i].vertices[1],
                                     object1.data.polygons[i].vertices[2], object1.data.polygons[i].vertices[3], Verts)
            type_dood = random.randint(0, len(bpy.context.scene.discomb.DISC_doodads) - 1)
            polygons_add = []
            verts_add = []

            # First we have to apply scaling and rotation to the mesh
            bpy.ops.object.select_pattern(pattern=bpy.context.scene.discomb.DISC_doodads[type_dood], extend=False)
            bpy.context.scene.objects.active = bpy.data.objects[bpy.context.scene.discomb.DISC_doodads[type_dood]]
            bpy.ops.object.transform_apply(rotation=True, scale=True)

            for polygon in bpy.data.objects[bpy.context.scene.discomb.DISC_doodads[type_dood]].data.polygons:
                polygons_add.append(polygon.vertices)
            for vertex in bpy.data.objects[bpy.context.scene.discomb.DISC_doodads[type_dood]].data.vertices:
                verts_add.append(vertex.co.copy())
            normal_original_polygon = object1.data.polygons[i].normal

            nor_def = Vector((0.0, 0.0, 1.0))
            qr = nor_def.rotation_difference(normal_original_polygon.normalized())

            if(test_v2_near_v1(nor_def, -normal_original_polygon)):
                qr = Quaternion((0.0, 0.0, 0.0, 0.0))

            # qr = angle_between_nor(nor_def, normal_original_polygon)
            for vertex in verts_add:
                vertex.rotate(qr)
                vertex += origin_dood
            findex = len(dVerts)

            for polygon in polygons_add:
                dPolygons.append([polygon[0] + findex, polygon[1] + findex, polygon[2] + findex, polygon[3] + findex])
                i_dood_type.append(bpy.data.objects[bpy.context.scene.discomb.DISC_doodads[type_dood]].name)

            for vertex in verts_add:
                dVerts.append(vertex)
            j += 1
        i += 5
def doodads(object1, mesh1, dmin, dmax):
    """function to generate the doodads"""
    global dVerts
    global dPolygons
    i = 0
    # on parcoure cette boucle pour ajouter des doodads a toutes les polygons
    # english translation: this loops adds doodads to all polygons
    while(i < len(object1.data.polygons)):
        if object1.data.polygons[i].select is False:
            continue

        doods_nbr = random.randint(dmin, dmax)
        j = 0

        while(j <= doods_nbr):
            origin_dood = randVertex(object1.data.polygons[i].vertices[0], object1.data.polygons[i].vertices[1],
                                     object1.data.polygons[i].vertices[2], object1.data.polygons[i].vertices[3], Verts)
            type_dood = random.randint(0, len(self.DISC_doodads) - 1)
            polygons_add = []
            verts_add = []

            # First we have to apply scaling and rotation to the mesh
            bpy.ops.object.select_pattern(pattern=self.DISC_doodads[type_dood], extend=False)
            bpy.context.view_layer.objects.active = bpy.data.objects[self.DISC_doodads[type_dood]]
            bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)

            for polygon in bpy.data.objects[self.DISC_doodads[type_dood]].data.polygons:
                polygons_add.append(polygon.vertices)
            for vertex in bpy.data.objects[self.DISC_doodads[type_dood]].data.vertices:
                verts_add.append(vertex.co.copy())
            normal_original_polygon = object1.data.polygons[i].normal

            nor_def = Vector((0.0, 0.0, 1.0))
            qr = nor_def.rotation_difference(normal_original_polygon.normalized())

            if(test_v2_near_v1(nor_def, -normal_original_polygon)):
                qr = Quaternion((0.0, 0.0, 0.0, 0.0))

            # qr = angle_between_nor(nor_def, normal_original_polygon)
            for vertex in verts_add:
                vertex.rotate(qr)
                vertex += origin_dood
            findex = len(dVerts)

            for polygon in polygons_add:
                dPolygons.append([polygon[0] + findex, polygon[1] + findex, polygon[2] + findex, polygon[3] + findex])
                i_dood_type.append(bpy.data.objects[self.DISC_doodads[type_dood]].name)

            for vertex in verts_add:
                dVerts.append(vertex)
            j += 1
        i += 5
Example #17
0
def Rotation(self, context, vec):
    obj = bpy.context.active_object
    #obj.hide
    axis = Vector((0.0, 0.0, 1.0))
    q = axis.rotation_difference(vec)
    loc, rot, scale = obj.matrix_world.decompose()
    mat_scale = Matrix()

    for i in range(3):
        mat_scale[i][i] = scale[i]

    obj.matrix_world = (Matrix.Translation(loc) * q.to_matrix().to_4x4() *
                        mat_scale)
def createDimOffsetGiz(group, dim, objIndex, idx, dimStr):
    context = bpy.context
    dimProps = dim
    if dim.uses_style:
        for alignedDimStyle in context.scene.StyleGenerator.alignedDimensions:
            if alignedDimStyle.name == dim.style:
                dimProps = alignedDimStyle

    # Set Matrix
    k = Vector((0, 0, 1))
    basisMatrix = Matrix.Translation(Vector((0, 0, 0)))
    rot = k.rotation_difference(dim.gizRotDir)
    rotMatrix = rot.to_matrix()
    rotMatrix.resize_4x4()

    basisMatrix.translation = Vector(
        dim.gizLoc) + (Vector(dim.gizRotDir) * 0.2)
    basisMatrix = basisMatrix @ rotMatrix

    # Offset Gizmo
    dimOffsetGiz = group.gizmos.new("GIZMO_GT_arrow_3d")
    op = dimOffsetGiz.target_set_operator("measureit_arch.dimesnion_offset")
    op.objIndex = objIndex
    op.idx = idx
    op.dimType = dimStr
    dimOffsetGiz.draw_style = "NORMAL"
    dimOffsetGiz.use_draw_modal = False

    dimOffsetGiz.length = 0
    dimOffsetGiz.matrix_basis = basisMatrix
    dimOffsetGiz.use_draw_value = False

    dimOffsetGiz.scale_basis = 1
    dimOffsetGiz.color = (pow(dimProps.color[0],
                              (1 / 2.2)), pow(dimProps.color[1], (1 / 2.2)),
                          pow(dimProps.color[2], (1 / 2.2)))
    dimOffsetGiz.alpha = 0.3

    dimOffsetGiz.color_highlight = (pow(dimProps.color[0], (1 / 2.2)),
                                    pow(dimProps.color[1], (1 / 2.2)),
                                    pow(dimProps.color[2], (1 / 2.2)))
    dimOffsetGiz.alpha_highlight = 1

    # Button Gizmo
    #dimButton = group.gizmos.new("GIZMO_GT_button_2d")
    #dimButton.icon = 'PREFERENCES'
    #dimButton.scale_basis = 0.2
    #dimButton.matrix_basis = basisMatrix

    # Add Gizmos to group
    group.offset_widget = dimOffsetGiz
Example #19
0
    def execute(self, context):
        obj = context.active_object
        bm = bmesh.from_edit_mesh(obj.data)
        if common.check_version(2, 73, 0) >= 0:
            bm.faces.ensure_lookup_table()

        # get UV layer
        if not bm.loops.layers.uv:
            if self.assign_uvmap:
                bm.loops.layers.uv.new()
            else:
                self.report({'WARNING'},
                            "Object must have more than one UV map")
                return {'CANCELLED'}

        uv_layer = bm.loops.layers.uv.verify()

        scale = 1.0 / self.size

        sx = 1.0 * scale
        sy = 1.0 * scale
        ofx = self.offset[0]
        ofy = self.offset[1]
        rz = self.rotation * pi / 180.0
        aspect = self.tex_aspect

        sel_faces = [f for f in bm.faces if f.select]

        # calculate average of normal
        n_ave = Vector((0.0, 0.0, 0.0))
        for f in sel_faces:
            n_ave = n_ave + f.normal
        q = n_ave.rotation_difference(Vector((0.0, 0.0, 1.0)))

        # update UV coordinate
        for f in sel_faces:
            for l in f.loops:
                co = q * l.vert.co
                x = co.x * sx
                y = co.y * sy

                u = x * cos(rz) - y * sin(rz) + ofx
                v = -x * aspect * sin(rz) - y * aspect * cos(rz) + ofy

                l[uv_layer].uv = Vector((u, v))

        bmesh.update_edit_mesh(obj.data)

        return {'FINISHED'}
Example #20
0
    def execute(self, context):
        orientation = get_orientation(context)
        if not orientation:
            return {'CANCELLED'}

        def normalize(vec, index):
            if vec.length == 0.0:
                vec[:] = [0.0] * 3
                vec[index] = 1.0
            else:
                vec.normalize()

        mat = orientation.matrix
        axes = ['XYZ'.index(s) for s in self.axes]
        i, j, k = axes

        vec1 = mat.col[i]
        normalize(vec1, i)

        vec2 = mat.col[j]
        normalize(vec2, j)

        vec3 = mat.col[k]
        normalize(vec3, k)

        if vec1 != vec2:
            if (i + 1) % 3 == j:
                vec3[:] = vec1.cross(vec2).normalized()
                vec2[:] = vec3.cross(vec1).normalized()
            else:
                vec3[:] = vec2.cross(vec1).normalized()
                vec2[:] = vec1.cross(vec3).normalized()
        elif vec1 != vec3:
            if (i + 1) % 3 != k:
                vec2[:] = vec1.cross(vec3).normalized()
                vec3[:] = vec2.cross(vec1).normalized()
            else:
                vec2[:] = vec3.cross(vec1).normalized()
                vec3[:] = vec1.cross(vec2).normalized()
        else:
            v = Vector([0.0] * 3)
            v[i] = 1.0
            q = v.rotation_difference(vec1)
            m = q.to_matrix()
            for c in range(3):
                mat.col[c] = m.col[c]

        return {'FINISHED'}
Example #21
0
def bead_instancing(context, group, bead, hair, position):
    print("instancing beads...")
    #only_render_in_display()

    new_instance = bpy.data.objects.new("Instance", None)
    new_instance.dupli_type = 'GROUP'
    new_instance.dupli_group = group
    new_instance.location = position

    v1 = get_hair_dir(hair)
    v0 = Vector((0, 0, 1))
    rot = v0.rotation_difference(v1).to_euler()
    new_instance.rotation_euler = rot
    scene.objects.link(new_instance)

    print("got through bead instancing function")
Example #22
0
    def execute(self, context):
        obj = context.active_object
        bm = bmesh.from_edit_mesh(obj.data)
        if muv_common.check_version(2, 73, 0) >= 0:
            bm.faces.ensure_lookup_table()

        # get UV layer
        if not bm.loops.layers.uv:
            self.report(
                {'WARNING'}, "Object must have more than one UV map")
            return {'CANCELLED'}

        uv_layer = bm.loops.layers.uv.verify()

        scale = 1.0 / self.size

        sx = 1.0 * scale
        sy = 1.0 * scale
        ofx = self.offset[0]
        ofy = self.offset[1]
        rz = self.rotation * pi / 180.0
        aspect = self.tex_aspect

        sel_faces = [f for f in bm.faces if f.select]

        # calculate average of normal
        n_ave = Vector((0.0, 0.0, 0.0))
        for f in sel_faces:
            n_ave = n_ave + f.normal
        q = n_ave.rotation_difference(Vector((0.0, 0.0, 1.0)))

        # update UV coordinate
        for f in sel_faces:
            for l in f.loops:
                co = q * l.vert.co
                x = co.x * sx
                y = co.y * sy

                u = x * cos(rz) - y * sin(rz) + ofx
                v = -x * aspect * sin(rz) - y * aspect * cos(rz) + ofy

                l[uv_layer].uv = Vector((u, v))

        bmesh.update_edit_mesh(obj.data)

        return {'FINISHED'}
    def invoke(self, context, event):
        if context.object:
            click_placer = context.scene.click_placer
            mouse_pos = [event.mouse_region_x, event.mouse_region_y]

            viewport_region = context.region
            viewport_region_data = context.space_data.region_3d
            viewport_matrix = viewport_region_data.view_matrix.inverted()

            ray_start = viewport_matrix.to_translation()
            ray_depth = viewport_matrix @ Vector((0, 0, -1000))

            ray_end = view3d_utils.region_2d_to_location_3d(
                viewport_region, viewport_region_data, mouse_pos, ray_depth)

            ray_dir = ray_end.normalized()

            despgraph = context.evaluated_depsgraph_get()

            self.cast = context.scene.ray_cast(despgraph,
                                               origin=ray_start,
                                               direction=ray_dir,
                                               distance=1000.0)

            if not self.cast[0]:
                return {'CANCELLED'}

            # linked copy
            bpy.ops.object.duplicate(
                {
                    "object": context.object,
                    "selected_objects": [context.object]
                },
                linked=True)

            self.new_obj = bpy.context.object
            self.new_obj.location = self.cast[1]

            if click_placer.rotate_to_normal:
                axis = Vector(axis_dict[click_placer.up_axis])
                rot = axis.rotation_difference(self.cast[2]).to_euler()
                self.new_obj.rotation_euler = rot

        return {'FINISHED'}
def draw_text(self, context, event):
    wm = context.window_manager
    region = bpy.context.region
    rv3d = bpy.context.space_data.region_3d

    self.circle_color = [0.102758, 0.643065, 1.000000, 1.000000]
    if event.ctrl and not self.f_key:
        self.circle_color = [1.000000, 0.202489, 0.401234, 1.000000]
    elif self.f_key:
        self.circle_color = [1.0, 1.0, 1.0, .7]

    ### draw brush size text

    if self.f_key or event.alt or self.f_key_shift or self.scale_stroke:
        bgl.glColor4f(1.0, 1.0, 1.0, .7)
        text_pos = bpy_extras.view3d_utils.location_3d_to_region_2d(
            region, rv3d, self.projected_mouse)
        if text_pos != None:
            blf.position(0, text_pos[0] - 30, text_pos[1] + 10, 0)
        blf.size(0, 18, 72)

    if self.f_key:

        blf.draw(0, "Size: " + str(round(wm.asset_sketcher.brush_size, 2)))
    elif self.f_key_shift:
        blf.draw(0, "Density: " + str(wm.asset_sketcher.brush_density))
    elif event.alt:
        blf.draw(0, str(self.picked_asset_name))
    if self.scale_stroke:
        vec = Vector((0, 1, 0))  # * self.ground_normal_mat
        angle = vec.rotation_difference(
            self.stroke_direction.normalized()).to_euler()

        #angle = self.stroke_direction.normalized().rotation_difference(Vector((0,1,0))).to_euler()

        text1 = "Scale: " + str(round(self.stroke_length, 2))
        text2 = "Angle: " + str(round(math.degrees(angle[2]), 2))
        blf.draw(0, text1)
        #blf.position(0, text_pos[0]-30, text_pos[1]+10+20, 0)
        #blf.draw(0, text2)

    restore_opengl_defaults()
Example #25
0
def distribute_beads(ps, context, num_beads, bead):
    print("distributing beads...")
    bead.select = True
    #hairs = context.object.particle_systems[scene.particle_system_index].particles
    hairs = context.object.particle_systems[0].particles
    for i in range(0, num_beads):
        random_hair = hairs[random.randrange(len(hairs))]
        random_segment = random_hair.hair_keys[random.randrange(
            len(random_hair.hair_keys) - 1)]
        new_pos = random_segment.co

        new_bead = bead.copy()
        new_bead.data = bead.data.copy()

        new_bead.location = new_pos
        v1 = get_hair_dir(random_hair)
        v0 = Vector((0, 0, 1))
        rot = v0.rotation_difference(v1).to_euler()
        new_bead.rotation_euler = rot
        scene.objects.link(new_bead)
Example #26
0
def add_light(name, type, intensity, color, vector, angle):
    out_color = SRGBToLinear(color)

    if type == "SUN":
        light = bpy.data.lights.get(name)
        if light == None:
            light = bpy.data.lights.new(name=name, type='SUN')
            light.energy = intensity * 0.1
            light.shadow_cascade_max_distance = 12000
            light.color = out_color
            light.angle = angle
    elif type == "SPOT":
        light = bpy.data.lights.get(name)
        if light == None:
            light = bpy.data.lights.new(name=name, type='SPOT')
            light.energy = intensity * 750.0
            light.shadow_buffer_clip_start = 4
            light.color = out_color
            light.spot_size = angle
            light.spot_blend = 1.0
    else:
        light = bpy.data.lights.get(name)
        if light == None:
            light = bpy.data.lights.new(name=name, type='POINT')
            light.energy = intensity * 750.0
            light.shadow_buffer_clip_start = 4
            light.color = out_color
            light.shadow_soft_size = angle

    obj_vec = Vector((0.0, 0.0, 1.0))
    rotation_vec = Vector((vector[0], vector[1], vector[2]))
    obj = bpy.data.objects.get(name)
    if obj == None:
        obj = bpy.data.objects.new(name=name, object_data=light)
        bpy.context.collection.objects.link(obj)
        obj.rotation_euler = obj_vec.rotation_difference(
            rotation_vec).to_euler()

    return obj
Example #27
0
def drawBone2(p1, p2, radiuses, material):
  length = dist(p1,p2)
  print('length :',length)
  v = Vector(diffv(p1, p2))
  up = Vector((0,0,1))
  if v!=-up:
    rot = up.rotation_difference(v)
  else:
    rot = Quaternion((1,0,0),math.pi)
  s1 = drawEllipsoid((0,0,-0.5*length),radiuses,material)
  s2 = drawEllipsoid((0,0,0.5*length),radiuses,material)
  c1 = drawCylinder(zero,radiuses,length,materials.blue)
  s1.select = True
  s2.select = True
  c1.select = True
  #bpy.ops.transform.translate(value=(0,0,length/2))
  #bpy.ops.object.editmode_toggle()
  bpy.ops.transform.rotate(value=rot.angle, axis=rot.axis)
  #bpy.ops.object.editmode_toggle()
  #bpy.ops.transform.translate(value=Vector((0,0,-0.5*length))*rot.to_matrix())
  rot.normalize();
  bpy.ops.transform.translate(value=Vector((0,0,0.5*length))*rot.to_matrix())
  bpy.ops.transform.translate(value=p1)
  return (s1,s2,c1)
Example #28
0
def get_point_rotation(context, scene, curve_obj, index=0, spline_index=0):

    # Get curve attributes
    curve_mat = curve_obj.matrix_world
    curve = curve_obj.data
    points = get_spline_points(curve.splines[spline_index])

    # new temp object to detect local x-axis and y-axis of first handle
    # Temp Bevel Object for temp curve
    temp_bevel_curve = bpy.data.curves.new('__temp_bevel', 'CURVE')
    temp_spline = temp_bevel_curve.splines.new('POLY')
    temp_spline.points.add(2)
    temp_spline.points[0].co = Vector((1.0, 0.0, 0.0, 1.0))
    temp_spline.points[1].co = Vector((0.0, 1.0, 0.0, 1.0))
    temp_bevel_obj = bpy.data.objects.new('__temp_bevel', temp_bevel_curve)
    link_object(scene, temp_bevel_obj)
    # Temp Curve
    curve_copy = curve_obj.data.copy()
    curve_copy.use_fill_caps = False
    curve_copy.bevel_object = temp_bevel_obj
    temp_obj = bpy.data.objects.new('__temp', curve_copy)
    link_object(scene, temp_obj)
    temp_obj.location = curve_obj.location
    temp_obj.rotation_mode = curve_obj.rotation_mode
    temp_obj.rotation_quaternion = curve_obj.rotation_quaternion
    temp_obj.rotation_euler = curve_obj.rotation_euler

    # Convert temp curve to mesh
    bpy.ops.object.select_all(action='DESELECT')  # deselect all first
    set_active_object(temp_obj)
    set_object_select(temp_obj, True)
    bpy.ops.object.convert(target='MESH')

    offset = 0
    micro_offset = 0

    #cyclic check
    for i, spline in enumerate(curve.splines):
        if i > spline_index:
            break
        #ps = get_spline_points(spline)
        if i > 0:
            ps_count = len(get_spline_points(curve.splines[i - 1]))
            offset += ps_count - 1
        if spline.use_cyclic_u:
            offset += 1
        elif i > 0:
            micro_offset += 1

    #offset += spline_index * curve.resolution_u
    #print(offset)

    # get x-axis and y-axis of the first handle
    handle_x = temp_obj.data.vertices[curve.resolution_u *
                                      (index + offset) * 3 +
                                      micro_offset * 3].co
    handle_y = temp_obj.data.vertices[curve.resolution_u *
                                      (index + offset) * 3 + 1 +
                                      micro_offset * 3].co

    target_x = handle_x - points[index].co.xyz
    target_y = handle_y - points[index].co.xyz
    target_x.normalize()
    target_y.normalize()

    # delete temp objects
    set_object_select(temp_bevel_obj, True)
    bpy.ops.object.delete()

    # Match bevel x-axis to handle x-axis
    bevel_x = Vector((1.0, 0.0, 0.0))
    target_x = mul(curve_mat.to_3x3(), target_x)
    rot_1 = bevel_x.rotation_difference(target_x)

    # Match bevel y-axis to handle y-axis
    bevel_y = mul(rot_1.to_matrix(), Vector((0.0, 1.0, 0.0)))
    target_y = mul(curve_mat.to_3x3(), target_y)
    rot_2 = bevel_y.rotation_difference(target_y)

    # Select curve object again
    set_active_object(curve_obj)
    set_object_select(curve_obj, True)

    return mul(rot_2, rot_1)
Example #29
0
    def paintVerts(self,
                   context,
                   start_point,
                   end_point,
                   start_color,
                   end_color,
                   circular_gradient=False,
                   use_hue_blend=False):
        region = context.region
        rv3d = context.region_data

        obj = context.active_object
        mesh = obj.data

        # Create a new bmesh to work with
        bm = bmesh.new()
        bm.from_mesh(mesh)
        bm.verts.ensure_lookup_table()

        # List of structures containing 3d vertex and project 2d position of vertex
        vertex_data = None  # Will contain vert, and vert coordinates in 2d view space
        if mesh.use_paint_mask_vertex:  # Face masking not currently supported
            vertex_data = [(v,
                            view3d_utils.location_3d_to_region_2d(
                                region, rv3d, obj.matrix_world @ v.co))
                           for v in bm.verts if v.select]
        else:
            vertex_data = [(v,
                            view3d_utils.location_3d_to_region_2d(
                                region, rv3d, obj.matrix_world @ v.co))
                           for v in bm.verts]

        # Vertex transformation math
        down_vector = Vector((0, -1, 0))
        direction_vector = Vector(
            (end_point.x - start_point.x, end_point.y - start_point.y,
             0)).normalized()
        rotation = direction_vector.rotation_difference(down_vector)

        translation_matrix = Matrix.Translation(
            Vector((-start_point.x, -start_point.y, 0)))
        inverse_translation_matrix = translation_matrix.inverted()
        rotation_matrix = rotation.to_matrix().to_4x4()
        combinedMat = inverse_translation_matrix @ rotation_matrix @ translation_matrix

        transStart = combinedMat @ start_point.to_4d(
        )  # Transform drawn line : rotate it to align to horizontal line
        transEnd = combinedMat @ end_point.to_4d()
        minY = transStart.y
        maxY = transEnd.y
        heightTrans = maxY - minY  # Get the height of transformed vector

        transVector = transEnd - transStart
        transLen = transVector.length

        # Calculate hue, saturation and value shift for blending
        if use_hue_blend:
            start_color = Color(start_color[:3])
            end_color = Color(end_color[:3])
            c1_hue = start_color.h
            c2_hue = end_color.h
            hue_separation = c2_hue - c1_hue
            if hue_separation > 0.5:
                hue_separation = hue_separation - 1
            elif hue_separation < -0.5:
                hue_separation = hue_separation + 1
            c1_sat = start_color.s
            sat_separation = end_color.s - c1_sat
            c1_val = start_color.v
            val_separation = end_color.v - c1_val

        color_layer = bm.loops.layers.color.active

        for data in vertex_data:
            vertex = data[0]
            vertCo4d = Vector((data[1].x, data[1].y, 0))
            transVec = combinedMat @ vertCo4d

            t = 0

            if circular_gradient:
                curVector = transVec.to_4d() - transStart
                curLen = curVector.length
                t = abs(max(min(curLen / transLen, 1), 0))
            else:
                t = abs(max(min((transVec.y - minY) / heightTrans, 1), 0))

            color = Color((1, 0, 0))
            if use_hue_blend:
                # Hue wraps, and fmod doesn't work with negative values
                color.h = fmod(1.0 + c1_hue + hue_separation * t, 1.0)
                color.s = c1_sat + sat_separation * t
                color.v = c1_val + val_separation * t
            else:
                color.r = start_color[0] + (end_color[0] - start_color[0]) * t
                color.g = start_color[1] + (end_color[1] - start_color[1]) * t
                color.b = start_color[2] + (end_color[2] - start_color[2]) * t

            if mesh.use_paint_mask:  # Masking by face
                face_loops = [
                    loop for loop in vertex.link_loops if loop.face.select
                ]  # Get only loops that belong to selected faces
            else:  # Masking by verts or no masking at all
                face_loops = [loop for loop in vertex.link_loops
                              ]  # Get remaining vert loops

            for loop in face_loops:
                new_color = loop[color_layer]
                new_color[:3] = color
                loop[color_layer] = new_color

        bm.to_mesh(mesh)
        bm.free()
        bpy.ops.object.mode_set(mode='VERTEX_PAINT')
Example #30
0
def main2():
    global all_scale_def,xoffset_def,yoffset_def,zrot_def
    
    obj = bpy.context.active_object
    mesh = obj.data

    is_editmode = (obj.mode == 'EDIT')

    # if in EDIT Mode switch to OBJECT
    if is_editmode:
        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

    # if no UVtex - create it
    if not mesh.uv_textures:
        uvtex = bpy.ops.mesh.uv_texture_add()
    uvtex = mesh.uv_textures.active
    uvtex.active_render = True
    
    img = None    
    aspect = 1.0
    mat = obj.active_material
    try:
        if mat:
            img = mat.active_texture
            aspect = img.image.size[0]/img.image.size[1]
            for f in mesh.faces:  
                if not is_editmode or f.select:
                    uvtex.data[f.index].image = img.image
        else:
            img = None        
    except:
        pass

                
    
    #
    # Main action
    #
    if all_scale_def:
        sc = 1.0/all_scale_def
    else:
        sc = 1.0   

    # Calculate Average Normal
    v = Vector((0,0,0))
    cnt = 0
    for f in mesh.faces:  
        if f.select:
            cnt += 1
            v = v + f.normal
    
    zv = Vector((0,0,1))
    q = v.rotation_difference(zv)
            

    sx = 1 * sc
    sy = 1 * sc
    sz = 1 * sc
    ofx = xoffset_def
    ofy = yoffset_def
    rz = zrot_def / 180 * pi


    for i, uv in enumerate(uvtex.data):
        if mesh.faces[i].select:
            uvs = uv.uv1, uv.uv2, uv.uv3, uv.uv4
            for j, v_idx in enumerate(mesh.faces[i].vertices):
                n = mesh.faces[i].normal
                co = q * mesh.vertices[v_idx].co
                x = co.x * sx
                y = co.y * sy
                z = co.z * sz
                uvs[j][0] =  x * cos(rz) - y * sin(rz) + xoffset_def
                uvs[j][1] =  aspect*(- x * sin(rz) - y * cos(rz)) + yoffset_def



    # Back to EDIT Mode
    if is_editmode:
        bpy.ops.object.mode_set(mode='EDIT', toggle=False)
Example #31
0
class VIEW3D_OT_MeshPaint(Operator):
    bl_idname = "viev3d.mesh_paint"
    bl_label = "Mesh Paint"

    @classmethod
    def poll(cls, context):
        return (context.mode == "OBJECT")

    def invoke(self, context, event):
        if context.area.type == "VIEW_3D":
            # the arguments we pass the the callback
            args = (self, context)
            # Add the region OpenGL drawing callback
            # draw in view space with "POST_VIEW" and "PRE_VIEW"
            self._handle_3d = bpy.types.SpaceView3D.draw_handler_add(
                draw_callback_3d, args, "WINDOW", "POST_VIEW")
            self._handle_2d = bpy.types.SpaceView3D.draw_handler_add(
                draw_callback_2d, args, "WINDOW", "POST_PIXEL")

            self.transform_mode = "MOVE"

            self.mouse_path = [Vector((0, 0, 0)), Vector((0, 0, 1))]
            self.normal = Vector((0, 0, 1))

            self.rot_dir_arrow = Vector((1, 0, 0))
            self.scale_model = 1.0
            self.rotate_angle = 0
            self.rotate_angle_old = 0

            self.model_2d_point = None

            self.LMB_PRESS = False
            # self.draw_mouse_path = [] # 2d path screen space
            self.prev_location = None

            # self.start_distance_scale = 0
            # self.current_distance_scale = 0

            self.current_model = add_model(context, self.mouse_path[0],
                                           self.normal, self.scale_model)

            context.window_manager.modal_handler_add(self)
            return {"RUNNING_MODAL"}
        else:
            self.report({"WARNING"}, "View3D not found, cannot run operator")
            return {"CANCELLED"}

    def get_origin_and_direction(self, event, context):
        region = context.region
        region_3d = context.space_data.region_3d

        mouse_coord = (event.mouse_region_x, event.mouse_region_y)

        origin = region_2d_to_origin_3d(region, region_3d, mouse_coord)
        direction = region_2d_to_vector_3d(region, region_3d, mouse_coord)

        return origin, direction

    def get_2d_point_from_3d(self, event, context):
        region = context.region
        region_3d = context.space_data.region_3d

        result = location_3d_to_region_2d(region, region_3d,
                                          self.current_model.location)

        return result

    def calculate_angle(self, event, context):
        self.model_2d_point = self.get_2d_point_from_3d(event, context)
        self.mouse_coord = Vector((event.mouse_region_x, event.mouse_region_y))

        dir = self.mouse_coord - self.model_2d_point
        dir.normalize()

        self.mouse_coord = self.model_2d_point + dir * 100

        self.rotate_angle = math.degrees(
            math.atan2(self.mouse_coord.y - self.model_2d_point.y,
                       self.mouse_coord.x - self.model_2d_point.x))

        if self.rotate_angle < 0:
            self.rotate_angle += 360

    def change_scale_current_model(self, context, event):
        loc, rot, scale = self.current_model.matrix_world.decompose()

        loc = Matrix.Translation(self.mouse_path[0])
        rot = rot.to_matrix().to_4x4()
        scale = Matrix.Scale(self.scale_model, 4)

        mat_w = loc @ rot @ scale
        self.current_model.matrix_world = mat_w

    def draw_asset(self, context, event):
        if self.LMB_PRESS:
            nexus_model_SCN = context.scene.nexus_model_manager
            # self.draw_mouse_path.append((event.mouse_region_x, event.mouse_region_y)) # 2d path screen space
            distance = 0
            distance_vector = Vector(
                (self.prev_location.x - self.current_model.location.x,
                 self.prev_location.y - self.current_model.location.y,
                 self.prev_location.z - self.current_model.location.z))

            distance = distance_vector.length

            # for point in self.draw_mouse_path:
            # 	if old_point != None:
            # 		distance += math.hypot(old_point[0] - point[0], old_point[1] - point[1])
            # 	# else:
            # 	# 	distance += math.hypot(point[0], point[1])

            # 	old_point = point

            if distance >= nexus_model_SCN.distance_between_asset:
                # self.draw_mouse_path = []
                # self.draw_mouse_path.append((event.mouse_region_x, event.mouse_region_y))
                self.prev_location = self.current_model.location
                distance = 0

                random_scale_and_rotation(self.current_model, self.normal,
                                          nexus_model_SCN, self)

                self.current_model = add_model(context, self.mouse_path[0],
                                               self.normal, self.scale_model)

    def modal(self, context, event):
        context.area.tag_redraw()
        nexus_model_SCN = context.scene.nexus_model_manager
        mod = None
        if event.shift:
            mod = "SHIFT"
        elif event.ctrl:
            mod = "CTRL"

# if event.alt:
#     mod.append("Alt")
# if event.ctrl:
#     mod.append("Ctrl")
        tip_text = "LMB - Add Model | G - Move, R - Rotate, MOUSEWHEEL +ctrl 0.1, +shift 0.01 - Scale | N - Align by normal | RMB / ESC - Cancel"
        context.area.header_text_set(tip_text)

        if event.type == "MOUSEMOVE":
            if self.transform_mode == "MOVE":
                # new origin and normal
                origin, direction = self.get_origin_and_direction(
                    event, context)

                bHit = None
                pos_hit = None
                normal_hit = None
                face_index_hit = None
                obj_hit = None
                matrix_world = None

                # hide mesh
                self.current_model.hide_set(True)

                canvas = nexus_model_SCN.canvas_object
                if canvas == None:
                    # trace
                    bHit, pos_hit, normal_hit, face_index_hit, obj_hit, matrix_world = context.scene.ray_cast(
                        view_layer=context.view_layer,
                        origin=origin,
                        direction=direction)
                else:
                    # trace
                    bHit, pos_hit, normal_hit, face_index_hit = canvas.ray_cast(
                        origin=origin, direction=direction)

                # show mesh
                self.current_model.hide_set(False)

                if bHit:
                    self.normal = normal_hit.normalized()
                    self.mouse_path[0] = pos_hit
                    self.mouse_path[1] = pos_hit + (self.normal * 2.0)

                    loc, rot, scale = self.current_model.matrix_world.decompose(
                    )

                    loc = Matrix.Translation(self.mouse_path[0])

                    rot_add = Euler(
                        Vector((0, 0, math.radians(self.rotate_angle))))
                    rot_add = rot_add.to_matrix().to_4x4()

                    scale = Matrix.Scale(self.scale_model, 4)

                    # apply rotation by normal if checked "align_by_normal"
                    if nexus_model_SCN.align_by_normal:
                        # rot = self.normal.to_track_quat("Z","Y").to_euler()
                        rot = self.normal.rotation_difference(Vector(
                            (0, 0, 1)))
                        rot.invert()
                        rot = rot.to_euler().to_matrix().to_4x4()
                    else:
                        rot = Euler((0, 0, 0)).to_matrix().to_4x4()

                    rot = rot @ rot_add
                    mat_w = loc @ rot @ scale

                    self.current_model.matrix_world = mat_w

                    # draw assets
                    self.draw_asset(context, event)

            elif self.transform_mode == "ROTATE":
                self.calculate_angle(event, context)

                delta_angle = self.rotate_angle - self.rotate_angle_old
                self.current_model.rotation_euler.rotate_axis(
                    "Z", math.radians(delta_angle))
                self.rotate_angle_old = self.rotate_angle

            # elif self.transform_mode == "SCALE":
            # self.model_2d_point = self.get_2d_point_from_3d(event, context)
            # x = self.model_2d_point.x - event.mouse_region_x
            # y = self.model_2d_point.y - event.mouse_region_y
            # self.current_distance_scale = math.hypot(x, y)
            # delta_scale = self.current_distance_scale - self.start_distance_scale
            # self.scale_model = self.scale_model + delta_scale * 0.1
            # self.current_model.scale = Vector((self.scale_model, self.scale_model, self.scale_model))

        if event.type == "WHEELUPMOUSE":
            if mod == "CTRL":
                self.scale_model += 0.1
            elif mod == "SHIFT":
                self.scale_model += 0.01
            self.change_scale_current_model(context, event)
        elif event.type == "WHEELDOWNMOUSE":
            if mod == "CTRL":
                self.scale_model -= 0.1
            elif mod == "SHIFT":
                self.scale_model -= 0.01
            self.change_scale_current_model(context, event)

        if event.value == "PRESS":
            if event.type == "LEFTMOUSE":
                self.transform_mode = "MOVE"
                self.LMB_PRESS = True
                # self.draw_mouse_path.append((event.mouse_region_x, event.mouse_region_y)) # 2d path screen space
                random_scale_and_rotation(self.current_model, self.normal,
                                          nexus_model_SCN, self)
                self.prev_location = self.current_model.location  # 3d path world path
                self.current_model = add_model(context, self.mouse_path[0],
                                               self.normal, self.scale_model)
                return {"RUNNING_MODAL"}
            elif event.type == "R":
                self.transform_mode = "ROTATE"
                return {"RUNNING_MODAL"}
            elif event.type == "G":
                self.transform_mode = "MOVE"
                return {"RUNNING_MODAL"}
            # elif event.type == "S":
            # 	self.transform_mode = "SCALE"
            # 	self.model_2d_point = self.get_2d_point_from_3d(event, context)
            # 	x = self.model_2d_point.x - event.mouse_region_x
            # 	y = self.model_2d_point.y - event.mouse_region_y
            # 	self.start_distance_scale = math.hypot(x, y)
            # 	return {"RUNNING_MODAL"}
            elif event.type == "N":
                nexus_model_SCN.align_by_normal = not nexus_model_SCN.align_by_normal
                return {"RUNNING_MODAL"}
            elif event.type in {"RIGHTMOUSE", "ESC"}:

                bpy.ops.object.select_all(action="DESELECT")
                self.current_model.select_set(True)
                bpy.ops.object.delete()

                bpy.types.SpaceView3D.draw_handler_remove(
                    self._handle_3d, "WINDOW")
                bpy.types.SpaceView3D.draw_handler_remove(
                    self._handle_2d, "WINDOW")
                context.area.header_text_set(
                    text=None)  # return header text to default
                return {"CANCELLED"}

        if event.value == "RELEASE":
            if event.type == "LEFTMOUSE":
                self.LMB_PRESS = False
                # self.draw_mouse_path = [] # 2d path screen space

        return {"RUNNING_MODAL"}
Example #32
0
    def process(self):
        verts_socket, poly_socket = self.inputs
        norm_socket, norm_abs_socket, origins_socket, centers_socket = self.outputs

        if not any([s.is_linked for s in self.outputs]):
            return

        if not (verts_socket.is_linked and poly_socket.is_linked):
            return

        pols_ = poly_socket.sv_get()
        vers_tupls = verts_socket.sv_get()
        vers_vects = Vector_generate(vers_tupls)
        
        # make mesh temp утилитарно - удалить в конце
        mat_collect = []
        normals_out = []
        origins = []
        norm_abs_out = []
        for verst, versv, pols in zip(vers_tupls, vers_vects, pols_):
            # medians в векторах
            medians = []
            normals = []
            centrs = []
            norm_abs = []
            for p in pols:
                # medians
                # it calcs middle point of opposite edges, 
                # than finds length vector between this two points
                v0 = versv[p[0]]
                v1 = versv[p[1]]
                v2 = versv[p[2]]
                lp=len(p)
                if lp >= 4:
                    l = ((lp-2)//2) + 2
                    v3 = versv[p[l]]
                    poi_2 = (v2+v3)/2
                    # normals
                    norm = geometry.normal(v0, v1, v2, v3)
                    normals.append(norm)
                else:
                    poi_2 = v2
                    # normals
                    norm = geometry.normal(v0, v1, v2)
                    normals.append(norm)
                poi_1 = (v0+v1)/2
                vm = poi_2 - poi_1
                medians.append(vm)
                # centrs
                x,y,z = zip(*[verst[poi] for poi in p])
                x,y,z = sum(x)/len(x), sum(y)/len(y), sum(z)/len(z)
                current_center = Vector((x,y,z))
                centrs.append(current_center)
                # normal absolute !!!
                # это совершенно нормально!!! ;-)
                norm_abs.append(current_center+norm)
                
            if self.Separate:
                norm_abs_out.append(norm_abs)    
                origins.append(centrs)
                normals_out.append(normals)
            else:
                norm_abs_out.extend(norm_abs)    
                origins.extend(centrs)
                normals_out.extend(normals)
            mat_collect_ = []
            for cen, med, nor in zip(centrs, medians, normals):
                loc = Matrix.Translation(cen)
                # need better solution for Z,Y vectors + may be X vector correction
                vecz = Vector((0, 1e-6, 1))
                q_rot0 = vecz.rotation_difference(nor).to_matrix().to_4x4()
                q_rot2 = nor.rotation_difference(vecz).to_matrix().to_4x4()
                if med[1]>med[0]:
                    vecy = Vector((1e-6, 1, 0)) * q_rot2
                else:
                    vecy = Vector((1, 1e-6, 0)) * q_rot2
                q_rot1 = vecy.rotation_difference(med).to_matrix().to_4x4()
                # loc is matrix * rot vector * rot vector
                M = loc*q_rot1*q_rot0
                lM = [ j[:] for j in M ]
                mat_collect_.append(lM)
            mat_collect.extend(mat_collect_)

        
        if not self.Separate:
            norm_abs_out = [norm_abs_out]
            origins = [origins]
            normals_out = [normals_out]

        centers_socket.sv_set(mat_collect)
        norm_abs_socket.sv_set(Vector_degenerate(norm_abs_out))
        origins_socket.sv_set(Vector_degenerate(origins))
        norm_socket.sv_set(Vector_degenerate(normals_out))
Example #33
0
def best_planar_map():
    global all_scale_def,xoffset_def,yoffset_def,zrot_def, tex_aspect
    
    obj = bpy.context.active_object
    mesh = obj.data

    is_editmode = (obj.mode == 'EDIT')

    # if in EDIT Mode switch to OBJECT
    if is_editmode:
        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

    # if no UVtex - create it
    if not mesh.uv_textures:
        uvtex = bpy.ops.mesh.uv_texture_add()
    uvtex = mesh.uv_textures.active
    #uvtex.active_render = True
    
    img = None    
    aspect = 1.0
    mat = obj.active_material
    try:
        if mat:
            img = mat.active_texture
            aspect = img.image.size[0]/img.image.size[1]
    except:
        pass
    aspect = aspect * tex_aspect
                
    
    #
    # Main action
    #
    if all_scale_def:
        sc = 1.0/all_scale_def
    else:
        sc = 1.0   

    # Calculate Average Normal
    v = Vector((0,0,0))
    cnt = 0
    for f in mesh.polygons:  
        if f.select:
            cnt += 1
            v = v + f.normal
    
    zv = Vector((0,0,1))
    q = v.rotation_difference(zv)
            

    sx = 1 * sc
    sy = 1 * sc
    sz = 1 * sc
    ofx = xoffset_def
    ofy = yoffset_def
    rz = zrot_def / 180 * pi

    cosrz = cos(rz)
    sinrz = sin(rz)

    #uvs = mesh.uv_loop_layers[mesh.uv_loop_layers.active_index].data
    uvs = mesh.uv_layers.active.data
    for i, pol in enumerate(mesh.polygons):
        if not is_editmode or mesh.polygons[i].select:
            for j, loop in enumerate(mesh.polygons[i].loop_indices):
                v_idx = mesh.loops[loop].vertex_index

                n = pol.normal
                co = q * mesh.vertices[v_idx].co
                x = co.x * sx
                y = co.y * sy
                z = co.z * sz
                uvs[loop].uv[0] =  x * cosrz - y * sinrz + xoffset_def
                uvs[loop].uv[1] =  aspect*(- x * sinrz - y * cosrz) + yoffset_def



    # Back to EDIT Mode
    if is_editmode:
        bpy.ops.object.mode_set(mode='EDIT', toggle=False)
def extract_primitives(glTF, blender_mesh, library, blender_object,
                       blender_vertex_groups, modifiers, export_settings):
    """
    Extract primitives from a mesh. Polygons are triangulated and sorted by material.
    Vertices in multiple faces get split up as necessary.
    """
    print_console('INFO', 'Extracting primitive: ' + blender_mesh.name)

    #
    # First, decide what attributes to gather (eg. how many COLOR_n, etc.)
    # Also calculate normals/tangents now if necessary.
    #

    use_normals = export_settings[gltf2_blender_export_keys.NORMALS]
    if use_normals:
        blender_mesh.calc_normals_split()

    use_tangents = False
    if use_normals and export_settings[gltf2_blender_export_keys.TANGENTS]:
        if blender_mesh.uv_layers.active and len(blender_mesh.uv_layers) > 0:
            try:
                blender_mesh.calc_tangents()
                use_tangents = True
            except Exception:
                print_console(
                    'WARNING',
                    'Could not calculate tangents. Please try to triangulate the mesh first.'
                )

    tex_coord_max = 0
    if export_settings[gltf2_blender_export_keys.TEX_COORDS]:
        if blender_mesh.uv_layers.active:
            tex_coord_max = len(blender_mesh.uv_layers)

    color_max = 0
    if export_settings[gltf2_blender_export_keys.COLORS]:
        color_max = len(blender_mesh.vertex_colors)

    bone_max = 0  # number of JOINTS_n sets needed (1 set = 4 influences)
    armature = None
    if blender_vertex_groups and export_settings[
            gltf2_blender_export_keys.SKINS]:
        if modifiers is not None:
            modifiers_dict = {m.type: m for m in modifiers}
            if "ARMATURE" in modifiers_dict:
                modifier = modifiers_dict["ARMATURE"]
                armature = modifier.object

        # Skin must be ignored if the object is parented to a bone of the armature
        # (This creates an infinite recursive error)
        # So ignoring skin in that case
        is_child_of_arma = (armature and blender_object
                            and blender_object.parent_type == "BONE"
                            and blender_object.parent.name == armature.name)
        if is_child_of_arma:
            armature = None

        if armature:
            skin = gltf2_blender_gather_skins.gather_skin(
                armature, export_settings)
            if not skin:
                armature = None
            else:
                joint_name_to_index = {
                    joint.name: index
                    for index, joint in enumerate(skin.joints)
                }
                group_to_joint = [
                    joint_name_to_index.get(g.name)
                    for g in blender_vertex_groups
                ]

                # Find out max number of bone influences
                for blender_polygon in blender_mesh.polygons:
                    for loop_index in blender_polygon.loop_indices:
                        vertex_index = blender_mesh.loops[
                            loop_index].vertex_index
                        groups_count = len(
                            blender_mesh.vertices[vertex_index].groups)
                        bones_count = (groups_count + 3) // 4
                        bone_max = max(bone_max, bones_count)

    use_morph_normals = use_normals and export_settings[
        gltf2_blender_export_keys.MORPH_NORMAL]
    use_morph_tangents = use_morph_normals and use_tangents and export_settings[
        gltf2_blender_export_keys.MORPH_TANGENT]

    shape_keys = []
    if blender_mesh.shape_keys and export_settings[
            gltf2_blender_export_keys.MORPH]:
        for blender_shape_key in blender_mesh.shape_keys.key_blocks:
            if blender_shape_key == blender_shape_key.relative_key or blender_shape_key.mute:
                continue

            split_normals = None
            if use_morph_normals:
                split_normals = blender_shape_key.normals_split_get()

            shape_keys.append(ShapeKey(
                blender_shape_key,
                split_normals,
            ))

    use_materials = export_settings[gltf2_blender_export_keys.MATERIALS]

    #
    # Gather the verts and indices for each primitive.
    #

    prims = {}

    blender_mesh.calc_loop_triangles()

    for loop_tri in blender_mesh.loop_triangles:
        blender_polygon = blender_mesh.polygons[loop_tri.polygon_index]

        material_idx = -1
        if use_materials:
            material_idx = blender_polygon.material_index

        prim = prims.get(material_idx)
        if not prim:
            prim = Prim()
            prims[material_idx] = prim

        for loop_index in loop_tri.loops:
            vertex_index = blender_mesh.loops[loop_index].vertex_index
            vertex = blender_mesh.vertices[vertex_index]

            # vert will be a tuple of all the vertex attributes.
            # Used as cache key in prim.verts.
            vert = (vertex_index, )

            v = vertex.co
            vert += ((v[0], v[1], v[2]), )

            if use_normals:
                n = blender_mesh.loops[loop_index].normal
                vert += ((n[0], n[1], n[2]), )
                if use_tangents:
                    t = blender_mesh.loops[loop_index].tangent
                    b = blender_mesh.loops[loop_index].bitangent
                    vert += ((t[0], t[1], t[2]), )
                    vert += ((b[0], b[1], b[2]), )
                    # TODO: store just bitangent_sign in vert, not whole bitangent?

            for tex_coord_index in range(0, tex_coord_max):
                uv = blender_mesh.uv_layers[tex_coord_index].data[
                    loop_index].uv
                uv = (uv.x, 1.0 - uv.y)
                vert += (uv, )

            for color_index in range(0, color_max):
                color = blender_mesh.vertex_colors[color_index].data[
                    loop_index].color
                col = (
                    color_srgb_to_scene_linear(color[0]),
                    color_srgb_to_scene_linear(color[1]),
                    color_srgb_to_scene_linear(color[2]),
                    color[3],
                )
                vert += (col, )

            if bone_max:
                bones = []
                if vertex.groups:
                    for group_element in vertex.groups:
                        weight = group_element.weight
                        if weight <= 0.0:
                            continue
                        try:
                            joint = group_to_joint[group_element.group]
                        except Exception:
                            continue
                        if joint is None:
                            continue
                        bones.append((joint, weight))
                bones.sort(key=lambda x: x[1], reverse=True)
                bones = tuple(bones)
                vert += (bones, )

            for shape_key in shape_keys:
                v_morph = shape_key.shape_key.data[vertex_index].co
                v_morph = v_morph - v  # store delta
                vert += ((v_morph[0], v_morph[1], v_morph[2]), )

                if use_morph_normals:
                    normals = shape_key.split_normals
                    n_morph = Vector(normals[loop_index * 3:loop_index * 3 +
                                             3])
                    n_morph = n_morph - n  # store delta
                    vert += ((n_morph[0], n_morph[1], n_morph[2]), )

            vert_idx = prim.verts.setdefault(vert, len(prim.verts))
            prim.indices.append(vert_idx)

    #
    # Put the verts into attribute arrays.
    #

    result_primitives = []

    for material_idx, prim in prims.items():
        if not prim.indices:
            continue

        vs = []
        ns = []
        ts = []
        uvs = [[] for _ in range(tex_coord_max)]
        cols = [[] for _ in range(color_max)]
        joints = [[] for _ in range(bone_max)]
        weights = [[] for _ in range(bone_max)]
        vs_morph = [[] for _ in shape_keys]
        ns_morph = [[] for _ in shape_keys]
        ts_morph = [[] for _ in shape_keys]

        for vert in prim.verts.keys():
            i = 0

            i += 1  # skip over Blender mesh index

            v = vert[i]
            i += 1
            v = convert_swizzle_location(v, armature, blender_object,
                                         export_settings)
            vs.extend(v)

            if use_normals:
                n = vert[i]
                i += 1
                n = convert_swizzle_normal(n, armature, blender_object,
                                           export_settings)
                ns.extend(n)

                if use_tangents:
                    t = vert[i]
                    i += 1
                    t = convert_swizzle_tangent(t, armature, blender_object,
                                                export_settings)
                    ts.extend(t)

                    b = vert[i]
                    i += 1
                    b = convert_swizzle_tangent(b, armature, blender_object,
                                                export_settings)
                    b_sign = -1.0 if (Vector(n).cross(Vector(t))).dot(
                        Vector(b)) < 0.0 else 1.0
                    ts.append(b_sign)

            for tex_coord_index in range(0, tex_coord_max):
                uv = vert[i]
                i += 1
                uvs[tex_coord_index].extend(uv)

            for color_index in range(0, color_max):
                col = vert[i]
                i += 1
                cols[color_index].extend(col)

            if bone_max:
                bones = vert[i]
                i += 1
                for j in range(0, 4 * bone_max):
                    if j < len(bones):
                        joint, weight = bones[j]
                    else:
                        joint, weight = 0, 0.0
                    joints[j // 4].append(joint)
                    weights[j // 4].append(weight)

            for shape_key_index in range(0, len(shape_keys)):
                v_morph = vert[i]
                i += 1
                v_morph = convert_swizzle_location(v_morph, armature,
                                                   blender_object,
                                                   export_settings)
                vs_morph[shape_key_index].extend(v_morph)

                if use_morph_normals:
                    n_morph = vert[i]
                    i += 1
                    n_morph = convert_swizzle_normal(n_morph, armature,
                                                     blender_object,
                                                     export_settings)
                    ns_morph[shape_key_index].extend(n_morph)

                if use_morph_tangents:
                    rotation = n_morph.rotation_difference(n)
                    t_morph = Vector(t)
                    t_morph.rotate(rotation)
                    ts_morph[shape_key_index].extend(t_morph)

        attributes = {}
        attributes['POSITION'] = vs
        if ns: attributes['NORMAL'] = ns
        if ts: attributes['TANGENT'] = ts
        for i, uv in enumerate(uvs):
            attributes['TEXCOORD_%d' % i] = uv
        for i, col in enumerate(cols):
            attributes['COLOR_%d' % i] = col
        for i, js in enumerate(joints):
            attributes['JOINTS_%d' % i] = js
        for i, ws in enumerate(weights):
            attributes['WEIGHTS_%d' % i] = ws
        for i, vm in enumerate(vs_morph):
            attributes['MORPH_POSITION_%d' % i] = vm
        for i, nm in enumerate(ns_morph):
            attributes['MORPH_NORMAL_%d' % i] = nm
        for i, tm in enumerate(ts_morph):
            attributes['MORPH_TANGENT_%d' % i] = tm

        result_primitives.append({
            'attributes': attributes,
            'indices': prim.indices,
            'material': material_idx,
        })

    print_console('INFO', 'Primitives created: %d' % len(result_primitives))

    return result_primitives
def best_planar_map():
    global all_scale_def, xoffset_def, yoffset_def, zrot_def, tex_aspect

    obj = bpy.context.active_object
    mesh = obj.data

    is_editmode = (obj.mode == 'EDIT')

    # if in EDIT Mode switch to OBJECT
    if is_editmode:
        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

    # if no UVtex - create it
    if not mesh.uv_layers:
        uvtex = bpy.ops.mesh.uv_texture_add()
    uvtex = mesh.uv_layers.active
    #uvtex.active_render = True

    img = None
    aspect = 1.0
    mat = obj.active_material
    try:
        if mat:
            img = mat.active_texture
            aspect = img.image.size[0] / img.image.size[1]
    except:
        pass
    aspect = aspect * tex_aspect

    #
    # Main action
    #
    if all_scale_def:
        sc = 1.0 / all_scale_def
    else:
        sc = 1.0

    # Calculate Average Normal
    v = Vector((0, 0, 0))
    cnt = 0
    for f in mesh.polygons:
        if f.select:
            cnt += 1
            v = v + f.normal

    zv = Vector((0, 0, 1))
    q = v.rotation_difference(zv)

    sx = 1 * sc
    sy = 1 * sc
    sz = 1 * sc
    ofx = xoffset_def
    ofy = yoffset_def
    rz = zrot_def / 180 * pi

    cosrz = cos(rz)
    sinrz = sin(rz)

    #uvs = mesh.uv_loop_layers[mesh.uv_loop_layers.active_index].data
    uvs = mesh.uv_layers.active.data
    for i, pol in enumerate(mesh.polygons):
        if not is_editmode or mesh.polygons[i].select:
            for j, loop in enumerate(mesh.polygons[i].loop_indices):
                v_idx = mesh.loops[loop].vertex_index

                n = pol.normal
                co = q @ (mesh.vertices[v_idx].co)

                x = co.x * sx
                y = co.y * sy
                z = co.z * sz
                uvs[loop].uv[0] = x * cosrz - y * sinrz + xoffset_def
                uvs[loop].uv[1] = aspect * (-x * sinrz -
                                            y * cosrz) + yoffset_def

    # Back to EDIT Mode
    if is_editmode:
        bpy.ops.object.mode_set(mode='EDIT', toggle=False)
Example #36
0
    def process(self):
        verts_socket, poly_socket = self.inputs
        norm_socket, norm_abs_socket, origins_socket, centers_socket = self.outputs

        if not any([s.is_linked for s in self.outputs]):
            return

        if not (verts_socket.is_linked and poly_socket.is_linked):
            return

        pols_ = poly_socket.sv_get()
        vers_tupls = verts_socket.sv_get()
        vers_vects = Vector_generate(vers_tupls)

        # make mesh temp утилитарно - удалить в конце
        mat_collect = []
        normals_out = []
        origins = []
        norm_abs_out = []
        for verst, versv, pols in zip(vers_tupls, vers_vects, pols_):
            # medians в векторах
            medians = []
            normals = []
            centrs = []
            norm_abs = []
            for p in pols:
                # medians
                # it calcs middle point of opposite edges,
                # than finds length vector between this two points
                v0 = versv[p[0]]
                v1 = versv[p[1]]
                v2 = versv[p[2]]
                lp = len(p)
                if lp >= 4:
                    l = ((lp - 2) // 2) + 2
                    v3 = versv[p[l]]
                    poi_2 = (v2 + v3) / 2
                    # normals
                    norm = geometry.normal(v0, v1, v2, v3)
                    normals.append(norm)
                else:
                    poi_2 = v2
                    # normals
                    norm = geometry.normal(v0, v1, v2)
                    normals.append(norm)
                poi_1 = (v0 + v1) / 2
                vm = poi_2 - poi_1
                medians.append(vm)
                # centrs
                x, y, z = zip(*[verst[poi] for poi in p])
                x, y, z = sum(x) / len(x), sum(y) / len(y), sum(z) / len(z)
                current_center = Vector((x, y, z))
                centrs.append(current_center)
                # normal absolute !!!
                # это совершенно нормально!!! ;-)
                norm_abs.append(current_center + norm)

            if self.Separate:
                norm_abs_out.append(norm_abs)
                origins.append(centrs)
                normals_out.append(normals)
            else:
                norm_abs_out.extend(norm_abs)
                origins.extend(centrs)
                normals_out.extend(normals)
            mat_collect_ = []
            for cen, med, nor in zip(centrs, medians, normals):
                loc = Matrix.Translation(cen)
                # need better solution for Z,Y vectors + may be X vector correction
                vecz = Vector((0, 1e-6, 1))
                q_rot0 = vecz.rotation_difference(nor).to_matrix().to_4x4()
                q_rot2 = nor.rotation_difference(vecz).to_matrix().to_4x4()
                if med[1] > med[0]:
                    vecy = Vector((1e-6, 1, 0)) * q_rot2
                else:
                    vecy = Vector((1, 1e-6, 0)) * q_rot2
                q_rot1 = vecy.rotation_difference(med).to_matrix().to_4x4()
                # loc is matrix * rot vector * rot vector
                M = loc * q_rot1 * q_rot0
                lM = [j[:] for j in M]
                mat_collect_.append(lM)
            mat_collect.extend(mat_collect_)

        if not self.Separate:
            norm_abs_out = [norm_abs_out]
            origins = [origins]
            normals_out = [normals_out]

        centers_socket.sv_set(mat_collect)
        norm_abs_socket.sv_set(Vector_degenerate(norm_abs_out))
        origins_socket.sv_set(Vector_degenerate(origins))
        norm_socket.sv_set(Vector_degenerate(normals_out))
#file = csv.reader(open('Coordenadas.csv', newline=''), delimiter=',')

#for row in file:
#    x = row[0]
#    y = row[1]
#    z = row[2]
#    bpy.ops.mesh.primitive_uv_cilinder_add(location = (float(x),float(y),float(z)))

#Laptop
#Add path file.
fp = "Coordenadas.csv"

with open(fp) as csvfile:
    rdr = csv.reader(csvfile)
    for i, row in enumerate(rdr):
        x = row[0]
        y = row[1]
        z = row[2]
        #bpy.ops.mesh.primitive_uv_sphere_add(location = (float(x),float(y),float(z)))
        myStartLoc = Vector((float(x), float(y), float(z)))
        myRotQuaternion = upVector.rotation_difference(myStartLoc)
        myRotEulerAngles = myRotQuaternion.to_euler()
        myRotEulerAnglesVec = ((myRotEulerAngles.x, myRotEulerAngles.y,
                                myRotEulerAngles.z))
        bpy.ops.mesh.primitive_cylinder_add(vertices=8,
                                            radius=7.5,
                                            depth=75,
                                            end_fill_type='NGON',
                                            location=myStartLoc,
                                            rotation=myRotEulerAnglesVec)
Example #38
0
def get_point_rotation(scene, curve_obj, index=0, spline_index=0):

    # Get curve attributes
    curve_mat = curve_obj.matrix_world
    curve = curve_obj.data
    points = get_spline_points(curve.splines[spline_index])

    # new temp object to detect local x-axis and y-axis of first handle
    # Temp Bevel Object for temp curve
    temp_bevel_curve = bpy.data.curves.new('__temp_bevel', 'CURVE')
    temp_spline = temp_bevel_curve.splines.new('POLY')
    temp_spline.points.add(2)
    temp_spline.points[0].co = Vector((1.0, 0.0, 0.0, 1.0))
    temp_spline.points[1].co = Vector((0.0, 1.0, 0.0, 1.0))
    temp_bevel_obj = bpy.data.objects.new('__temp_bevel', temp_bevel_curve)
    scene.objects.link(temp_bevel_obj)
    # Temp Curve
    curve_copy = curve_obj.data.copy()
    curve_copy.use_fill_caps = False
    curve_copy.bevel_object = temp_bevel_obj
    temp_obj = bpy.data.objects.new('__temp', curve_copy)
    scene.objects.link(temp_obj)
    temp_obj.location = curve_obj.location
    temp_obj.rotation_mode = curve_obj.rotation_mode
    temp_obj.rotation_quaternion = curve_obj.rotation_quaternion
    temp_obj.rotation_euler = curve_obj.rotation_euler

    # Convert temp curve to mesh
    bpy.ops.object.select_all(action='DESELECT') # deselect all first
    scene.objects.active = temp_obj
    temp_obj.select = True
    bpy.ops.object.convert(target='MESH')

    offset = 0
    micro_offset = 0

    #cyclic check
    for i, spline in enumerate(curve.splines):
        if i > spline_index:
            break
        #ps = get_spline_points(spline)
        if i > 0:
            ps_count = len(get_spline_points(curve.splines[i-1]))
            offset += ps_count-1
        if spline.use_cyclic_u:
            offset += 1
        elif i > 0:
            micro_offset += 1

    #offset += spline_index * curve.resolution_u
    #print(offset)

    # get x-axis and y-axis of the first handle
    handle_x = temp_obj.data.vertices[curve.resolution_u * (index + offset) * 3 + micro_offset * 3].co
    handle_y = temp_obj.data.vertices[curve.resolution_u * (index + offset) * 3 + 1 + micro_offset * 3].co

    target_x = handle_x - points[index].co.xyz
    target_y = handle_y - points[index].co.xyz
    target_x.normalize()
    target_y.normalize()

    # delete temp objects
    temp_bevel_obj.select = True
    bpy.ops.object.delete()
    
    # Match bevel x-axis to handle x-axis
    bevel_x = Vector((1.0, 0.0, 0.0))
    target_x = curve_mat.to_3x3() * target_x
    rot_1 = bevel_x.rotation_difference(target_x)

    # Match bevel y-axis to handle y-axis
    bevel_y = rot_1.to_matrix() * Vector((0.0, 1.0, 0.0))
    target_y = curve_mat.to_3x3() * target_y
    rot_2 = bevel_y.rotation_difference(target_y)

    # Select curve object again
    scene.objects.active = curve_obj
    curve_obj.select = True

    return rot_2 * rot_1
    def process(self):
        if self.outputs['Centers'].is_linked or self.outputs['Normals'].is_linked or \
                self.outputs['Origins'].is_linked or self.outputs['Norm_abs'].is_linked:
            if 'Polygons' in self.inputs and 'Vertices' in self.inputs \
                and self.inputs['Polygons'].is_linked and self.inputs['Vertices'].is_linked:

                pols_ = SvGetSocketAnyType(self, self.inputs['Polygons'])
                vers_tupls = SvGetSocketAnyType(self, self.inputs['Vertices'])
                vers_vects = Vector_generate(vers_tupls)
                
                # make mesh temp утилитарно - удалить в конце
                mat_collect = []
                normals_out = []
                origins = []
                norm_abs_out = []
                for verst, versv, pols in zip(vers_tupls, vers_vects, pols_):
                    # medians в векторах
                    medians = []
                    normals = []
                    centrs = []
                    norm_abs = []
                    for p in pols:
                        # medians
                        # it calcs middle point of opposite edges, 
                        # than finds length vector between this two points
                        v0 = versv[p[0]]
                        v1 = versv[p[1]]
                        v2 = versv[p[2]]
                        lp=len(p)
                        if lp >= 4:
                            l = ((lp-2)//2) + 2
                            v3 = versv[p[l]]
                            poi_2 = (v2+v3)/2
                            # normals
                            norm = geometry.normal(v0, v1, v2, v3)
                            normals.append(norm)
                        else:
                            poi_2 = v2
                            # normals
                            norm = geometry.normal(v0, v1, v2)
                            normals.append(norm)
                        poi_1 = (v0+v1)/2
                        vm = poi_2 - poi_1
                        medians.append(vm)
                        # centrs
                        x,y,z = zip(*[verst[poi] for poi in p])
                        x,y,z = sum(x)/len(x), sum(y)/len(y), sum(z)/len(z)
                        current_center = Vector((x,y,z))
                        centrs.append(current_center)
                        # normal absolute !!!
                        # это совершенно нормально!!! ;-)
                        norm_abs.append(current_center+norm)
                        
                    norm_abs_out.append(norm_abs)    
                    origins.append(centrs)
                    normals_out.extend(normals)
                    mat_collect_ = []
                    for cen, med, nor in zip(centrs, medians, normals):
                        loc = Matrix.Translation(cen)
                        # need better solution for Z,Y vectors + may be X vector correction
                        vecz = Vector((0, 1e-6, 1))
                        q_rot0 = vecz.rotation_difference(nor).to_matrix().to_4x4()
                        q_rot2 = nor.rotation_difference(vecz).to_matrix().to_4x4()
                        vecy = Vector((1e-6, 1, 0)) * q_rot2
                        q_rot1 = vecy.rotation_difference(med).to_matrix().to_4x4()
                        # loc is matrix * rot vector * rot vector
                        M = loc*q_rot1*q_rot0
                        lM = [ j[:] for j in M ]
                        mat_collect_.append(lM)
                    mat_collect.extend(mat_collect_)
                
                SvSetSocketAnyType(self, 'Centers', mat_collect)
                SvSetSocketAnyType(self, 'Norm_abs', Vector_degenerate(norm_abs_out))
                SvSetSocketAnyType(self, 'Origins', Vector_degenerate(origins))
                SvSetSocketAnyType(self, 'Normals', Vector_degenerate([normals_out]))