from bpy_extras import bpy,bmesh 
from mathutils import Vector, Matrix
from pathlib import Path

def setViewport(space, ctx, position):
	rv3d = space.region_3d
	rv3d.view_matrix = position 
	bpy.ops.object.select_all(action='DESELECT')
	bpy.ops.object.select_all(action='SELECT')
	bpy.ops.view3d.view_selected(ctx)
	bpy.ops.object.select_all(action='DESELECT')
	
frontier = r"G:\Frontier"
for filepath in list(Path(frontier).rglob("*.fmod")):
    filepath = filepath.resolve().as_posix()
    bpy.ops.custom_import.import_mhf_fmod(filepath = filepath)   
    space, area = next(((space, area) for area in bpy.context.screen.areas if area.type == 'VIEW_3D' for space in area.spaces if space.type == 'VIEW_3D'))
    ctx = bpy.context.copy()
    ctx['area'] = area
    ctx['region'] = area.regions[-1]
    space.viewport_shade = 'TEXTURED'
    for ix,position in enumerate([Matrix.Rotation(i,4,'Z')*Matrix.Rotation(j,4,'Y')*Matrix.Rotation(k,4,'X') for i in range(-45,46,45) for j in range(-45,46,45) for k in range(-45,46,45)]):		
#Y is axis of weapons and armour
        setViewport(space, ctx, position)
        bpy.context.scene.render.image_settings.file_format='PNG'
        bpy.context.scene.render.alpha_mode = "TRANSPARENT"
        bpy.context.scene.render.resolution_percentage = 100
        bpy.context.scene.render.filepath = filepath[:-4]+"-Angle %d"%ix+".JPEG"
        bpy.ops.render.opengl(write_still=True)
Esempio n. 2
0
	def makeObject(self):
		print("Creating mesh", end='')
		# Create the mesh
		mesh = bpy.data.meshes.new(self.name)

		# Prepare vertices and faces
		mesh.vertices.add(self.numVerts)
		mesh.tessfaces.add(self.numTris)
		print('.', end='')

		# Verts
		mesh.vertices.foreach_set("co", unpack_list(self.frames[0]))
		mesh.transform(Matrix.Rotation(-pi / 2, 4, 'Z'))
		print('.', end='')

		# Tris
		mesh.tessfaces.foreach_set("vertices_raw", unpack_face_list([face[0] for face in self.tris]))
		print('.', end='')

		# Skins
		mesh.tessface_uv_textures.new()
		if self.numSkins > 0:
			material = bpy.data.materials.new(self.name)
			for skin in self.skins:
				skinImg = Util.loadImage(skin, self.filePath)
				if skinImg == None:
					skinImg = bpy.data.images.new(os.path.join(self.filePath, skin), self.skinWidth, self.skinHeight)
				skinImg.mapping = 'UV'
				skinImg.name = skin
				skinTex = bpy.data.textures.new(self.name + skin, type='IMAGE')
				skinTex.image = skinImg
				matTex = material.texture_slots.add()
				matTex.texture = skinTex
				matTex.texture_coords = 'UV'
				matTex.use_map_color_diffuse = True
				matTex.use_map_alpha = True
				matTex.uv_layer = mesh.tessface_uv_textures[0].name
			mesh.materials.append(material)
		print('.', end='')

		# UV
		mesh.tessface_uv_textures[0].data.foreach_set("uv_raw", unpack_list([self.uvs[i] for i in unpack_face_list([face[1] for face in self.tris])]))
		if self.numSkins > 0:
			image = mesh.materials[0].texture_slots[0].texture.image
			if image != None:
				for uv in mesh.tessface_uv_textures[0].data:
					uv.image = image
		print('.', end='')

		mesh.validate()
		mesh.update()
		obj = bpy.data.objects.new(mesh.name, mesh)
		base = bpy.context.scene.objects.link(obj)
		bpy.context.scene.objects.active = obj
		base.select = True
		print("Done")

		# Animate
		if self.options.fImportAnimation and self.numFrames > 1:
			for i, frame in enumerate(self.frames):
				progressStatus = i / self.numFrames * 100
				#bpy.context.scene.frame_set(i + 1)
				obj.shape_key_add(from_mix=False)
				mesh.vertices.foreach_set("co", unpack_list(frame))
				mesh.transform(Matrix.Rotation(-pi / 2, 4, 'Z'))
				mesh.shape_keys.key_blocks[i].value = 1.0
				mesh.shape_keys.key_blocks[i].keyframe_insert("value", frame=i + 1)
				if i < len(self.frames) - 1:
					mesh.shape_keys.key_blocks[i].value = 0.0
					mesh.shape_keys.key_blocks[i].keyframe_insert("value", frame=i + 2)
				if i > 0:
					mesh.shape_keys.key_blocks[i].value = 0.0
					mesh.shape_keys.key_blocks[i].keyframe_insert("value", frame=i)
				print("Animating - progress: %3i%%\r" % int(progressStatus), end='')
			print("Animating - progress: 100%.")

		bpy.context.scene.update()
		print("Model imported")
Esempio n. 3
0
 def make_ik_spin_control_widget(self):
     if self.pivot_type == 'ANKLE_TOE':
         obj = create_ballsocket_widget(self.obj, self.bones.ctrl.ik_spin, size=0.75)
         rotfix = Matrix.Rotation(math.pi/2, 4, self.main_axis.upper())
         adjust_widget_transform_mesh(obj, rotfix, local=True)
def _main(self,
          obj,
          group,
          DENSITY=1.0,
          SCALE=0.6,
          RAND_LOC=0.8,
          RAND_ALIGN=0.75,
          ):

    from math import radians, pi

    # OFS = 0.2
    SEEK = 2.0  # distance for ray to seek
    BAD_NORMAL = Vector((0.0, 0.0, -1.0))
    WALL_LIMIT = radians(45.0)

    mats = (Matrix.Rotation(radians(-45), 3, 'X'),
            Matrix.Rotation(radians(+45), 3, 'X'),
            Matrix.Rotation(radians(-45), 3, 'Y'),
            Matrix.Rotation(radians(+45), 3, 'Y'),
            Matrix.Rotation(radians(-45), 3, 'Z'),
            Matrix.Rotation(radians(+45), 3, 'Z'),
            )

    Z_UP = Vector((0.0, 0.0, 1.0))
    Y_UP = Vector((0.0, 1.0, 0.0))

    if not group:
        self.report({'WARNING'}, "Group '%s' not found" % obj.name)
        return

    def debug_edge(v1, v2):
        mesh = bpy.data.meshes.new("Retopo")
        mesh.from_pydata([v1, v2], [(0.0, 1.0)], [])

        scene = bpy.context.scene
        mesh.update()
        obj_new = bpy.data.objects.new("Torus", mesh)
        scene.objects.link(obj_new)

    ray = obj.ray_cast
    closest_point_on_mesh = obj.closest_point_on_mesh

    obj_mat = obj.matrix_world.copy()
    obj_mat_inv = obj_mat.inverted()
    # obj_quat = obj_mat.to_quaternion()
    # obj_quat_inv = obj_mat_inv.to_quaternion()

    DEBUG = False

    def fix_point(p):
        ok, hit, no, ind = closest_point_on_mesh(obj_mat_inv * p)
        if ok:
            if DEBUG:
                return [p, no, None]
            else:
                # print("good", hit, no)
                return [hit, no, None]

        # worry!
        print("bad!", p, BAD_NORMAL)

        return [p, BAD_NORMAL, None]

    def get_points(stroke):
        return [fix_point(point.co) for point in stroke.points]

    def get_splines(gp):
        if gp.layers.active:
            frame = gp.layers.active.active_frame
            return [get_points(stroke) for stroke in frame.strokes]
        else:
            return []

    def main():
        scene = bpy.context.scene
        obj = bpy.context.object

        gp = None

        if obj:
            gp = obj.grease_pencil

        if not gp:
            gp = scene.grease_pencil

        if not gp:
            self.report({'WARNING'}, "No grease pencil layer found")
            return

        splines = get_splines(gp)

        for s in splines:
            for pt in s:
                p = pt[0]
                n = pt[1]
                # print(p, n)
                if n is BAD_NORMAL:
                    continue

                # # dont self intersect
                best_nor = None
                #best_hit = None
                best_dist = 10000000.0
                pofs = p + n * 0.01

                n_seek = n * SEEK
                m_alt_1 = Matrix.Rotation(radians(22.5), 3, n)
                m_alt_2 = Matrix.Rotation(radians(-22.5), 3, n)
                for _m in mats:
                    for m in (_m, m_alt_1 * _m, m_alt_2 * _m):
                        pdir = m * n_seek
                        ok, hit, nor, ind = ray(pofs, pdir, best_dist)
                        if ok:
                            best_dist = (pofs - hit).length
                            best_nor = nor
                            # best_hit = hit

                if best_nor:
                    pt[1].length = best_dist
                    best_nor.negate()
                    pt[2] = best_nor

                    #scene.cursor_location[:] = best_hitnyway
                    # bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP',
                    #                         iterations=1)
                    # debug_edge(p, best_hit)
                    # p[:] = best_hit

        # Now we need to do scattering.
        # first corners
        hits = []
        nors = []
        oris = []
        for s in splines:
            # point, normal, n_other the closest hit normal
            for p, n, n_other in s:
                if n is BAD_NORMAL:
                    continue
                if n_other:
                    # cast vectors twice as long as the distance
                    # needed just in case.
                    n_down = (n * -SEEK)
                    l = n_down.length
                    n_other.length = l

                    vantage = p + n
                    if DEBUG:
                        p[:] = vantage

                    # We should cast rays between n_down and n_other
                    #for f in (0.0, 0.2, 0.4, 0.6, 0.8, 1.0):
                    TOT = int(10 * DENSITY)
                    #for i in list(range(TOT)):
                    for i in list(range(TOT))[int(TOT / 1.5):]:  # second half
                        f = i / (TOT - 1)

                        # focus on the center
                        '''
                        f -= 0.5
                        f = f*f
                        f += 0.5
                        '''

                        ntmp = f * n_down + (1.0 - f) * n_other
                        # randomize
                        ntmp.x += uniform(-l, l) * RAND_LOC
                        ntmp.y += uniform(-l, l) * RAND_LOC
                        ntmp.z += uniform(-l, l) * RAND_LOC

                        ok, hit, hit_no, ind = ray(vantage, ntmp, ntmp.length)
                        # print(hit, hit_no)
                        if ok:
                            if hit_no.angle(Z_UP) < WALL_LIMIT:
                                hits.append(hit)
                                nors.append(hit_no)
                                oris.append(n_other.cross(hit_no))
                                #oris.append(n_other)

        if 0:
            mesh = bpy.data.meshes.new("ScatterDupliFace")
            mesh.from_pydata(hits, [], [])

            scene = bpy.context.scene
            mesh.update()
            obj_new = bpy.data.objects.new("ScatterPar", mesh)
            scene.objects.link(obj_new)
            obj_new.layers[:] = obj.layers

            # Now setup dupli-faces
            obj_new.dupli_type = 'VERTS'
            ob_child = bpy.data.objects["trash"]
            ob_child.location = obj_new.location
            ob_child.parent = obj_new
        else:

            def apply_faces(triples):
                # first randomize the faces
                shuffle(triples)

                obs = group.objects[:]
                tot = len(obs)
                tot_div = int(len(triples) / tot)

                for inst_ob in obs:
                    triple_sub = triples[0:tot_div]
                    triples[0:tot_div] = []

                    vv = [tuple(v) for f in triple_sub for v in f]

                    mesh = bpy.data.meshes.new("ScatterDupliFace")
                    mesh.from_pydata(vv, [], [(i * 3, i * 3 + 1, i * 3 + 2)
                                              for i in range(len(triple_sub))])

                    scene = bpy.context.scene
                    mesh.update()
                    obj_new = bpy.data.objects.new("ScatterPar", mesh)

                    scene.objects.link(obj_new)
                    obj_new.layers[:] = obj.layers

                    # Now setup dupli-faces
                    obj_new.dupli_type = 'FACES'
                    obj_new.use_dupli_faces_scale = True
                    obj_new.dupli_faces_scale = 100.0

                    inst_ob.location = 0.0, 0.0, 0.0
                    inst_ob.parent = obj_new

                    # align the object with worldspace
                    obj_new.matrix_world = obj_mat

                    # BGE settings for testing
                    '''
                    inst_ob.game.physics_type = 'RIGID_BODY'
                    inst_ob.game.use_collision_bounds = True
                    inst_ob.game.collision_bounds = 'TRIANGLE_MESH'
                    inst_ob.game.collision_margin = 0.1
                    obj_new.select = True
                    '''

            # build faces from vert/normals
            tri = (Vector((0.0, 0.0, 0.01)),
                   Vector((0.0, 0.0, 0.0)),
                   Vector((0.0, 0.01, 0.01)))

            coords = []
            # face_ind = []
            for i in range(len(hits)):
                co = hits[i]
                no = nors[i]
                ori = oris[i]
                quat = no.to_track_quat('X', 'Z')

                # make 2 angles and blend
                angle = uniform(-pi, pi)
                angle_aligned = -(ori.angle(quat * Y_UP, pi))

                quat = Quaternion(no,
                                  (angle * (1.0 - RAND_ALIGN)) +
                                  (angle_aligned * RAND_ALIGN)
                                  ).cross(quat)

                f = uniform(0.1, 1.2) * SCALE

                coords.append([co + (quat * (tri[0] * f)),
                               co + (quat * (tri[1] * f)),
                               co + (quat * (tri[2] * f)),
                               ])

            apply_faces(coords)

    main()
Esempio n. 5
0
def rotate_uvs(uv_points, angle):

    if angle != 0.0:
        mat = Matrix.Rotation(angle, 2)
        for uv in uv_points:
            uv[:] = mat * uv
Esempio n. 6
0
FBX_DEFORMER_SHAPE_VERSION = 100
FBX_DEFORMER_SHAPECHANNEL_VERSION = 100
FBX_POSE_BIND_VERSION = 100
FBX_DEFORMER_SKIN_VERSION = 101
FBX_DEFORMER_CLUSTER_VERSION = 100
FBX_MATERIAL_VERSION = 102
FBX_TEXTURE_VERSION = 202
FBX_ANIM_KEY_VERSION = 4008

FBX_NAME_CLASS_SEP = b"\x00\x01"
FBX_ANIM_PROPSGROUP_NAME = "d"

FBX_KTIME = 46186158000  # This is the number of "ktimes" in one second (yep, precision over the nanosecond...)


MAT_CONVERT_LIGHT = Matrix.Rotation(math.pi / 2.0, 4, 'X')  # Blender is -Z, FBX is -Y.
MAT_CONVERT_CAMERA = Matrix.Rotation(math.pi / 2.0, 4, 'Y')  # Blender is -Z, FBX is +X.
# XXX I can't get this working :(
# MAT_CONVERT_BONE = Matrix.Rotation(math.pi / 2.0, 4, 'Z')  # Blender is +Y, FBX is -X.
MAT_CONVERT_BONE = Matrix()


