def obj_orientation(obj, alpha, beta, gamma):
    '''Set obj orientation, angle in degrees'''
    alpha = alpha * pi / 180
    beta = beta * pi / 180
    gamma = gamma * pi / 180
    rot_in_euler = Euler([alpha, beta, gamma])
    obj.worldOrientation = rot_in_euler.to_matrix()
示例#2
0
def createSceneFromXML(scene_file):
    # parse xml
    sceneTree = ET.parse(scene_file)
    root = sceneTree.getroot()
    # traverse scene xml
    materialStack.append(createDefaultMaterial())
    transformStack.append(Matrix.Identity(4))
    rootObject = createObjectFromXML(root, root[0], './sceneRoot', None, True)
    # create coordinate conversion root
    sceneObject = bpy.data.objects.new('JReality Scene', None)
    jrealityToBlender = Euler((math.pi / 2, 0.0, math.pi / 2), 'XYZ')
    sceneObject.matrix_local = jrealityToBlender.to_matrix().to_4x4()
    bpy.context.scene.objects.link(sceneObject)
    rootObject.parent = sceneObject
    # find active camera
    cameraPath = root.find("scenePaths/path[@name='cameraPath']")
    if cameraPath != None:
        cameraPathXpath = resolveReferencePath(
            root, cameraPath, "./scenePaths/path[@name='cameraPath']")
        cameraPath = resolveReference(root, cameraPath,
                                      "./scenePaths/path[@name='cameraPath']")
        node = cameraPath.find('node[last()]')
        camTag = resolveReference(root, node,
                                  cameraPathXpath + "/node[last()]")
        bpy.context.scene.camera = tagToObject[camTag]
    else:
        print('WARNING: no camera path set')
示例#3
0
def create_armature(mdl: Mdl, collection):
    model_name = Path(mdl.header.name).stem
    armature = bpy.data.armatures.new(f"{model_name}_ARM_DATA")
    armature_obj = bpy.data.objects.new(f"{model_name}_ARM", armature)
    armature_obj.show_in_front = True
    collection.objects.link(armature_obj)

    armature_obj.select_set(True)
    bpy.context.view_layer.objects.active = armature_obj

    bpy.ops.object.mode_set(mode='EDIT')
    bl_bones = []
    for bone in mdl.bones:
        bl_bone = armature.edit_bones.new(bone.name)
        bl_bones.append(bl_bone)

    for bl_bone, s_bone in zip(bl_bones, mdl.bones):
        if s_bone.parent_bone_index != -1:
            bl_parent = bl_bones[s_bone.parent_bone_index]
            bl_bone.parent = bl_parent
        bl_bone.tail = Vector([0, 0, 1]) + bl_bone.head

    bpy.ops.object.mode_set(mode='POSE')
    for se_bone in mdl.bones:
        bl_bone = armature_obj.pose.bones.get(se_bone.name)
        pos = Vector(se_bone.position)
        rot = Euler(se_bone.rotation)
        mat = Matrix.Translation(pos) @ rot.to_matrix().to_4x4()
        bl_bone.matrix_basis.identity()

        bl_bone.matrix = bl_bone.parent.matrix @ mat if bl_bone.parent else mat
    bpy.ops.pose.armature_apply()
    bpy.ops.object.mode_set(mode='OBJECT')

    return armature_obj
示例#4
0
def cek(cont):
	thisTime = time.time()
	
	#debugging
	#thisTime = lastNewMoonRecord + (7.3825 * 24 * 60 * 60)#first quarter
	#thisTime = lastNewMoonRecord + (14.765 * 24 * 60 * 60)#full moon
	#thisTime = lastNewMoonRecord + (22.1475 * 24 * 60 * 60)#third quarter
	
	x = thisTime - lastNewMoonRecord

	moonPhase = (x%mc) / 60 / 60 / 24 / 29.53
	
	#cont.owner["pos"] = moonPhase
	#print(moonPhase)#for debugging
	
	own = cont.owner
	if "moon" in own:
		moon = own.scene.objects[own['moon']]
		
		#rot = 45
		rot = 360 * -moonPhase
		r = radians(rot)
		el = Euler((0, 0, r))
		#print(el)
		moon.worldOrientation = el.to_matrix()
		
示例#5
0
def euler_matrices(params, euler_order, angle_units):
    mat_num = max(map(len, params))
    params2 = make_repeaters(params)
    matrices = []
    for i, location, angleX, angleY, angleZ, scale in zip(
            range(mat_num), *params2):
        # translation
        mat_t[0][3] = location[0]
        mat_t[1][3] = location[1]
        mat_t[2][3] = location[2]
        # rotation
        angles = (angleX * angle_units, angleY * angle_units,
                  angleZ * angle_units)
        euler = Euler(angles, euler_order)
        # mat_r = euler.to_quaternion().to_matrix().to_4x4()
        mat_r = euler.to_matrix().to_4x4()

        # scale
        mat_s[0][0] = scale[0]
        mat_s[1][1] = scale[1]
        mat_s[2][2] = scale[2]
        # composite matrix
        m = mat_t @ mat_r @ mat_s
        matrices.append(m)
    return matrices
示例#6
0
    def __getAxisAngleBasedRotation(self, rotate, translate):

        euler = Euler(rotate)

        self.logger.debug("Injecting rotation: '%s'", str(euler))

        vector_translate = Vector((translate[0], translate[1], translate[2]))

        # actually the translation is also needed to be passed here
        rotate_mtx = Matrix.to_4x4(euler.to_matrix())
        translate_mtx = Matrix.Translation(vector_translate)

        cameraMatrix = translate_mtx * rotate_mtx

        # global matrix rotate (guess it is for world coordinate system rotating)

        mtx = Matrix.Rotation(-(math.pi / 2.0), 4, 'X')
        mtx = mtx * cameraMatrix

        (loc, quat, _) = mtx.decompose()

        # get the values the way that in x3d exporter does
        quat = quat.normalized()

        # some weird stuff
        axises = list(quat.axis.to_tuple())
        angle = quat.angle

        orientation = self.__getStringRepresentation(axises) + " " + str(angle)
        translation = self.__getStringRepresentation(loc)

        return translation, orientation
示例#7
0
def get_matrix_world_at_frame(obj, frame_id):
    rotation_mode = get_rotation_mode_at_frame(obj, frame_id)
    if rotation_mode == 'AXIS_ANGLE':
        axis_angle = get_vector4_at_frame(obj, "rotation_axis_angle", frame_id)
        angle = axis_angle[0]
        axis = Vector(axis_angle[1], axis_angle[2], axis_angle[3])
        rotation_matrix = Matrix.Rotation(angle, 4, axis)
    elif rotation_mode == 'QUATERNION':
        rotation_quat = get_vector4_at_frame(obj, "rotation_quaternion",
                                             frame_id)
        quat = Quaternion(rotation_quat)
        rotation_matrix = quat.to_matrix().to_4x4()
    else:
        rotation = get_vector3_at_frame(obj, "rotation_euler", frame_id)
        e = Euler(rotation, rotation_mode)
        rotation_matrix = e.to_matrix().to_4x4()

    location = get_vector3_at_frame(obj, "location", frame_id)
    location_matrix = Matrix.Translation(location).to_4x4()

    scale = get_vector3_at_frame(obj, "scale", frame_id)
    scale_matrix = Matrix.Identity(4)
    scale_matrix[0][0] = scale[0]
    scale_matrix[1][1] = scale[1]
    scale_matrix[2][2] = scale[2]

    return vcu.element_multiply(
        vcu.element_multiply(location_matrix, rotation_matrix), scale_matrix)
示例#8
0
    def execute(self, context):
        from . import import_ac3d
        keywords = self.as_keywords(ignore=("axis_forward",
                                            "axis_up",
                                            "filter_glob",
                                            "rotation",
                                            "translation",
                                            "hide_props_region"))

        eul = Euler((radians(self.rotation[0]),
                     radians(self.rotation[1]),
                     radians(self.rotation[2])), 'XYZ')

        global_matrix = eul.to_matrix().to_4x4() @ \
            axis_conversion(from_forward=self.axis_forward,
                            from_up=self.axis_up).to_4x4()

        keywords["global_matrix"] = global_matrix

        t = time.mktime(datetime.datetime.now().timetuple())

        import_ac3d.AC3D_OT_Import(self, context, **keywords)

        t = time.mktime(datetime.datetime.now().timetuple()) - t
        print('Finished importing in', t, 'seconds')

        return {'FINISHED'}
def obj_orientation(obj, alpha, beta, gamma):
    '''Set obj orientation, angle in degrees'''
    alpha = alpha*pi/180
    beta = beta*pi/180
    gamma = gamma*pi/180
    rot_in_euler = Euler([alpha, beta, gamma])
    obj.worldOrientation = rot_in_euler.to_matrix()
示例#10
0
def draw_arc12(x, y, radius, start_angle, end_angle, subdivide):  # いずれ削除
    # 十二時から時計回りに描画
    v = Vector([0, 1, 0])
    e = Euler((0, 0, -start_angle))
    m = e.to_matrix()
    v = m * v
    if end_angle >= start_angle:
        a = (end_angle - start_angle) / (subdivide + 1)
    else:
        a = (end_angle + math.pi * 2 - start_angle) / (subdivide + 1)
    e = Euler((0, 0, -a))
    m = e.to_matrix()

    bgl.glBegin(bgl.GL_LINE_STRIP)
    for i in range(subdivide + 2):
        v1 = v * radius
        bgl.glVertex2f(x + v1[0], y + v1[1])
        v = m * v
    bgl.glEnd()
示例#11
0
def draw_arc12(x, y, radius, start_angle, end_angle, subdivide):  # いずれ削除
    # 十二時から時計回りに描画
    v = Vector([0, 1, 0])
    e = Euler((0, 0, -start_angle))
    m = e.to_matrix()
    v = v * m
    if end_angle >= start_angle:
        a = (end_angle - start_angle) / (subdivide + 1)
    else:
        a = (end_angle + math.pi * 2 - start_angle) / (subdivide + 1)
    e = Euler((0, 0, -a))
    m = e.to_matrix()

    bgl.glBegin(bgl.GL_LINE_STRIP)
    for i in range(subdivide + 2):
        v1 = v * radius
        bgl.glVertex2f(x + v1[0], y + v1[1])
        v = v * m
    bgl.glEnd()
示例#12
0
def compute_offset(xml_file):

    e = xml_file.parent_eulerXYZ
    eleur = Euler((e.x, e.y, e.z))

    mat4 = eleur.to_matrix().to_4x4()
    pos = mat4 * xml_file.offset

    #tr = xml_file.offset - pos
    xml_file.offset = xml_file.parent_offset + pos
    xml_file.eulerXYZ = xml_file.eulerXYZ + xml_file.parent_eulerXYZ
示例#13
0
def compute_offset_text(text):

    e = text.xml_eulerXYZ
    eleur = Euler((e.x, e.y, e.z))

    mat4 = eleur.to_matrix().to_4x4()
    pos = mat4 * text.offset

    #tr = xml_file.offset - pos
    text.offset = text.xml_offset + pos
    text.eulerXYZ = text.eulerXYZ + text.xml_eulerXYZ
示例#14
0
			def main(_self, entity_object, plugin_data):               
				# Restore Euler structure
				new_orientation = [0, 0, 0]
				for value in plugin_data:
					new_orientation[value[1]] = value[0]
				euler_orientation = Euler(new_orientation)
				
				# Interpolate between data and use for extrapolation
				interpolator = setdefaultdict(entity_object, "interpolate_orientation", interpolate([entity_object.worldOrientation.to_quaternion(), 0.0]))     
				orientation = [euler_orientation.to_quaternion(), time.time()]
				interpolator.update(orientation)            
					
				entity_object.worldOrientation = euler_orientation.to_matrix()
示例#15
0
    def test_loc_rot_scale(self):
        euler = Euler((math.radians(90), 0, math.radians(90)), 'ZYX')
        expected = Matrix(
            ((0, -5, 0, 1), (0, 0, -6, 2), (4, 0, 0, 3), (0, 0, 0, 1)))

        result = Matrix.LocRotScale((1, 2, 3), euler, (4, 5, 6))
        self.assertAlmostEqualMatrix(result, expected, 4)

        result = Matrix.LocRotScale((1, 2, 3), euler.to_quaternion(),
                                    (4, 5, 6))
        self.assertAlmostEqualMatrix(result, expected, 4)

        result = Matrix.LocRotScale((1, 2, 3), euler.to_matrix(), (4, 5, 6))
        self.assertAlmostEqualMatrix(result, expected, 4)
def save_md3(settings):
    from mathutils import Euler, Matrix, Vector
    from math import radians
    starttime = time.clock()  # start timer
    fullpath = splitext(settings.savepath)[0]
    modelname = basename(fullpath)
    logname = modelname + ".log"
    logfpath = fullpath + ".log"
    if settings.name == "":
        settings.name = modelname
    dumpall = settings.dumpall
    if settings.logtype == "append":
        log = open(logfpath,"a")
    elif settings.logtype == "overwrite":
        log = open(logfpath,"w")
    elif settings.logtype == "blender":
        log = bpy.data.texts.new(logname)
        log.clear()
    else:
        log = None
    ref_frame = settings.refframe
    if settings.refframe == -1:
        ref_frame = bpy.context.scene.frame_current
    message(log, "###################### BEGIN ######################")
    model = BlenderModelManager(settings.gzdoom, ref_frame)
    # Set up fix transformation matrix
    model.fix_transform *= Matrix.Scale(settings.scale, 4)
    model.fix_transform *= Matrix.Translation(Vector((
        settings.offsetx, settings.offsety, settings.offsetz)))
    rotation_fix = Euler()
    rotation_fix.z = radians(90)
    model.fix_transform *= rotation_fix.to_matrix().to_4x4()
    model.md3.name = settings.name
    # Add objects to model manager
    if len(bpy.context.selected_objects) == 0:
        message(log, "Select an object to export!")
    else:
        # If multiple objects are selected, they are joined together
        for bobject in bpy.context.selected_objects:
            if bobject.type == 'MESH':
                model.add_mesh(bobject)
            elif bobject.type == 'EMPTY':
                model.add_tag(bobject)
    model.setup_frames()
    model.md3.GetSize()
    print_md3(log, model.md3, dumpall)
    model.save(settings.savepath)
    endtime = time.clock() - starttime
    message(log, "Export took {:.3f} seconds".format(endtime))
示例#17
0
def draw_cloud(bm, prefs, translation=(0, 0, 0)):
    mat = Matrix()
    mat.translation = translation
    smin = prefs.lp_Cloud_Scale_Min
    smax = prefs.lp_Cloud_Scale_Max
    sx = uniform(smin[0], smax[0])
    sy = uniform(smin[1], smax[1])
    sz = uniform(smin[2], smax[2])
    scale = (sx, sy, sz)
    mat[0][0], mat[1][1], mat[2][2] = scale[0], scale[1], scale[2]
    e = Euler((uniform(0, 3.14), uniform(0, 3.14), uniform(0, 3.14)), 'XYZ')
    mat = mat * e.to_matrix().to_4x4()
    bmesh.ops.create_icosphere(bm, subdivisions=prefs.lp_Cloud_Subdivisions,
                               diameter=1.0, matrix=mat)
    return scale
def rotate_eye(obj, x_angle, z_angle):
    obj.rotation_mode = 'XYZ'
    deg_to_rad = np.pi * 2 / 360
    outer_eye = bpy.data.collections["Collection 1"].objects['eye-outer']
    x_rot = -x_angle * deg_to_rad
    z_rot = z_angle * deg_to_rad
    euler_rotation = Euler((x_rot, 0, z_rot), 'XYZ')
    obj.rotation_euler = euler_rotation
    outer_eye.rotation_euler = Euler((-x_rot - np.pi / 2, 0, z_rot), 'XYZ')
    obj_rot_mat = euler_rotation.to_matrix()

    #obj_rot_mat = initPoseMat

    if obj.parent:
        P = obj.parent.matrix.decompose()[1].to_matrix()
        obj_rot_mat = P * obj_rot_mat * P.inverted()
示例#19
0
def compute_extra_transforme(obj, translate, rotate):
    if translate:
        obj.delta_location = Vector((0.0, 0.0, 0.0)) + translate

    if rotate:
        e = rotate
        eleur = Euler((e.x, e.y, e.z))

        mat4 = eleur.to_matrix().to_4x4()
        w = Vector((0.0, 0.0, 0.0)) + obj.location
        pos = mat4 * w
        tr = Vector((0.0, 0.0, 0.0)) + pos - w
        w = Vector((0.0, 0.0, 0.0)) + obj.delta_location

        obj.delta_location = Vector((0.0, 0.0, 0.0)) + w + tr
        obj.delta_rotation_euler = Euler((rotate.x, rotate.y, rotate.z))
示例#20
0
    def _get_global_vertices(self, obj, bm):
        # Get world rotation matrix.
        eular = Euler(obj.rotation_euler)
        rotation_mat = eular.to_matrix()

        # Get center location of all vertices.
        center_location = Vector((0.0, 0.0, 0.0))
        for v in bm.verts:
            center_location += v.co
        center_location /= len(bm.verts)

        # Move to local to global.
        transformed = {}
        for v in bm.verts:
            transformed[v] = compat.matmul(rotation_mat, v.co)
            transformed[v] -= center_location

        return transformed
示例#21
0
 def find_fcurve_matrix(self, id_data, bone_name, sourceaction, frame):
     # anim_data = id_data.animation_data
     location = Vector([0.0, 0.0, 0.0])
     quat_rotation = Quaternion()
     # print("Rot mode: ", id_data.pose.bones[bone_name].rotation_mode)
     pose_bone = id_data.pose.bones[bone_name]
     rot_mode = pose_bone.rotation_mode
     if len(rot_mode) > 3:
         rot_mode = "XYZ"
     euler_rotation = Euler((0, 0, 0), rot_mode)
     rotmat = None
     rotmat_e = None
     for fcurve in sourceaction.fcurves:
         # print(fcurve.data_path)
         if '["' + bone_name + '"]' in fcurve.data_path:
             if ".location" in fcurve.data_path:
                 location[fcurve.array_index] = fcurve.evaluate(frame)
             if "_quaternion" in fcurve.data_path:
                 quat_rotation[fcurve.array_index] = fcurve.evaluate(frame)
                 rotmat = quat_rotation.to_matrix()
             if "_euler" in fcurve.data_path:
                 euler_rotation[fcurve.array_index] = fcurve.evaluate(frame)
                 rotmat_e = euler_rotation.to_matrix()
                 # print("Frame, Euler: ", frame, fcurve.evaluate(frame), euler_rotation)
                 # print("Rotmat: ", rotmat_e)
     mat = Matrix.Translation(location)
     # print("Reading loc: ", bone_name, frame, location)
     if rotmat is not None:
         rotmat.resize_4x4()
         mat = mat @ rotmat
     if rotmat_e is not None:
         rotmat_e.resize_4x4()
         mat = mat @ rotmat_e
     posemat = pose_bone.id_data.convert_space(matrix=mat,
                                               pose_bone=pose_bone,
                                               from_space='LOCAL',
                                               to_space='POSE')
     if bone_name == "foot_ik.L":
         print("foundrotmat: ", frame)
         print(mat)
         print(posemat)
     return posemat
示例#22
0
def compute_box_3d_euler_angel(location, box3d_dimensions, angles):
    ''' compute_box_3d based on location, box3d_dimensions, Euler angles
    https://docs.blender.org/api/blender_python_api_current/mathutils.html#mathutils.Matrix
     input:
        box3d_dimensions:3    dimensions   3D object dimensions: height, width, length (in meters)
        location: 3    location     3D object location x,y,z in camera coordinates (in meters)
        angles:3    euler angles in order='XYZ' (3d vector) – Three angles, in radians.

         qs: (8,3) array of vertices for the 3d box in following order:
            7 -------- 6
           /|         /|
          4 -------- 5 .
          | |        | |
          . 3 -------- 2
          |/         |/
          0 -------- 1

     Returns:
         corners_3d: (8,3) array in rect camera coord.
    '''

    eul = Euler(angles)

    # 3d bounding box dimensions
    w, h, l = box3d_dimensions
    # 3d bounding box corners
    x_corners = [-w / 2, w / 2, w / 2, -w / 2, -w / 2, w / 2, w / 2, -w / 2]
    y_corners = [h / 2, h / 2, h / 2, h / 2, -h / 2, -h / 2, -h / 2, -h / 2]
    z_corners = [-l / 2, -l / 2, l / 2, l / 2, -l / 2, -l / 2, l / 2, l / 2]

    R = eul.to_matrix()

    # rotate and translate 3d bounding box
    corners_3d = np.dot(R, np.vstack([x_corners, y_corners, z_corners]))
    # print(corners_3d.shape)
    corners_3d[0, :] = corners_3d[0, :] + location[0]
    corners_3d[1, :] = corners_3d[1, :] + location[1]
    corners_3d[2, :] = corners_3d[2, :] + location[2]
    # print('cornsers_3d: ', corners_3d)
    # only draw 3d bounding box for objs in front of the camera

    return np.transpose(corners_3d)