BLENDER_OTHER_OBJECT_TYPES = {'CURVE', 'SURFACE', 'FONT', 'META'}
BLENDER_OBJECT_TYPES_MESHLIKE = {'MESH'} | BLENDER_OTHER_OBJECT_TYPES


# Lamps.
FBX_LIGHT_TYPES = {
    'POINT': 0,  # Point.
    'SUN': 1,    # Directional.
    'SPOT': 2,   # Spot.
    def make_armature(self, context):
        bpy.ops.object.add(type="ARMATURE", enter_editmode=True, location=(0, 0, 0))
        armature = context.object
        armature.name = "skeleton"
        armature.show_in_front = True

        bone_dic = {}

        def bone_add(name, head_pos, tail_pos, parent_bone=None, radius=0.1, roll=0):
            added_bone = armature.data.edit_bones.new(name)
            added_bone.head = head_pos
            added_bone.tail = tail_pos
            added_bone.head_radius = radius
            added_bone.tail_radius = radius
            added_bone.envelope_distance = 0.01
            added_bone.roll = radians(roll)
            if parent_bone is not None:
                added_bone.parent = parent_bone
            bone_dic.update({name: added_bone})
            return added_bone

        # bone_type = "leg" or "arm" for roll setting
        def x_mirror_bones_add(
            base_name,
            right_head_pos,
            right_tail_pos,
            parent_bones,
            radius=0.1,
            bone_type="other",
        ):
            right_roll = 0
            left_roll = 0
            if bone_type == "arm":
                right_roll = 180
            elif bone_type == "leg":
                right_roll = 90
                left_roll = 90
            left_bone = bone_add(
                base_name + "_L",
                right_head_pos,
                right_tail_pos,
                parent_bones[0],
                radius=radius,
                roll=left_roll,
            )
            right_bone = bone_add(
                base_name + "_R",
                [pos * axis for pos, axis in zip(right_head_pos, (-1, 1, 1))],
                [pos * axis for pos, axis in zip(right_tail_pos, (-1, 1, 1))],
                parent_bones[1],
                radius=radius,
                roll=right_roll,
            )

            return left_bone, right_bone

        def x_add(pos_a, add_x):
            pos = [p_a + _add for p_a, _add in zip(pos_a, [add_x, 0, 0])]
            return pos

        def y_add(pos_a, add_y):
            pos = [p_a + _add for p_a, _add in zip(pos_a, [0, add_y, 0])]
            return pos

        def z_add(pos_a, add_z):
            pos = [p_a + _add for p_a, _add in zip(pos_a, [0, 0, add_z])]
            return pos

        root = bone_add("root", (0, 0, 0), (0, 0, 0.3))
        head_size = self.tall / self.head_ratio
        # down side (前は8頭身の時の股上/股下の股下側割合、後ろは4頭身のときの〃を年齢具合で線形補完)(股上高めにすると破綻する)
        eight_upside_ratio, four_upside_ratio = (
            1 - self.leg_length_ratio,
            (2.5 / 4) * (1 - self.aging_ratio)
            + (1 - self.leg_length_ratio) * self.aging_ratio,
        )
        hip_up_down_ratio = (
            eight_upside_ratio * (1 - (8 - self.head_ratio) / 4)
            + four_upside_ratio * (8 - self.head_ratio) / 4
        )
        # 体幹
        # 股間
        body_separate = self.tall * (1 - hip_up_down_ratio)
        # 首の長さ
        neck_len = head_size * 2 / 3
        # 仙骨(骨盤脊柱基部)
        hips_tall = body_separate + head_size * 3 / 4
        # 胸椎・spineの全長 #首の1/3は顎の後ろに隠れてる
        backbone_len = self.tall - hips_tall - head_size - neck_len / 2
        # FIXME 胸椎と脊椎の割合の確認 //脊椎の基部に位置する主となる屈曲点と、胸郭基部に位置するもうひとつの屈曲点byHumanoid Doc
        chest_len = backbone_len * 12 / 17  # noqa: F841 mesh生成で使ってる
        spine_len = backbone_len * 5 / 17

        # 仙骨基部
        hips = bone_add("Hips", (0, 0, body_separate), (0, 0, hips_tall), root, roll=90)
        # 骨盤基部->胸郭基部
        spine = bone_add(
            "Spine", hips.tail, z_add(hips.tail, spine_len), hips, roll=-90
        )
        # 胸郭基部->首元
        chest = bone_add(
            "Chest", spine.tail, z_add(hips.tail, backbone_len), spine, roll=-90
        )
        neck = bone_add(
            "Neck",
            (0, 0, self.tall - head_size - neck_len / 2),
            (0, 0, self.tall - head_size + neck_len / 2),
            chest,
            roll=-90,
        )
        # 首の1/2は顎の後ろに隠れてる
        head = bone_add(
            "Head",
            (0, 0, self.tall - head_size + neck_len / 2),
            (0, 0, self.tall),
            neck,
            roll=-90,
        )

        # 目
        eye_depth = self.eye_depth
        eyes = x_mirror_bones_add(
            "eye",
            (head_size * self.head_width_ratio / 5, 0, self.tall - head_size / 2),
            (
                head_size * self.head_width_ratio / 5,
                eye_depth,
                self.tall - head_size / 2,
            ),
            (head, head),
        )
        # 足
        leg_width = head_size / 4 * self.leg_width_ratio
        leg_size = self.leg_size

        leg_bone_length = (body_separate + head_size * 3 / 8 - self.tall * 0.05) / 2
        upside_legs = x_mirror_bones_add(
            "Upper_Leg",
            x_add((0, 0, body_separate + head_size * 3 / 8), leg_width),
            x_add(
                z_add((0, 0, body_separate + head_size * 3 / 8), -leg_bone_length),
                leg_width,
            ),
            (hips, hips),
            radius=leg_width * 0.9,
            bone_type="leg",
        )
        lower_legs = x_mirror_bones_add(
            "Lower_Leg",
            upside_legs[0].tail,
            (leg_width, 0, self.tall * 0.05),
            upside_legs,
            radius=leg_width * 0.9,
            bone_type="leg",
        )
        foots = x_mirror_bones_add(
            "Foot",
            lower_legs[0].tail,
            (leg_width, -leg_size * (2 / 3), 0),
            lower_legs,
            radius=leg_width * 0.9,
            bone_type="leg",
        )
        toes = x_mirror_bones_add(
            "Toes",
            foots[0].tail,
            (leg_width, -leg_size, 0),
            foots,
            radius=leg_width * 0.5,
            bone_type="leg",
        )

        # 肩~指
        self.hand_size = head_size * 0.75 * self.hand_ratio
        shoulder_in_pos = self.shoulder_in_width / 2

        shoulder_parent = chest
        shoulders = x_mirror_bones_add(
            "shoulder",
            x_add(shoulder_parent.tail, shoulder_in_pos),
            x_add(shoulder_parent.tail, shoulder_in_pos + self.shoulder_width),
            (shoulder_parent, shoulder_parent),
            radius=self.hand_size * 0.4,
            bone_type="arm",
        )

        arm_length = (
            head_size
            * (1 * (1 - (self.head_ratio - 6) / 2) + 1.5 * ((self.head_ratio - 6) / 2))
            * self.arm_length_ratio
        )
        arms = x_mirror_bones_add(
            "Arm",
            shoulders[0].tail,
            x_add(shoulders[0].tail, arm_length),
            shoulders,
            radius=self.hand_size * 0.4,
            bone_type="arm",
        )

        # グーにするとパーの半分くらいになる、グーのとき手を含む下腕の長さと上腕の長さが概ね一緒、けど手がでかすぎると破綻する
        forearm_length = max(arm_length - self.hand_size / 2, arm_length * 0.8)
        forearms = x_mirror_bones_add(
            "forearm",
            arms[0].tail,
            x_add(arms[0].tail, forearm_length),
            arms,
            radius=self.hand_size * 0.4,
            bone_type="arm",
        )
        hands = x_mirror_bones_add(
            "hand",
            forearms[0].tail,
            x_add(forearms[0].tail, self.hand_size / 2),
            forearms,
            radius=self.hand_size / 4,
            bone_type="arm",
        )

        def fingers(finger_name, proximal_pos, finger_len_sum):

            finger_normalize = 1 / (
                self.finger_1_2_ratio * self.finger_2_3_ratio
                + self.finger_1_2_ratio
                + 1
            )
            proximal_finger_len = finger_len_sum * finger_normalize
            intermediate_finger_len = (
                finger_len_sum * finger_normalize * self.finger_1_2_ratio
            )
            distal_finger_len = (
                finger_len_sum
                * finger_normalize
                * self.finger_1_2_ratio
                * self.finger_2_3_ratio
            )
            proximal_bones = x_mirror_bones_add(
                f"{finger_name}_proximal",
                proximal_pos,
                x_add(proximal_pos, proximal_finger_len),
                hands,
                self.hand_size / 18,
                bone_type="arm",
            )
            intermediate_bones = x_mirror_bones_add(
                f"{finger_name}_intermediate",
                proximal_bones[0].tail,
                x_add(proximal_bones[0].tail, intermediate_finger_len),
                proximal_bones,
                self.hand_size / 18,
                bone_type="arm",
            )
            distal_bones = x_mirror_bones_add(
                f"{finger_name}_distal",
                intermediate_bones[0].tail,
                x_add(intermediate_bones[0].tail, distal_finger_len),
                intermediate_bones,
                self.hand_size / 18,
                bone_type="arm",
            )
            if self.nail_bone:
                x_mirror_bones_add(
                    f"{finger_name}_nail",
                    distal_bones[0].tail,
                    x_add(distal_bones[0].tail, distal_finger_len),
                    distal_bones,
                    self.hand_size / 20,
                    bone_type="arm",
                )
            return proximal_bones, intermediate_bones, distal_bones

        finger_y_offset = -self.hand_size / 16
        thumbs = fingers(
            "finger_thumbs",
            y_add(hands[0].head, finger_y_offset * 3),
            self.hand_size / 2,
        )

        mats = [thumbs[0][i].matrix.translation for i in [0, 1]]
        mats = [Matrix.Translation(mat) for mat in mats]
        for j in range(3):
            for n, angle in enumerate([-45, 45]):
                thumbs[j][n].transform(mats[n].inverted())
                thumbs[j][n].transform(Matrix.Rotation(radians(angle), 4, "Z"))
                thumbs[j][n].transform(mats[n])
                thumbs[j][n].roll = [0, radians(180)][n]

        index_fingers = fingers(
            "finger_index",
            y_add(hands[0].tail, finger_y_offset * 3),
            (self.hand_size / 2) - (1 / 2.3125) * (self.hand_size / 2) / 3,
        )
        middle_fingers = fingers(
            "finger_middle", y_add(hands[0].tail, finger_y_offset), self.hand_size / 2
        )
        ring_fingers = fingers(
            "finger_ring",
            y_add(hands[0].tail, -finger_y_offset),
            (self.hand_size / 2) - (1 / 2.3125) * (self.hand_size / 2) / 3,
        )
        little_fingers = fingers(
            "finger_little",
            y_add(hands[0].tail, -finger_y_offset * 3),
            ((self.hand_size / 2) - (1 / 2.3125) * (self.hand_size / 2) / 3)
            * ((1 / 2.3125) + (1 / 2.3125) * 0.75),
        )

        body_dict = {
            "hips": hips.name,
            "spine": spine.name,
            "chest": chest.name,
            "neck": neck.name,
            "head": head.name,
        }

        left_right_body_dict = {
            f"{left_right}{bone_name}": bones[lr].name
            for bone_name, bones in {
                "Eye": eyes,
                "UpperLeg": upside_legs,
                "LowerLeg": lower_legs,
                "Foot": foots,
                "Toes": toes,
                "Shoulder": shoulders,
                "UpperArm": arms,
                "LowerArm": forearms,
                "Hand": hands,
            }.items()
            for lr, left_right in enumerate(["left", "right"])
        }

        # VRM finger like name key
        fingers_dict = {
            f"{left_right}{finger_name}{position}": finger[i][lr].name
            for finger_name, finger in zip(
                ["Thumb", "Index", "Middle", "Ring", "Little"],
                [thumbs, index_fingers, middle_fingers, ring_fingers, little_fingers],
            )
            for i, position in enumerate(["Proximal", "Intermediate", "Distal"])
            for lr, left_right in enumerate(["left", "right"])
        }

        # VRM bone name : blender bone name
        bone_name_all_dict = {}
        bone_name_all_dict.update(body_dict)
        bone_name_all_dict.update(left_right_body_dict)
        bone_name_all_dict.update(fingers_dict)

        context.scene.view_layers.update()
        bpy.ops.object.mode_set(mode="OBJECT")
        context.scene.view_layers.update()
        return armature, bone_name_all_dict
Esempio n. 8
0
    def execute(self, context):
        scene = context.scene
        ofst = scene.cursor_location if self.use_cursor else (0.0, 0.0, 0.0)

        mat_z = Matrix.Rotation(self.rot_z, 4, 'Z')

        mat_y_180 = Matrix.Rotation(radians(180.0), 4, 'Y')
        mat_z_180 = Matrix.Rotation(radians(180.0), 4, 'Z')

        for ob in context.selected_objects:

            ob_copy = ob.copy()
            scene.objects.link(ob_copy)
            ob_copy.parent = None
            ob.select = False

            if ob_copy.constraints:
                for con in ob_copy.constraints:
                    ob_copy.constraints.remove(con)

            ob_copy.matrix_world = ob.matrix_world

            # Mirror axes
            # ---------------------------

            if self.x:

                ob_copy.rotation_euler[1] = -ob_copy.rotation_euler[1]
                ob_copy.rotation_euler[2] = -ob_copy.rotation_euler[2]

                ob_copy.location[0] = ob_copy.location[0] - (
                    ob_copy.location[0] - ofst[0]) * 2

            if self.y:

                ob_copy.rotation_euler[0] = -ob_copy.rotation_euler[0]
                ob_copy.rotation_euler[2] = -ob_copy.rotation_euler[2]

                ob_copy.location[1] = ob_copy.location[1] - (
                    ob_copy.location[1] - ofst[1]) * 2

                ob_copy.matrix_basis *= mat_z_180

            if self.z:

                ob_copy.rotation_euler[0] = -ob_copy.rotation_euler[0]
                ob_copy.rotation_euler[1] = -ob_copy.rotation_euler[1]

                ob_copy.location[2] = ob_copy.location[2] - (
                    ob_copy.location[2] - ofst[2]) * 2

                ob_copy.matrix_basis *= mat_y_180

            # Adjust orientation for mirrored objects
            # ---------------------------------------------

            if self.rot_z:
                ob_copy.matrix_basis *= mat_z

        scene.objects.active = ob_copy

        return {'FINISHED'}
Esempio n. 9
0
    def execute(self, context):

        if self.reset_values is True:
            self.reset_all_values()

        active_obj = context.active_object

        bm = bmesh.from_edit_mesh(active_obj.data)
        bm.verts.ensure_lookup_table()
        #verts = [v for v in bm.verts if v.select]

        # get loops
        loops = loop_t.get_connected_input(bm)
        loops = loop_t.check_loops(loops, bm)

        if not loops:
            self.report({'WARNING'}, "No Loops!")
            return {'CANCELLED'}

        first_indexes = []
        if isinstance(bm.select_history[0], bmesh.types.BMVert):
            for element in bm.select_history:
                first_indexes.append(element.index)
        elif isinstance(bm.select_history[0], bmesh.types.BMEdge):
            for element in bm.select_history:
                el_verts = element.verts
                first_indexes.append(el_verts[0].index)
                first_indexes.append(el_verts[1].index)

        for loop in loops:
            if loop[1] is True:
                continue

            loop_verts = []

            for ind in loop[0]:
                loop_verts.append(bm.verts[ind])

            #  for the case if we need to reverse it
            if loop[0][-1] in first_indexes:
                loop_verts = list(reversed(loop_verts))

            # reverse again for the direction
            if self.reverse_direction is True:
                loop_verts = list(reversed(loop_verts))

            # positions
            first_vert_pos = active_obj.matrix_world @ loop_verts[0].co
            last_vert_pos = active_obj.matrix_world @ loop_verts[-1].co

            loop_centr_orig = first_vert_pos.lerp(last_vert_pos, 0.5)
            relative_dist = (first_vert_pos - loop_centr_orig).length
            sidevec = (first_vert_pos - last_vert_pos).normalized()

            obj_matrix = active_obj.matrix_world
            obj_matrix_inv = obj_matrix.inverted()

            if self.direction_vector == 'Custom':
                rot_dir = Vector((self.rotate_axis[0], self.rotate_axis[1], self.rotate_axis[2])).normalized()

            elif self.direction_vector == 'MiddleCrossed':
                middle_nor = loop_verts[int(len(loop_verts) / 2)].normal.copy().normalized()
                middle_nor = ut_base.get_normal_world(middle_nor, obj_matrix, obj_matrix_inv)
                rot_dir = middle_nor.cross(sidevec).normalized()

                # fix only for MiddleCrossed
                if not self.reverse_direction:
                    rot_dir.negate()

            elif self.direction_vector == 'Middle':
                middle_nor = loop_verts[int(len(loop_verts) / 2)].normal.copy().normalized()
                middle_nor = ut_base.get_normal_world(middle_nor, obj_matrix, obj_matrix_inv)
                middle_nor = middle_nor.cross(sidevec).normalized()
                rot_dir = middle_nor.cross(sidevec).normalized()
                rot_dir.negate()

            # Auto Direction
            else:
                auto_loop_vec = (loop_verts[0].co - loop_verts[1].co).normalized()
                test_auto_vec = (loop_verts[0].co - loop_verts[-1].co).normalized()
                auto_loop_vec_angle = auto_loop_vec.angle(test_auto_vec)

                for loop in loop_verts:
                    if loop != loop_verts[1] and loop != loop_verts[0] and loop != loop_verts[-1]:
                        auto_loop_vec_2 = (loop_verts[0].co - loop.co).normalized()
                        auto_loop_vec_angle_2 = auto_loop_vec_2.angle(test_auto_vec)
                        if auto_loop_vec_angle < auto_loop_vec_angle_2:
                            auto_loop_vec = auto_loop_vec_2
                            auto_loop_vec_angle = auto_loop_vec_angle_2

                rot_dir = (auto_loop_vec).cross(test_auto_vec).normalized()

                # If Reverse Direction is True
                if self.reverse_direction:
                    rot_dir.negate()


            upvec = rot_dir.cross(sidevec).normalized()
            loop_centr = (self.upvec_offset * upvec * relative_dist) + loop_centr_orig

            loop_angle = (first_vert_pos - loop_centr).normalized().angle((last_vert_pos - loop_centr).normalized())
            if self.upvec_offset > 0:
                loop_angle = math.radians((360 - math.degrees(loop_angle)))

            # even spread
            line_data = None
            if self.spread_mode == 'Even':
                world_verts = [active_obj.matrix_world @ vert.co for vert in loop_verts]

                line_data = []
                line_length = 0.0
                for i, vec in enumerate(world_verts):
                    if i == 0:
                        line_data.append(0)
                    else:
                        line_length += (vec - world_verts[i-1]).length
                        line_data.append(line_length)

            # make arc!
            for i, vert in enumerate(loop_verts):
                if i != 0 and i != len(loop_verts)-1:
                    if self.spread_mode == 'Normal':
                        rot_angle = loop_angle * (i / (len(loop_verts) - 1))
                    else:
                        rot_angle = loop_angle * (line_data[i] / line_data[len(loop_verts)-1])

                    rot_mat = Matrix.Rotation(rot_angle, 3, rot_dir)
                    vert_pos = (rot_mat @ (first_vert_pos - loop_centr)) + loop_centr

                    if self.scale_arc != 0:
                        vert_rel_dist = mathu.geometry.distance_point_to_plane(vert_pos, loop_centr_orig, upvec)
                        vert_rel_dist_max = self.upvec_offset + relative_dist

                        if vert_rel_dist != 0 and vert_rel_dist_max != 0:
                            vert_pos_offset = vert_rel_dist / vert_rel_dist_max
                            vert_pos += (self.scale_arc * upvec * vert_pos_offset * vert_rel_dist_max)

                    # rotate arc
                    if self.rotate_arc_axis != 0:
                        rot_mat_2 = Matrix.Rotation(math.radians(self.rotate_arc_axis), 3, sidevec)
                        vert_pos = (rot_mat_2 @ (vert_pos - loop_centr_orig)) + loop_centr_orig

                    vert.co = active_obj.matrix_world.inverted() @ vert_pos

        bm.normal_update()
        bmesh.update_edit_mesh(active_obj.data)

        return {'FINISHED'}
Esempio n. 10
0
def get_uv_pos_size(data, image_size, target_grid, origin_xy, size_x, size_y,
                    up_vector, right_vector, verts, vtx_center):
    pixel_uv_x = 1.0 / image_size[0]
    pixel_uv_y = 1.0 / image_size[1]

    uv_unit_x = pixel_uv_x * size_x
    uv_unit_y = pixel_uv_y * size_y

    world_units = data.world_pixels
    world_convert = Vector((size_x / world_units, size_y / world_units))

    # Build the translation matrix
    offset_matrix = Matrix.Translation((target_grid.offset[0] * pixel_uv_x,
                                        target_grid.offset[1] * pixel_uv_y, 0))
    rotate_matrix = Matrix.Rotation(target_grid.rotate, 4, 'Z')

    origin_x = target_grid.grid[0] + (
        target_grid.padding[0] *
        2) + target_grid.margin[1] + target_grid.margin[3]
    origin_x *= origin_xy[0]
    origin_x += target_grid.padding[0]
    origin_x = pixel_uv_x * origin_x

    origin_y = target_grid.grid[1] + (
        target_grid.padding[1] *
        2) + target_grid.margin[0] + target_grid.margin[2]
    origin_y *= origin_xy[1]
    origin_y += target_grid.padding[1]
    origin_y = pixel_uv_y * origin_y
    origin_matrix = Matrix.Translation((origin_x, origin_y, 0))

    uv_matrix = offset_matrix @ rotate_matrix @ origin_matrix

    flip_x = -1 if data.uv_flip_x else 1
    flip_y = -1 if data.uv_flip_y else 1
    flip_matrix = Matrix.Scale(flip_x, 4, right_vector) @ Matrix.Scale(
        flip_y, 4, up_vector)

    pad_offset = target_grid.auto_pad_offset
    if target_grid.auto_pad is False:
        pad_offset = 0
    pad_scale = Vector(
        ((size_x - pad_offset) / size_x, (size_y - pad_offset) / size_y))
    pad_matrix = Matrix.Scale(pad_scale.x, 4, right_vector) @ Matrix.Scale(
        pad_scale.y, 4, up_vector)

    uv_min = Vector((float('inf'), float('inf')))
    uv_max = Vector((float('-inf'), float('-inf')))

    uv_verts = []
    for vert in verts:
        # Around center
        vert_pos = vert - vtx_center
        # Apply flip scaling
        vert_pos = flip_matrix @ vert_pos
        # Apply padding
        vert_pos = pad_matrix @ vert_pos
        # Get x/y values by using the right/up vectors
        vert_xy = (right_vector.dot(vert_pos), up_vector.dot(vert_pos), 0)
        vert_xy = Vector(vert_xy)
        # Convert to -0.5 to 0.5 space
        vert_xy.x /= world_convert.x
        vert_xy.y /= world_convert.y
        # Offset by half, to move coordinates back into 0-1 range
        vert_xy += Vector((0.5, 0.5, 0))
        # Multiply by the uv unit sizes to get actual UV space
        vert_xy.x *= uv_unit_x
        vert_xy.y *= uv_unit_y
        # Then offset the actual UV space by the translation matrix
        vert_xy = uv_matrix @ vert_xy
        # Record min/max for tile alignment step
        uv_min.x = min(uv_min.x, vert_xy.x)
        uv_min.y = min(uv_min.y, vert_xy.y)
        uv_max.x = max(uv_max.x, vert_xy.x)
        uv_max.y = max(uv_max.y, vert_xy.y)
        # Save to uv verts
        uv_verts.append(vert_xy)

    # In paint mode, do alignment and stretching steps
    if data.paint_mode == 'PAINT':
        # Convert vert origin to UV space, for use with paint modify
        uv_center = Vector((0.5, 0.5, 0.0))
        uv_center.x *= uv_unit_x
        uv_center.y *= uv_unit_y
        uv_center = uv_matrix @ uv_center
        uv_verts = get_uv_paint_modify(data, uv_verts, uv_matrix, pad_scale,
                                       uv_unit_x, uv_unit_y, uv_min, uv_max,
                                       uv_center,
                                       Vector((pixel_uv_x, pixel_uv_y)))

    # One final loop to snap the UVs to the pixel grid
    # Always snap if not in paint mode, paint mode does
    # UV snapping in UV map paint modify function
    do_snap = data.paint_mode != 'PAINT'
    if do_snap and pixel_uv_x > 0 and pixel_uv_y > 0:
        for uv_vert in uv_verts:
            p_x = uv_vert.x / pixel_uv_x
            p_y = uv_vert.y / pixel_uv_y
            if math.isnan(p_x) or math.isnan(p_y):
                return None
            uv_pixel_x = int(round(p_x))
            uv_pixel_y = int(round(p_y))
            uv_vert.x = min(uv_max.x, max(uv_pixel_x * pixel_uv_x, uv_min.x))
            uv_vert.y = min(uv_max.y, max(uv_pixel_y * pixel_uv_y, uv_min.y))

    return uv_verts
Esempio n. 11
0
 def direction_set_cb(value):
     op = SelectSideOfPlaneGizmoGroup.my_target_operator(context)
     matrix_rotate = Matrix.Rotation(-value, 3, self.rotate_axis)
     no = matrix_rotate @ self.widget_dial.matrix_basis.col[1].xyz
     op.plane_no = no
     op.execute(context)
Esempio n. 12
0
    def rotatescreen_main(self):
        if self.rfcontext.actions.pressed('confirm'):
            return 'main'
        if self.rfcontext.actions.pressed('cancel'):
            self.rfcontext.undo_cancel()
            return 'main'

        if self.rfcontext.actions.pressed('rotate plane'):
            self.rfcontext.undo_cancel()
            return 'rotate plane'

        # only update cut on timer events and when mouse has moved
        if not self.rfcontext.actions.timer: return
        if self.move_prevmouse == self.rfcontext.actions.mouse: return
        self.move_prevmouse = self.rfcontext.actions.mouse

        delta = Vec2D(self.rfcontext.actions.mouse - self.rotate_about)
        rotate = (math.atan2(delta.y, delta.x) - self.rotate_start + math.pi) % (math.pi * 2)

        raycast,project = self.rfcontext.raycast_sources_Point2D,self.rfcontext.Point_to_Point2D
        for i_cloop in range(len(self.move_cloops)):
            cloop  = self.move_cloops[i_cloop]
            verts  = self.move_verts[i_cloop]
            pts    = self.move_pts[i_cloop]
            dists  = self.move_dists[i_cloop]
            origin = self.move_origins[i_cloop]
            proj_dists = self.move_proj_dists[i_cloop]
            circumference = self.move_circumferences[i_cloop]

            origin2D = self.rfcontext.Point_to_Point2D(origin)
            ray = self.rfcontext.Point_to_Ray(origin)
            rmat = Matrix.Rotation(rotate, 4, -ray.d)
            normal = matrix_vector_mult(rmat, cloop.plane.n)
            plane = Plane(cloop.plane.o, normal)
            ray = self.rfcontext.Point2D_to_Ray(origin2D)
            crawl = self.rfcontext.plane_intersection_crawl(ray, plane, walk_to_plane=True)
            if not crawl: continue
            crawl_pts = [c for _,c,_ in crawl]
            connected = crawl[0][0] is not None
            crawl_pts,connected = self.rfcontext.clip_pointloop(crawl_pts, connected)
            if not crawl_pts or connected != cloop.connected: continue
            cl_cut = Contours_Loop(crawl_pts, connected)

            cl_cut.align_to(cloop)
            lc = cl_cut.circumference
            ndists = [cl_cut.offset] + [0.999 * lc * (d/circumference) for d in dists]
            i,dist = 0,ndists[0]
            l = len(ndists)-1 if cloop.connected else len(ndists)
            for c0,c1 in cl_cut.iter_pts(repeat=True):
                d = (c1-c0).length
                d = max(0.00000001, d)
                while dist - d <= 0:
                    # create new vert between c0 and c1
                    p = c0 + (c1 - c0) * (dist / d) + (cloop.plane.n * proj_dists[i])
                    p,_,_,_ = self.rfcontext.nearest_sources_Point(p)
                    verts[i].co = p
                    i += 1
                    if i == l: break
                    dist += ndists[i]
                dist -= d
                if i == l: break

            self.rfcontext.update_verts_faces(verts)
Esempio n. 13
0
def rotate(co):
    """
    Set the human orientation in reference to the camera orientation.
    """

    ow = co.owner

    # get the suffix of the human to reference the right objects
    suffix = ow.name[-4:] if ow.name[-4] == "." else ""

    keyboard = co.sensors['All_Keys']
    scene = blenderapi.scene()
    human_pos = co.owner
    pos = scene.objects['POS_EMPTY' + suffix]
    active_camera = scene.active_camera

    # if the human is external, do nothing
    if human_pos.get(
            'External_Robot_Tag') or human_pos['disable_keyboard_control']:
        return

    if human_pos['move_cameraFP'] and active_camera.name != ('Human_Camera' +
                                                             suffix):
        return

    keylist = keyboard.events

    k = []  #initiate a list with all currently pressed keys
    for key in keylist:
        if key[1] == blenderapi.input_active():
            k.append(key[0])  # add all pressed keys to a list - as ASCII CODES

    pos.worldPosition = ow.worldPosition

    # Get active camera
    scene = blenderapi.scene()
    active_camera = scene.active_camera

    if ow['Manipulate']:
        ow.worldOrientation = pos.worldOrientation
        # lock camera to head in Manipulation Mode
    else:
        if FORWARDS in k and not (LEFT in k or RIGHT in k):
            if active_camera.name == ("Human_Camera" + suffix):
                applyrotate(pos.worldOrientation, ow)
            else:
                applyrotate(human_pos.worldOrientation, ow)
        elif LEFT in k and not (FORWARDS in k or BACKWARDS in k):
            if active_camera.name == ("Human_Camera" + suffix):
                applyrotate(
                    pos.worldOrientation *
                    Matrix.Rotation(math.pi / 2, 3, 'Z'), ow)
            else:
                applyrotate(
                    human_pos.worldOrientation *
                    Matrix.Rotation(math.pi / 2, 3, 'Z'), ow)
            # turn around 90 deg
        elif RIGHT in k and not (FORWARDS in k or BACKWARDS in k):
            if active_camera.name == ("Human_Camera" + suffix):
                applyrotate(
                    pos.worldOrientation *
                    Matrix.Rotation(math.pi * 3 / 2, 3, 'Z'), ow)
            else:
                applyrotate(
                    human_pos.worldOrientation *
                    Matrix.Rotation(math.pi * 3 / 2, 3, 'Z'), ow)
            # turn around 270 deg
        elif LEFT in k and FORWARDS in k:
            if active_camera.name == ("Human_Camera" + suffix):
                applyrotate(
                    pos.worldOrientation *
                    Matrix.Rotation(math.pi / 4, 3, 'Z'), ow)
            else:
                applyrotate(
                    human_pos.worldOrientation *
                    Matrix.Rotation(math.pi / 4, 3, 'Z'), ow)
            # turn around 45 deg
        elif RIGHT in k and FORWARDS in k:
            if active_camera.name == ("Human_Camera" + suffix):
                applyrotate(
                    pos.worldOrientation *
                    Matrix.Rotation(math.pi * 7 / 4, 3, 'Z'), ow)
            else:
                applyrotate(
                    human_pos.worldOrientation *
                    Matrix.Rotation(math.pi * 7 / 4, 3, 'Z'), ow)
            # turn around 315 deg
        elif BACKWARDS in k and not (LEFT in k or RIGHT in k):
            if active_camera.name == ("Human_Camera" + suffix):
                applyrotate(
                    pos.worldOrientation * Matrix.Rotation(math.pi, 3, 'Z'),
                    ow)
            # turn around 180 deg if in game-mode
        elif LEFT in k and BACKWARDS in k:
            if active_camera.name == ("Human_Camera" + suffix):
                applyrotate(
                    pos.worldOrientation *
                    Matrix.Rotation(math.pi * 3 / 4, 3, 'Z'), ow)
            else:
                applyrotate(
                    human_pos.worldOrientation *
                    Matrix.Rotation(math.pi / 4, 3, 'Z'), ow)
            # turn around 135 deg if in game-mode, else turn 45 deg
        elif RIGHT in k and BACKWARDS in k:
            if active_camera.name == ("Human_Camera" + suffix):
                applyrotate(
                    pos.worldOrientation *
                    Matrix.Rotation(math.pi * 5 / 4, 3, 'Z'), ow)
            else:
                applyrotate(
                    human_pos.worldOrientation *
                    Matrix.Rotation(math.pi * 7 / 4, 3, 'Z'), ow)
Esempio n. 14
0
    def draw_prepare(self, context):

        preference = addon.preference()

        abc = active_tool()
        if abc.idname != 'BoxCutter':
            bpy.context.window_manager.gizmo_group_type_unlink_delayed(BC_WGT_GizmoGroup.bl_idname)

        mpr_z = self.mpr_z
        dial_z = self.dial_z
        mpr_x = self.mpr_x
        dial_x = self.dial_x
        mpr_y = self.mpr_y
        dial_y = self.dial_y
        mid = self.mid

        if bpy.context.window_manager.bc.running:
            mpr_z.hide = True
            dial_z.hide = True
            mpr_x.hide = True
            dial_x.hide = True
            mpr_y.hide = True
            dial_y.hide = True
            mid.hide = True
        else:
            if preference.surface == 'CURSOR':
                mpr_z.hide = False
                dial_z.hide = False
                mpr_x.hide = False
                dial_x.hide = False
                mpr_y.hide = False
                dial_y.hide = False
                mid.hide = False
            else:
                mpr_z.hide = True
                dial_z.hide = True
                mpr_x.hide = True
                dial_x.hide = True
                mpr_y.hide = True
                dial_y.hide = True
                mid.hide = True

        orig_loc = context.scene.cursor.location
        orig_rot = context.scene.cursor.rotation_euler

        x_rot_mat = orig_rot.to_matrix().to_4x4() @ Matrix.Rotation(radians(90), 4, 'Y')
        x_dial_rot_mat = orig_rot.to_matrix().to_4x4() @ Matrix.Rotation(radians(-90), 4, 'Y')
        y_rot_mat = orig_rot.to_matrix().to_4x4() @ Matrix.Rotation(radians(-90), 4, 'X')
        z_rot_mat = orig_rot.to_matrix().to_4x4() @ Matrix.Rotation(radians(90), 4, 'Z')

        orig_loc_mat = Matrix.Translation(orig_loc)
        orig_scale_mat = Matrix.Scale(1, 4, (1, 0, 0)) @ Matrix.Scale(1, 4, (0, 1, 0)) @ Matrix.Scale(1, 4, (0, 0, 1))

        z_matrix_world = orig_loc_mat @ z_rot_mat @ orig_scale_mat
        x_matrix_world = orig_loc_mat @ x_rot_mat @ orig_scale_mat
        x_dial_matrix_world = orig_loc_mat @ x_dial_rot_mat @ orig_scale_mat
        y_matrix_world = orig_loc_mat @ y_rot_mat @ orig_scale_mat
        mid_matrix_world = orig_loc_mat @ orig_rot.to_matrix().to_4x4() @ orig_scale_mat

        mpr_z.matrix_basis = z_matrix_world.normalized()
        mpr_x.matrix_basis = x_matrix_world.normalized()
        mpr_y.matrix_basis = y_matrix_world.normalized()

        dial_x.matrix_basis = x_dial_matrix_world.normalized()
        dial_y.matrix_basis = y_matrix_world.normalized()
        dial_z.matrix_basis = z_matrix_world.normalized()

        mid.matrix_basis = mid_matrix_world.normalized()
Esempio n. 15
0
    def IsAdmited(self):
        global faces_to_unfold, mesh_to_unfold, island_verts, island_faces
        if (self.parentface_relationships == None):
            root = True
            print("La face ", self.srcfaceindex, " est la racine de son îlot.")
        else:
            root = False
            print("La face ", self.srcfaceindex, "est l'enfant de la face",
                  self.parentface_relationships.srcfaceindex)
        fa = mesh_to_unfold.polygons[self.srcfaceindex]
        if root:

            def minz(vertice):
                """
                trouve parmi une liste d'indices de vertices, l'indice du vertex dont la coordonée z est la plus basse              
                """
                #global mesh_to_unfold
                lowestve_meshindice = vertice[
                    0]  #indice par rapport au mesh du vertice le plus bas (ie dont la coordonnée z est  la plus petite)
                lowestve_faindice = 0  #indice par rapport au poly de l'indice par rapport au mesh du vertice le plus bas
                for i, ve in enumerate(vertice):
                    if mesh_to_unfold.vertices[ve].co[
                            2] <= mesh_to_unfold.vertices[
                                lowestve_meshindice].co[2]:
                        lowestve_faindice = i
                        lowestve_meshindice = ve
                return (lowestve_meshindice, lowestve_faindice)

            #choix du premier vertex de référence
            #celui qui va définir la translation qu'on va appliquer à la face
            #pour que ce premier vertex de référence se retrouve dans le plan z=0
            vertref1_meshindice = minz(fa.vertices)[0]
            vertref1 = mesh_to_unfold.vertices[
                vertref1_meshindice]  #de la classe MeshVertex
            #calcul des vecteurs de départ et d'arrivée de la transtation
            v1 = Vector(vertref1.co)
            v2 = Vector((vertref1.co.x, vertref1.co.y,
                         0))  #v2 projection de v1 sur le plan z=0
            vertref1_faindice = minz(fa.vertices)[1]
        else:
            #si la face courante a déjà une face parente dans l'îlot,
            #on recherche l'arête commune entre la face courante et la face parente.
            parentfa = mesh_to_unfold.polygons[
                self.parentface_relationships.srcfaceindex]
            commonedgevertice_meshindexes = [
            ]  #les indices absolus des 2 vertices de l'arête commune
            commonedgevertice_faindexes = [
            ]  #les indices des 2 vertices de l'arête commune dans la face courante
            commonedgevertice_parentfaindexes = [
            ]  #les indices des 2 vertices de l'arête commune dans la face parente
            for i, vi in enumerate(fa.vertices):
                for j, vj in enumerate(parentfa.vertices):
                    if (vi == vj):
                        commonedgevertice_meshindexes.append(vi)
                        commonedgevertice_faindexes.append(i)
                        commonedgevertice_parentfaindexes.append(j)
            vertref1_meshindice = commonedgevertice_meshindexes[
                0]  #index absolu du premier vertex de l'arête commune
            print("index absolu du premier vertex de l'arête commune : ",
                  vertref1_meshindice)
            v1 = Vector(mesh_to_unfold.vertices[vertref1_meshindice].co)
            vertref1_parentfaindice = commonedgevertice_parentfaindexes[
                0]  #index relatif à la face parente, du premier vertex de l'arête commune
            v2 = Vector(
                island_verts[self.parentface_relationships.
                             destfacevertsindexes[vertref1_parentfaindice]][1])
            vertref1_faindice = commonedgevertice_faindexes[
                0]  #index relatif à la face courante, du premier vertex de l'arête commune

        #calcul du vecteur de translation
        vt = v2 - v1
        #calcul des vertices translatés de la face courante
        vectors = [
            Vector(mesh_to_unfold.vertices[ve].co) + vt for ve in fa.vertices
        ]
        print("vectors après translation: ", vectors)

        if root:
            #choix du deuxième vertex de référence,
            #celui qui va définir la 1ère rotation qu'on va appliquer aux vertice de la face
            #cette rotation appliquée au deuxième vertex de référence va le ramener dans le plan z=0
            possiblechoices = [i for i in range(len(vectors))]
            possiblechoices.remove(
                vertref1_faindice
            )  # on écarte le vertex qui vient d'être translaté dans le plan z=0
            for i in possiblechoices:  # on écarte également un éventuel vertex qui serait à la verticale du 1er vertex de référence
                if (vectors[i].x == v2.x) and (vectors[i].y == v2.y):
                    possiblechoices.remove(i)
            vertref2_faindice = possiblechoices[
                0]  # sachant qu'on ne traite que des faces triangulaires, il reste 1 ou 2 choix possible, on prend arbitrairement le premier
            for i in possiblechoices:  # et on le compare au 2eme (s'il y en a un pour choisir celui qui est le plus près du plan z=0
                if abs(vectors[i].z) <= abs(vectors[vertref2_faindice].z):
                    vertref2_faindice = i

            #calcul des vecteurs définissant la 1ere rotation
            v1 = vectors[vertref2_faindice] - vectors[vertref1_faindice]
            pvertref2 = Vector(
                (vectors[vertref2_faindice].x, vectors[vertref2_faindice].y,
                 0))  #projection de vertref2 sur le plan z=0
            v2 = pvertref2 - vectors[vertref1_faindice]
        else:
            vertref2_faindice = commonedgevertice_faindexes[
                1]  #index relatif à la face courante du deuxième vertex de l'arête commune
            v1 = vectors[vertref2_faindice] - vectors[vertref1_faindice]
            print("v1 = ", v1)
            v2 = Vector(island_verts[
                self.parentface_relationships.destfacevertsindexes[
                    commonedgevertice_parentfaindexes[1]]]
                        [1]) - vectors[vertref1_faindice]
            print("v2 = ", v2)  # transformé du 2eme vertex de l'arête commune

        #calcul de la matrice de rotation
        angle12 = v1.angle(v2)
        print("angle de rotation : ", angle12)

        #calcul de l'axe de rotation
        v12 = v1.cross(v2)
        print("axe de rotation : ", v12)

        #calcul de la matrice de rotation
        rot1mat = Matrix.Rotation(angle12, 3, v12)
        print("matrice de rotation : ", rot1mat)

        def TransformVectors(vecs, vt, rotmat):
            """
            applique successivement une translation vt, une rotation rotmat, 
            et la translation inverse à tous les vecteurs de la liste vecs
            """
            vecs1 = [v + vt for v in vecs]
            vecs2 = [rotmat * v for v in vecs1]
            vecs3 = [v - vt for v in vecs2]
            return vecs3

        #applications de la transformation en 3 étapes
        #translation vers l'origine de sorte que le 1er vertex de référence soit inchangé par la rotation
        #rotation qui amène le 2eme vertex de référence dans le plan z=0, puis translation inverse
        vectors = TransformVectors(vectors, -vectors[vertref1_faindice],
                                   rot1mat)
        print("vectors après rotation 1 == ", vectors)

        #choix du 3eme vertex de reférence
        possiblechoices = [i for i in range(len(vectors))]
        possiblechoices.remove(vertref1_faindice)
        possiblechoices.remove(vertref2_faindice)
        vertref3_faindice = possiblechoices[0]
        print("ordre des indices = ", vertref1_faindice, ", ",
              vertref2_faindice, ", ", vertref3_faindice)

        #on veut poser la face sur le plan z=0 de sorte que sa normale pointe vers le haut
        #or on connait la normale de la face avant transformation
        #mais pas après les transformations qui viennent d'etre faite
        #on va donc comparer la normale avec le produit vectoriel des vecteurs v12(vertref1, vertref2) et v13(vertref1, vertref3)
        #et en fonction du résultat de la comparaison,
        #c'est soit le produit vectoriel des vecteurs transformés
        #soit le vecteur inverse qui servira au calcul de l'angle de rotation
        vertref1_meindice = fa.vertices[
            vertref1_faindice]  #on retrouve l'indice absolu du vertref1 à partir de son indice par rapport à la face courante
        vertref2_meindice = fa.vertices[vertref2_faindice]
        vertref3_meindice = fa.vertices[vertref3_faindice]
        print("indice absolu de vertref1 : ", vertref1_meindice,
              "vérification : ", vertref1_meshindice)
        print("indice absolu de vertref2 : ", vertref2_meindice)
        print("indice absolu de vertref3 : ", vertref3_meindice)
        vi1 = Vector(
            mesh_to_unfold.vertices[vertref1_meindice].co
        )  #vecteur initial 1 représentant le vertref1 avant transformation
        vi2 = Vector(mesh_to_unfold.vertices[vertref2_meindice].co)
        vi3 = Vector(mesh_to_unfold.vertices[vertref3_meindice].co)
        print("vi1 : ", vi1)
        print("vi2 : ", vi2)
        print("vi3 : ", vi3)
        vi12 = vi2 - vi1
        print("vi12 : ", vi12)
        vi13 = vi3 - vi1
        print("vi13 : ", vi13)
        vi12vi13 = vi12.cross(vi13)
        print("vi12vi13 : ", vi12vi13)
        angle_vi12vi13_no = vi12vi13.angle(fa.normal)
        if (angle_vi12vi13_no < pi): coef = 1
        else: coef = -1  #coeficient qui déterminera l'orientation du vecteur
        #on calcule maintenant le produit vectoriel de ces meme deux vecteurs dans leur position courante après transformation
        vc12 = vectors[vertref2_faindice] - vectors[vertref1_faindice]
        print("vc12 : ", vc12)
        vc13 = vectors[vertref3_faindice] - vectors[vertref1_faindice]
        print("vc13 : ", vc13)
        vc12vc13 = vc12.cross(vc13)
        print("vc12vc13 : ", vc12vc13)
        vo = vc12vc13 * coef  #vecteur "origine" de la rotation
        print("vo : ", vo)
        vd = Vector((0, 0, 1))  #vecteur "destination" de la rotation
        print("vd : ", vd)
        ar = vo.angle(vd)  #angle de la rotation
        print("angle de la rotation vo vd : ", ar)
        if (-0.001 < ar < 0.001) or (pi - 0.001 < ar < pi + 0.001):
            va = vc12  # dans ce cas particulier d'une rotation de 0 ou de 180p
        else:
            vod = vo.cross(
                vd
            )  #pour déterminer l'orientation du vecteur axe de la rotation
            angle_vod_vc12 = vod.angle(vc12)
            if (angle_vod_vc12 < pi): va = vc12
            else: va = -vc12
        print("axe de la rotation = ", va)
        print("angle de la rotation = ", ar)
        rot2mat = Matrix.Rotation(ar, 3, va)

        vectors = TransformVectors(vectors, -vectors[vertref1_faindice],
                                   rot2mat)
        print("vectors après rotation 2: ", vectors)

        if root:
            #puisque on commence un ilot, les 3 vertices de la face en cours sont nouveaux dans l'ilot
            #pour chaque vertex on renseigne son index dans le mesh source et ses coordonnées dans l'ilot en création.
            self.newverts = [[
                fa.vertices[i], [vectors[i].x, vectors[i].y, vectors[i].z]
            ] for i in range(len(fa.vertices))]
            #définition de la 1ere face de l'ilot
            self.destfacevertsindexes = [i for i in range(len(fa.vertices))]
        else:
            for i, vi in enumerate([ve for ve in fa.vertices]):
                if vi in commonedgevertice_meshindexes:  # si le vertice appartiend à l'arête commune, on ne l'ajoute pas à newverts parce qu'il y est déjà suite au traitement de la face parente
                    refindex = commonedgevertice_meshindexes.index(
                        vi
                    )  # index de ce vertice dans la liste des vertices de l'arête commune (0 ou 1)
                    parentfavertindex = commonedgevertice_parentfaindexes[
                        refindex]  #index de ce même vertice dans la liste des vertice de la face parente
                    self.destfacevertsindexes.append(
                        self.parentface_relationships.
                        destfacevertsindexes[parentfavertindex]
                    )  # l'index du vertice correspondant dans l'ilot
                else:
                    self.destfacevertsindexes.append(
                        len(island_verts)
                    )  # creation d'un nouvel index pour ajouter ce vertex à l'ilot en cours
                    self.newverts.append(
                        [vi, [vectors[i].x, vectors[i].y, vectors[i].z]]
                    )  #on ajoute à la liste des nouveaux vertice, les vertices qui n'appartiennent pas à l'arête commune
        return True  # pour l'instant on admet toutes les faces sans vérifier le chevauchement.
Esempio n. 16
0
    def _export(self, filepath, objs):
        _rotate_axis = lambda angle, axis: Matrix.Rotation(
            math.radians(angle), 4, axis)

        _debug_print_quaternion = lambda q: [(math.degrees(x)
                                              if (x <= -1.0e-05) or
                                              (x >= 1.0e-05) else 0.0)
                                             for x in q.to_euler()]
        _debug_print_rot_matrix = lambda m: _debug_print_quaternion(
            m.decompose()[1])

        def _get_axis_root_matrix(obj):
            return _rotate_axis(-90.0, 'X').inverted()

        def _get_axis_matrix(obj, rot_mat=Matrix()):
            r1 = _rotate_axis(-90.0, 'X')
            r2 = _rotate_axis(180.0, 'Y')
            return ((r2 * (r1 * ((obj.matrix_local * rot_mat) * r2))))

        def _rotate_camera(obj, is_root):
            _rotate_object(obj, is_root, _rotate_axis(90.0, 'Y').inverted())

        def _rotate_empty(obj, is_root):
            _rotate_object(obj, is_root, _rotate_axis(90.0, 'X'))

        def _scale_mesh(obj, is_root):
            _, _, scale = obj.matrix_local.decompose()
            mesh = obj.data
            new_bmesh = bmesh.new()
            new_bmesh.from_mesh(mesh)
            unique_verts = sorted(list(
                set([vert for face in new_bmesh.faces
                     for vert in face.verts])),
                                  key=lambda vert: vert.index)
            bmesh.ops.scale(new_bmesh, vec=scale, verts=unique_verts)
            new_bmesh.to_mesh(mesh)
            mesh.update()
            new_bmesh.free()
            obj.scale = (1.0, 1.0, 1.0)
            bpy.context.scene.update()

        def _rotate_mesh(obj, is_root, apply_rotation):
            _, rotation, _ = obj.matrix_local.decompose()
            mesh_rot_matrix = (_rotate_axis(180.0, 'Z') *
                               _rotate_axis(90.0, 'X') *
                               (rotation.to_matrix().to_4x4()
                                if apply_rotation else Matrix()))
            mesh = obj.data
            new_bmesh = bmesh.new()
            new_bmesh.from_mesh(mesh)
            unique_verts = sorted(list(
                set([vert for face in new_bmesh.faces
                     for vert in face.verts])),
                                  key=lambda vert: vert.index)
            bmesh.ops.rotate(new_bmesh,
                             cent=(0.0, 0.0, 0.0),
                             matrix=mesh_rot_matrix,
                             verts=unique_verts)
            new_bmesh.to_mesh(mesh)
            mesh.update()
            new_bmesh.free()
            bpy.context.scene.update()
            if apply_rotation:
                _rotate_root_object(obj, is_root)
            else:
                _rotate_object(obj, is_root, _rotate_axis(90.0, 'X'))

        def _rotate_root_object(obj, is_root):
            matrix = _get_axis_root_matrix(obj) if is_root else Matrix()
            _, rotation, _ = matrix.decompose()
            obj.rotation_euler = rotation.to_euler()

        def _rotate_object(obj, is_root, rot_mat=Matrix()):
            matrix = ((_get_axis_root_matrix(obj) if is_root else Matrix()) *
                      _get_axis_matrix(obj, rot_mat))
            _, rotation, _ = matrix.decompose()
            obj.rotation_euler = rotation.to_euler()

        def _translate_object(obj, is_root):
            local_loc = obj.matrix_local.to_translation()
            world_loc = obj.matrix_world.to_translation()
            diff_loc = world_loc - local_loc
            if is_root:
                obj.location = -diff_loc + (_rotate_axis(180.0, 'Z') *
                                            (diff_loc + local_loc))
            else:
                obj.location = (_rotate_axis(180.0, 'Z') *
                                _rotate_axis(90.0, 'X')) * local_loc

        def _parent_in_list(obj, objs):
            """Return True if obj has a parent in objs. False otherwise."""
            def _parent_in_list(obj, first_obj, objs):
                if obj is None:
                    return []
                return [obj if (obj in objs) and (obj != first_obj) else None
                        ] + _parent_in_list(obj.parent, first_obj, objs)

            return any(_parent_in_list(obj, obj, objs))

        with helper_utils.DuplicateScene() as override_context:
            objs = [obj for obj in bpy.context.selected_objects]
            for obj in objs:
                is_root = not _parent_in_list(obj, objs)
                if obj.type == 'MESH':
                    _translate_object(obj, is_root)
                    _scale_mesh(obj, is_root)
                    _rotate_mesh(obj, is_root, obj.apply_rotation)
                elif obj.type == 'CAMERA':
                    _translate_object(obj, is_root)
                    _rotate_camera(obj, is_root)
                elif obj.type == 'EMPTY':
                    _translate_object(obj, is_root)
                    _rotate_empty(obj, is_root)
            # Update override context
            override_context['selected_objects'] = objs
            # Finally, export
            bpy.ops.export_scene.fbx(
                override_context,
                filepath=self.filepath,
                check_existing=False,
                axis_forward='Y',
                axis_up='Z',
                use_selection=True,
                global_scale=1.0,
                apply_unit_scale=False,
                bake_anim=False,
                object_types={'EMPTY', 'CAMERA', 'LAMP', 'MESH'},
                use_custom_props=True)
class ReconstructionBundle(ReconstructionBase):
    """The actual SfM reconstruction imported form a Bundle file.

    https://www.cs.cornell.edu/~snavely/bundler/
    File format: https://www.cs.cornell.edu/~snavely/bundler/bundler-v0.4-manual.html#S6
    """

    SUPPORTED_EXTENSION = ".rd.out"

    # coordinates conversion matrix, from canonical right handed (Y-up) to blender's (Z-up)
    BUNDLE_TO_BLENDER = Matrix.Rotation(-pi / 2, 4, 'X')

    LIST_FILE_REGEX = re.compile(r'(.*?[0-9]+\.[a-zA-Z]+)(\s|$)')

    ################################################################################################
    # Constructor and destructor
    #

    # ==============================================================================================
    def __init__(self, name: str, bundle_file_path: str):
        """Create a reconstruction object and load the reconstruction from the Bundle file.

        Arguments:
            name {str} -- reconstruction name
            file_path {str} -- path to the bundle.rd.out reconstruction file
        """
        super().__init__(name)
        #
        self.file_path = os.path.abspath(bundle_file_path)
        self.file = open(self.file_path, "r")
        self.file.seek(0, 2)
        self.file_end = self.file.tell()  # get char count
        self.file.seek(0)
        #
        self._load_reconstruction()

    # ==============================================================================================
    def __del__(self):
        """Ensure file release on object deletion."""
        if hasattr(self, "file"):
            self.close()
        super().__del__()

    # ==============================================================================================
    def close(self) -> None:
        """Close the Bundle file if necessary.
        This is called by '__del__' to enure proper resource release.
        """
        if self.file:
            self.file.close()

    ################################################################################################
    # Helpers
    #

    # ==============================================================================================
    def _load_reconstruction(self) -> None:
        """Read the content of an Bundle reconstruction file and populate data structures.

        File format: https://www.cs.cornell.edu/~snavely/bundler/bundler-v0.4-manual.html

        Raises:
            ValueError: if something goes wrong reading the Bundle file (unexpected header, wrong cameras or points).
                        Other errors are raised if there are errors in the Bundle file structure or file access.
        """
        cam_name_list = self._load_camera_list()
        # read file header
        header = self.file.readline().strip()
        if header != "# Bundle file v0.3":
            msg = "Unexpected header '{}' (expected '# Bundle file v0.3')".format(
                header)
            logger.error(msg)
            raise ValueError(msg)
        #
        # get quantity of available cameras and points in file
        l = self._read_line()
        camera_count = int(l[0])
        point_count = int(l[1])
        assert camera_count == len(
            cam_name_list)  # the amount of cameras must match across files
        #
        model = ReconModel(self.name + '_0')
        model.number_of_cameras = camera_count
        #
        # load reconstructed camera poses
        for i in range(0, camera_count):
            #
            # <f> <k1> <k2>   [focal length follwed by 2 radial distortion coefficients]
            f_k1_k2 = self._read_line()
            #
            # <R>             [3x3 matrix, camera rotation]
            r = Matrix.Identity(3)
            for row in range(3):
                r[row] = list(map(float, self._read_line()))
            #
            # <t>             [XYZ vector, camera translation]
            t = Vector(list(map(float, self._read_line())))
            #
            # build world matrix
            w2c = r.to_4x4()
            w2c[0][3] = t.x
            w2c[1][3] = t.y
            w2c[2][3] = t.z
            c2w = w2c.inverted()
            c2w = ReconstructionBundle.BUNDLE_TO_BLENDER @ c2w
            #
            model.add_camera(
                ReconCamera(cam_name_list[i], float(f_k1_k2[0]), c2w,
                            list(map(float, f_k1_k2[1:2]))))
        #
        # load reconstructed point cloud
        pc = PointCloud(point_count)
        for i in range(0, point_count):
            #
            # <position>      [a 3-vector describing the 3D position of the point]
            p = ReconstructionBundle.BUNDLE_TO_BLENDER @ Vector(
                list(map(float, self._read_line())))
            #
            # <color>         [a 3-vector describing the RGB color of the point]
            c = Color(list(map(int, self._read_line()))) / 255.
            #
            # <view list>     [a list of views the point is visible in]
            self._read_line()  # currently unused
            #
            pc.add_point(p, c)
        #
        model.point_cloud = pc
        self.add_model(model)
        #
        # close, everything has been read
        self.close()

    # ==============================================================================================
    def _load_camera_list(self) -> List[str]:
        """Load the camera list file names in the same order of appearance in the bundle.rd.out file.

        Raises:
            FileNotFoundError: if bundle.rd.out.list.txt OR list.txt are missing

        Returns:
            List[str] -- list of file names
        """
        files_dir = os.path.dirname(self.file_path)
        f_names = []
        #
        # handle VisualSfM special case, images are renamed during export for PMVS.
        # in this case original images names (frame numbers) can be found in
        # "cameras_v2.txt" instead of "bundle.rd.out.list.txt"
        camera_list_filename = os.path.join(files_dir, "cameras_v2.txt")
        if os.path.isfile(
                camera_list_filename
        ):  # if file exists assume is a VisualSfM reconstruction
            with open(camera_list_filename, "r") as f:
                #
                # check header
                header = f.readline().strip()
                if not header == "# Camera parameter file.":
                    raise ValueError("Wrong file format (" + header +
                                     ") for VisualSfM \"cameras_v2.txt\"")
                logger.info("Found VisualSfM cameras v2 file")
                for _ in range(15):
                    f.readline()  # discard header
                #
                # get camera quantity
                cam_count = int(f.readline().strip())
                #
                # load frame numbers form file
                for _ in range(cam_count):
                    while f.readline() != "\n":  # discard unused data
                        pass
                    f.readline()  # discard first line (new filename)
                    #
                    f_names.append(f.readline())  # get original image path
        #
        #
        # back to normal case
        else:
            cameraListFileName = os.path.join(files_dir,
                                              "bundle.rd.out.list.txt")
            if not os.path.isfile(cameraListFileName):
                cameraListFileName = os.path.join(files_dir, "list.txt")
                if not os.path.isfile(cameraListFileName):
                    raise FileNotFoundError(
                        "Could not find bundle.rd.out.list.txt OR list.txt")
            #
            with open(cameraListFileName, "r") as f:
                for _, line in enumerate(iter(f.readline, '')):
                    filename = ReconstructionBundle.LIST_FILE_REGEX.match(line)
                    filename = filename.group(1)
                    f_names.append(filename)
        #
        return f_names

    # ==============================================================================================
    def _read_line(self) -> List[str]:
        """Read a line from the bundle file. Automatically discard empty lines and comments.

        Returns:
            List[str] -- the list of string tokens in the line

        Raises:
            EOFError: if reading lines after end of file
        """
        while True:
            line = self.file.readline().strip()
            if line == '' and self.file.tell() >= self.file_end:
                raise EOFError("Reading after file end!")
            elif line != '' and not line.startswith(
                    '#'):  # skip empty lines and comments
                return line.split()
Esempio n. 18
0
def update_mesh_to_curve(self, bm, deform_type, obj):
    lw_tool_vec = self.lw_tool.end_point.position - self.lw_tool.start_point.position
    lw_tool_dir = (self.lw_tool.end_point.position -
                   self.lw_tool.start_point.position).normalized()

    if deform_type == 'Deform':  # DEFORM TYPE ONLY
        deform_lines, points_indexes = get_bezier_area_data(self.curve_tool)
        line_len = deform_lines[-1][1]

        zero_vec = Vector((0.0, 0.0, 0.0))

        # get bezier dirs
        b_dirs = []
        for b_point_data in deform_lines:
            # bezier point direction
            b_point_dir = None
            index_point = deform_lines.index(b_point_data)
            if index_point < len(deform_lines) - 1:
                b_point_dir = deform_lines[index_point - 1][3]
            else:
                b_point_dir = b_point_data[3]

            #check_angle = b_point_dir.angle(self.tool_up_vec)

            ### upVec approach by me
            ## calculate using cross vec
            #b_point_up = b_point_dir.cross(self.tool_up_vec).normalized()

            # upVec approach by mano-wii version 1
            pzv = self.tool_up_vec.project(
                b_point_dir)  # here we project the direction to get upVec
            b_point_up = (self.tool_up_vec - pzv).normalized()

            ## upVec approach by mano-wii version 2
            #dot = self.tool_up_vec.dot(b_point_dir)
            #pzv = dot * b_point_dir  # here we dot the direction to get upVec
            #b_point_up = (self.tool_up_vec - pzv).normalized()

            # invert direction feature
            if self.invert_deform_upvec is True:
                b_point_up.negate()

            # fix directions according to previous upvec
            if b_dirs:
                if b_point_up.length == 0.0:
                    b_point_up = b_dirs[-1][1].copy()
                elif b_dirs[-1][1].angle(b_point_up) > math.radians(90.0):
                    # here we invert upVec if it was incorrect according to previous one
                    b_point_up.negate()

            b_point_side = b_point_dir.cross(b_point_up).normalized()

            b_dirs.append([b_point_dir, b_point_up, b_point_side])

        # find the best point for every vert
        for vert_id in self.work_verts.keys():
            vert = bm.verts[vert_id]
            vert_data = self.work_verts[vert_id]

            for i, point in enumerate(self.curve_tool.curve_points):
                if i > 0:
                    point_len = deform_lines[points_indexes.get(
                        point.point_id)][1] / line_len
                    vert_len = vert_data[1] / lw_tool_vec.length
                    if point_len >= vert_len:
                        # max is for the first point
                        first_index = 0
                        if i > 0:
                            first_index = points_indexes.get(
                                self.curve_tool.curve_points[
                                    self.curve_tool.curve_points.index(point) -
                                    1].point_id)

                        # get the best point
                        #b_point_up = None
                        #b_point_side = None
                        best_pos = None
                        for b_point_data in deform_lines[first_index:]:
                            j = deform_lines.index(b_point_data)
                            #print(j, jj)
                            if j > 0:
                                b_point_len = b_point_data[1] / line_len
                                if b_point_len >= vert_len:

                                    b_point_dirs = b_dirs[deform_lines.index(
                                        b_point_data)]

                                    # best position
                                    if b_point_len == vert_len:
                                        best_pos = b_point_data[0]
                                    else:
                                        previous_pos_len = deform_lines[
                                            j - 1][1] / line_len

                                        interp_pos = (
                                            vert_len -
                                            previous_pos_len) * line_len

                                        # fix for interpolation between lines
                                        if j > 1 and j < len(deform_lines) - 1:
                                            prev_b_point_dirs = b_dirs[
                                                deform_lines.index(
                                                    b_point_data)]
                                            b_point_dirs_temp = b_dirs[
                                                deform_lines.index(
                                                    b_point_data) + 1]
                                            b_point_dirs = b_point_dirs.copy()

                                            new_side_vec = prev_b_point_dirs[
                                                1].lerp(
                                                    b_point_dirs_temp[1],
                                                    interp_pos).normalized()
                                            b_point_dirs[1] = new_side_vec
                                            new_side_vec = prev_b_point_dirs[
                                                2].lerp(
                                                    b_point_dirs_temp[2],
                                                    interp_pos).normalized()
                                            b_point_dirs[2] = new_side_vec

                                        best_pos = deform_lines[j - 1][0] + (
                                            (interp_pos) * b_point_dirs[0])

                                    break

                        vert.co = obj.matrix_world.inverted() * (
                            best_pos + (b_point_dirs[1] * vert_data[3]) -
                            (b_point_dirs[2] * vert_data[2]))
                        break

    else:  # ALL OTHER TYPES
        # get points dists
        points_dists = []
        for point in self.curve_tool.curve_points:
            bezier_dists = []
            p_dist = mathu.geometry.distance_point_to_plane(
                point.position, self.lw_tool.start_point.position, lw_tool_dir)

            # add bezer dists
            if self.curve_tool.curve_points.index(point) > 0:
                for b_point in self.curve_tool.display_bezier[point.point_id]:
                    b_p_dist = mathu.geometry.distance_point_to_plane(
                        b_point, self.lw_tool.start_point.position,
                        lw_tool_dir)
                    b_p_side_dist = mathu.geometry.distance_point_to_plane(
                        b_point, self.lw_tool.start_point.position,
                        self.tool_side_vec)
                    bezier_dists.append((b_p_dist, b_p_side_dist, b_point))

            points_dists.append((p_dist, bezier_dists))

        # find the best point for every vert
        for vert_id in self.work_verts.keys():
            vert = bm.verts[vert_id]
            vert_data = self.work_verts[vert_id]

            deform_dir = None
            if deform_type == 'Scale':
                deform_dir = (vert_data[0] -
                              (self.lw_tool.start_point.position +
                               (lw_tool_dir * vert_data[1]))).normalized()
            else:
                deform_dir = self.tool_side_vec

            for i, point_data in enumerate(points_dists):
                if point_data[0] >= vert_data[1]:
                    best_bezier_len = None
                    vert_front_pos = self.lw_tool.start_point.position + (
                        lw_tool_dir * vert_data[1])

                    # loop bezier points according to vert
                    for j, b_point in enumerate(point_data[1]):
                        if not best_bezier_len:
                            best_bezier_len = b_point[1]
                        elif b_point[0] >= vert_data[1]:
                            bp_nor = (b_point[2] -
                                      point_data[1][j - 1][2]).normalized()
                            bp_nor = bp_nor.cross(
                                self.tool_up_vec).normalized()
                            final_pos = mathu.geometry.intersect_line_plane(
                                vert_front_pos - (self.tool_side_vec * 1000.0),
                                vert_front_pos + (self.tool_side_vec * 1000.0),
                                b_point[2], bp_nor)

                            best_bezier_len = (
                                final_pos -
                                vert_front_pos).length  # the length!

                            if deform_type in {'Shear', 'Twist'}:
                                if (final_pos - vert_front_pos).normalized(
                                ).angle(self.tool_side_vec) > math.radians(90):
                                    best_bezier_len = -best_bezier_len
                            break

                    #final_dist = best_bezier_len

                    # multiplier for the vert
                    dir_multilpier = None
                    if deform_type == 'Stretch':
                        dir_multilpier = (
                            vert_data[2] *
                            (best_bezier_len /
                             self.tool_side_vec_len)) - vert_data[2]
                    elif deform_type in {'Shear', 'Twist'}:
                        dir_multilpier = best_bezier_len - self.tool_side_vec_len
                    else:
                        vert_dist_scale = (vert_data[0] -
                                           vert_front_pos).length
                        dir_multilpier = abs(
                            vert_dist_scale *
                            (best_bezier_len /
                             self.tool_side_vec_len)) - vert_dist_scale

                    # modify vert position
                    if deform_type == 'Twist':
                        twist_angle = dir_multilpier * math.radians(90)
                        rot_mat = Matrix.Rotation(twist_angle, 3, lw_tool_dir)
                        vert.co = obj.matrix_world.inverted() * (
                            rot_mat *
                            (vert_data[0] - self.lw_tool.start_point.position)
                            + self.lw_tool.start_point.position)
                    else:
                        vert.co = obj.matrix_world.inverted() * (
                            vert_data[0] + (deform_dir * dir_multilpier))
                    break
def fillets(list_0, startv, vertlist, face, adj, n, out, flip, radius):
    try:
        dict_0 = get_adj_v_(list_0)
        list_1 = [[dict_0[i][0], i, dict_0[i][1]] for i in dict_0 if (len(dict_0[i]) == 2)][0]
        list_3 = []
        for elem in list_1:
            list_3.append(bm.verts[elem])
        list_2 = []

        p_ = list_3[1]
        p = (list_3[1].co).copy()
        p1 = (list_3[0].co).copy()
        p2 = (list_3[2].co).copy()

        vec1 = p - p1
        vec2 = p - p2

        ang = vec1.angle(vec2, any)
        check_angle = round(degrees(ang))

        if check_angle == 180 or check_angle == 0.0:
            return False
        else:
            f_buf.check = True

        opp = adj

        if radius is False:
            h = adj * (1 / cos(ang * 0.5))
            adj_ = adj
        elif radius is True:
            h = opp / sin(ang * 0.5)
            adj_ = opp / tan(ang * 0.5)

        p3 = p - (vec1.normalized() * adj_)
        p4 = p - (vec2.normalized() * adj_)
        rp = p - ((p - ((p3 + p4) * 0.5)).normalized() * h)

        vec3 = rp - p3
        vec4 = rp - p4

        axis = vec1.cross(vec2)

        if out is False:
            if flip is False:
                rot_ang = vec3.angle(vec4)
            elif flip is True:
                rot_ang = vec1.angle(vec2)
        elif out is True:
            rot_ang = (2 * pi) - vec1.angle(vec2)

        for j in range(n + 1):
            new_angle = rot_ang * j / n
            mtrx = Matrix.Rotation(new_angle, 3, axis)
            if out is False:
                if flip is False:
                    tmp = p4 - rp
                    tmp1 = mtrx @ tmp
                    tmp2 = tmp1 + rp
                elif flip is True:
                    p3 = p - (vec1.normalized() * opp)
                    tmp = p3 - p
                    tmp1 = mtrx @ tmp
                    tmp2 = tmp1 + p
            elif out is True:
                p4 = p - (vec2.normalized() * opp)
                tmp = p4 - p
                tmp1 = mtrx @ tmp
                tmp2 = tmp1 + p

            v = bm.verts.new(tmp2)
            list_2.append(v)

        if flip is True:
            list_3[1:2] = list_2
        else:
            list_2.reverse()
            list_3[1:2] = list_2

        list_clear_(list_2)

        n1 = len(list_3)

        for t in range(n1 - 1):
            bm.edges.new([list_3[t], list_3[(t + 1) % n1]])

            v = bm.verts.new(p)
            bm.edges.new([v, p_])

        bm.edges.ensure_lookup_table()

        if face is not None:
            for l in face.loops:
                if l.vert == list_3[0]:
                    startl = l
                    break
            vertlist2 = []

            if startl.link_loop_next.vert == startv:
                l = startl.link_loop_prev
                while len(vertlist) > 0:
                    vertlist2.insert(0, l.vert)
                    vertlist.pop(vertlist.index(l.vert))
                    l = l.link_loop_prev
            else:
                l = startl.link_loop_next
                while len(vertlist) > 0:
                    vertlist2.insert(0, l.vert)
                    vertlist.pop(vertlist.index(l.vert))
                    l = l.link_loop_next

            for v in list_3:
                vertlist2.append(v)
            bm.faces.new(vertlist2)
        if startv.is_valid:
            bm.verts.remove(startv)
        else:
            print("\n[Function fillets Error]\n"
                  "Starting vertex (startv var) couldn't be removed\n")
            return False
        bm.verts.ensure_lookup_table()
        bm.edges.ensure_lookup_table()
        bm.faces.ensure_lookup_table()
        list_3[1].select = 1
        list_3[-2].select = 1
        bm.edges.get([list_3[0], list_3[1]]).select = 1
        bm.edges.get([list_3[-1], list_3[-2]]).select = 1
        bm.verts.index_update()
        bm.edges.index_update()
        bm.faces.index_update()

        me.update(calc_edges=True, calc_loop_triangles=True)
        bmesh.ops.recalc_face_normals(bm, faces=bm.faces)

    except Exception as e:
        print("\n[Function fillets Error]\n{}\n".format(e))
        return False
    def execute(self, context):
        obj = bpy.context.edit_object
        bm = bmesh.from_edit_mesh(obj.data)
        uv = bm.loops.layers.uv[int(self.p_dest_uv)]
        grid_scale = context.space_data.overlay.grid_scale
        selected_faces = [face for face in bm.faces if face.select and not face.hide]
        active_face = bm.select_history.active
        size = bpy.data.images[int(self.p_checker)].size; size = Vector((1.0 / size[0], 1.0 / size[1]))
        negate_first = Vector((-1, 1))

        # auto pick axis
        axis = self.p_axis
        if axis == 'CLOSEST':
            if type(active_face) is not BMFace:
                self.report({'WARNING'}, "Operation cancelled: No active face")
                return {'CANCELLED'}
            axis = self.closest_axis(active_face.normal)

        # projection
        if axis == 'XPOS':
            for face in selected_faces:
                for loop in face.loops:
                    loop[uv].uv.xy = loop.vert.co.yz * size / grid_scale
        elif axis == 'XNEG':
            for face in selected_faces:
                for loop in face.loops:
                    loop[uv].uv.xy = loop.vert.co.yz * negate_first * size / grid_scale
        elif axis == 'YPOS':
            for face in selected_faces:
                for loop in face.loops:
                    loop[uv].uv.xy = loop.vert.co.xz * negate_first * size / grid_scale
        elif axis == 'YNEG':
            for face in selected_faces:
                for loop in face.loops:
                    loop[uv].uv.xy = loop.vert.co.xz * size / grid_scale
        elif axis == 'ZPOS':
            for face in selected_faces:
                for loop in face.loops:
                    loop[uv].uv.xy = loop.vert.co.xy * size / grid_scale
        elif axis == 'ZNEG':
            for face in selected_faces:
                for loop in face.loops:
                    loop[uv].uv.xy = loop.vert.co.xy * negate_first * size / grid_scale
        elif axis == 'ACTIVE':
            # a very different case
            if type(active_face) is not BMFace:
                self.report({'WARNING'}, "Operation cancelled: No active face")
                return {'CANCELLED'}
            
            # grab some edge as a temporary axis, then rotate the basis the same amount in 3d it has to be rotated in the uv
            # to align with pixel edges
            edge:bmesh.types.BMEdge = None
            for e in active_face.edges:
                if e in active_face.edges and e.calc_length() > 0:
                    edge = e
                    break
            assert edge is not None
            ends = [l for l in active_face.loops if edge in l.vert.link_edges]

            dir_uv = Vector((ends[1][uv].uv.x - ends[0][uv].uv.x, ends[1][uv].uv.y - ends[0][uv].uv.y))
            to_x = dir_uv.angle((1.0, 0.0))

            z_3d = active_face.normal
            dir_3d = Vector((ends[1].vert.co.x - ends[0].vert.co.x, ends[1].vert.co.y - ends[0].vert.co.y, ends[1].vert.co.z - ends[0].vert.co.z))
            dir_3d.normalize()
            x_3d = Matrix.Rotation(to_x, 4, z_3d) @ dir_3d
            y_3d = z_3d.cross(x_3d)

            print(x_3d, y_3d, z_3d)
            # basis = Matrix(x_3d, y_3d, z_3d).to_4x4()

        # pin if asked
        if self.p_pin:
            for face in selected_faces:
                for loop in face.loops:
                    loop[uv].pin_uv = True

        # apply changes
        bmesh.update_edit_mesh(obj.data)

        return {'FINISHED'}
Esempio n. 21
0
 def getNeckData(self):
     bones = bpy.evaAnimationManager.deformObj.pose.bones
     rneck = bones['DEF-neck'].matrix * Matrix.Rotation(-pi / 2, 4, 'X')
     q = rneck.to_quaternion()
     return {'x': q.x, 'y': q.y, 'z': q.z, 'w': q.w}
Esempio n. 22
0
    def process(self):

        inputs = self.inputs
        outputs = self.outputs

        if not (inputs['Vertices'].is_linked and inputs['Polygons'].is_linked):
            return
        if not any(socket.is_linked for socket in outputs):
            return

        vector_in = self.scale_socket_type

        vertices_s = inputs['Vertices'].sv_get()
        edges_s = inputs['Edges'].sv_get(default=[[]])
        faces_s = inputs['Polygons'].sv_get(default=[[]])
        masks_s = inputs['Mask'].sv_get(default=[[1]])
        heights_s = inputs['Height'].sv_get()
        scales_s = inputs['Scale'].sv_get()

        linked_extruded_polygons = outputs['ExtrudedPolys'].is_linked
        linked_other_polygons = outputs['OtherPolys'].is_linked

        result_vertices = []
        result_edges = []
        result_faces = []
        result_extruded_faces = []
        result_other_faces = []

        meshes = match_long_repeat(
            [vertices_s, edges_s, faces_s, masks_s, heights_s, scales_s])

        for vertices, edges, faces, masks, heights, scales in zip(*meshes):

            new_extruded_faces = []
            new_extruded_faces_append = new_extruded_faces.append
            fullList(heights, len(faces))
            fullList(scales, len(faces))
            fullList(masks, len(faces))

            bm = bmesh_from_pydata(vertices, edges, faces)
            extruded_faces = bmesh.ops.extrude_discrete_faces(
                bm, faces=bm.faces)['faces']

            for face, mask, height, scale in zip(extruded_faces, masks,
                                                 heights, scales):

                if not mask:
                    continue

                vec = scale if vector_in else (scale, scale, scale)

                # preparing matrix
                normal = face.normal
                if normal[0] == 0 and normal[1] == 0:
                    m_r = Matrix() if normal[2] >= 0 else Matrix.Rotation(
                        pi, 4, 'X')
                else:
                    z_axis = normal
                    x_axis = (Vector(
                        (z_axis[1] * -1, z_axis[0], 0))).normalized()
                    y_axis = (z_axis.cross(x_axis)).normalized()
                    m_r = Matrix(list([*zip(x_axis[:], y_axis[:], z_axis[:])
                                       ])).to_4x4()

                dr = face.normal * height
                center = face.calc_center_median()
                translation = Matrix.Translation(center)
                m = (translation * m_r).inverted()

                # inset, scale and push operations
                bmesh.ops.scale(bm, vec=vec, space=m, verts=face.verts)
                bmesh.ops.translate(bm, verts=face.verts, vec=dr)

                if linked_extruded_polygons or linked_other_polygons:
                    new_extruded_faces_append([v.index for v in face.verts])

            new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
            bm.free()

            new_other_faces = [
                f for f in new_faces if f not in new_extruded_faces
            ] if linked_other_polygons else []

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_extruded_faces.append(new_extruded_faces)
            result_other_faces.append(new_other_faces)

        outputs['Vertices'].sv_set(result_vertices)
        outputs['Edges'].sv_set(result_edges)
        outputs['Polygons'].sv_set(result_faces)
        outputs['ExtrudedPolys'].sv_set(result_extruded_faces)
        outputs['OtherPolys'].sv_set(result_other_faces)
Esempio n. 23
0
flip_x_z = {
    "L": Matrix(((1, 0, 0, 0), (0, 0, 0, 1), (0, 0, -1, 0), (0, -1, 0, 0))),
    "R": Matrix(((1, 0, 0, 0), (0, 0, 0, -1), (0, 0, 1, 0), (0, 1, 0, 0))),
}


def qrotation(mat):
    def rot(v):
        return (v[3], v[0], v[1], v[2])

    return Matrix((rot(mat[3]), rot(mat[0]), rot(mat[1]), rot(mat[2])))


shoulder_angle = 1.3960005939006805
shoulder_rot = {
    "L": qrotation(Matrix.Rotation(shoulder_angle, 4, (0, 1, 0))),
    "R": qrotation(Matrix.Rotation(-shoulder_angle, 4, (0, 1, 0))),
}

bone_map = {
    "root": ("root", m2),
    "pelvis":
    ("torso", qrotation(Matrix.Rotation(1.4466689567595232, 4, (1, 0, 0)))),
    "spine01": ("spine_fk.001", m1),
    "spine02": ("spine_fk.002", m1),
    "spine03": ("spine_fk.003", m1),
    "neck": ("neck", m1),
    "head": ("head", m1),
}

for side in ["L", "R"]:
Esempio n. 24
0
def deform_obj(obj, context, self):
    offset_rotation = 0.2
    offset_axis = 5.0
    bend_scale = 0.7

    # get vertices
    verts = None
    if obj.mode == 'EDIT':
        # this works only in edit mode,
        bm = bmesh.from_edit_mesh(obj.data)

        verts = [v for v in bm.verts if v.select]
        if len(verts) == 0:
            verts = [v for v in bm.verts if v.hide is False]

    else:
        # this works only in object mode,
        verts = [v for v in obj.data.vertices if v.select]
        if len(verts) == 0:
            verts = [v for v in obj.data.vertices if v.hide is False]

    # TODO Move it into utilities method. As Extrude class has the same
    # min/max.
    if verts:
        if obj.mode == 'EDIT':
            bm.verts.ensure_lookup_table()
        x_min = verts[0].co.x
        x_max = verts[0].co.x
        y_min = verts[0].co.y
        y_max = verts[0].co.y
        z_min = verts[0].co.z
        z_max = verts[0].co.z

        for vert in verts:
            if vert.co.x > x_max:
                x_max = vert.co.x
            if vert.co.x < x_min:
                x_min = vert.co.x
            if vert.co.y > y_max:
                y_max = vert.co.y
            if vert.co.y < y_min:
                y_min = vert.co.y
            if vert.co.z > z_max:
                z_max = vert.co.z
            if vert.co.z < z_min:
                z_min = vert.co.z

        x_orig = ((x_max - x_min) / 2.0) + x_min
        y_orig = ((y_max - y_min) / 2.0) + y_min
        z_orig = z_min
        if self.deform_axis == 'Z':
            y_orig = y_min
            z_orig = ((z_max - z_min) / 2.0) + z_min

        rot_origin = Vector((x_orig, y_orig, z_orig))

        visual_max = z_max - z_min
        if self.deform_axis == 'Z':
            visual_max = y_max - y_min

        for vert in verts:
            print(vert.hide)
            vec = vert.co.copy()
            visual_up_pos = None
            if self.deform_axis != 'Z':
                visual_up_pos = vec.z - z_min
            else:
                visual_up_pos = vec.y - y_min

            # TAPER CODE
            # scale the vert
            if self.taper_value != 0:
                taper_value = ((self.taper_value) *
                               (visual_up_pos / visual_max))
                if self.deform_axis != 'Z':
                    vert.co.xy -= (vert.co.xy - rot_origin.xy) * taper_value
                else:
                    vert.co.xz -= (vert.co.xz - rot_origin.xz) * taper_value

            # TWIST CODE
            # rotate the vert
            if self.twist_angle != 0:
                twist_angle = self.twist_angle * (visual_up_pos / visual_max)
                # if self.deform_axis == 'X':
                # rot_angle = -rot_angle
                rot_mat = None
                if self.deform_axis != 'Z':
                    rot_mat = Matrix.Rotation(twist_angle, 3, 'Z')
                else:
                    rot_mat = Matrix.Rotation(twist_angle, 3, 'Y')
                vert.co = rot_mat * (vert.co - rot_origin) + rot_origin

            # BEND CODE
            beta = math.radians(self.bend_angle * (visual_up_pos / visual_max))
            if beta != 0:
                final_offset = visual_up_pos * self.offset_rotation
                if beta < 0:
                    final_offset = -final_offset

                move_to_rotate = (
                    (visual_up_pos / beta) + final_offset) * self.bend_scale
                if self.deform_axis == 'X':
                    vert.co.y -= move_to_rotate
                elif self.deform_axis == 'Y' or self.deform_axis == 'Z':
                    vert.co.x -= move_to_rotate

                if self.deform_axis != 'Z':
                    vert.co.z = rot_origin.z
                else:
                    vert.co.y = rot_origin.y

                # rotate the vert
                rot_angle = beta
                if self.deform_axis == 'X' or self.deform_axis == 'Z':
                    rot_angle = -rot_angle
                rot_mat = Matrix.Rotation(rot_angle, 3, self.deform_axis)
                vert.co = rot_mat * (vert.co - rot_origin) + rot_origin

                # back the rotation offset
                back_offset = (visual_up_pos / (beta)) * self.bend_scale
                if self.deform_axis == 'X':
                    vert.co.y += back_offset
                elif self.deform_axis == 'Y' or self.deform_axis == 'Z':
                    vert.co.x += back_offset

                # offset axys
                move_offset = self.offset_axis * (visual_up_pos / visual_max)
                if self.deform_axis == 'X':
                    vert.co.x += move_offset
                elif self.deform_axis == 'Y':
                    vert.co.y += move_offset
                elif self.deform_axis == 'Z':
                    vert.co.z += move_offset

    # obj.data.update()
    #bpy.ops.mesh.normals_make_consistent()  # recalculate normals
    #bpy.ops.object.editmode_toggle()
    #bpy.ops.object.editmode_toggle()
    bm.normal_update()
    bmesh.update_edit_mesh(obj.data)
Esempio n. 25
0
def calc_pose_mats(iqmodel, iqpose, bone_axis):
    loc_pose_mat = [None] * len(iqmodel.bones)
    abs_pose_mat = [None] * len(iqmodel.bones)
    recalc = False

    # convert pose to local matrix and compute absolute matrix
    for n in range(len(iqmodel.bones)):
        iqbone = iqmodel.bones[n]

        pose_pos = iqpose[n].translate
        pose_rot = iqpose[n].rotate
        pose_scale = iqpose[n].scale

        local_pos = Vector(pose_pos)
        local_rot = Quaternion(
            (pose_rot[3], pose_rot[0], pose_rot[1], pose_rot[2]))
        local_scale = Vector(pose_scale)

        mat_pos = Matrix.Translation(local_pos)
        mat_rot = local_rot.to_matrix().to_4x4()
        mat_scale = Matrix.Scale(local_scale.x, 3).to_4x4()
        loc_pose_mat[n] = matmul(matmul(mat_pos, mat_rot), mat_scale)

        if iqbone.parent >= 0:
            abs_pose_mat[n] = matmul(abs_pose_mat[iqbone.parent],
                                     loc_pose_mat[n])
        else:
            abs_pose_mat[n] = loc_pose_mat[n]

    # Remove negative scaling from bones.
    # Due to numerical instabilities in blender's matrix <-> head/tail/roll math
    # this isn't always stable when the bones are in the X axis. If the bones
    # end up rotated 90 degrees from what they should be, that's the reason.
    for n in range(len(iqmodel.bones)):
        if abs_pose_mat[n].is_negative:
            if not hasattr(iqmodel, 'abs_bind_mat'):
                print("warning: removing negative scale in bone",
                      iqmodel.bones[n].name)
            abs_pose_mat[n] = matmul(abs_pose_mat[n], Matrix.Scale(-1, 4))
            recalc = True

    # flip bone axis (and recompute local matrix if needed)
    if bone_axis == 'X':
        axis_flip = Matrix.Rotation(math.radians(-90), 4, 'Z')
        abs_pose_mat = [matmul(m, axis_flip) for m in abs_pose_mat]
        recalc = True
    if bone_axis == 'Z':
        axis_flip = Matrix.Rotation(math.radians(-90), 4, 'X')
        abs_pose_mat = [matmul(m, axis_flip) for m in abs_pose_mat]
        recalc = True

    if recalc:
        inv_pose_mat = [m.inverted() for m in abs_pose_mat]
        for n in range(len(iqmodel.bones)):
            iqbone = iqmodel.bones[n]
            if iqbone.parent >= 0:
                loc_pose_mat[n] = matmul(inv_pose_mat[iqbone.parent],
                                         abs_pose_mat[n])
            else:
                loc_pose_mat[n] = abs_pose_mat[n]

    return loc_pose_mat, abs_pose_mat
Esempio n. 26
0
    def execute(self, context):

        #if self.reset_values is True:
        #self.reset_all_values()

        active_obj = context.active_object

        bm = bmesh.from_edit_mesh(active_obj.data)
        bm.verts.ensure_lookup_table()
        #verts = [v for v in bm.verts if v.select]

        # get loops
        loops = loop_t.get_connected_input(bm)
        loops = loop_t.check_loops(loops, bm)

        if not loops:
            self.report({'WARNING'}, "No Loops!")
            return {'CANCELLED'}

        #obj_matrix = active_obj.matrix_world
        #obj_matrix_inv = obj_matrix.inverted()

        if self.unbevel_value != 1:

            for loop in loops:
                if loop[1] is True:
                    continue

                loop_verts = []

                for ind in loop[0]:
                    loop_verts.append(bm.verts[ind])

                v1 = (loop_verts[1].co - loop_verts[0].co).normalized()
                v2 = (loop_verts[2].co - loop_verts[1].co).normalized()
                angle_1 = v1.angle(v2) / 2

                v3 = (loop_verts[-2].co - loop_verts[-1].co).normalized()
                v4 = (loop_verts[-3].co - loop_verts[-2].co).normalized()
                angle_2 = v1.angle(v2) / 2
                degree_90 = 1.5708

                rot_dir = v1.cross(v2).normalized()
                rot_mat = Matrix.Rotation(-angle_1, 3, rot_dir)
                rot_mat_2 = Matrix.Rotation((angle_2 - degree_90), 3, rot_dir)
                v1_nor = (
                    (rot_mat @ v1).normalized() * 10000) + loop_verts[0].co
                v3_nor = (rot_mat_2 @ v3).normalized()

                scale_pos = mathu.geometry.intersect_line_plane(
                    loop_verts[0].co, v1_nor, loop_verts[-1].co, v3_nor)

                for vert in loop_verts:
                    vert.co = scale_pos.lerp(vert.co, self.unbevel_value)

            if self.unbevel_value == 0:
                bpy.ops.mesh.merge(type='COLLAPSE')

            bm.normal_update()
            bmesh.update_edit_mesh(active_obj.data)

        return {'FINISHED'}
Esempio n. 27
0
	def outFrame(self, file, frameName = "frame"):
		mesh = self.object.to_mesh(bpy.context.scene, True, 'PREVIEW')

		mesh.transform(self.object.matrix_world)
		mesh.transform(Matrix.Rotation(pi / 2, 4, 'Z'))

		if not self.options.fUseSharedBoundingBox:
			###### compute the bounding box ###############
			min = [mesh.vertices[0].co[0],
				   mesh.vertices[0].co[1],
				   mesh.vertices[0].co[2]]
			max = [mesh.vertices[0].co[0],
				   mesh.vertices[0].co[1],
				   mesh.vertices[0].co[2]]

			for vert in mesh.vertices:
				for i in range(3):
					if vert.co[i] < min[i]:
						min[i] = vert.co[i]
					if vert.co[i] > max[i]:
						max[i] = vert.co[i]
			########################################
		else:
			min = self.bbox_min
			max = self.bbox_max

		# BL: some caching to speed it up:
		# -> sd_ gets the vertices between [0 and 255]
		#    which is our important quantization.
		dx = max[0] - min[0] if max[0] - min[0] != 0.0 else 1.0
		dy = max[1] - min[1] if max[1] - min[1] != 0.0 else 1.0
		dz = max[2] - min[2] if max[2] - min[2] != 0.0 else 1.0
		sdx = dx / 255.0
		sdy = dy / 255.0
		sdz = dz / 255.0
		isdx = 255.0 / dx
		isdy = 255.0 / dy
		isdz = 255.0 / dz

		# note about the scale: self.object.scale is already applied via matrix_world
		data = struct.pack("<6f16s",
							# writing the scale of the model
							sdx,
							sdy,
							sdz,
							## now the initial offset (= min of bounding box)
							min[0],
							min[1],
							min[2],
							# and finally the name.
							bytes(frameName, encoding="utf8"))

		file.write(data) # frame header

		for vert in mesh.vertices:
			# find the closest normal for every vertex
			for iN in range(162):
				dot = vert.normal[1] * MD2_NORMALS[iN][0] + \
					-vert.normal[0] * MD2_NORMALS[iN][1] + \
					vert.normal[2] * MD2_NORMALS[iN][2]

				if iN == 0 or dot > maxDot:
					maxDot = dot
					bestNormalIndex = iN

			# and now write the normal.
			data = struct.pack("<4B",
								int((vert.co[0] - min[0]) * isdx),
								int((vert.co[1] - min[1]) * isdy),
								int((vert.co[2] - min[2]) * isdz),
								bestNormalIndex)

			file.write(data) # write vertex and normal
Esempio n. 28
0
def get_dim_coords(context, myobj, DimGen, dim, mat, offset_pos=True):
    dimProps = dim
    if dim.uses_style:
        for alignedDimStyle in context.scene.StyleGenerator.alignedDimensions:
            if alignedDimStyle.name == dim.style:
                dimProps = alignedDimStyle

    # get points positions from indicies
    aMatrix = dim.dimObjectA.matrix_world
    bMatrix = dim.dimObjectB.matrix_world

    offset = dim.dimOffset
    geoOffset = dim.dimLeaderOffset

    # get points positions from indicies
    p1Local = None
    p2Local = None

    try:
        p1Local = get_mesh_vertex(dim.dimObjectA, dim.dimPointA,
                                  dimProps.evalMods)
    except IndexError:
        print('p1 excepted for ' + dim.name + ' on ' + myobj.name)

    try:
        p2Local = get_mesh_vertex(dim.dimObjectB, dim.dimPointB,
                                  dimProps.evalMods)
    except IndexError:
        print('p2 excepted for ' + dim.name + ' on ' + myobj.name)

    p1 = get_point(p1Local, dim.dimObjectA, aMatrix)
    p2 = get_point(p2Local, dim.dimObjectB, bMatrix)

    # check dominant Axis
    sortedPoints = sortPoints(p1, p2)
    p1 = sortedPoints[0]
    p2 = sortedPoints[1]

    distVector = Vector(p1) - Vector(p2)
    dist = distVector.length
    midpoint = interpolate3d(p1, p2, fabs(dist / 2))
    normDistVector = distVector.normalized()

    # Compute offset vector from face normal and user input
    rotationMatrix = Matrix.Rotation(dim.dimRotation, 4, normDistVector)
    selectedNormal = Vector(
        select_normal(myobj, dim, normDistVector, midpoint, dimProps))

    userOffsetVector = rotationMatrix @ selectedNormal
    offsetDistance = userOffsetVector * offset
    geoOffsetDistance = offsetDistance.normalized() * geoOffset

    if offsetDistance < geoOffsetDistance:
        offsetDistance = geoOffsetDistance

    dimLineStart = Vector(p1) + offsetDistance
    dimLineEnd = Vector(p2) + offsetDistance

    if offset_pos:
        return [dimLineStart, dimLineEnd]
    else:
        return [p1, p2]
Esempio n. 29
0
def OBB(vecs, r_indices=None, eps=1e-6):
    """Convex hull を用いたOBBを返す。
    Z->Y->Xの順で長さが最少となる軸を求める。
    :param vecs: list of Vector
    :type vecs: list | tuple
    :param r_indices: listを渡すとconvexhullの結果を格納する
    :type r_indices: None | list
    :param eps: 種々の計算の閾値
    :return:
        (matrix, obb_size)
        matrix:
            type: Matrx
            OBBの回転と中心を表す。vecsが二次元ベクトルの場合は3x3, 三次元なら4x4。
        obb_size:
            type: Vector
            OBBの各軸の長さ。vecsと同じ次元。
    :rtype: (Matrix, Vector)
    """

    if not vecs:
        return None, None

    # 2D ----------------------------------------------------------------------
    if len(vecs[0]) == 2:
        mat = Matrix.Identity(3)
        bb_size = Vector((0, 0))

        indices = convex_hull_2d(vecs, eps)
        if r_indices:
            r_indices[:] = indices

        if len(indices) == 1:
            mat.col[2][:2] = vecs[0]
        elif len(indices) == 2:
            v1 = vecs[indices[0]]
            v2 = vecs[indices[1]]
            xaxis = (v2 - v1).normalized()
            angle = math.atan2(xaxis[1], xaxis[0])
            mat2 = Matrix.Rotation(angle, 2)
            mat.col[0][:2] = mat2.col[0]
            mat.col[1][:2] = mat2.col[1]
            mat.col[2][:2] = (v1 + v2) / 2
            bb_size[0] = (v2 - v1).length
        else:
            yaxis = _closest_axis_on_plane(vecs, indices)
            angle = math.atan2(yaxis[1], yaxis[0]) - math.pi / 2  # X軸
            mat2 = Matrix.Rotation(angle, 2)
            imat2 = Matrix.Rotation(-angle, 2)
            rotvecs = [imat2 * v for v in vecs]
            loc = Vector((0, 0))
            for i in range(2):
                rotvecs.sort(key=lambda v: v[i])
                bb_size[i] = rotvecs[-1][i] - rotvecs[0][i]
                loc[i] = (rotvecs[0][i] + rotvecs[-1][i]) / 2
            mat.col[0][:2] = mat2.col[0]
            mat.col[1][:2] = mat2.col[1]
            mat.col[2][:2] = mat2 * loc
        return mat, bb_size

    # 3D ----------------------------------------------------------------------
    mat = Matrix.Identity(4)
    bb_size = Vector((0, 0, 0))

    indices = convex_hull(vecs, eps)

    if r_indices:
        r_indices[:] = indices

    if isinstance(indices[0], int):  # 2d
        if len(indices) == 1:
            mat.col[3][:3] = vecs[0]
            return mat, bb_size

        elif len(indices) == 2:
            # 同一線上
            v1 = vecs[indices[0]]
            v2 = vecs[indices[1]]
            xaxis = (v2 - v1).normalized()
            quat = Vector((1, 0, 0)).rotation_difference(xaxis)
            mat = quat.to_matrix().to_4x4()
            mat.col[3][:3] = (v1 + v2) / 2
            bb_size[0] = (v2 - v1).length
            return mat, bb_size

        else:
            # 同一平面上
            medium = reduce(lambda a, b: a + b, vecs) / len(vecs)
            v1 = max(vecs, key=lambda v: (v - medium).length)
            v2 = max(vecs, key=lambda v: (v - v1).length)
            line = v2 - v1
            v3 = max(vecs, key=lambda v: line.cross(v - v1).length)
            zaxis = geom.normal(v1, v2, v3)
            if zaxis[2] < 0.0:
                zaxis.negate()

            quat = zaxis.rotation_difference(Vector((0, 0, 1)))
            rotvecs = [quat * v for v in vecs]
            indices_2d = indices

    else:  # 3d
        indices_set = set(chain(*indices))
        zaxis = None
        dist = 0.0
        # 最も距離の近い面(平面)と頂点を求める
        for tri in indices:
            v1, v2, v3 = [vecs[i] for i in tri]
            normal = geom.normal(v1, v2, v3)
            d = 0.0
            for v4 in (vecs[i] for i in indices_set if i not in tri):
                f = abs(geom.distance_point_to_plane(v4, v1, normal))
                d = max(f, d)
            if zaxis is None or d < dist:
                zaxis = -normal
                dist = d

        quat = zaxis.rotation_difference(Vector((0, 0, 1)))
        rotvecs = [(quat * v).to_2d() for v in vecs]
        indices_2d = convex_hull_2d(rotvecs, eps)

    yaxis = _closest_axis_on_plane(rotvecs, indices_2d)
    yaxis = quat.inverted() * yaxis.to_3d()

    xaxis = yaxis.cross(zaxis)
    xaxis.normalize()  # 不要?

    mat.col[0][:3] = xaxis
    mat.col[1][:3] = yaxis
    mat.col[2][:3] = zaxis

    # OBBの大きさと中心を求める
    imat = mat.inverted()
    rotvecs = [imat * v for v in vecs]
    loc = Vector()
    for i in range(3):
        rotvecs.sort(key=lambda v: v[i])
        bb_size[i] = rotvecs[-1][i] - rotvecs[0][i]
        loc[i] = (rotvecs[0][i] + rotvecs[-1][i]) / 2
    mat.col[3][:3] = mat * loc
    return mat, bb_size
Esempio n. 30
0
def create_prongs(self):

    # Prong
    # ---------------------------

    prong_rad = self.diameter / 2
    taper = self.taper + 1

    if self.bump_scale:

        curve_resolution = int(self.detalization / 4) + 1
        angle = (pi / 2) / (curve_resolution - 1)

        v_cos = [(
            0.0,
            sin(i * angle) * prong_rad,
            cos(i * angle) * prong_rad * self.bump_scale + self.z_top,
        ) for i in range(curve_resolution)]

        v_cos.append((0.0, prong_rad * taper, -self.z_btm))

    else:

        v_cos = (
            (0.0, 0.0, self.z_top),
            (0.0, prong_rad, self.z_top),
            (0.0, prong_rad * taper, -self.z_btm),
        )

    bm = bmesh.new()
    v_profile = [bm.verts.new(v) for v in v_cos]

    for vs in zip(v_profile, v_profile[1:]):
        bm.edges.new(vs)

    bmesh.ops.spin(bm,
                   geom=bm.edges,
                   angle=tau,
                   steps=self.detalization,
                   axis=(0.0, 0.0, 1.0),
                   cent=(0.0, 0.0, 0.0))
    bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.00001)

    v_boundary = [x for x in bm.verts if x.is_boundary]
    bm.faces.new(reversed(v_boundary))

    # Transforms
    # ---------------------------

    pos_offset = (self.gem_l / 2 + prong_rad) - (self.diameter *
                                                 (self.intersection / 100))
    spin_steps = self.number - 1

    if self.alignment:
        bmesh.ops.rotate(bm,
                         verts=bm.verts,
                         cent=(0.0, 0.0, 0.0),
                         matrix=Matrix.Rotation(-self.alignment, 4, "X"))

    bmesh.ops.translate(bm, verts=bm.verts, vec=(0.0, pos_offset, 0.0))

    if spin_steps:
        spin_angle = tau - tau / self.number
        bmesh.ops.spin(bm,
                       geom=bm.faces,
                       angle=spin_angle,
                       steps=spin_steps,
                       axis=(0.0, 0.0, 1.0),
                       cent=(0.0, 0.0, 0.0),
                       use_duplicate=True)

    bmesh.ops.rotate(bm,
                     verts=bm.verts,
                     cent=(0.0, 0.0, 0.0),
                     matrix=Matrix.Rotation(-self.position, 4, "Z"))

    if self.use_symmetry:
        bmesh.ops.mirror(bm, geom=bm.faces, merge_dist=0, axis="Y")
        bmesh.ops.recalc_face_normals(bm, faces=bm.faces)
        bmesh.ops.rotate(bm,
                         verts=bm.verts,
                         cent=(0.0, 0.0, 0.0),
                         matrix=Matrix.Rotation(-self.symmetry_pivot, 4, "Z"))

    return bm