示例#23
0
	def rotation(self, xyz):
		if len(xyz) != 3: utils.debug("Rotation assignment failed on " + self.obj.name + " object. xyz size != 3.")
		if isinstance(xyz, (list, tuple)) or len(xyz) == 3:
			xyz = Euler(xyz, 'XYZ')
		srt = self.obj.localOrientation.copy()
		xyz = xyz.to_matrix()
			
		for obj in self.transformable:
			if obj.__class__.__name__ == "KX_GameObject":
				if obj == self.obj: obj.localOrientation = xyz
				else:
					srr = obj.worldOrientation.copy()
					srr.rotate(xyz)
					srr = srr.to_euler()
					obj.localOrientation = srr
			else:
				srr = obj.rotation.copy()
				srr.rotate(xyz)
				obj.localOrientation = srr
				obj.rotation = srr
		self._rotation = self.ProxyRotation()
示例#24
0
def compute_box_3d_euler_angel_batch(inputs):
    location = inputs[:3]
    box3d_dimensions = inputs[3:6]
    angles = inputs[6:9]
    eul = Euler(angles)

    # 3d bounding box dimensions
    w, h, l = box3d_dimensions
    # 3d bounding box corners
    x_corners = [-w / 2, -w / 2, w / 2, w / 2, -w / 2, -w / 2, w / 2, w / 2]
    y_corners = [h / 2, h / 2, h / 2, h / 2, -h / 2, -h / 2, -h / 2, -h / 2]
    z_corners = [-l / 2, l / 2, l / 2, -l / 2, -l / 2, l / 2, l / 2, -l / 2]

    R = eul.to_matrix()

    corners_3d = np.dot(R, np.vstack([x_corners, y_corners, z_corners]))
    corners_3d[0, :] = corners_3d[0, :] + location[0]
    corners_3d[1, :] = corners_3d[1, :] + location[1]
    corners_3d[2, :] = corners_3d[2, :] + location[2]

    return np.transpose(corners_3d)
def transform_data_to_world_matrix(transform):
    mat_loc = Matrix.Translation(transform['location']).to_4x4()

    if transform['rotation_mode'] == "AXIS_ANGLE":
        angle = transform['rotation'][0]
        axis = Vector(transform['rotation'][1], transform['rotation'][2],
                      transform['rotation'][3])
        mat_rot = Matrix.Rotation(angle, 4, axis)
    elif transform['rotation_mode'] == "QUATERNION":
        q = Quaternion(transform['rotation'])
        mat_rot = q.to_matrix().to_4x4()
    else:
        e = Euler(transform['rotation'], transform['rotation_mode'])
        mat_rot = e.to_matrix().to_4x4()

    mat_scale = Matrix.Identity(4)
    mat_scale[0][0] = transform['scale'][0]
    mat_scale[1][1] = transform['scale'][1]
    mat_scale[2][2] = transform['scale'][2]

    return mat_loc * mat_rot * mat_scale
示例#26
0
    def rotation(self, xyz):
        if len(xyz) != 3:
            utils.debug("Rotation assignment failed on " + self.obj.name +
                        " object. xyz size != 3.")
        if isinstance(xyz, (list, tuple)) or len(xyz) == 3:
            xyz = Euler(xyz, 'XYZ')
        srt = self.obj.localOrientation.copy()
        xyz = xyz.to_matrix()

        for obj in self.transformable:
            if obj.__class__.__name__ == "KX_GameObject":
                if obj == self.obj: obj.localOrientation = xyz
                else:
                    srr = obj.worldOrientation.copy()
                    srr.rotate(xyz)
                    srr = srr.to_euler()
                    obj.localOrientation = srr
            else:
                srr = obj.rotation.copy()
                srr.rotate(xyz)
                obj.localOrientation = srr
                obj.rotation = srr
        self._rotation = self.ProxyRotation()
示例#27
0
def random_scale_and_rotation(obj, normal, NM_SCN, self_data):
    loc, rot, scale = obj.matrix_world.decompose()

    loc = Matrix.Translation(loc)
    rot = rot.to_euler().to_matrix().to_4x4()

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

    if NM_SCN.use_random_scale:
        new_scale = uniform(NM_SCN.random_scale_from, NM_SCN.random_scale_to)
        scale = Matrix.Scale(new_scale, 4)
    else:
        scale = Matrix.Scale(self_data.scale_model, 4)

    # apply rotation by normal if checked "align_by_normal"
    if NM_SCN.align_by_normal:
        rot_by_normal = normal.rotation_difference(Vector((0, 0, 1)))
        rot_by_normal.invert()
        rot_by_normal = rot_by_normal.to_euler().to_matrix().to_4x4()
        rot = rot_by_normal @ rot_add
    else:
        rot = Euler((0, 0, 0)).to_matrix().to_4x4()
        rot = rot @ rot_add

    if NM_SCN.use_random_rotation:
        x_angle = math.radians(uniform(0, NM_SCN.random_rotation_x))
        y_angle = math.radians(uniform(0, NM_SCN.random_rotation_y))
        z_angle = math.radians(uniform(0, NM_SCN.random_rotation_z))

        rot_rand = Euler(Vector(
            (x_angle, y_angle, z_angle))).to_matrix().to_4x4()
        rot = rot @ rot_rand

    mat_w = loc @ rot @ scale

    obj.matrix_world = mat_w
示例#28
0
def createSceneFromXML(scene_file):
    # parse xml
    sceneTree = ET.parse(scene_file)
    root = sceneTree.getroot()
    # traverse scene xml
    materialStack.append(createDefaultMaterial())
    transformStack.append(Matrix.Identity(4))
    rootObject = createObjectFromXML(root, root[0], './sceneRoot', None, True)
    # create coordinate conversion root
    sceneObject = bpy.data.objects.new('JReality Scene', None)
    jrealityToBlender = Euler((math.pi/2, 0.0, math.pi/2), 'XYZ')
    sceneObject.matrix_local = jrealityToBlender.to_matrix().to_4x4()
    bpy.context.scene.objects.link(sceneObject)
    rootObject.parent = sceneObject;
    # find active camera
    cameraPath = root.find("scenePaths/path[@name='cameraPath']")
    if cameraPath != None:
        cameraPathXpath = resolveReferencePath(root, cameraPath, "./scenePaths/path[@name='cameraPath']")
        cameraPath = resolveReference(root, cameraPath, "./scenePaths/path[@name='cameraPath']")
        node = cameraPath.find('node[last()]')
        camTag = resolveReference(root, node, cameraPathXpath + "/node[last()]")
        bpy.context.scene.camera = tagToObject[camTag]
    else:
        print('WARNING: no camera path set')
示例#29
0
def joueur_clavier(gl):
    '''Un joueur joue au clavier et avec la souris
    Avec la souris:
    Haut bas pour avancer reculer donc y
    Gauche droite pour le déplacement latéral donc x
    Molette pour régler l'élévation du tir
    Q pour sauter
    Espace pour ajouter un livre donc accx
    Le joueur au clavier est toujours le 0
    Si clavier, ajout de la flèche de tir
    '''
    # Récupération des entrées clavier et de la position de la souris
    # Space donne accx = -6
    accx = gl.clavier["accx"]
    # Repasse à 0
    gl.clavier["accx"] = 0
    # Saut
    accz = gl.clavier["accz"]
    # Souris
    x = gl.mouse_x
    y = gl.mouse_y
    accy = 2 - gl.clavier["wheel"]

    # Définir la direction de la flèche
    alpha = 0.3 + accy / 9  # élévation
    beta = 0
    gamma = 0  # direction mais définit par x, y

    # set objects orientation with alpha, beta, gamma in degrees
    rot_en_euler = Euler([alpha, beta, gamma])

    # Orientation de la flèche
    gl.fleche.worldOrientation = rot_en_euler.to_matrix()

    data = ["clavier", accx, accy, accz, x, y]
    return data
示例#30
0
def bvh_node_dict2armature(context,
                           bvh_name,
                           bvh_nodes,
                           bvh_frame_time,
                           rotate_mode='XYZ',
                           frame_start=1,
                           IMPORT_LOOP=False,
                           global_matrix=None,
                           use_fps_scale=False,
                           use_frame_step=False,
                           only_rootbone_location=True,
                           rig_only=False,
                           ):

    ZERO_AREA_BONES = []
    scene = context.scene

    def add_armature():
            # Add the new armature,
        for obj in scene.objects:
            obj.select = False

        arm_data = bpy.data.armatures.new(bvh_name)
        arm_ob = bpy.data.objects.new(bvh_name, arm_data)

        scene.objects.link(arm_ob)

        arm_ob.select = True
        scene.objects.active = arm_ob

        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
        bpy.ops.object.mode_set(mode='EDIT', toggle=False)

        bvh_nodes_list = sorted_nodes(bvh_nodes)

        # Get the average bone length for zero length bones, we may not use this.
        average_bone_length = 0.0
        nonzero_count = 0
        for bvh_node in bvh_nodes_list:
            l = (bvh_node.rest_head_local - bvh_node.rest_tail_local).length
            if l:
                average_bone_length += l
                nonzero_count += 1

        # Very rare cases all bones could be zero length???
        if not average_bone_length:
            average_bone_length = 0.1
        else:
            # Normal operation
            average_bone_length = average_bone_length / nonzero_count

        # XXX, annoying, remove bone.
        while arm_data.edit_bones:
            arm_ob.edit_bones.remove(arm_data.edit_bones[-1])

        #ZERO_AREA_BONES = []
        for bvh_node in bvh_nodes_list:
            if bvh_node.zero_length:
                print("ZZZZZZZZZZZZZZZZZZZZZZ", bvh_node)

            # New editbone
            bone = bvh_node.temp = arm_data.edit_bones.new(bvh_node.name)

            bone.head = bvh_node.rest_head_world
            bone.tail = bvh_node.rest_tail_world

            # Zero Length Bones! (an exceptional case)
            if (bone.head - bone.tail).length < 0.001:
                print("\tzero length bone found:", bone.name)
                if bvh_node.parent:
                    ofs = bvh_node.parent.rest_head_local - bvh_node.parent.rest_tail_local
                    if ofs.length:  # is our parent zero length also?? unlikely
                        bone.tail = bone.tail - ofs
                    else:
                        bone.tail.y = bone.tail.y + average_bone_length
                else:
                    # HANDLE ZERO LENGTH BONES
                    bone.tail += average_bone_length * Vector((0,1,0))
                    #bone.tail.y = bone.tail.y + average_bone_length

                ZERO_AREA_BONES.append(bone.name)

        for bvh_node in bvh_nodes_list:
            if bvh_node.zero_length:
                pass

            if bvh_node.parent:
                # bvh_node.temp is the Editbone

                # Set the bone parent
                bvh_node.temp.parent = bvh_node.parent.temp

                # Set the connection state
                if((not bvh_node.has_loc) and
                   (bvh_node.parent.temp.name not in ZERO_AREA_BONES) and
                   (bvh_node.parent.rest_tail_local == bvh_node.rest_head_local)):

                    bvh_node.temp.use_connect = True

        # Replace the editbone with the editbone name,
        # to avoid memory errors accessing the editbone outside editmode
        for bvh_node in bvh_nodes_list:
            bvh_node.temp = bvh_node.temp.name

        return arm_ob, bvh_nodes_list


    if frame_start < 1:
        frame_start = 1

    arm_ob, bvh_nodes_list = add_armature()
    # zero length nodes
    X = [n for n in bvh_nodes_list if n.zero_length]
    print("ZEROOOOOOO", X)
    # bone taken out no longer needed 
    #bone = None

    arm_data = arm_ob.data
    # Now Apply the animation to the armature

    # Get armature animation data
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

    pose = arm_ob.pose
    pose_bones = pose.bones

    if rotate_mode == 'NATIVE':
        for bvh_node in bvh_nodes_list:
            bone_name = bvh_node.temp  # may not be the same name as the bvh_node, could have been shortened.
            pose_bone = pose_bones[bone_name]
            if bone_name in ZERO_AREA_BONES:
                print("ZLB", bone_name)
                pose_bone["zero"] = True
            pose_bone.rotation_mode = bvh_node.rot_order_str

    elif rotate_mode != 'QUATERNION':
        for pose_bone in pose_bones:
            pose_bone.rotation_mode = rotate_mode
    else:
        # Quats default
        pass

    context.scene.update()

    if rig_only:
        # fix this to have action part too.
        arm_ob.matrix_world = global_matrix
        bpy.ops.object.transform_apply(rotation=True)

        return arm_ob

    arm_ob.animation_data_create()
    action = bpy.data.actions.new(name=bvh_name)
    arm_ob.animation_data.action = action

    # Replace the bvh_node.temp (currently an editbone)
    # With a tuple  (pose_bone, armature_bone, bone_rest_matrix, bone_rest_matrix_inv)
    num_frame = 0
    for bvh_node in bvh_nodes_list:
        bone_name = bvh_node.temp  # may not be the same name as the bvh_node, could have been shortened.
        pose_bone = pose_bones[bone_name]
        rest_bone = arm_data.bones[bone_name]
        bone_rest_matrix = rest_bone.matrix_local.to_3x3()

        bone_rest_matrix_inv = Matrix(bone_rest_matrix)
        bone_rest_matrix_inv.invert()

        bone_rest_matrix_inv.resize_4x4()
        bone_rest_matrix.resize_4x4()
        #XXXX bone removed from bvh_node.temp
        bvh_node.temp = (pose_bone, bone_rest_matrix, bone_rest_matrix_inv)

        if 0 == num_frame:
            num_frame = len(bvh_node.anim_data)

    # Choose to skip some frames at the beginning. Frame 0 is the rest pose
    # used internally by this importer. Frame 1, by convention, is also often
    # the rest pose of the skeleton exported by the motion capture system.
    bt = 1.0 / context.scene.render.fps
    print("FT, BT", bvh_frame_time, bt, floor(bt / bvh_frame_time))
    sub_frame_step = 1
    if use_frame_step:
        sub_frame_step = floor(bt / bvh_frame_time)
        if sub_frame_step == 0:
            sub_frame_step = 1
    skip_frame = 1
    if num_frame > skip_frame:
        num_frame = num_frame - skip_frame

    # Create a shared time axis for all animation curves.
    time = [float(frame_start)] * num_frame
    dt = 0.0
    if use_fps_scale:
        dt = scene.render.fps * bvh_frame_time
        for frame_i in range(1, num_frame):
            time[frame_i] += float(frame_i) * dt
    else:
        sub_frame_step = 1
        for frame_i in range(1, num_frame):
            time[frame_i] += float(frame_i)

    frange = range(0, num_frame, sub_frame_step)
    print("bvh_frame_time = %f, dt = %f, num_frame = %d"
          % (bvh_frame_time, dt, num_frame))

    for i, bvh_node in enumerate(bvh_nodes_list):
        pose_bone, bone_rest_matrix, bone_rest_matrix_inv = bvh_node.temp

        #print("FRANGE:", frange)
        if bvh_node.has_loc:
            # Not sure if there is a way to query this or access it in the
            # PoseBone structure.
            if (pose_bone.parent is None and only_rootbone_location) or not only_rootbone_location:
                data_path = 'pose.bones["%s"].location' % pose_bone.name

                location = [(0.0, 0.0, 0.0)] * num_frame
                for frame_i in range(0, num_frame):
                    bvh_loc = bvh_node.anim_data[frame_i + skip_frame][:3]

                    bone_translate_matrix = Matrix.Translation(
                            Vector(bvh_loc) - bvh_node.rest_head_local)
                    location[frame_i] = (bone_rest_matrix_inv *
                                         bone_translate_matrix).to_translation()

                # For each location x, y, z.
                for axis_i in range(3):
                    curve = action.fcurves.new(data_path=data_path, index=axis_i)
                    keyframe_points = curve.keyframe_points
                    keyframe_points.add(len(frange))

                    for i, frame_i in enumerate(frange):
                        keyframe_points[i].co = \
                                (time[frame_i], location[frame_i][axis_i])

        if bvh_node.has_rot:
            data_path = None
            rotate = None

            if 'QUATERNION' == rotate_mode:
                rotate = [(1.0, 0.0, 0.0, 0.0)] * num_frame
                data_path = ('pose.bones["%s"].rotation_quaternion'
                             % pose_bone.name)
            else:
                rotate = [(0.0, 0.0, 0.0)] * num_frame
                data_path = ('pose.bones["%s"].rotation_euler' %
                             pose_bone.name)

            prev_euler = Euler((0.0, 0.0, 0.0))
            for frame_i in range(0, num_frame):
                bvh_rot = bvh_node.anim_data[frame_i + skip_frame][3:]

                # apply rotation order and convert to XYZ
                # note that the rot_order_str is reversed.
                euler = Euler(bvh_rot, bvh_node.rot_order_str[::-1])
                bone_rotation_matrix = euler.to_matrix().to_4x4()
                bone_rotation_matrix = (bone_rest_matrix_inv *
                                        bone_rotation_matrix *
                                        bone_rest_matrix)

                if 4 == len(rotate[frame_i]):
                    rotate[frame_i] = bone_rotation_matrix.to_quaternion()
                else:
                    rotate[frame_i] = bone_rotation_matrix.to_euler(
                            pose_bone.rotation_mode, prev_euler)
                    prev_euler = rotate[frame_i]

            # For each Euler angle x, y, z (or Quaternion w, x, y, z).
            for axis_i in range(len(rotate[0])):
                curve = action.fcurves.new(data_path=data_path, index=axis_i)
                keyframe_points = curve.keyframe_points
                keyframe_points.add(len(frange))

                for i, frame_i in enumerate(frange):
                    keyframe_points[i].co = \
                            (time[frame_i], rotate[frame_i][axis_i])

    for cu in action.fcurves:
        if IMPORT_LOOP:
            pass  # 2.5 doenst have cyclic now?

        for bez in cu.keyframe_points:
            bez.interpolation = 'LINEAR'

    # finally apply matrix
    arm_ob.matrix_world = global_matrix
    bpy.ops.object.transform_apply(rotation=True)

    return arm_ob
示例#31
0
def read_chan(context, filepath, z_up, rot_ord, sensor_width, sensor_height):

    # get the active object
    scene = context.scene
    obj = context.active_object
    camera = obj.data if obj.type == 'CAMERA' else None

    # prepare the correcting matrix
    rot_mat = Matrix.Rotation(radians(90.0), 4, 'X').to_4x4()

    # read the file
    filehandle = open(filepath, 'r')

    # iterate through the files lines
    for line in filehandle:
        # reset the target objects matrix
        # (the one from which one we'll extract the final transforms)
        m_trans_mat = Matrix()

        # strip the line
        data = line.split()

        # test if the line is not commented out
        if data and not data[0].startswith("#"):

            # set the frame number basing on the chan file
            scene.frame_set(int(data[0]))

            # read the translation values from the first three columns of line
            v_transl = Vector((float(data[1]), float(data[2]), float(data[3])))
            translation_mat = Matrix.Translation(v_transl)
            translation_mat.to_4x4()

            # read the rotations, and set the rotation order basing on the
            # order set during the export (it's not being saved in the chan
            # file you have to keep it noted somewhere
            # the actual objects rotation order doesn't matter since the
            # rotations are being extracted from the matrix afterwards
            e_rot = Euler((radians(float(data[4])), radians(float(data[5])),
                           radians(float(data[6]))))
            e_rot.order = rot_ord
            mrot_mat = e_rot.to_matrix()
            mrot_mat.resize_4x4()

            # merge the rotation and translation
            m_trans_mat = translation_mat * mrot_mat

            # correct the world space
            # (nuke's and blenders scene spaces are different)
            if z_up:
                m_trans_mat = rot_mat * m_trans_mat

            # break the matrix into a set of the coordinates
            trns = m_trans_mat.decompose()

            # set the location and the location's keyframe
            obj.location = trns[0]
            obj.keyframe_insert("location")

            # convert the rotation to euler angles (or not)
            # basing on the objects rotation mode
            if obj.rotation_mode == 'QUATERNION':
                obj.rotation_quaternion = trns[1]
                obj.keyframe_insert("rotation_quaternion")
            elif obj.rotation_mode == 'AXIS_ANGLE':
                tmp_rot = trns[1].to_axis_angle()
                obj.rotation_axis_angle = (tmp_rot[1], *tmp_rot[0])
                obj.keyframe_insert("rotation_axis_angle")
                del tmp_rot
            else:
                obj.rotation_euler = trns[1].to_euler(obj.rotation_mode)
                obj.keyframe_insert("rotation_euler")

            # check if the object is camera and fov data is present
            if camera and len(data) > 7:
                camera.sensor_fit = 'HORIZONTAL'
                camera.sensor_width = sensor_width
                camera.sensor_height = sensor_height
                camera.angle_y = radians(float(data[7]))
                camera.keyframe_insert("lens")
    filehandle.close()

    return {'FINISHED'}
def read_chan(context, filepath, z_up, rot_ord, sensor_width, sensor_height):

    # get the active object
    scene = context.scene
    obj = context.active_object
    camera = obj.data if obj.type == 'CAMERA' else None

    # prepare the correcting matrix
    rot_mat = Matrix.Rotation(radians(90.0), 4, 'X').to_4x4()

    # read the file
    filehandle = open(filepath, 'r')

    # iterate throug the files lines
    for line in filehandle:
        # reset the target objects matrix
        # (the one from whitch one we'll extract the final transforms)
        m_trans_mat = Matrix()

        # strip the line
        data = line.split()

        # test if the line is not commented out
        if data and not data[0].startswith("#"):

            # set the frame number basing on the chan file
            scene.frame_set(int(data[0]))

            # read the translation values from the first three columns of line
            v_transl = Vector((float(data[1]),
                               float(data[2]),
                               float(data[3])))
            translation_mat = Matrix.Translation(v_transl)
            translation_mat.to_4x4()

            # read the rotations, and set the rotation order basing on the
            # order set during the export (it's not being saved in the chan
            # file you have to keep it noted somewhere
            # the actual objects rotation order doesn't matter since the
            # rotations are being extracted from the matrix afterwards
            e_rot = Euler((radians(float(data[4])),
                           radians(float(data[5])),
                           radians(float(data[6]))))
            e_rot.order = rot_ord
            mrot_mat = e_rot.to_matrix()
            mrot_mat.resize_4x4()

            # merge the rotation and translation
            m_trans_mat = translation_mat * mrot_mat

            # correct the world space
            # (nuke's and blenders scene spaces are different)
            if z_up:
                m_trans_mat = rot_mat * m_trans_mat

            # break the matrix into a set of the coordinates
            trns = m_trans_mat.decompose()

            # set the location and the location's keyframe
            obj.location = trns[0]
            obj.keyframe_insert("location")

            # convert the rotation to euler angles (or not)
            # basing on the objects rotation mode
            if obj.rotation_mode == 'QUATERNION':
                obj.rotation_quaternion = trns[1]
                obj.keyframe_insert("rotation_quaternion")
            elif obj.rotation_mode == 'AXIS_ANGLE':
                tmp_rot = trns[1].to_axis_angle()
                obj.rotation_axis_angle = (tmp_rot[1], *tmp_rot[0])
                obj.keyframe_insert("rotation_axis_angle")
                del tmp_rot
            else:
                obj.rotation_euler = trns[1].to_euler(obj.rotation_mode)
                obj.keyframe_insert("rotation_euler")

            # check if the object is camera and fov data is present
            if camera and len(data) > 7:
                camera.sensor_fit = 'HORIZONTAL'
                camera.sensor_width = sensor_width
                camera.sensor_height = sensor_height
                camera.angle_y = radians(float(data[7]))
                camera.keyframe_insert("lens")
    filehandle.close()

    return {'FINISHED'}
示例#33
0
def _get_bone_channels(bone_list, action, export_scale):
    """Takes a bone list and action and returns bone channels.
    bone_channels structure example:
    [("Bone", [("_TIME", [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]), ("_MATRIX", [])])]"""
    bone_channels = []
    frame_start = action.frame_range[0]
    frame_end = action.frame_range[1]
    total_time = action.scs_props.action_length
    anim_export_step = action.scs_props.anim_export_step
    total_frames = (frame_end - frame_start) / anim_export_step
    # print(' -- action: %r' % str(action))
    for bone in bone_list:
        # print(' oo bone: %r' % str(bone))
        if bone:
            # print(' -- bone_name: %r' % bone.name)
            bone_name = bone.name
            bone_rest_mat = bone.matrix_local
            if bone.parent:
                parent_bone_rest_mat = Matrix.Scale(export_scale, 4) * _convert_utils.scs_to_blend_matrix().inverted() * bone.parent.matrix_local
            else:
                parent_bone_rest_mat = Matrix()
            for group in action.groups:
                if group.name == bone_name:
                    # print(' -- group: %r' % str(group))

                    # GET CHANELS' CURVES
                    loc_curves = {}
                    euler_rot_curves = {}
                    quat_rot_curves = {}
                    sca_curves = {}
                    rot_mode = ''
                    for channel in group.channels:
                        data_path = channel.data_path
                        array_index = channel.array_index
                        # channel_start = channel.range()[0]
                        # channel_end = channel.range()[1]
                        # print('      channel: %r (%s) [%s - %s]' % (data_path, array_index, channel_start, channel_end))
                        if data_path.endswith("location"):
                            loc_curves[array_index] = channel
                        elif data_path.endswith("rotation_euler"):
                            euler_rot_curves[array_index] = channel
                            rot_mode = 'euler'
                        elif data_path.endswith("rotation_quaternion"):
                            quat_rot_curves[array_index] = channel
                            rot_mode = 'quat'
                        elif data_path.endswith("scale"):
                            sca_curves[array_index] = channel

                    # GO THOUGH FRAMES
                    actual_frame = frame_start
                    timings_stream = []
                    matrices_stream = []
                    while actual_frame <= frame_end:
                        mat_loc = Matrix()
                        mat_rot = Matrix()
                        mat_sca = Matrix()

                        # LOCATION MATRIX
                        if len(loc_curves) > 0:
                            location = Vector()
                            for index in range(3):
                                if index in loc_curves:
                                    location[index] = loc_curves[index].evaluate(actual_frame)
                            mat_loc = Matrix.Translation(location)

                        # ROTATION MATRIX
                        if rot_mode == 'euler' and len(euler_rot_curves) > 0:
                            rotation = Euler()
                            for index in range(3):
                                if index in euler_rot_curves:
                                    rotation[index] = euler_rot_curves[index].evaluate(actual_frame)
                            mat_rot = Euler(rotation, 'XYZ').to_matrix().to_4x4()  # TODO: Solve the other rotation modes.
                        if rot_mode == 'quat' and len(quat_rot_curves) > 0:
                            rotation = Quaternion()
                            for index in range(4):
                                if index in quat_rot_curves:
                                    rotation[index] = quat_rot_curves[index].evaluate(actual_frame)
                            mat_rot = rotation.to_matrix().to_4x4()

                        # SCALE MATRIX
                        if len(sca_curves) > 0:
                            scale = Vector((1.0, 1.0, 1.0))
                            for index in range(3):
                                if index in sca_curves:
                                    scale[index] = sca_curves[index].evaluate(actual_frame)
                            mat_sca = Matrix()
                            mat_sca[0] = (scale[0], 0, 0, 0)
                            mat_sca[1] = (0, scale[2], 0, 0)
                            mat_sca[2] = (0, 0, scale[1], 0)
                            mat_sca[3] = (0, 0, 0, 1)

                        # BLENDER FRAME MATRIX
                        mat = mat_loc * mat_rot * mat_sca

                        # SCALE REMOVAL MATRIX
                        rest_location, rest_rotation, rest_scale = bone_rest_mat.decompose()
                        # print(' BONES rest_scale: %s' % str(rest_scale))
                        rest_scale = rest_scale * export_scale
                        scale_removal_matrix = Matrix()
                        scale_removal_matrix[0] = (1.0 / rest_scale[0], 0, 0, 0)
                        scale_removal_matrix[1] = (0, 1.0 / rest_scale[1], 0, 0)
                        scale_removal_matrix[2] = (0, 0, 1.0 / rest_scale[2], 0)
                        scale_removal_matrix[3] = (0, 0, 0, 1)

                        # SCALE MATRIX
                        scale_matrix = Matrix.Scale(export_scale, 4)

                        # COMPUTE SCS FRAME MATRIX
                        frame_matrix = (parent_bone_rest_mat.inverted() * _convert_utils.scs_to_blend_matrix().inverted() *
                                        scale_matrix.inverted() * bone_rest_mat * mat * scale_removal_matrix.inverted())

                        # print('          actual_frame: %s - value: %s' % (actual_frame, frame_matrix))
                        timings_stream.append(("__time__", total_time / total_frames), )
                        matrices_stream.append(("__matrix__", frame_matrix.transposed()), )
                        actual_frame += anim_export_step
                    anim_timing = ("_TIME", timings_stream)
                    anim_matrices = ("_MATRIX", matrices_stream)
                    bone_anim = (anim_timing, anim_matrices)
                    bone_data = (bone_name, bone_anim)
                    bone_channels.append(bone_data)
        else:
            lprint('W bone %r is not part of the actual Armature!', bone.name)
            # print(' -- bone.name: %r' % (bone.name))
    return bone_channels
示例#34
0
    def modal(self, context, event):
        context.area.tag_redraw()
        nexus_model_SCN = context.scene.nexus_model_manager
        mod = None
        if event.shift:
            mod = "SHIFT"
        elif event.ctrl:
            mod = "CTRL"

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

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

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

                # hide mesh
                self.current_model.hide_set(True)

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

                # show mesh
                self.current_model.hide_set(False)

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

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

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

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

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

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

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

                    self.current_model.matrix_world = mat_w

                    # draw assets
                    self.draw_asset(context, event)

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

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

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

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

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

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

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

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

        return {"RUNNING_MODAL"}
示例#35
0
def bvh_node_dict2armature(
    context,
    bvh_name,
    bvh_nodes,
    bvh_frame_time,
    rotate_mode='XYZ',
    frame_start=1,
    IMPORT_LOOP=False,
    global_matrix=None,
    use_fps_scale=False,
):

    if frame_start < 1:
        frame_start = 1

    # Add the new armature,
    scene = context.scene
    for obj in scene.objects:
        obj.select_set(False)

    arm_data = bpy.data.armatures.new(bvh_name)
    arm_ob = bpy.data.objects.new(bvh_name, arm_data)

    context.collection.objects.link(arm_ob)

    arm_ob.select_set(True)
    context.view_layer.objects.active = arm_ob

    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
    bpy.ops.object.mode_set(mode='EDIT', toggle=False)

    bvh_nodes_list = sorted_nodes(bvh_nodes)

    # Get the average bone length for zero length bones, we may not use this.
    average_bone_length = 0.0
    nonzero_count = 0
    for bvh_node in bvh_nodes_list:
        l = (bvh_node.rest_head_local - bvh_node.rest_tail_local).length
        if l:
            average_bone_length += l
            nonzero_count += 1

    # Very rare cases all bones could be zero length???
    if not average_bone_length:
        average_bone_length = 0.1
    else:
        # Normal operation
        average_bone_length = average_bone_length / nonzero_count

    # XXX, annoying, remove bone.
    while arm_data.edit_bones:
        arm_ob.edit_bones.remove(arm_data.edit_bones[-1])

    ZERO_AREA_BONES = []
    for bvh_node in bvh_nodes_list:

        # New editbone
        bone = bvh_node.temp = arm_data.edit_bones.new(bvh_node.name)

        bone.head = bvh_node.rest_head_world
        bone.tail = bvh_node.rest_tail_world

        # Zero Length Bones! (an exceptional case)
        if (bone.head - bone.tail).length < 0.001:
            print("\tzero length bone found:", bone.name)
            if bvh_node.parent:
                ofs = bvh_node.parent.rest_head_local - bvh_node.parent.rest_tail_local
                if ofs.length:  # is our parent zero length also?? unlikely
                    bone.tail = bone.tail - ofs
                else:
                    bone.tail.y = bone.tail.y + average_bone_length
            else:
                bone.tail.y = bone.tail.y + average_bone_length

            ZERO_AREA_BONES.append(bone.name)

    for bvh_node in bvh_nodes_list:
        if bvh_node.parent:
            # bvh_node.temp is the Editbone

            # Set the bone parent
            bvh_node.temp.parent = bvh_node.parent.temp

            # Set the connection state
            if ((not bvh_node.has_loc)
                    and (bvh_node.parent.temp.name not in ZERO_AREA_BONES) and
                (bvh_node.parent.rest_tail_local == bvh_node.rest_head_local)):
                bvh_node.temp.use_connect = True

    # Replace the editbone with the editbone name,
    # to avoid memory errors accessing the editbone outside editmode
    for bvh_node in bvh_nodes_list:
        bvh_node.temp = bvh_node.temp.name

    # Now Apply the animation to the armature

    # Get armature animation data
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

    pose = arm_ob.pose
    pose_bones = pose.bones

    if rotate_mode == 'NATIVE':
        for bvh_node in bvh_nodes_list:
            bone_name = bvh_node.temp  # may not be the same name as the bvh_node, could have been shortened.
            pose_bone = pose_bones[bone_name]
            pose_bone.rotation_mode = bvh_node.rot_order_str

    elif rotate_mode != 'QUATERNION':
        for pose_bone in pose_bones:
            pose_bone.rotation_mode = rotate_mode
    else:
        # Quats default
        pass

    context.view_layer.update()

    arm_ob.animation_data_create()
    action = bpy.data.actions.new(name=bvh_name)
    arm_ob.animation_data.action = action

    # Replace the bvh_node.temp (currently an editbone)
    # With a tuple  (pose_bone, armature_bone, bone_rest_matrix, bone_rest_matrix_inv)
    num_frame = 0
    for bvh_node in bvh_nodes_list:
        bone_name = bvh_node.temp  # may not be the same name as the bvh_node, could have been shortened.
        pose_bone = pose_bones[bone_name]
        rest_bone = arm_data.bones[bone_name]
        bone_rest_matrix = rest_bone.matrix_local.to_3x3()

        bone_rest_matrix_inv = Matrix(bone_rest_matrix)
        bone_rest_matrix_inv.invert()

        bone_rest_matrix_inv.resize_4x4()
        bone_rest_matrix.resize_4x4()
        bvh_node.temp = (pose_bone, bone, bone_rest_matrix,
                         bone_rest_matrix_inv)

        if 0 == num_frame:
            num_frame = len(bvh_node.anim_data)

    # Choose to skip some frames at the beginning. Frame 0 is the rest pose
    # used internally by this importer. Frame 1, by convention, is also often
    # the rest pose of the skeleton exported by the motion capture system.
    skip_frame = 1
    if num_frame > skip_frame:
        num_frame = num_frame - skip_frame

    # Create a shared time axis for all animation curves.
    time = [float(frame_start)] * num_frame
    if use_fps_scale:
        dt = scene.render.fps * bvh_frame_time
        for frame_i in range(1, num_frame):
            time[frame_i] += float(frame_i) * dt
    else:
        for frame_i in range(1, num_frame):
            time[frame_i] += float(frame_i)

    # print("bvh_frame_time = %f, dt = %f, num_frame = %d"
    #      % (bvh_frame_time, dt, num_frame]))

    for i, bvh_node in enumerate(bvh_nodes_list):
        pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv = bvh_node.temp

        if bvh_node.has_loc:
            # Not sure if there is a way to query this or access it in the
            # PoseBone structure.
            data_path = 'pose.bones["%s"].location' % pose_bone.name

            location = [(0.0, 0.0, 0.0)] * num_frame
            for frame_i in range(num_frame):
                bvh_loc = bvh_node.anim_data[frame_i + skip_frame][:3]

                bone_translate_matrix = Matrix.Translation(
                    Vector(bvh_loc) - bvh_node.rest_head_local)
                location[frame_i] = (bone_rest_matrix_inv
                                     @ bone_translate_matrix).to_translation()

            # For each location x, y, z.
            for axis_i in range(3):
                curve = action.fcurves.new(data_path=data_path, index=axis_i)
                keyframe_points = curve.keyframe_points
                keyframe_points.add(num_frame)

                for frame_i in range(num_frame):
                    keyframe_points[frame_i].co = (
                        time[frame_i],
                        location[frame_i][axis_i],
                    )

        if bvh_node.has_rot:
            data_path = None
            rotate = None

            if 'QUATERNION' == rotate_mode:
                rotate = [(1.0, 0.0, 0.0, 0.0)] * num_frame
                data_path = ('pose.bones["%s"].rotation_quaternion' %
                             pose_bone.name)
            else:
                rotate = [(0.0, 0.0, 0.0)] * num_frame
                data_path = ('pose.bones["%s"].rotation_euler' %
                             pose_bone.name)

            prev_euler = Euler((0.0, 0.0, 0.0))
            for frame_i in range(num_frame):
                bvh_rot = bvh_node.anim_data[frame_i + skip_frame][3:]

                # apply rotation order and convert to XYZ
                # note that the rot_order_str is reversed.
                euler = Euler(bvh_rot, bvh_node.rot_order_str[::-1])
                bone_rotation_matrix = euler.to_matrix().to_4x4()
                bone_rotation_matrix = (
                    bone_rest_matrix_inv @ bone_rotation_matrix
                    @ bone_rest_matrix)

                if len(rotate[frame_i]) == 4:
                    rotate[frame_i] = bone_rotation_matrix.to_quaternion()
                else:
                    rotate[frame_i] = bone_rotation_matrix.to_euler(
                        pose_bone.rotation_mode, prev_euler)
                    prev_euler = rotate[frame_i]

            # For each euler angle x, y, z (or quaternion w, x, y, z).
            for axis_i in range(len(rotate[0])):
                curve = action.fcurves.new(data_path=data_path, index=axis_i)
                keyframe_points = curve.keyframe_points
                keyframe_points.add(num_frame)

                for frame_i in range(num_frame):
                    keyframe_points[frame_i].co = (
                        time[frame_i],
                        rotate[frame_i][axis_i],
                    )

    for cu in action.fcurves:
        if IMPORT_LOOP:
            pass  # 2.5 doenst have cyclic now?

        for bez in cu.keyframe_points:
            bez.interpolation = 'LINEAR'

    # finally apply matrix
    arm_ob.matrix_world = global_matrix
    bpy.ops.object.transform_apply(location=False, rotation=True, scale=False)

    return arm_ob
示例#36
0
def draw_ig(obj, draw_collision_grid):
    if "collisionStartX" not in obj.keys():
        return

    startX = obj["collisionStartX"]
    startY = -obj["collisionStartY"]
    stepX = obj["collisionStepX"]
    stepY = -obj["collisionStepY"]
    stepCountX = obj["collisionStepCountX"]
    stepCountY = obj["collisionStepCountY"]

    conveyorEndPos = (obj["conveyorX"] * 40, obj["conveyorZ"] * -40,
                      obj["conveyorY"] * 40)

    # Draw collision grid
    gpu.matrix.push()

    if obj.animation_data is not None and obj.animation_data.action is not None:
        action = obj.animation_data.action

        start_frame = bpy.context.scene.frame_start
        current_frame = bpy.context.scene.frame_current
        pos_delta = Vector((0, 0, 0))
        rot_mode = obj.rotation_mode
        rot_delta = Euler((0, 0, 0), rot_mode)

        for i in range(3):
            if action.fcurves.find("location", index=i):
                c = action.fcurves.find("location", index=i)
                delta = c.evaluate(current_frame) - c.evaluate(start_frame)
                pos_delta[i] = delta
            if action.fcurves.find("rotation_euler", index=i):
                c = action.fcurves.find("rotation_euler", index=i)
                delta = c.evaluate(current_frame) - c.evaluate(start_frame)
                rot_delta[i] = delta

        grid_mtx_rot = rot_delta.to_matrix().to_4x4()
        grid_mtx_pos = Matrix.Translation(pos_delta)
        grid_mtx = grid_mtx_pos @ grid_mtx_rot

        gpu.matrix.multiply_matrix(grid_mtx)

    bgl.glLineWidth(2)
    if draw_collision_grid:
        draw_grid(startX, startY, stepX, stepY, stepCountX, stepCountY, 0,
                  COLOR_GREEN_FAINT)

    gpu.matrix.pop()

    # Draw conveyor arrow
    conveyorObjects = [
        child for child in obj.children if child.data is not None
    ]
    if obj.data is not None: conveyorObjects.append(obj)

    for conveyorObject in conveyorObjects:
        gpu.matrix.push()
        gpu.matrix.multiply_matrix(conveyorObject.matrix_world)
        if 0 not in conveyorObject.scale:
            gpu.matrix.scale(
                (1 / conveyorObject.scale.x, 1 / conveyorObject.scale.y,
                 1 / conveyorObject.scale.z))  # No scaling
        lineWidth = [(6, COLOR_BLACK), (2, COLOR_GREEN)]
        for (width, color) in lineWidth:
            coords = [ZERO_VEC, conveyorEndPos]
            bgl.glLineWidth(width)
            draw_batch(coords, color, 'LINES')
        gpu.matrix.pop()
示例#37
0
def _get_bone_channels(scs_root_obj, armature, scs_animation, action,
                       export_scale):
    """Takes armature and action and returns bone channels.
    bone_channels structure example:
    [("Bone", [("_TIME", [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]), ("_MATRIX", [])])]"""
    bone_channels = []
    frame_start = scs_animation.anim_start
    frame_end = scs_animation.anim_end
    anim_export_step = action.scs_props.anim_export_step
    total_frames = (frame_end - frame_start) / anim_export_step

    # armature matrix stores transformation of armature object against scs root
    # and has to be added to all bones as they only armature space transformations
    armature_mat = scs_root_obj.matrix_world.inverted() * armature.matrix_world

    invalid_data = False  # flag to indicate invalid data state
    curves_per_bone = OrderedDict(
    )  # store all the curves we are interested in per bone names

    for bone in armature.data.bones:
        for fcurve in action.fcurves:

            # check if curve belongs to bone
            if '["' + bone.name + '"]' in fcurve.data_path:

                data_path = fcurve.data_path
                array_index = fcurve.array_index

                if data_path.endswith("location"):
                    curve_type = "location"
                elif data_path.endswith("rotation_euler"):
                    curve_type = "euler_rotation"
                elif data_path.endswith("rotation_quaternion"):
                    curve_type = "quat_rotation"
                elif data_path.endswith("scale"):
                    curve_type = "scale"
                else:
                    curve_type = None

                # write only recognized curves
                if curve_type is not None:
                    if bone.name not in curves_per_bone:
                        curves_per_bone[bone.name] = {
                            "location": {},
                            "euler_rotation": {},
                            "quat_rotation": {},
                            "scale": {}
                        }

                    curves_per_bone[
                        bone.name][curve_type][array_index] = fcurve

    for bone_name, bone_curves in curves_per_bone.items():

        bone = armature.data.bones[bone_name]
        pose_bone = armature.pose.bones[bone_name]
        loc_curves = bone_curves["location"]
        euler_rot_curves = bone_curves["euler_rotation"]
        quat_rot_curves = bone_curves["quat_rotation"]
        sca_curves = bone_curves["scale"]

        bone_rest_mat = armature_mat * bone.matrix_local
        if bone.parent:
            parent_bone_rest_mat = (
                Matrix.Scale(export_scale, 4) *
                _convert_utils.scs_to_blend_matrix().inverted() *
                armature_mat * bone.parent.matrix_local)
        else:
            parent_bone_rest_mat = Matrix()

        # GO THOUGH FRAMES
        actual_frame = frame_start
        timings_stream = []
        matrices_stream = []
        while actual_frame <= frame_end:
            mat_loc = Matrix()
            mat_rot = Matrix()
            mat_sca = Matrix()

            # LOCATION MATRIX
            if len(loc_curves) > 0:
                location = Vector()
                for index in range(3):
                    if index in loc_curves:
                        location[index] = loc_curves[index].evaluate(
                            actual_frame)
                mat_loc = Matrix.Translation(location)

            # ROTATION MATRIX
            if len(euler_rot_curves) > 0:
                rotation = Euler()
                for index in range(3):
                    if index in euler_rot_curves:
                        rotation[index] = euler_rot_curves[index].evaluate(
                            actual_frame)
                mat_rot = Euler(rotation, pose_bone.rotation_mode).to_matrix(
                ).to_4x4()  # calc rotation by pose rotation mode

            elif len(quat_rot_curves) > 0:
                rotation = Quaternion()
                for index in range(4):
                    if index in quat_rot_curves:
                        rotation[index] = quat_rot_curves[index].evaluate(
                            actual_frame)
                mat_rot = rotation.to_matrix().to_4x4()

            # SCALE MATRIX
            if len(sca_curves) > 0:
                scale = Vector((1.0, 1.0, 1.0))
                for index in range(3):
                    if index in sca_curves:
                        scale[index] = sca_curves[index].evaluate(actual_frame)

                        if scale[index] < 0:
                            lprint(
                                str("E Negative scale detected on bone %r:\n\t   "
                                    "(Action: %r, keyframe no.: %s, SCS Animation: %r)."
                                    ), (bone_name, action.name, actual_frame,
                                        scs_animation.name))
                            invalid_data = True

                mat_sca = Matrix()
                mat_sca[0] = (scale[0], 0, 0, 0)
                mat_sca[1] = (0, scale[2], 0, 0)
                mat_sca[2] = (0, 0, scale[1], 0)
                mat_sca[3] = (0, 0, 0, 1)

            # BLENDER FRAME MATRIX
            mat = mat_loc * mat_rot * mat_sca

            # SCALE REMOVAL MATRIX
            rest_location, rest_rotation, rest_scale = bone_rest_mat.decompose(
            )
            # print(' BONES rest_scale: %s' % str(rest_scale))
            rest_scale = rest_scale * export_scale
            scale_removal_matrix = Matrix()
            scale_removal_matrix[0] = (1.0 / rest_scale[0], 0, 0, 0)
            scale_removal_matrix[1] = (0, 1.0 / rest_scale[1], 0, 0)
            scale_removal_matrix[2] = (0, 0, 1.0 / rest_scale[2], 0)
            scale_removal_matrix[3] = (0, 0, 0, 1)

            # SCALE MATRIX
            scale_matrix = Matrix.Scale(export_scale, 4)

            # COMPUTE SCS FRAME MATRIX
            frame_matrix = (parent_bone_rest_mat.inverted() *
                            _convert_utils.scs_to_blend_matrix().inverted() *
                            scale_matrix.inverted() * bone_rest_mat * mat *
                            scale_removal_matrix.inverted())

            # print('          actual_frame: %s - value: %s' % (actual_frame, frame_matrix))
            timings_stream.append(
                ("__time__", scs_animation.length / total_frames), )
            matrices_stream.append(("__matrix__", frame_matrix.transposed()), )
            actual_frame += anim_export_step

        anim_timing = ("_TIME", timings_stream)
        anim_matrices = ("_MATRIX", matrices_stream)
        bone_anim = (anim_timing, anim_matrices)
        bone_data = (bone_name, bone_anim)
        bone_channels.append(bone_data)

    # return empty bone channels if data are invalid
    if invalid_data:
        return []

    return bone_channels
示例#38
0
def import_animations(mdl: MdlV44, armature, scale):
    bpy.ops.object.select_all(action="DESELECT")
    armature.select_set(True)
    bpy.context.view_layer.objects.active = armature
    bpy.ops.object.mode_set(mode='POSE')
    if not armature.animation_data:
        armature.animation_data_create()
    # for var_pos in ['XYZ', 'YXZ', ]:
    #     for var_rot in ['XYZ', 'XZY', 'YZX', 'ZYX', 'YXZ', 'ZXY', ]:
    for var_pos in ['XYZ']:
        for var_rot in ['XYZ']:
            for anim_desc in mdl.anim_descs:
                anim_name = f'pos_{var_pos}_rot_{var_rot}_{anim_desc.name}'
                action = bpy.data.actions.new(anim_name)
                armature.animation_data.action = action
                curve_per_bone = {}
                for bone in anim_desc.anim_bones:
                    if bone.bone_id == -1:
                        continue
                    bone_name = mdl.bones[bone.bone_id].name

                    bone_string = f'pose.bones["{bone_name}"].'
                    group = action.groups.new(name=bone_name)
                    pos_curves = []
                    rot_curves = []
                    for i in range(3):
                        pos_curve = action.fcurves.new(data_path=bone_string +
                                                       "location",
                                                       index=i)
                        pos_curve.keyframe_points.add(anim_desc.frame_count)
                        pos_curves.append(pos_curve)
                        pos_curve.group = group
                    for i in range(3):
                        # rot_curve = action.fcurves.new(data_path=bone_string + "rotation_quaternion", index=i)
                        rot_curve = action.fcurves.new(data_path=bone_string +
                                                       "rotation_euler",
                                                       index=i)
                        rot_curve.keyframe_points.add(anim_desc.frame_count)
                        rot_curves.append(rot_curve)
                        rot_curve.group = group
                    curve_per_bone[bone_name] = pos_curves, rot_curves

                for bone in anim_desc.anim_bones:
                    if bone.bone_id == -1:
                        continue
                    mdl_bone = mdl.bones[bone.bone_id]

                    bl_bone = armature.pose.bones.get(mdl_bone.name)
                    bl_bone.rotation_mode = 'XYZ'

                    pos_scale = mdl_bone.position_scale
                    rot_scale = mdl_bone.rotation_scale
                    if bone.is_raw_pos:
                        pos_frames = [
                            Vector(
                                np.multiply(np.multiply(bone.pos, pos_scale),
                                            scale))
                        ]
                    elif bone.is_anim_pos:
                        pos_frames = [
                            Vector(
                                np.multiply(np.multiply(pos, pos_scale),
                                            scale)) for pos in bone.pos_anim
                        ]
                    else:
                        pos_frames = []

                    if bone.is_raw_rot:
                        rot_frames = [
                            Euler(
                                np.multiply(
                                    Quaternion(bone.quat).to_euler('XYZ'),
                                    rot_scale))
                        ]
                    elif bone.is_anim_rot:
                        rot_frames = [
                            Euler(np.multiply(rot, rot_scale))
                            for rot in bone.vec_rot_anim
                        ]
                    else:
                        rot_frames = []

                    pos_curves, rot_curves = curve_per_bone[mdl_bone.name]
                    for n, pos_frame in enumerate(pos_frames):
                        pos = __swap_components(pos_frame, var_pos)

                        for i in range(3):
                            pos_curves[i].keyframe_points.add(1)
                            pos_curves[i].keyframe_points[-1].co = (n, pos[i])

                    for n, rot_frame in enumerate(rot_frames):
                        fixed_rot = rot_frame
                        if mdl_bone.parent_bone_index == -1:
                            fixed_rot.x += math.radians(-90)
                            fixed_rot.y += math.radians(180)
                            fixed_rot.z += math.radians(-90)
                        fixed_rot = Euler(__swap_components(
                            fixed_rot, var_rot))
                        # qx = Quaternion([1, 0, 0], fixed_rot[0])
                        # qy = Quaternion([0, 1, 0], -fixed_rot[1])
                        # qz = Quaternion([0, 0, 1], -fixed_rot[2])
                        # fixed_rot: Euler = (qx @ qy @ qz).to_euler()
                        # fixed_rot.x += mdl_bone.rotation[0]
                        # fixed_rot.y += mdl_bone.rotation[1]
                        # fixed_rot.z += mdl_bone.rotation[2]
                        fixed_rot.rotate(
                            Euler([
                                math.radians(90),
                                math.radians(0),
                                math.radians(0)
                            ]))
                        fixed_rot.rotate(
                            Euler([
                                math.radians(0),
                                math.radians(0),
                                math.radians(90)
                            ]))
                        fixed_rot = (
                            fixed_rot.to_matrix().to_4x4()
                            @ bl_bone.rotation_euler.to_matrix().to_4x4()
                        ).to_euler()
                        for i in range(3):
                            rot_curves[i].keyframe_points.add(1)
                            rot_curves[i].keyframe_points[-1].co = (
                                n, fixed_rot[i])

                        bpy.ops.object.mode_set(mode='OBJECT')
def get_top_mesh(context, prefs):
    me = context.blend_data.meshes.new("temp_mesh")
    bm = bmesh.new()
    bm.from_mesh(me)
    mat = Matrix()
    tt = prefs.lp_Tree_Type

    if tt == "lp_Tree_Oak":
        mat.translation = (0, 0, prefs.trunk_depth)
        tsmin = prefs.lp_Tree_Top_Scale_Min
        tsmax = prefs.lp_Tree_Top_Scale_Max
        mat[0][0], mat[1][1], mat[2][2] = (
            uniform(tsmin[0], tsmax[0]),
            uniform(tsmin[1], tsmax[1]),
            uniform(tsmin[2], tsmax[2]),
        )
        bmesh.ops.create_icosphere(bm, subdivisions=prefs.lp_Tree_Top_Subdivisions, diameter=1.0, matrix=mat)
    elif tt == "lp_Tree_Pine":
        segments = get_random(prefs.lp_Tree_Top_Stage_Segments_Min, prefs.lp_Tree_Top_Stage_Segments_Max)
        stages = get_random(prefs.lp_Tree_Top_Stages_Min, prefs.lp_Tree_Top_Stages_Max)
        td = prefs.trunk_depth - 0.7
        sstep = uniform(prefs.lp_Tree_Top_Stage_Step_Min, prefs.lp_Tree_Top_Stage_Step_Max)
        ssmin = prefs.lp_Tree_Top_Stage_Size_Min
        ssmax = prefs.lp_Tree_Top_Stage_Size_Max
        ssize = (uniform(ssmin[0], ssmax[0]), uniform(ssmin[1], ssmax[1]), uniform(ssmin[2], ssmax[2]))
        for i in range(0, stages):
            mult = prefs.lp_Tree_Top_Stage_Shrink_Multiplier * (i / 4)
            sc = (1 - i * prefs.lp_Tree_Top_Stage_Shrink * mult) * 0.9
            if sc < 0.01:
                sc = 0.01
            mat[0][0], mat[1][1], mat[2][2] = (sc * ssize[0], sc * ssize[1], sc * ssize[2])
            mat.translation = (0, 0, (td + ((ssize[2] - 1) / 2) + i * sstep) * 0.85)
            if prefs.lp_Tree_Top_Rotate_Stages:
                e = Euler((0, 0, uniform(0, 3.14)), "XYZ")
                mat = mat * e.to_matrix().to_4x4()
            bmesh.ops.create_cone(
                bm,
                cap_ends=True,
                cap_tris=True,
                segments=segments,
                diameter1=(prefs.lp_Tree_Top_Stage_Diameter),
                diameter2=0,
                depth=(0.85),
                matrix=mat,
            )
            mat = Matrix()
    elif tt == "lp_Tree_Palm":
        trunk_length = prefs.palm_stage_length * prefs.palm_stages
        leaf_length = get_random(prefs.lp_Tree_Palm_Top_Leaf_Length_Min, prefs.lp_Tree_Palm_Top_Leaf_Length_Max)
        leaf_size = uniform(prefs.lp_Tree_Palm_Top_Leaf_Size_Min, prefs.lp_Tree_Palm_Top_Leaf_Size_Max)

        mat.translation = (0, 0, trunk_length)
        leaves = get_random(prefs.lp_Tree_Palm_Top_Leaves_Min, prefs.lp_Tree_Palm_Top_Leaves_Max)
        bmesh.ops.create_cone(
            bm,
            cap_ends=True,
            cap_tris=True,
            segments=leaves,
            diameter1=leaf_size,
            diameter2=leaf_size,
            depth=0.1,
            matrix=mat,
        )
        faces = bm.faces[:]
        for face in faces:
            nor = face.normal  # Asume normalized normal
            dir = (nor.x * 0.3, nor.y * 0.3, -0.12)
            if nor.z == 0:
                for i in range(0, leaf_length):
                    r = bmesh.ops.extrude_discrete_faces(bm, faces=[face])
                    bmesh.ops.translate(bm, vec=dir, verts=r["faces"][0].verts)
                    face = r["faces"][0]
                    dir = (dir[0], dir[1], dir[2] - 0.08)
                # Align last face verts
                mid = [0, 0, 0]
                for v in face.verts:
                    mid[0] += v.co.x
                    mid[1] += v.co.y
                    mid[2] += v.co.z
                mid[0] /= len(face.verts)
                mid[1] /= len(face.verts)
                mid[2] /= len(face.verts)
                for v in face.verts:
                    v.co.x, v.co.y, v.co.z = mid[0], mid[1], mid[2]

    bm.to_mesh(me)
    return me
 def __init__(self, name, root, length, chord, incidence, twist, taper, sweep, dihedral):
     
     # transform angles to rad
     sweep *= DEG2RAD
     twist *= DEG2RAD
     
     dihedral *= DEG2RAD
     incidence *=DEG2RAD
     
     # find out if it's a symetric element
     self.is_symetric = not name.startswith("YASim_vstab")
     
     # create the wing mesh object
     # the wing is first created at ORIGIN w/o incidence/dihedral
     
     base = ORIGIN
     basefore = ORIGIN + 0.5 * chord * X
     baseaft = ORIGIN - 0.5 * chord * X
     
     tip = ORIGIN + (math.cos(sweep) * length * Y) - (math.sin(sweep) * length * X)
     
     tipfore = tip + (0.5 * taper * chord * math.cos(twist) * X) + (0.5 * taper * chord * math.sin(twist) * Z)
     tipaft = tip + tip - tipfore
     #  <1--0--2
     #   \  |  /
     #    4-3-5
     wing_obj = mesh_create(name, ORIGIN, [base, basefore, baseaft, tip, tipfore, tipaft], [], 
                             [(0, 1, 4, 3), (2, 0, 3, 5)])
     
     # now transform the mesh
     # set the created object active !!!!!!!
     bpy.context.scene.objects.active = wing_obj
     # get the active mesh
     mesh = bpy.context.object.data
     
     # create a rotation matrix, for dihedral and incidence rotation
     e = Euler((dihedral, -incidence, 0))
     m1 = e.to_matrix()
     m = m1.to_4x4()
     
     # rotate it
     mesh.transform(m)
     
     mesh.update()
     
     # position the object
     #wing_obj.location = root
     # use the matrix to position it
     wing_obj.matrix_world = Matrix.Translation(root)
     
     # assign materials
     if self.is_symetric:
         Item.set_material('tgreen-1', (0.0,0.5,0.0), 0.5)
         
         Symetric.list_append(wing_obj)
     
     else:
         Item.set_material('tred-1', (0.5,0.0,0.0), 0.5)
     
     # write out the vars for the flaps
     self.baseaft = baseaft
     self.tipaft = tipaft
     self.base = base
     self.wing_obj = wing_obj
     self.mesh_matrix = m
示例#41
0
def _get_bone_channels(scs_root_obj, armature, scs_animation, action, export_scale):
    """Takes armature and action and returns bone channels.
    bone_channels structure example:
    [("Bone", [("_TIME", [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]), ("_MATRIX", [])])]"""
    bone_channels = []
    frame_start = scs_animation.anim_start
    frame_end = scs_animation.anim_end
    anim_export_step = action.scs_props.anim_export_step
    total_frames = (frame_end - frame_start) / anim_export_step

    # armature matrix stores transformation of armature object against scs root
    # and has to be added to all bones as they only armature space transformations
    armature_mat = scs_root_obj.matrix_world.inverted() * armature.matrix_world

    invalid_data = False  # flag to indicate invalid data state
    curves_per_bone = {}  # store all the curves we are interested in per bone names

    for bone in armature.data.bones:
        for fcurve in action.fcurves:

            # check if curve belongs to bone
            if '["' + bone.name + '"]' in fcurve.data_path:

                data_path = fcurve.data_path
                array_index = fcurve.array_index

                if data_path.endswith("location"):
                    curve_type = "location"
                elif data_path.endswith("rotation_euler"):
                    curve_type = "euler_rotation"
                elif data_path.endswith("rotation_quaternion"):
                    curve_type = "quat_rotation"
                elif data_path.endswith("scale"):
                    curve_type = "scale"
                else:
                    curve_type = None

                # write only recognized curves
                if curve_type is not None:
                    if bone.name not in curves_per_bone:
                        curves_per_bone[bone.name] = {
                            "location": {},
                            "euler_rotation": {},
                            "quat_rotation": {},
                            "scale": {}
                        }

                    curves_per_bone[bone.name][curve_type][array_index] = fcurve

    for bone_name, bone_curves in curves_per_bone.items():

        bone = armature.data.bones[bone_name]
        pose_bone = armature.pose.bones[bone_name]
        loc_curves = bone_curves["location"]
        euler_rot_curves = bone_curves["euler_rotation"]
        quat_rot_curves = bone_curves["quat_rotation"]
        sca_curves = bone_curves["scale"]

        bone_rest_mat = armature_mat * bone.matrix_local
        if bone.parent:
            parent_bone_rest_mat = (Matrix.Scale(export_scale, 4) * _convert_utils.scs_to_blend_matrix().inverted() *
                                    armature_mat * bone.parent.matrix_local)
        else:
            parent_bone_rest_mat = Matrix()

        # GO THOUGH FRAMES
        actual_frame = frame_start
        timings_stream = []
        matrices_stream = []
        while actual_frame <= frame_end:
            mat_loc = Matrix()
            mat_rot = Matrix()
            mat_sca = Matrix()

            # LOCATION MATRIX
            if len(loc_curves) > 0:
                location = Vector()
                for index in range(3):
                    if index in loc_curves:
                        location[index] = loc_curves[index].evaluate(actual_frame)
                mat_loc = Matrix.Translation(location)

            # ROTATION MATRIX
            if len(euler_rot_curves) > 0:
                rotation = Euler()
                for index in range(3):
                    if index in euler_rot_curves:
                        rotation[index] = euler_rot_curves[index].evaluate(actual_frame)
                mat_rot = Euler(rotation, pose_bone.rotation_mode).to_matrix().to_4x4()  # calc rotation by pose rotation mode

            elif len(quat_rot_curves) > 0:
                rotation = Quaternion()
                for index in range(4):
                    if index in quat_rot_curves:
                        rotation[index] = quat_rot_curves[index].evaluate(actual_frame)
                mat_rot = rotation.to_matrix().to_4x4()

            # SCALE MATRIX
            if len(sca_curves) > 0:
                scale = Vector((1.0, 1.0, 1.0))
                for index in range(3):
                    if index in sca_curves:
                        scale[index] = sca_curves[index].evaluate(actual_frame)

                        if scale[index] < 0:
                            lprint(str("E Negative scale detected on bone %r:\n\t   "
                                       "(Action: %r, keyframe no.: %s, SCS Animation: %r)."),
                                   (bone_name, action.name, actual_frame, scs_animation.name))
                            invalid_data = True

                mat_sca = Matrix()
                mat_sca[0] = (scale[0], 0, 0, 0)
                mat_sca[1] = (0, scale[2], 0, 0)
                mat_sca[2] = (0, 0, scale[1], 0)
                mat_sca[3] = (0, 0, 0, 1)

            # BLENDER FRAME MATRIX
            mat = mat_loc * mat_rot * mat_sca

            # SCALE REMOVAL MATRIX
            rest_location, rest_rotation, rest_scale = bone_rest_mat.decompose()
            # print(' BONES rest_scale: %s' % str(rest_scale))
            rest_scale = rest_scale * export_scale
            scale_removal_matrix = Matrix()
            scale_removal_matrix[0] = (1.0 / rest_scale[0], 0, 0, 0)
            scale_removal_matrix[1] = (0, 1.0 / rest_scale[1], 0, 0)
            scale_removal_matrix[2] = (0, 0, 1.0 / rest_scale[2], 0)
            scale_removal_matrix[3] = (0, 0, 0, 1)

            # SCALE MATRIX
            scale_matrix = Matrix.Scale(export_scale, 4)

            # COMPUTE SCS FRAME MATRIX
            frame_matrix = (parent_bone_rest_mat.inverted() * _convert_utils.scs_to_blend_matrix().inverted() *
                            scale_matrix.inverted() * bone_rest_mat * mat * scale_removal_matrix.inverted())

            # print('          actual_frame: %s - value: %s' % (actual_frame, frame_matrix))
            timings_stream.append(("__time__", scs_animation.length / total_frames), )
            matrices_stream.append(("__matrix__", frame_matrix.transposed()), )
            actual_frame += anim_export_step

        anim_timing = ("_TIME", timings_stream)
        anim_matrices = ("_MATRIX", matrices_stream)
        bone_anim = (anim_timing, anim_matrices)
        bone_data = (bone_name, bone_anim)
        bone_channels.append(bone_data)

    # return empty bone channels if data are invalid
    if invalid_data:
        return []

    return bone_channels