示例#1
0
def add_object_align_init(context, operator):
    """
    Return a matrix using the operator settings and view context.

    :arg context: The context to use.
    :type context: :class:`bpy.types.Context`
    :arg operator: The operator, checked for location and rotation properties.
    :type operator: :class:`bpy.types.Operator`
    :return: the matrix from the context and settings.
    :rtype: :class:`mathutils.Matrix`
    """

    from mathutils import Matrix, Vector, Euler
    properties = operator.properties if operator is not None else None

    space_data = context.space_data
    if space_data and space_data.type != 'VIEW_3D':
        space_data = None

    # location
    if operator and properties.is_property_set("location"):
        location = Matrix.Translation(Vector(properties.location))
    else:
        location = Matrix.Translation(context.scene.cursor.location)

        if operator:
            properties.location = location.to_translation()

    # rotation
    view_align = (context.preferences.edit.object_align == 'VIEW')
    view_align_force = False
    if operator:
        if properties.is_property_set("view_align"):
            view_align = view_align_force = operator.view_align
        else:
            if properties.is_property_set("rotation"):
                # ugh, 'view_align' callback resets
                value = properties.rotation[:]
                properties.view_align = view_align
                properties.rotation = value
                del value
            else:
                properties.view_align = view_align

    if operator and (properties.is_property_set("rotation") and
                     not view_align_force):

        rotation = Euler(properties.rotation).to_matrix().to_4x4()
    else:
        if view_align and space_data:
            rotation = space_data.region_3d.view_matrix.to_3x3().inverted()
            rotation.resize_4x4()
        else:
            rotation = Matrix()

        # set the operator properties
        if operator:
            properties.rotation = rotation.to_euler()

    return location @ rotation
示例#2
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
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()
    def getTransformFromParent(self):
        rot = Euler((radians(self.alpha.value), radians(self.beta.value),
                     radians(self.gamma.value)), 'XYZ').to_matrix()
        rot.resize_4x4()

        transl = Matrix.Translation((self.x.value, self.y.value, self.z.value))
        # print("here",transl * rot)
        return transl * rot
示例#5
0
def mapping_node_order_flip(orientation):
    """
    Flip euler order of mapping shader node
    see: Blender #a1ffb49
    """
    rot = Euler(orientation)
    rot.order = 'ZYX'
    quat = rot.to_quaternion()
    return quat.to_euler('XYZ')
示例#6
0
    def process(self):
        if not self.outputs['Quaternions'].is_linked:
            return

        inputs = self.inputs

        quaternionList = []

        if self.mode == "WXYZ":
            I = [inputs[n].sv_get()[0] for n in "WXYZ"]
            params = match_long_repeat(I)
            for wxyz in zip(*params):
                q = Quaternion(wxyz)
                if self.normalize:
                    q.normalize()
                quaternionList.append(q)

        elif self.mode == "SCALARVECTOR":
            I = [inputs[n].sv_get()[0] for n in ["Scalar", "Vector"]]
            params = match_long_repeat(I)
            for scalar, vector in zip(*params):
                q = Quaternion([scalar, *vector])
                if self.normalize:
                    q.normalize()
                quaternionList.append(q)

        elif self.mode == "EULER":
            I = [inputs["Angle " + n].sv_get()[0] for n in "XYZ"]
            params = match_long_repeat(I)
            au = angleConversion[self.angleUnits]
            for angleX, angleY, angleZ in zip(*params):
                euler = Euler((angleX * au, angleY * au, angleZ * au), self.eulerOrder)
                q = euler.to_quaternion()
                if self.normalize:
                    q.normalize()
                quaternionList.append(q)

        elif self.mode == "AXISANGLE":
            I = [inputs[n].sv_get()[0] for n in ["Axis", "Angle"]]
            params = match_long_repeat(I)
            au = angleConversion[self.angleUnits]
            for axis, angle in zip(*params):
                q = Quaternion(axis, angle * au)
                if self.normalize:
                    q.normalize()
                quaternionList.append(q)

        elif self.mode == "MATRIX":
            input_M = inputs["Matrix"].sv_get(default=idMat)
            for m in input_M:
                q = Matrix(m).to_quaternion()
                if self.normalize:
                    q.normalize()
                quaternionList.append(q)

        self.outputs['Quaternions'].sv_set([quaternionList])
示例#7
0
def eval_planet_rotation(scn_name, obj_name, index=None, time=None):
    """Evaluate the planets rotation, used by driver.

    scn_name = Name of a scene which contains the object
    obj_name = Name of the object to simulate
    index = index of the rotation channel,
            usually only z-axis (index=2) changes
    time = time when to calculate, if not given use current scene time
            time is in seconds of the simulation
    returns an Euler in mode ZYX or, if index given, an angle in radians
    """
    scn = bpy.data.scenes.get(scn_name)
    obj = bpy.data.objects.get(obj_name)
    if not obj or not scn:
        errmsg = "DRIVER ERROR: Invalid obj_name ({}) or scn_name ({})"
        print(errmsg.format(obj_name, scn_name))
        return 0

    simscn = scn.sssim_scn
    simrot = obj.sssim_rotation

    # time = time in seconds, if None use current scene time
    if time is None:
        time = simscn.time

    # rotation_period is also in seconds
    rotation_period = simrot.rotation_period
    if rotation_period != 0:
        rot_z = 2 * pi * time / rotation_period
    else:
        # invalid input -> no rotation
        rot_z = 0

    tilt = simrot.axis_tilt
    planet_rot = Euler((tilt, 0.0, 0.0), 'ZYX')  # note that mode is 'ZYX'

    # rotate around global (not local) z-axis
    direction = simrot.axis_direction
    planet_rot.rotate(Euler((0.0, 0.0, direction), 'XYZ'))

    # rotate around local z-axis
    # NOTE: we won't use planet_rot.rotate_axis('Z', rot_z) because then
    # all rotations are between -180 and 180 and for the rotation around
    # z we need a continous motion with increasing z values
    planet_rot.z += rot_z

    if simrot.relative_to_orbit and obj.sssim_obj.object_type == 'PLANET':
        planet_rot = orbit_rotate(planet_rot, obj.sssim_orbit)

    if index is None:
        return planet_rot
    else:
        return planet_rot[index]
示例#8
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()
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
示例#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 = 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()
示例#11
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()
示例#12
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')
    def getTransformFromParent(self):
        alphaMatrix = Euler((radians(self.alpha.value), 0, 0),
                            'XYZ').to_matrix()
        alphaMatrix.resize_4x4()

        thetaMatrix = Euler((0, 0, radians(self.theta.value)),
                            'XYZ').to_matrix()
        thetaMatrix.resize_4x4()

        translation = Matrix.Translation((self.a.value, 0, self.d.value, 1))

        return translation * alphaMatrix * thetaMatrix
示例#14
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[1], 0, 0)
                mat_sca[2] = (0, 0, scale[2], 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
示例#15
0
import bge
import time
from rift import PyRift
from mathutils import Quaternion, Euler, Vector

# Functions
def poll():
    bge.logic.rift.pollSensor()
    bge.logic.rotation = Quaternion((bge.logic.rift.headPose[3], bge.logic.rift.headPose[4], bge.logic.rift.headPose[5], bge.logic.rift.headPose[6]))
    bge.logic.position = Vector((bge.logic.rift.headPose[0],bge.logic.rift.headPose[1],bge.logic.rift.headPose[2]))

# Main
try:
    eu = bge.logic.rotation.to_euler()
    fix = Euler((-1.57, 0, 0), 'XYZ')
    rot = Euler((-eu.z, eu.y, -eu.x), 'XYZ')
    rot.rotate(fix)
    
    bge.logic.prev_orientation = rot;
    poll()
    
except:
    bge.logic.rift = PyRift()
    bge.logic.rift.connect()
            
    scene_e = bge.logic.getCurrentScene()
    cam_e = scene_e.active_camera
    bge.logic.init_position = Vector((cam_e.localPosition[0],cam_e.localPosition[1],cam_e.localPosition[2]))
    bge.logic.init_orientation = cam_e.localOrientation.to_euler() 

    eu = Euler()
示例#16
0
    def modal(self, context, event):
        if event.type == "TIMER":

            if context.scene.com_props.prop_running_nav and not context.scene.com_props.prop_paused_nav:
                last_pose = pc.PathContainer().poses[-1]
                reached_poses = cnh.Buffer().get_reached_poses()
                num_reached_poses = len(reached_poses)
                num_path_poses = len(pc.PathContainer().poses)
                end_reached = cnh.Buffer().end_reached()

                if num_reached_poses == num_path_poses and end_reached:
                    context.scene.com_props.prop_running_nav = False
                    context.scene.com_props.prop_paused_nav = False

                    if RUNNING_STATUS in hudWriter.HUDWriterOperator._textos:
                        del hudWriter.HUDWriterOperator._textos[RUNNING_STATUS]

                if num_reached_poses != num_path_poses and end_reached:
                    self.report({'ERROR'}, "End reached not expected")
                    context.scene.com_props.prop_running_nav = False
                    context.scene.com_props.prop_paused_nav = False

                capture_started = cnh.Buffer().capture_started()
                capture_ended = cnh.Buffer().capture_ended()

                if capture_started:
                    prop_capture_running = context.scene.com_props.prop_capture_running
                    if prop_capture_running:
                        self.report({'ERROR'}, "Capture is already started")
                    else:
                        context.scene.com_props.prop_capture_running = True
                        self.report({'INFO'}, "Capture started")
                    hudWriter.HUDWriterOperator._textos[
                        CAPTURE_STATUS] = SocketModalOperator.CAPTURE_ON

                if capture_ended:
                    prop_capture_running = context.scene.com_props.prop_capture_running
                    if not prop_capture_running:
                        self.report({'ERROR'}, "Capture was not started")
                    else:
                        context.scene.com_props.prop_capture_running = False
                        self.report({'INFO'}, "Capture ended")

                    if CAPTURE_STATUS in hudWriter.HUDWriterOperator._textos:
                        del hudWriter.HUDWriterOperator._textos[CAPTURE_STATUS]

            if not SocketModalOperator.closed and context.scene.com_props.prop_rendering:
                # Render robot position
                sel_robot_id = bpy.context.scene.selected_robot_props.prop_robot_id
                if sel_robot_id < 0:
                    self.report({'ERROR'}, "No robot selected")
                else:
                    r = robot.RobotSet().getRobot(sel_robot_id)
                    trace = cnh.Buffer().get_last_trace_packet()

                    if trace is not None:
                        pose = trace.pose
                        r.loc = Vector((pose.x, pose.y, 0))
                        r.rotation = Euler((0, 0, pose.gamma))

            if SocketModalOperator.closed:
                SocketModalOperator.switching = True

                if SocketModalOperator.error != "":
                    self.report({'ERROR'}, self.error)
                    SocketModalOperator.running = False
                    cnh.ConnectionHandler().remove_socket()
                else:
                    bpy.context.scene.com_props.prop_last_sent_packet += 1
                    new_pid = bpy.context.scene.com_props.prop_last_sent_packet
                    new_mode = robot_modes_summary.index("EDITOR_MODE")
                    initial_speed = context.scene.com_props.prop_speed
                    bpy.context.scene.com_props.prop_mode = robot_modes_summary.index(
                        "EDITOR_MODE")

                    if not cnh.ConnectionHandler().send_change_mode(
                            new_pid, new_mode, initial_speed):
                        self.report({
                            'ERROR'
                        }, "Changed to editor mode but not in server : ack not received"
                                    )
                        SocketModalOperator.switching = False
                        SocketModalOperator.running = False

                        self.thread.join()  # se espera a que acabe el hilo

                        cnh.ConnectionHandler().remove_socket()

                        self.clear_hud(context)
                        return {'FINISHED'}

                    #update_gui()
                    toggle_deactivate_options(
                        robot_modes_summary.index("EDITOR_MODE"))

                    SocketModalOperator.running = False
                    self.thread.join()  # se espera a que acabe el hilo

                    cnh.ConnectionHandler().remove_socket()

                    if context.scene.is_cursor_active:
                        bpy.ops.scene.stop_cursor_listener()

                cnh.Buffer().clear_reached_poses()
                SocketModalOperator.switching = False
                self.report({'INFO'}, "Socket closed")

                context.scene.com_props.prop_running_nav = False
                context.scene.com_props.prop_paused_nav = False

                self.clear_hud(context)
                return {'FINISHED'}

        return {'PASS_THROUGH'}
示例#17
0
    def execute(self, context):

        from .model import SelectModel
        from .rigid_bodies import SelectGeometry, AssignGeometry
        from .segments import SelectSegment

        C = bpy.context
        D = bpy.data

        model = C.active_object

        bone_name = C.active_bone.name
        axis = C.active_bone.RobotEditor.axis
        pose_bone = C.active_object.pose.bones[bone_name]
        parent_bone = pose_bone.parent
        bone_to_parent = pose_bone.matrix.inverted() * parent_bone.matrix
        bone_world = model.matrix_world * pose_bone.matrix

        segment_length = bone_to_parent.translation.length
        distance_to_children = [
            (child.matrix.inverted() * pose_bone.matrix).translation.length
            for child in pose_bone.children
        ]

        self.logger.debug("%s, %s", segment_length, distance_to_children)

        # if there is no translation to parent, the parent (or its parent) draws the joint
        if bone_to_parent.translation.length > 0.001:

            max_length = max(distance_to_children + [segment_length])
            # If there is only one children, and its a distance 0, we have a ball joint
            if len(pose_bone.children
                   ) == 1 and distance_to_children[0] < 0.001:

                bpy.ops.mesh.primitive_uv_sphere_add(size=segment_length /
                                                     15.0)
                C.active_object.matrix_world = bone_world
            # if there IS a child, at distance >0 (or more than one child), draw a hinge joint
            elif len(pose_bone.children):
                bpy.ops.mesh.primitive_cylinder_add(radius=max_length / 15,
                                                    depth=max_length / 5)
                if axis == 'X':
                    m = Euler((0, 0, pi / 4)).to_matrix().to_4x4()
                elif axis == 'Y':
                    m = Euler((0, 0, pi / 4)).to_matrix().to_4x4()
                else:
                    m = Matrix()

                C.active_object.matrix_world = bone_world * m
            else:
                bpy.ops.mesh.primitive_cone_add(radius1=segment_length / 10,
                                                radius2=segment_length / 10)

            C.active_object.name = bone_name + '_axis'
            new_name = C.active_object.name
            SelectModel.run(model_name=model.name)
            SelectSegment.run(bone_name)
            SelectGeometry.run(new_name)
            AssignGeometry.run()

        return {'FINISHED'}
示例#18
0
 def create(cls, object, name):
     cls.set(object, name, ((0.0, 0.0, 0.0), Euler((0.0, 0.0, 0.0)), (1.0, 1.0, 1.0)))
示例#19
0
def bvh_node_dict2armature(context,
                           bvh_name,
                           bvh_nodes,
                           rotate_mode='XYZ',
                           frame_start=1,
                           IMPORT_LOOP=False,
                           global_matrix=None,
                           ):

    if frame_start < 1:
        frame_start = 1

    # Add the new armature,
    scene = context.scene
    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)

    # 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.values():
        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 couldbe 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 name, bvh_node in bvh_nodes.items():
        # New editbone
        bone = bvh_node.temp = arm_data.edit_bones.new(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.values():
        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 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.values():
        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.values():
            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.scene.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)
    for bvh_node in bvh_nodes.values():
        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)

    # Make a dict for fast access without rebuilding a list all the time.

    # KEYFRAME METHOD, SLOW, USE IPOS DIRECT
    # TODO: use f-point samples instead (Aligorith)
    if rotate_mode != 'QUATERNION':
        prev_euler = [Euler() for i in range(len(bvh_nodes))]

    # Animate the data, the last used bvh_node will do since they all have the same number of frames
    for frame_current in range(len(bvh_node.anim_data) - 1):  # skip the first frame (rest frame)
        # print frame_current

        # if frame_current==40: # debugging
        # 	break

        scene.frame_set(frame_start + frame_current)

        # Dont neet to set the current frame
        for i, bvh_node in enumerate(bvh_nodes.values()):
            pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv = bvh_node.temp
            lx, ly, lz, rx, ry, rz = bvh_node.anim_data[frame_current + 1]

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

                if rotate_mode == 'QUATERNION':
                    pose_bone.rotation_quaternion = bone_rotation_matrix.to_quaternion()
                else:
                    euler = bone_rotation_matrix.to_euler(pose_bone.rotation_mode, prev_euler[i])
                    pose_bone.rotation_euler = euler
                    prev_euler[i] = euler

            if bvh_node.has_loc:
                pose_bone.location = (bone_rest_matrix_inv * Matrix.Translation(Vector((lx, ly, lz)) - bvh_node.rest_head_local)).to_translation()

            if bvh_node.has_loc:
                pose_bone.keyframe_insert("location")
            if bvh_node.has_rot:
                if rotate_mode == 'QUATERNION':
                    pose_bone.keyframe_insert("rotation_quaternion")
                else:
                    pose_bone.keyframe_insert("rotation_euler")

    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
	def execute(self, context):
		os.system("cls")
		vars = context.scene
		target = bpy.data.objects[vars.Target]
		tool = bpy.data.objects[vars.Tool]
		orig_Euler = target.rotation_euler
		orig_Location = target.location
		print('RTL: ', vars.ReturnToLoc)
		print(orig_Euler)
		print(orig_Location)
		return2_eul = rot_eul = [orig_Euler[0],orig_Euler[1],orig_Euler[2]]
		return2_loc = slide_loc = [orig_Location[0],orig_Location[1],orig_Location[2]]
		toolRotRads = [radians(vars.MMToolXVal),radians(vars.MMToolYVal),radians(vars.MMToolZVal)]
		toolSlideUnits = [vars.MMToolXVal,vars.MMToolYVal,vars.MMToolZVal]
		prestepRotRads = [radians(vars.MMPreStepXVal),radians(vars.MMPreStepYVal),radians(vars.MMPreStepZVal)]
		prestepSlideUnits = [vars.MMPreStepXVal,vars.MMPreStepYVal,vars.MMPreStepZVal]

		# print('orig: ',orig_Euler,orig_Location)
		# print('rot and slide: ',rot_eul,slide_loc)
		# print('tool: ',toolRotRads,toolSlideUnits)
		# print('pre: ',prestepRotRads,prestepSlideUnits)
		
		for r in range(vars.RepeaterCnt):
			# print ('rep_cnt: ',r)
			if (vars.MMPreStep =='Rotate'):
				rot_eul = Euler([sum(e) for e in zip(rot_eul, prestepRotRads)], "XYZ")
				target.rotation_euler = rot_eul
			elif (vars.MMPreStep =='Slide'):
				slide_loc = Vector([sum(v) for v in zip(slide_loc, prestepSlideUnits)])
				target.location = slide_loc
			
			# print('rot slide: ',rot_eul,slide_loc)
			
			for i in range(vars.NumSteps+1):
				# print('step: ',i)
				if (i > 0 ):
					if (vars.MMMove == 'Rotate'):
						rot_eul = Euler([sum(z) for z in zip(rot_eul, toolRotRads)], "XYZ")
					else: # Assumes 'Slide'
						slide_loc = Vector([sum(z) for z in zip(slide_loc, toolSlideUnits)])

				# At step 0 these are the original euler\location (or location after pre-step), else the eul\loc just set
				target.rotation_euler = rot_eul 
				target.location = slide_loc
				bpy.ops.object.select_all(action='DESELECT')
				target.select = True
				bpy.context.scene.objects.active = target
				
				if (i >= vars.StartSteps): # Execute tool action at this step
					bpy.ops.object.modifier_add(type='BOOLEAN')
					mod = target.modifiers
					mod[0].name = "MMTool"
					if (vars.MMAction == 'Diff'):
						# print('diff: ',rot_eul, slide_loc)
						mod[0].operation = 'DIFFERENCE'
					else: # Assumes 'Union'
						# print('union: ',rot_eul, slide_loc)
						mod[0].operation = 'UNION'
					if (vars.MMAction != 'None'):
						mod[0].object = tool
						bpy.ops.object.modifier_apply(apply_as='DATA', modifier=mod[0].name)
					
				i += 1
			r += 1
			
		if (vars.ReturnToLoc == True):
			print('Return!!!: ', return2_eul, return2_loc)
			target.rotation_euler = return2_eul
			target.location = return2_loc
			
		if self.country == '':
			print('Done')
		else:
			print("Don't Make Cuts from %s!" % self.country)
		return {"FINISHED"}
示例#21
0
 def get(cls, object, name):
     paths = tuple(cls.iterSubpropertyPaths(name))
     return (Vector(getattr(object, paths[0], (0.0, 0.0, 0.0))),
             Euler(getattr(object, paths[1], (0.0, 0.0, 0.0)), cls.getRotationOrder(object, name)),
             Vector(getattr(object, paths[2], (1.0, 1.0, 1.0))))
def extract(properties, *args, **kwargs):
    """
    :returns: {
        'resolution': (width, height),
        'trackers': { 
            int: (x, y, z),
        },
        'cameras': {
            int: {
                'filename': str,
                'f': float,
                'k': (k1, k2, k3),
                'c': (x, y, z),  # real world coord
                't': (x, y, z),  # pmvs transformed translation
                'R': ((r00, r01, r02),
                        (r10, r11, r12),
                        (r20, r21, r22)),
                'trackers': {
                    int: (x, y),
                }
            }
        }
    }
    """
    filename = bpy.path.abspath(properties.filepath)
    imagepaths = list(filter(None, bpy.path.abspath(properties.imagepath).split(';')))
    data = {
        'trackers': {},
        'cameras': {},
    }
    doc = ET.parse(filename)
    for locator in doc.findall('L'):
        co = locator.find('P').attrib
        data['trackers'][int(locator.attrib['i'])] = {
            'co': (float(co['x']), float(co['y']), float(co['z'])),
            'rgb': (0, 0, 0),
        }
    
    cinfs = {}
    for cinf in doc.findall('CINF'):
        cinfs[cinf.attrib['i']] = cinf.attrib
    # cinf = doc.find('CINF').attrib

    for shot in doc.findall('SHOT'):
        cfrm = shot.find('CFRM')

        # test data indicates frame wasn't matched if cfrm doesn't reference a camera
        if 'cf' not in cfrm.attrib:
            continue
        
        cinf = cinfs.get(cfrm.attrib['cf'], {})
        intrinsics = cfrm.attrib
        intrinsics.setdefault('rd', cinf.get('rd', 0))
        extrinsics = {
            'T': cfrm.find('T').attrib,
            'R': cfrm.find('R').attrib
        }
        
        extrinsics.update({
            'T': Vector((float(extrinsics['T']['x']), float(extrinsics['T']['y']), float(extrinsics['T']['z']))),
            'R': Euler((radians(float(extrinsics['R']['x'])),
                        radians(float(extrinsics['R']['y'])), 
                        radians(float(extrinsics['R']['z']))), 'XYZ').to_matrix()
        })
        extrinsics['R'].transpose()

        # pinhole camera model
        # https://photo.stackexchange.com/a/41280
        # FOV = 2 * atan((sensor_width / 2) / focal_length)
        # focal_length = (sensor_width / 2) / tan(FOV / 2)
        f = (float(cinf['fbw']) / 2) / tan(radians(float(intrinsics['fovx']) / 2))
        f_pixels = int(shot.attrib['w']) * (f / float(cinf['fbw']))

        # find any filename that exists
        filenames = [fp for fp in [os.path.join(*parts) for parts in zip(imagepaths, [shot.attrib['n'],] * len(imagepaths))] if os.path.exists(fp)]
        if not filenames:
            # wasn't in a root path, do we search sub directories?
            if properties.subdirs:
                for imagepath in imagepaths:
                    for root, dirs, files in os.walk(imagepath):
                        if shot.attrib['n'] in files:
                            filenames = [os.path.join(root, shot.attrib['n'])]

            # still didn't find file?
            if not filenames:
                raise Exception('Image not found for camera {}: {}'.format(shot.attrib['i'], shot.attrib['n']))

        camera = data['cameras'].setdefault(int(shot.attrib['i']), {
            'filename': filenames[0],
            'f': f_pixels,
            'k': (-float(intrinsics['rd']),) * 3,
            'c': extrinsics['T'],
            'R': tuple(map(tuple, tuple(extrinsics['R']))),
            't': tuple(-1 * extrinsics['R'] @ extrinsics['T']),
        })

        if 'resolution' not in data:
            data.setdefault('resolution', get_image_size(camera['filename']))

        trackers = camera.setdefault('trackers', {})
        for marker in shot.find('IPLN').find('IFRM').findall('M'):
            trackers[int(marker.attrib['i'])] = (float(marker.attrib['x']), float(marker.attrib['y']))

    return data
示例#23
0
def TrajectoryAngle(own, interceptPoint, velocity):
    try:
        scene = bge.logic.getCurrentScene()
        if 'calculate' not in own:
            own['calculate'] = True
        if 'trajectoryAngle' not in own:
            own['trajectoryAngle'] = ''
        else:
            try:
                gravity = scene.gravity.z
                own['reachable'] = True

                vec = interceptPoint.getVectTo(own)
                px = hypot(vec[1].x, vec[1].y) * vec[0]
                pz = vec[1].z * vec[0]

                #rumus pertama menggunakan plus berfungsi untuk rumus mortar
                #rad = atan((velocity**2 + sqrt(velocity**4-gravity*(gravity*px**2 + 2*pz*velocity**2))) / (gravity*px))

                #rumus kedua menggunakan minus
                rad = atan((velocity**2 -
                            sqrt(velocity**4 - gravity *
                                 (gravity * px**2 + 2 * pz * velocity**2))) /
                           (gravity * px))

                #rad = asin(jarak * gravity / velocity**2) / 2

                sRad = sin(rad)
                cRad = cos(rad)

                y = cRad * velocity
                z = sRad * velocity

                own['cosine'] = str([sRad, cRad])

                own['travelTime'] = px / y
                own['vy'] = y
                own['vz'] = z

                own['angle'] = degrees(rad)

                if own.parent == None:
                    Eul = Euler((rad, 0, 0), 'XYZ')
                else:
                    parent = own.parent
                    pR = parent.worldOrientation
                    pE = pR.to_euler()
                    Eul = Euler((-rad, pE.y, pE.z), 'XYZ')
                own.worldOrientation = Eul.to_matrix()
                own['reachable'] = True
                own['calculate'] = True
            except ValueError:
                own['reachable'] = False
                if own['calculate'] == True:
                    print("calculate error")
                    own['calculate'] = False
            except ZeroDivisionError:
                print('float division by zero')
    except:
        checker.getInfo()
        bge.logic.endGame()
示例#24
0
 def get_camera_rotation(self, degrees=0):
     return Euler(
         (math.radians(90), math.radians(0), math.radians(degrees)), 'XYZ')
示例#25
0
def import_motion(reader,
                  context,
                  bonesmap,
                  reported,
                  motions_filter=MOTIONS_FILTER_ALL):
    bpy_armature = context.armature
    name = reader.gets()

    if not motions_filter(name):
        skip = _skip_motion_rest(reader.getv(), 0)
        reader.skip(skip)
        return
    act = bpy.data.actions.new(name=name)
    act.use_fake_user = True
    xray = act.xray
    reader.getf('II')  # range
    fps, ver = reader.getf('fH')
    xray.fps = fps
    if ver < 6:
        raise AppError('unsupported motions version', log_props(version=ver))

    motion = bpy_armature.xray.motions_collection.add()
    motion.name = act.name
    if context.use_motion_prefix_name:
        bpy_armature.xray.use_custom_motion_names = True
        motion.export_name = name
        # cut extension
        filename = context.filename[0:-len(context.filename.split('.')[-1]) -
                                    1]
        name = '{0}_{1}'.format(filename, name)
        act.name = name
        motion.name = name

    if name != act.name and not context.use_motion_prefix_name:
        bpy_armature.xray.use_custom_motion_names = True
        motion.export_name = name

    xray.flags, xray.bonepart = reader.getf('<BH')
    xray.speed, xray.accrue, xray.falloff, xray.power = reader.getf('<ffff')
    for _bone_idx in range(reader.getf('H')[0]):
        tmpfc = [act.fcurves.new('temp', index=i) for i in range(6)]
        try:
            times = {}
            bname = reader.gets()
            flags = reader.getf('B')[0]
            if flags != 0:
                warn('bone has non-zero flags', bone=bname, flags=flags)
            for fcurve in tmpfc:
                behaviors = reader.getf('BB')
                if (behaviors[0] != 1) or (behaviors[1] != 1):
                    warn('bone has different behaviors',
                         bode=bname,
                         behaviors=behaviors)
                for _keyframe_idx in range(reader.getf('H')[0]):
                    val = reader.getf('f')[0]
                    time = reader.getf('f')[0] * fps
                    times[time] = True
                    key_frame = fcurve.keyframe_points.insert(time, val)
                    shape = Shape(reader.getf('B')[0])
                    if shape != Shape.STEPPED:
                        reader.getf('HHH')
                        reader.getf('HHHH')
                    else:
                        key_frame.interpolation = 'CONSTANT'
            bpy_bone = bpy_armature.data.bones.get(bname, None)
            if bpy_bone is None:
                bpy_bone = bonesmap.get(bname.lower(), None)
                if bpy_bone is None:
                    if bname not in reported:
                        warn('bone is not found', bone=bname)
                        reported.add(bname)
                    continue
                if bname not in reported:
                    warn('bone\'s reference will be replaced',
                         bone=bname,
                         replacement=bpy_bone.name)
                    reported.add(bname)
                bname = bpy_bone.name
            data_path = 'pose.bones["' + bname + '"]'
            fcs = [
                act.fcurves.new(data_path + '.location',
                                index=0,
                                action_group=bname),
                act.fcurves.new(data_path + '.location',
                                index=1,
                                action_group=bname),
                act.fcurves.new(data_path + '.location',
                                index=2,
                                action_group=bname),
                act.fcurves.new(data_path + '.rotation_euler',
                                index=0,
                                action_group=bname),
                act.fcurves.new(data_path + '.rotation_euler',
                                index=1,
                                action_group=bname),
                act.fcurves.new(data_path + '.rotation_euler',
                                index=2,
                                action_group=bname)
            ]
            xmat = bpy_bone.matrix_local.inverted()
            real_parent = find_bone_exportable_parent(bpy_bone)
            if real_parent:
                xmat = multiply(xmat, real_parent.matrix_local)
            else:
                xmat = multiply(xmat, MATRIX_BONE)
            for time in times:
                mat = multiply(
                    xmat,
                    Matrix.Translation((
                        +tmpfc[0].evaluate(time),
                        +tmpfc[1].evaluate(time),
                        -tmpfc[2].evaluate(time),
                    )),
                    Euler((
                        -tmpfc[4].evaluate(time),
                        -tmpfc[3].evaluate(time),
                        +tmpfc[5].evaluate(time),
                    ), 'ZXY').to_matrix().to_4x4())
                trn = mat.to_translation()
                rot = mat.to_euler('ZXY')
                for i in range(3):
                    fcs[i + 0].keyframe_points.insert(time, trn[i])
                for i in range(3):
                    fcs[i + 3].keyframe_points.insert(time, rot[i])
        finally:
            for fcurve in tmpfc:
                act.fcurves.remove(fcurve)
    if ver >= 7:
        for _bone_idx in range(reader.getf('I')[0]):
            name = reader.gets_a()
            reader.skip((4 + 4) * reader.getf('I')[0])
            warn('markers are not supported yet', name=name)
    return act
def save_objects(
    filepath,
    objects,
    rescale_to_max = False,
    use_head_upscaling_compensation = False,
    translate_coords = True,
    recenter_to_origin = False,
    blender_origin = [0., 0., 0.],
    generate_texture=True,
    use_only_exported_object_colors=False,
    texture_folder="",
    texture_filename="",
    export_uvs=True,
    minify=False,
    decimal_precision=-1,
    **kwargs):
    """Main exporter function. Parses Blender objects into Minecraft
    cuboid format, uvs, and handles texture read and generation.
    Will save .json file to output paths.

    Inputs:
    - filepath: Output file path name.
    - object: Iterable collection of Blender objects
    - rescale_to_max: Scale exported model to max volume allowed.
    - use_head_upscaling_compensation:
            Clamp over-sized models to max,
            but add upscaling in minecraft head slot (experimental,
            used with animation export, can allow up to 4x max size).
            Overridden by rescale_to_max (these are incompatible).
    - translate_coords: Translate into Minecraft [-16, 32] space so origin = (8,8,8)
    - recenter_to_origin: Recenter model so that its center is at Minecraft origin (8,8,8)
    - blender_origin: Origin in Blender coordinates (in Blender XYZ space).
            Use this to translate exported model.
    - generate_texture: Generate texture from solid material colors. By default, creates
            a color texture from all materials in file (so all groups of
            objects can share the same texture file).
    - use_only_exported_object_colors:
            Generate texture colors from only exported objects instead of default using
            all file materials.
    - texture_folder: Output texture subpath, for typical "item/texture_name" the
            texture folder would be "item".
    - texture_file_name: Name of texture file. TODO: auto-parse textures from materials.
    - export_uvs: Export object uvs.
    - minify: Minimize output file size (write into single line, remove spaces, ...)
    - decimal_precision: Number of digits after decimal to keep in numbers.
            Requires `minify = True`. Set to -1 to disable.
    """

    # output json model
    model_json = {
        "texture_size": [16, 16], # default, will be overridden
        "textures": {},
    }

    elements = []
    groups = {}

    # re-used buffers for every object
    v_world = np.zeros((3, 8))
    v_local = np.zeros((3, 8))
    face_normals = np.zeros((3,6))
    face_uvs = np.zeros((4,))
    face_colors = [None for _ in range(6)]

    # model bounding box vector
    # when re-centering to origin, these will clamp to true model bounding box
    # when not re-centering, bounding box must be relative to blender origin
    # so model min/max starts at (0,0,0) to account for origin point
    if recenter_to_origin:
        model_v_min = np.array([inf, inf, inf])
        model_v_max = np.array([-inf, -inf, -inf])
    else:
        model_v_min = np.array([0., 0., 0.,])
        model_v_max = np.array([0., 0., 0.,])
    
    # all material colors tuples from all object faces
    if use_only_exported_object_colors:
        model_colors = set()
    else:
        model_colors = None
    
    # all material texture str paths
    model_textures = set()
    
    for obj in objects:
        mesh = obj.data
        if not isinstance(mesh, bpy.types.Mesh):
            continue
        
        # object properties
        origin = np.array(obj.location)
        mat_world = obj.matrix_world
        
        # count number of vertices, ignore if not cuboid
        num_vertices = len(mesh.vertices)
        if num_vertices != 8:
            continue
        
        # get world space and local mesh coordinates
        for i, v in enumerate(mesh.vertices):
            v_local[0:3,i] = v.co
            v_world[0:3,i] = mat_world @ v.co
        
        # ================================
        # first reduce rotation to [-45, 45] by applying all 90 deg
        # rotations directly to vertices
        # ================================
        rotation = obj.rotation_euler
        
        rot_reduced = rotation.copy()
        rot_to_reduce_x = 0
        rot_to_reduce_y = 0
        rot_to_reduce_z = 0
        
        # get sign of euler angles
        rot_x_sign = sign(rotation.x)
        rot_y_sign = sign(rotation.y)
        rot_z_sign = sign(rotation.z)
        
        eps = 1e-6 # angle error range for floating point precision issues
        
        # included sign() in loop condition to avoid cases where angle
        # overflows to other polarity and infinite loops
        while abs(rot_reduced.x) > math.pi/4 + eps and sign(rot_reduced.x) == rot_x_sign:
            angle = rot_x_sign * math.pi/2
            rot_reduced.x = round_rotation(rot_reduced.x - angle)
            rot_to_reduce_x += rot_x_sign
        while abs(rot_reduced.y) > math.pi/4 + eps and sign(rot_reduced.y) == rot_y_sign:
            angle = rot_y_sign * math.pi/2
            rot_reduced.y = round_rotation(rot_reduced.y - angle)
            rot_to_reduce_y += rot_y_sign
        while abs(rot_reduced.z) > math.pi/4 + eps and sign(rot_reduced.z) == rot_z_sign:
            angle = rot_z_sign * math.pi/2
            rot_reduced.z = round_rotation(rot_reduced.z - angle)
            rot_to_reduce_z += rot_z_sign
        
        rot_to_reduce = Euler((rot_to_reduce_x * math.pi/2, rot_to_reduce_y * math.pi/2, rot_to_reduce_z * math.pi/2), "XYZ")

        mat_rot_reducer = np.array(rot_to_reduce.to_matrix())
        v_local_transformed = mat_rot_reducer @ v_local
        
        # ================================
        # determine best rotation:
        # 1. transform on all possible minecraft rotations
        # 2. select rotation with min chamfer distance
        # ================================
        # transform with all possible rotation matrices
        v_transformed = origin[...,np.newaxis] + MAT_ROTATIONS @ v_local_transformed[np.newaxis, ...]
        distance_metric = np.array([chamfer_distance(v_transformed[i,:,:], v_world) for i in range(v_transformed.shape[0])])
        
        # get best rotation
        idx_best_rot = np.argmin(distance_metric)
        rot_best = ROTATIONS[idx_best_rot]
        
        # ================================
        # find bounding box edge vertices
        # of transformed local coordinates
        # ================================
        v_local_transformed_translated = origin[...,np.newaxis] + v_local_transformed
        v_min = np.amin(v_local_transformed_translated, axis=1)
        v_max = np.amax(v_local_transformed_translated, axis=1)

        # ================================
        # update global bounding box
        # -> consider world coords, local coords, origin
        # ================================
        model_v_min = np.amin(np.append(v_world, model_v_min[...,np.newaxis], axis=1), axis=1)
        model_v_max = np.amax(np.append(v_world, model_v_max[...,np.newaxis], axis=1), axis=1)
        model_v_min = np.amin(np.append(v_local_transformed_translated, model_v_min[...,np.newaxis], axis=1), axis=1)
        model_v_max = np.amax(np.append(v_local_transformed_translated, model_v_max[...,np.newaxis], axis=1), axis=1)
        model_v_min = np.amin(np.append(origin[...,np.newaxis], model_v_min[...,np.newaxis], axis=1), axis=1)
        model_v_max = np.amax(np.append(origin[...,np.newaxis], model_v_max[...,np.newaxis], axis=1), axis=1)
        
        # ================================
        # output coordinate values
        # ================================
        # change axis to minecraft y-up axis
        v_min = to_y_up(v_min)
        v_max = to_y_up(v_max)
        origin = to_y_up(origin)
        rot_best = (to_minecraft_axis(rot_best[0]), rot_best[1])
        
        # ================================
        # texture/uv generation
        # 
        # NOTE: BLENDER VS MINECRAFT UV AXIS
        # - blender: uvs origin is bottom-left (0,0) to top-right (1, 1)
        # - minecraft: uvs origin is top-left (0,0) to bottom-right (16, 16)
        # minecraft uvs: [x1, y1, x2, y2], each value from [0, 16] as proportion of image
        # as well as 0, 90, 180, 270 degree uv rotation

        # uv loop to export depends on:
        # - clockwise/counterclockwise order
        # - uv starting coordinate (determines rotation) relative to face
        #   vertex loop starting coordinate
        # 
        # Assume "natural" index order of face vertices and uvs without
        # any rotations in local mesh space is counterclockwise loop:
        #   3___2      ^ +y
        #   |   |      |
        #   |___|      ---> +x
        #   0   1
        # 
        # uv, vertex starting coordinate is based on this loop.
        # Use the uv rotation lookup tables constants to determine rotation.
        # ================================

        # initialize faces
        faces = {
            "north": {"uv": [0, 0, 4, 4], "texture": "#0"},
            "east": {"uv": [0, 0, 4, 4], "texture": "#0"},
            "south": {"uv": [0, 0, 4, 4], "texture": "#0"},
            "west": {"uv": [0, 0, 4, 4], "texture": "#0"},
            "up": {"uv": [0, 0, 4, 4], "texture": "#0"},
            "down": {"uv": [0, 0, 4, 4], "texture": "#0"}
        }
        
        uv_layer = mesh.uv_layers.active.data

        for i, face in enumerate(mesh.polygons):
            if i > 5: # should be 6 faces only
                print(f"WARNING: {obj} has >6 faces")
                break
            
            face_normal = face.normal
            face_normal_world = mat_rot_reducer @ face_normal

            # stack + reshape to (6,3)
            face_normal_stacked = np.transpose(face_normal_world[..., np.newaxis], (1,0))
            face_normal_stacked = np.tile(face_normal_stacked, (6,1))

            # get face direction string
            face_direction_index = np.argmax(np.sum(face_normal_stacked * DIRECTION_NORMALS, axis=1), axis=0)
            d = DIRECTIONS[face_direction_index]
            
            face_color = get_object_color(obj, face.material_index)
            
            # solid color tuple
            if isinstance(face_color, tuple) and generate_texture:
                faces[d] = face_color # replace face with color
                if model_colors is not None:
                    model_colors.add(face_color)
            # texture
            elif isinstance(face_color, str):
                faces[d]["texture"] = face_color
                model_textures.add(face_color)

                if export_uvs:
                    # uv loop
                    loop_start = face.loop_start
                    face_uv_0 = uv_layer[loop_start].uv
                    face_uv_1 = uv_layer[loop_start+1].uv
                    face_uv_2 = uv_layer[loop_start+2].uv
                    face_uv_3 = uv_layer[loop_start+3].uv

                    uv_min_x = min(face_uv_0[0], face_uv_2[0])
                    uv_max_x = max(face_uv_0[0], face_uv_2[0])
                    uv_min_y = min(face_uv_0[1], face_uv_2[1])
                    uv_max_y = max(face_uv_0[1], face_uv_2[1])

                    uv_clockwise = loop_is_clockwise([face_uv_0, face_uv_1, face_uv_2, face_uv_3])

                    # vertices loop (using vertices transformed by all 90 deg angles)
                    # project 3d vertex loop onto 2d loop based on face normal,
                    # minecraft uv mapping starting corner experimentally determined
                    verts = [ v_local_transformed[:,v] for v in face.vertices ]
                    #face_normal_world = mat_rot_reducer @ face_normal
                    
                    if face_normal_world[0] > 0.5: # normal = (1, 0, 0)
                        verts = [ (v[1], v[2]) for v in verts ]
                    elif face_normal_world[0] < -0.5: # normal = (-1, 0, 0)
                        verts = [ (-v[1], v[2]) for v in verts ]
                    elif face_normal_world[1] > 0.5: # normal = (0, 1, 0)
                        verts = [ (-v[0], v[2]) for v in verts ]
                    elif face_normal_world[1] < -0.5: # normal = (0, -1, 0)
                        verts = [ (v[0], v[2]) for v in verts ]
                    elif face_normal_world[2] > 0.5: # normal = (0, 0, 1)
                        verts = [ (v[1], -v [0]) for v in verts ]
                    elif face_normal_world[2] < -0.5: # normal = (0, 0, -1)
                        verts = [ (v[1], v[0]) for v in verts ]
                    
                    vert_min_x = min(verts[0][0], verts[2][0])
                    vert_max_x = max(verts[0][0], verts[2][0])
                    vert_min_y = min(verts[0][1], verts[2][1])
                    vert_max_y = max(verts[0][1], verts[2][1])

                    vert_clockwise = loop_is_clockwise(verts)
                    
                    # get uv, vert loop starting corner index 0..3 in face loop

                    # uv start corner index
                    uv_start_x = face_uv_0[0]
                    uv_start_y = face_uv_0[1]
                    if uv_start_y < uv_max_y:
                        # start coord 0
                        if uv_start_x < uv_max_x:
                            uv_loop_start_index = 0
                        # start coord 1
                        else:
                            uv_loop_start_index = 1
                    else:
                        # start coord 2
                        if uv_start_x > uv_min_x:
                            uv_loop_start_index = 2
                        # start coord 3
                        else:
                            uv_loop_start_index = 3
                    
                    # vert start corner index
                    vert_start_x = verts[0][0]
                    vert_start_y = verts[0][1]
                    if vert_start_y < vert_max_y:
                        # start coord 0
                        if vert_start_x < vert_max_x:
                            vert_loop_start_index = 0
                        # start coord 1
                        else:
                            vert_loop_start_index = 1
                    else:
                        # start coord 2
                        if vert_start_x > vert_min_x:
                            vert_loop_start_index = 2
                        # start coord 3
                        else:
                            vert_loop_start_index = 3

                    # set uv flip and rotation based on
                    # 1. clockwise vs counterclockwise loop
                    # 2. relative starting corner difference between vertex loop and uv loop
                    # NOTE: if face normals correct, vertices should always be counterclockwise...
                    if uv_clockwise == False and vert_clockwise == False:
                        face_uvs[0] = uv_min_x
                        face_uvs[1] = uv_max_y
                        face_uvs[2] = uv_max_x
                        face_uvs[3] = uv_min_y
                        face_uv_rotation = COUNTERCLOCKWISE_UV_ROTATION_LOOKUP[uv_loop_start_index][vert_loop_start_index]
                    elif uv_clockwise == True and vert_clockwise == False:
                        # invert x face uvs
                        face_uvs[0] = uv_max_x
                        face_uvs[1] = uv_max_y
                        face_uvs[2] = uv_min_x
                        face_uvs[3] = uv_min_y
                        face_uv_rotation = CLOCKWISE_UV_ROTATION_LOOKUP[uv_loop_start_index][vert_loop_start_index]
                    elif uv_clockwise == False and vert_clockwise == True:
                        # invert y face uvs, case should not happen
                        face_uvs[0] = uv_max_x
                        face_uvs[1] = uv_max_y
                        face_uvs[2] = uv_min_x
                        face_uvs[3] = uv_min_y
                        face_uv_rotation = CLOCKWISE_UV_ROTATION_LOOKUP[uv_loop_start_index][vert_loop_start_index]
                    else: # uv_clockwise == True and vert_clockwise == True:
                        # case should not happen
                        face_uvs[0] = uv_min_x
                        face_uvs[1] = uv_max_y
                        face_uvs[2] = uv_max_x
                        face_uvs[3] = uv_min_y
                        face_uv_rotation = COUNTERCLOCKWISE_UV_ROTATION_LOOKUP[uv_loop_start_index][vert_loop_start_index]
                    
                    xmin = face_uvs[0] * 16
                    ymin = (1.0 - face_uvs[1]) * 16
                    xmax = face_uvs[2] * 16
                    ymax = (1.0 - face_uvs[3]) * 16
                    faces[d]["uv"] = [ xmin, ymin, xmax, ymax ]
                    
                    if face_uv_rotation != 0 and face_uv_rotation != 360:
                        faces[d]["rotation"] = face_uv_rotation if face_uv_rotation >= 0 else 360 + face_uv_rotation
        
        # ================================
        # get collection
        # ================================
        collection = obj.users_collection[0]
        if collection is not None:          
            add_to_group(groups, collection.name, len(elements))
        
        # add object to output
        elements.append({
            "name": obj.name,
            "from": v_min,
            "to": v_max,
            "rotation": {
                "angle": rot_best[1],
                "axis": rot_best[0].lower(),
                "origin": origin,
            },
            "faces": faces,
        })
    
    # tranpose model bbox to minecraft axes
    model_v_min = to_y_up(model_v_min)
    model_v_max = to_y_up(model_v_max)
    model_center = 0.5 * (model_v_min + model_v_max)
    
    # get rescaling factors
    if rescale_to_max:
        if recenter_to_origin:
            rescale_factor = np.min(MAX_SIZE / (model_v_max - model_center))
        # absolute scale relative to (0,0,0), min scaling of MAX/v_max and -MAX/v_min
        else:
            rescale_factor = np.min(np.abs(MAX_SIZE / np.concatenate((-model_v_min - blender_origin, model_v_max - blender_origin))))
    # rescaling, but add head display scaling to compensate for downscaling
    elif use_head_upscaling_compensation:
        if recenter_to_origin:
            rescale_factor = np.min(MAX_SIZE / (model_v_max - model_center))
        else:
            rescale_factor = np.min(np.abs(MAX_SIZE / np.concatenate((-model_v_min, model_v_max))))

        # clamp if not re-scaling to max
        if rescale_factor >= 1.0:
            if rescale_to_max == False:
                rescale_factor = 1.0
        # rescale < 1.0, model too large, inject head display scaling
        else:
            display_head_scale = np.clip(1.0 / rescale_factor, 0, 4)
            model_json["display"] = {
                "head": {
                    "scale": [display_head_scale, display_head_scale, display_head_scale]
                }
            }
    else:
        rescale_factor = 1.0
        
    # debug
    print("RESCALE", rescale_factor)
    print("BBOX MIN/MAX", model_v_min, "/", model_v_max)
    print("CENTER", model_center)
    print("BLENDER ORIGIN", blender_origin)
    print("")
    
    # model post-processing (recenter, rescaling coordinates)
    minecraft_origin = np.array([8, 8, 8])

    # re-center coordinates to minecraft origin and model bounding box center
    if recenter_to_origin:
        model_origin_shift = -model_center
    else:
        model_origin_shift = -to_y_up(blender_origin)
    
    # ===========================
    # generate texture images
    # ===========================
    if generate_texture:
        # default, get colors from all materials in file
        if model_colors is None:
            model_colors = set()
            for mat in bpy.data.materials:
                color = get_material_color(mat)
                if isinstance(color, tuple):
                    model_colors.add(color)
        
        tex_pixels, tex_size, color_tex_uv_map, default_color_uv = create_color_texture(model_colors)

        # texture output filepaths
        if texture_filename == "":
            current_dir = os.path.dirname(filepath)
            filepath_name = os.path.splitext(os.path.basename(filepath))[0]
            texture_save_path = os.path.join(current_dir, filepath_name + ".png")
            texture_model_path = posixpath.join(texture_folder, filepath_name)
        else:
            current_dir = os.path.dirname(filepath)
            texture_save_path = os.path.join(current_dir, texture_filename + ".png")
            texture_model_path = posixpath.join(texture_folder, texture_filename)
        
        # create + save texture
        tex = bpy.data.images.new("tex_colors", alpha=True, width=tex_size, height=tex_size)
        tex.file_format = "PNG"
        tex.pixels = tex_pixels
        tex.filepath_raw = texture_save_path
        tex.save()

        # write texture info to output model
        model_json["texture_size"] = [tex_size, tex_size]
        model_json["textures"]["0"] = texture_model_path
    
    # if not generating texture, just write texture path to json file
    # TODO: scan materials for textures, then update output size
    elif texture_filename != "":
        model_json["texture_size"] = [16, 16]
        model_json["textures"]["0"] = posixpath.join(texture_folder, texture_filename)
    
    # ===========================
    # process face texture paths
    # convert blender path names "//folder\tex.png" -> "item/tex"
    # add textures indices for textures, and create face mappings like "#1"
    # note: #0 id reserved for generated color texture
    # ===========================
    texture_refs = {} # maps blender path name -> #n identifiers
    texture_id = 1    # texture id in "#1" identifier
    for texture_path in model_textures:
        texture_out_path = texture_path
        if texture_out_path[0:2] == "//":
            texture_out_path = texture_out_path[2:]
        texture_out_path = texture_out_path.replace("\\", "/")
        texture_out_path = os.path.splitext(texture_out_path)[0]
        
        texture_refs[texture_path] = "#" + str(texture_id)
        model_json["textures"][str(texture_id)] = posixpath.join(texture_folder, texture_out_path)
        texture_id += 1

    # ===========================
    # final object + face processing
    # 1. recenter/rescale object
    # 2. map solid color face uv -> location in generated texture
    # 3. rewrite path textures -> texture name reference
    # ===========================
    for obj in elements:
        # re-center model
        obj["to"] = model_origin_shift + obj["to"]
        obj["from"] = model_origin_shift + obj["from"]
        obj["rotation"]["origin"] = model_origin_shift + obj["rotation"]["origin"]
        
        # re-scale objects
        obj["to"] = rescale_factor * obj["to"]
        obj["from"] = rescale_factor * obj["from"]
        obj["rotation"]["origin"] = rescale_factor * obj["rotation"]["origin"]

        # re-center coordinates to minecraft origin
        if translate_coords:
            obj["to"] = minecraft_origin + obj["to"]
            obj["from"] = minecraft_origin + obj["from"]
            obj["rotation"]["origin"] = minecraft_origin + obj["rotation"]["origin"]     

        # convert numpy to python list
        obj["to"] = obj["to"].tolist()
        obj["from"] = obj["from"].tolist()
        obj["rotation"]["origin"] = obj["rotation"]["origin"].tolist()

        faces = obj["faces"]
        for d, f in faces.items():
            if isinstance(f, tuple):
                color_uv = color_tex_uv_map[f] if f in color_tex_uv_map else default_color_uv
                faces[d] = {
                    "uv": color_uv,
                    "texture": "#0",
                }
            elif isinstance(f, dict):
                face_texture = f["texture"]
                if face_texture in texture_refs:
                    f["texture"] = texture_refs[face_texture]
                else:
                    face_texture = "#0"
    
    # ===========================
    # convert groups
    # ===========================
    groups_export = []
    for g in groups:
        groups_export.append({
            "name": g,
            "origin": [0, 0, 0],
            "children": groups[g],
        })

    # save
    model_json["elements"] = elements
    model_json["groups"] = groups_export

    # minification options to reduce .json file size
    if minify == True:
        # go through json dict and replace all float with rounded strings
        if decimal_precision >= 0:
            def round_float(x):
                return round(x, decimal_precision)
            
            for elem in model_json["elements"]:
                elem["from"] = [round_float(x) for x in elem["from"]]
                elem["to"] = [round_float(x) for x in elem["to"]]
                elem["rotation"]["origin"] = [round_float(x) for x in elem["rotation"]["origin"]]
                for face in elem["faces"].values():
                    face["uv"] = [round_float(x) for x in face["uv"]]
    
    # save json
    with open(filepath, "w") as f:
        json.dump(model_json, f, separators=(",", ":"))
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'}
示例#28
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
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
示例#30
0
faces = [(0, 1, 2, 3), (4, 5, 6, 7)]
mesh = bpy.data.meshes.new("Xpos")
obj = bpy.data.objects.new("Xpos", mesh)
bpy.context.scene.objects.link(obj)
mesh.from_pydata(verts, [], faces)
mesh.update(calc_edges=True)
bpy.data.objects["Xpos"].data.materials.append(
    material_options["wall"][randint(0,
                                     len(material_options["wall"]) - 1)])

# place corridor Y+
bpy.ops.object.select_all(action="DESELECT")
bpy.data.objects["Xpos"].select = True
bpy.ops.object.duplicate()
bpy.data.objects["Xpos.001"].name = "Ypos"
bpy.data.objects["Ypos"].rotation_euler = Euler((0, 0, math.radians(90)))

# place corridor X-
bpy.ops.object.select_all(action="DESELECT")
bpy.data.objects["Xpos"].select = True
bpy.ops.object.duplicate()
bpy.data.objects["Xpos.001"].name = "Xneg"
bpy.data.objects["Xneg"].rotation_euler = Euler((0, 0, math.radians(180)))

# place corridor Y-
bpy.ops.object.select_all(action="DESELECT")
bpy.data.objects["Xpos"].select = True
bpy.ops.object.duplicate()
bpy.data.objects["Xpos.001"].name = "Yneg"
bpy.data.objects["Yneg"].rotation_euler = Euler((0, 0, math.radians(-90)))
示例#31
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
示例#32
0
def draw_callback_px(self, context):
    font_id = 0
    region = context.region
    UIColor = (0.992, 0.5518, 0.0, 1.0)

    # Cut Type
    RECTANGLE = 0
    LINE = 1
    CIRCLE = 2
    self.carver_prefs = context.preferences.addons[__package__].preferences

    # Color
    color1 = (1.0, 1.0, 1.0, 1.0)
    color2 = UIColor

    #The mouse is outside the active region
    if not self.in_view_3d:
        color1 = color2 = (1.0, 0.2, 0.1, 1.0)

    # Primitives type
    PrimitiveType = "Rectangle"
    if self.CutType == CIRCLE:
        PrimitiveType = "Circle"
    if self.CutType == LINE:
        PrimitiveType = "Line"

    # Width screen
    overlap = context.preferences.system.use_region_overlap

    t_panel_width = 0
    if overlap:
        for region in context.area.regions:
            if region.type == 'TOOLS':
                t_panel_width = region.width

    # Initial position
    region_width = int(region.width / 2.0)
    y_txt = 10

    # Draw the center command from bottom to top

    # Get the size of the text
    text_size = 18 if region.width >= 850 else 12
    blf.size(0, int(round(text_size * bpy.context.preferences.view.ui_scale,
                          0)), 72)

    # Help Display
    if (self.ObjectMode is False) and (self.ProfileMode is False):

        # Depth Cursor
        TypeStr = "Cursor Depth [" + self.carver_prefs.Key_Depth + "]"
        BoolStr = "(ON)" if self.snapCursor else "(OFF)"
        help_txt = [[TypeStr, BoolStr]]

        # Close poygonal shape
        if self.CreateMode and self.CutType == LINE:
            TypeStr = "Close [" + self.carver_prefs.Key_Close + "]"
            BoolStr = "(ON)" if self.Closed else "(OFF)"
            help_txt += [[TypeStr, BoolStr]]

        if self.CreateMode is False:
            # Apply Booleans
            TypeStr = "Apply Operations [" + self.carver_prefs.Key_Apply + "]"
            BoolStr = "(OFF)" if self.dont_apply_boolean else "(ON)"
            help_txt += [[TypeStr, BoolStr]]

            #Auto update for bevel
            TypeStr = "Bevel Update [" + self.carver_prefs.Key_Update + "]"
            BoolStr = "(ON)" if self.Auto_BevelUpdate else "(OFF)"
            help_txt += [[TypeStr, BoolStr]]

        # Circle subdivisions
        if self.CutType == CIRCLE:
            TypeStr = "Subdivisions [" + self.carver_prefs.Key_Subrem + "][" + self.carver_prefs.Key_Subadd + "]"
            BoolStr = str((int(360 / self.stepAngle[self.step])))
            help_txt += [[TypeStr, BoolStr]]

        if self.CreateMode:
            help_txt += [["Type [Space]", PrimitiveType]]
        else:
            help_txt += [["Cut Type [Space]", PrimitiveType]]

    else:
        # Instantiate
        TypeStr = "Instantiate [" + self.carver_prefs.Key_Instant + "]"
        BoolStr = "(ON)" if self.Instantiate else "(OFF)"
        help_txt = [[TypeStr, BoolStr]]

        # Random rotation
        if self.alt:
            TypeStr = "Random Rotation [" + self.carver_prefs.Key_Randrot + "]"
            BoolStr = "(ON)" if self.RandomRotation else "(OFF)"
            help_txt += [[TypeStr, BoolStr]]

        # Thickness
        if self.BrushSolidify:
            TypeStr = "Thickness [" + self.carver_prefs.Key_Depth + "]"
            if self.ProfileMode:
                BoolStr = str(
                    round(self.ProfileBrush.modifiers["CT_SOLIDIFY"].thickness,
                          2))
            if self.ObjectMode:
                BoolStr = str(
                    round(self.ObjectBrush.modifiers["CT_SOLIDIFY"].thickness,
                          2))
            help_txt += [[TypeStr, BoolStr]]

        # Brush depth
        if (self.ObjectMode):
            TypeStr = "Carve Depth [" + self.carver_prefs.Key_Depth + "]"
            BoolStr = str(round(self.ObjectBrush.data.vertices[0].co.z, 2))
            help_txt += [[TypeStr, BoolStr]]

            TypeStr = "Brush Depth [" + self.carver_prefs.Key_BrushDepth + "]"
            BoolStr = str(round(self.BrushDepthOffset, 2))
            help_txt += [[TypeStr, BoolStr]]

    help_txt, bloc_height, max_option, max_key, comma = get_text_info(
        self, context, help_txt)
    xCmd = region_width - (max_option + max_key + comma) / 2
    draw_string(self,
                color1,
                color2,
                xCmd,
                y_txt,
                help_txt,
                max_option,
                divide=2)

    # Separator (Line)
    LineWidth = (max_option + max_key + comma) / 2
    if region.width >= 850:
        LineWidth = 140

    LineWidth = (max_option + max_key + comma)
    coords = [(int(region_width - LineWidth/2), y_txt + bloc_height + 8), \
        (int(region_width + LineWidth/2), y_txt + bloc_height + 8)]
    draw_shader(self, UIColor, 1, 'LINES', coords, self.carver_prefs.LineWidth)

    # Command Display
    if self.CreateMode and ((self.ObjectMode is False) and
                            (self.ProfileMode is False)):
        BooleanMode = "Create"
    else:
        if self.ObjectMode or self.ProfileMode:
            BooleanType = "Difference) [T]" if self.BoolOps == self.difference else "Union) [T]"
            BooleanMode = \
             "Object Brush (" + BooleanType if self.ObjectMode else "Profil Brush (" + BooleanType
        else:
            BooleanMode = \
             "Difference" if (self.shift is False) and (self.ForceRebool is False) else "Rebool"

    # Display boolean mode
    text_size = 40 if region.width >= 850 else 20
    blf.size(0, int(round(text_size * bpy.context.preferences.view.ui_scale,
                          0)), 72)

    draw_string(self, color2, color2, region_width - (blf.dimensions(0, BooleanMode)[0]) / 2, \
       y_txt + bloc_height + 16, BooleanMode, 0, divide = 2)

    if region.width >= 850:

        if self.AskHelp is False:
            # "H for Help" text
            blf.size(0,
                     int(round(13 * bpy.context.preferences.view.ui_scale, 0)),
                     72)
            help_txt = "[" + self.carver_prefs.Key_Help + "] for help"
            txt_width = blf.dimensions(0, help_txt)[0]
            txt_height = (blf.dimensions(0, "gM")[1] * 1.45)

            # Draw a rectangle and put the text "H for Help"
            xrect = 40
            yrect = 40
            rect_vertices = [(xrect - 5, yrect - 5), (xrect + txt_width + 5, yrect - 5), \
                 (xrect + txt_width + 5, yrect + txt_height + 5), (xrect - 5, yrect + txt_height + 5)]
            draw_shader(self, (0.0, 0.0, 0.0), 0.3, 'TRI_FAN', rect_vertices,
                        self.carver_prefs.LineWidth)
            draw_string(self, color1, color2, xrect, yrect, help_txt, 0)

        else:
            #Draw the help text
            xHelp = 30 + t_panel_width
            yHelp = 10

            if self.ObjectMode or self.ProfileMode:
                if self.ProfileMode:
                    help_txt = [["Object Mode", self.carver_prefs.Key_Brush]]
                else:
                    help_txt = [["Cut Mode", self.carver_prefs.Key_Brush]]

            else:
                help_txt =[
                   ["Profil Brush", self.carver_prefs.Key_Brush],\
                   ["Move Cursor", "Ctrl + LMB"]
                   ]

            if (self.ObjectMode is False) and (self.ProfileMode is False):
                if self.CreateMode is False:
                    help_txt +=[
                        ["Create geometry", self.carver_prefs.Key_Create],\
                        ]
                else:
                    help_txt +=[
                        ["Cut", self.carver_prefs.Key_Create],\
                        ]
                if self.CutMode == RECTANGLE:
                    help_txt +=[
                        ["Dimension", "MouseMove"],\
                        ["Move all", "Alt"],\
                        ["Validate", "LMB"],\
                        ["Rebool", "Shift"]
                        ]

                elif self.CutMode == CIRCLE:
                    help_txt +=[
                        ["Rotation and Radius", "MouseMove"],\
                        ["Move all", "Alt"],\
                        ["Subdivision", self.carver_prefs.Key_Subrem + " " + self.carver_prefs.Key_Subadd],\
                        ["Incremental rotation", "Ctrl"],\
                        ["Rebool", "Shift"]
                        ]

                elif self.CutMode == LINE:
                    help_txt +=[
                        ["Dimension", "MouseMove"],\
                        ["Move all", "Alt"],\
                        ["Validate", "Space"],\
                        ["Rebool", "Shift"],\
                        ["Snap", "Ctrl"],\
                        ["Scale Snap", "WheelMouse"],\
                        ]
            else:
                # ObjectMode
                help_txt +=[
                    ["Difference", "Space"],\
                    ["Rebool", "Shift + Space"],\
                    ["Duplicate", "Alt + Space"],\
                    ["Scale", self.carver_prefs.Key_Scale],\
                    ["Rotation", "LMB + Move"],\
                    ["Step Angle", "CTRL + LMB + Move"],\
                    ]

                if self.ProfileMode:
                    help_txt += [[
                        "Previous or Next Profile",
                        self.carver_prefs.Key_Subadd + " " +
                        self.carver_prefs.Key_Subrem
                    ]]

                help_txt +=[
                    ["Create / Delete rows",  chr(8597)],\
                    ["Create / Delete cols",  chr(8596)],\
                    ["Gap for rows or columns",  self.carver_prefs.Key_Gapy + " " + self.carver_prefs.Key_Gapx]
                    ]

            blf.size(0,
                     int(round(15 * bpy.context.preferences.view.ui_scale, 0)),
                     72)
            help_txt, bloc_height, max_option, max_key, comma = get_text_info(
                self, context, help_txt)
            draw_string(self, color1, color2, xHelp, yHelp, help_txt,
                        max_option)

    if self.ProfileMode:
        xrect = region.width - t_panel_width - 80
        yrect = 80
        coords = [(xrect, yrect), (xrect + 60, yrect),
                  (xrect + 60, yrect - 60), (xrect, yrect - 60)]

        # Draw rectangle background in the lower right
        draw_shader(self, (0.0, 0.0, 0.0),
                    0.3,
                    'TRI_FAN',
                    coords,
                    size=self.carver_prefs.LineWidth)

        # Use numpy to get the vertices and indices of the profile object to draw
        WidthProfil = 50
        location = Vector((region.width - t_panel_width - WidthProfil, 50, 0))
        ProfilScale = 20.0
        coords = []
        mesh = bpy.data.meshes[self.Profils[self.nProfil][0]]
        mesh.calc_loop_triangles()
        vertices = np.empty((len(mesh.vertices), 3), 'f')
        indices = np.empty((len(mesh.loop_triangles), 3), 'i')
        mesh.vertices.foreach_get("co",
                                  np.reshape(vertices,
                                             len(mesh.vertices) * 3))
        mesh.loop_triangles.foreach_get(
            "vertices", np.reshape(indices,
                                   len(mesh.loop_triangles) * 3))

        for idx, vals in enumerate(vertices):
            coords.append([
                vals[0] * ProfilScale + location.x,
                vals[1] * ProfilScale + location.y,
                vals[2] * ProfilScale + location.z
            ])

        #Draw the silhouette of the mesh
        draw_shader(self,
                    UIColor,
                    0.5,
                    'TRIS',
                    coords,
                    size=self.carver_prefs.LineWidth,
                    indices=indices)

    if self.CutMode:

        if len(self.mouse_path) > 1:
            x0 = self.mouse_path[0][0]
            y0 = self.mouse_path[0][1]
            x1 = self.mouse_path[1][0]
            y1 = self.mouse_path[1][1]

        # Cut rectangle
        if self.CutType == RECTANGLE:
            coords = [
            (x0 + self.xpos, y0 + self.ypos), (x1 + self.xpos, y0 + self.ypos), \
            (x1 + self.xpos, y1 + self.ypos), (x0 + self.xpos, y1 + self.ypos)
            ]
            indices = ((0, 1, 2), (2, 0, 3))

            self.rectangle_coord = coords

            draw_shader(self,
                        UIColor,
                        1,
                        'LINE_LOOP',
                        coords,
                        size=self.carver_prefs.LineWidth)

            #Draw points
            draw_shader(self, UIColor, 1, 'POINTS', coords, size=3)

            if self.shift or self.CreateMode:
                draw_shader(self,
                            UIColor,
                            0.5,
                            'TRIS',
                            coords,
                            size=self.carver_prefs.LineWidth,
                            indices=indices)

            # Draw grid (based on the overlay options) to show the incremental snapping
            if self.ctrl:
                mini_grid(self, context, UIColor)

        # Cut Line
        elif self.CutType == LINE:
            coords = []
            indices = []
            top_grid = False

            for idx, vals in enumerate(self.mouse_path):
                coords.append([vals[0] + self.xpos, vals[1] + self.ypos])
                indices.append([idx])

            # Draw lines
            if self.Closed:
                draw_shader(self,
                            UIColor,
                            1.0,
                            'LINE_LOOP',
                            coords,
                            size=self.carver_prefs.LineWidth)
            else:
                draw_shader(self,
                            UIColor,
                            1.0,
                            'LINE_STRIP',
                            coords,
                            size=self.carver_prefs.LineWidth)

            # Draw points
            draw_shader(self, UIColor, 1.0, 'POINTS', coords, size=3)

            # Draw polygon
            if (self.shift) or (self.CreateMode and self.Closed):
                draw_shader(self,
                            UIColor,
                            0.5,
                            'TRI_FAN',
                            coords,
                            size=self.carver_prefs.LineWidth)

            # Draw grid (based on the overlay options) to show the incremental snapping
            if self.ctrl:
                mini_grid(self, context, UIColor)

        # Circle Cut
        elif self.CutType == CIRCLE:
            # Create a circle using a tri fan
            tris_coords, indices = draw_circle(self, x0, y0)

            # Remove the vertex in the center to get the outer line of the circle
            line_coords = tris_coords[1:]
            draw_shader(self,
                        UIColor,
                        1.0,
                        'LINE_LOOP',
                        line_coords,
                        size=self.carver_prefs.LineWidth)

            if self.shift or self.CreateMode:
                draw_shader(self,
                            UIColor,
                            0.5,
                            'TRIS',
                            tris_coords,
                            size=self.carver_prefs.LineWidth,
                            indices=indices)

    if (self.ObjectMode
            or self.ProfileMode) and len(self.CurrentSelection) > 0:
        if self.ShowCursor:
            region = context.region
            rv3d = context.space_data.region_3d

            if self.ObjectMode:
                ob = self.ObjectBrush
            if self.ProfileMode:
                ob = self.ProfileBrush
            mat = ob.matrix_world

            # 50% alpha, 2 pixel width line
            bgl.glEnable(bgl.GL_BLEND)

            bbox = [mat @ Vector(b) for b in ob.bound_box]
            objBBDiagonal = objDiagonal(self.CurrentSelection[0])

            if self.shift:
                gl_size = 4
                UIColor = (0.5, 1.0, 0.0, 1.0)
            else:
                gl_size = 2
                UIColor = (1.0, 0.8, 0.0, 1.0)

            line_coords = []
            idx = 0
            CRadius = ((bbox[7] - bbox[0]).length) / 2
            for i in range(int(len(self.CLR_C) / 3)):
                vector3d = (self.CLR_C[idx * 3] * CRadius + self.CurLoc.x, \
                   self.CLR_C[idx * 3 + 1] * CRadius + self.CurLoc.y, \
                   self.CLR_C[idx * 3 + 2] * CRadius + self.CurLoc.z)
                vector2d = bpy_extras.view3d_utils.location_3d_to_region_2d(
                    region, rv3d, vector3d)
                if vector2d is not None:
                    line_coords.append((vector2d[0], vector2d[1]))
                idx += 1
            if len(line_coords) > 0:
                draw_shader(self,
                            UIColor,
                            1.0,
                            'LINE_LOOP',
                            line_coords,
                            size=gl_size)

            # Object display
            if self.quat_rot is not None:
                ob.location = self.CurLoc
                v = Vector()
                v.x = v.y = 0.0
                v.z = self.BrushDepthOffset
                ob.location += self.quat_rot @ v

                e = Euler()
                e.x = 0.0
                e.y = 0.0
                e.z = self.aRotZ / 25.0

                qe = e.to_quaternion()
                qRot = self.quat_rot @ qe
                ob.rotation_mode = 'QUATERNION'
                ob.rotation_quaternion = qRot
                ob.rotation_mode = 'XYZ'

                if self.ProfileMode:
                    if self.ProfileBrush is not None:
                        self.ProfileBrush.location = self.CurLoc
                        self.ProfileBrush.rotation_mode = 'QUATERNION'
                        self.ProfileBrush.rotation_quaternion = qRot
                        self.ProfileBrush.rotation_mode = 'XYZ'

    # Opengl defaults
    bgl.glLineWidth(1)
    bgl.glDisable(bgl.GL_BLEND)
示例#33
0
def bvh_node_dict2armature(
    context,
    bvh_name,
    bvh_nodes,
    rotate_mode='XYZ',
    frame_start=1,
    IMPORT_LOOP=False,
    global_matrix=None,
):

    if frame_start < 1:
        frame_start = 1

    # Add the new armature,
    scene = context.scene
    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)

    # 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.values():
        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 couldbe 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 name, bvh_node in bvh_nodes.items():
        # New editbone
        bone = bvh_node.temp = arm_data.edit_bones.new(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.values():
        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 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.values():
        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.values():
            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.scene.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)
    for bvh_node in bvh_nodes.values():
        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)

    # Make a dict for fast access without rebuilding a list all the time.

    # KEYFRAME METHOD, SLOW, USE IPOS DIRECT
    # TODO: use f-point samples instead (Aligorith)
    if rotate_mode != 'QUATERNION':
        prev_euler = [Euler() for i in range(len(bvh_nodes))]

    # Animate the data, the last used bvh_node will do since they all have the same number of frames
    for frame_current in range(len(bvh_node.anim_data) -
                               1):  # skip the first frame (rest frame)
        # print frame_current

        # if frame_current==40: # debugging
        # 	break

        scene.frame_set(frame_start + frame_current)

        # Dont neet to set the current frame
        for i, bvh_node in enumerate(bvh_nodes.values()):
            pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv = bvh_node.temp
            lx, ly, lz, rx, ry, rz = bvh_node.anim_data[frame_current + 1]

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

                if rotate_mode == 'QUATERNION':
                    pose_bone.rotation_quaternion = bone_rotation_matrix.to_quaternion(
                    )
                else:
                    euler = bone_rotation_matrix.to_euler(
                        pose_bone.rotation_mode, prev_euler[i])
                    pose_bone.rotation_euler = euler
                    prev_euler[i] = euler

            if bvh_node.has_loc:
                pose_bone.location = (
                    bone_rest_matrix_inv * Matrix.Translation(
                        Vector((lx, ly, lz)) -
                        bvh_node.rest_head_local)).to_translation()

            if bvh_node.has_loc:
                pose_bone.keyframe_insert("location")
            if bvh_node.has_rot:
                if rotate_mode == 'QUATERNION':
                    pose_bone.keyframe_insert("rotation_quaternion")
                else:
                    pose_bone.keyframe_insert("rotation_euler")

    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
def vrot(self, r):
    random.seed(self.ran + r)
    return Euler((radians(self.rotx) + gauss(0, self.var2 / 3),
                  radians(self.roty) + gauss(0, self.var2 / 3),
                  radians(self.rotz) + gauss(0, self.var2 / 3)), 'XYZ')
示例#35
0
def save(operator, context, filepath, debug_report=True):
    print("Exporting scene to DTS")

    scene = context.scene
    dsq = DsqFile()

    # Create a DTS node for every armature/empty in the scene
    node_ob = {}
    export_all_nodes(node_ob, dsq, filter(lambda o: not o.parent,
                                          scene.objects))

    # Figure out if we should create our own root node
    if "NodeOrder" in bpy.data.texts:
        order = bpy.data.texts["NodeOrder"].as_string().split("\n")
        order_key = {name: i for i, name in enumerate(order)}

        try:
            dsq.nodes = list(sorted(dsq.nodes, key=lambda n: order_key[n]))
        except KeyError as e:
            return fail(
                operator,
                "Node '{}' is missing from the 'NodeOrder' text block. This means that you may have added nodes to a skeleton when you shouldn't have, or that you forgot to remove the 'NodeOrder' text block. It is automatically created by the \"Import node order\" option when importing a DTS file. Perhaps you forgot to press Ctrl+N after you imported?"
                .format(e.args[0]))

        shape_node_names = set(dsq.nodes)
        missing_nodes = tuple(filter(lambda n: n not in dsq.nodes, order))

        if missing_nodes:
            return fail(
                operator,
                "The following nodes were found in the 'NodeOrder' text block but do not exist in the shape. This means that you may have removed nodes from a skeleton when you shouldn't have, or that you forgot to remove the 'NodeOrder' text block:\n{}"
                .format(", ".join(missing_nodes)))

    node_index = {node_ob[name]: i for i, name in enumerate(dsq.nodes)}
    animated_nodes = []

    for node in dsq.nodes:
        ob = node_ob[node]
        data = ob.animation_data
        if data and data.action and len(data.action.fcurves):
            animated_nodes.append(ob)

    for bobj in scene.objects:
        if bobj.type != "MESH":
            continue

        if bobj.users_group and bobj.users_group[0].name == "__ignore__":
            continue

        if not bobj.parent:
            if not auto_root_index:
                if "NodeOrder" in bpy.data.texts and "__auto_root__" not in order_key:
                    return fail(
                        operator,
                        "The mesh '{}' does not have a parent. Normally, the exporter would create a temporary parent for you to fix this, but you have a specified NodeOrder (may be created by previously importing a DTS file and not pressing Ctrl+N after you're done with it), which does not have the '__auto_root__' entry (name used for the automatic parent)."
                        .format(bobj.name))

                dsq.nodes.append("__auto_root__")

    sequences = {}

    for marker in context.scene.timeline_markers:
        if ":" not in marker.name:
            continue

        name, what = marker.name.rsplit(":", 1)

        if name not in sequences:
            sequences[name] = {}

        if what in sequences[name]:
            print(
                "Warning: Got duplicate '{}' marker for sequence '{}' at frame {} (first was at frame {}), ignoring"
                .format(what, name, marker.frame, sequences[name][what].frame))
            continue

        sequences[name][what] = marker

    sequence_flags_strict = False
    sequence_flags = {}
    sequence_missing = set()

    if "Sequences" in bpy.data.texts:
        for line in bpy.data.texts["Sequences"].as_string().split("\n"):
            line = line.strip()

            if not line:
                continue

            if line == "strict":
                sequence_flags_strict = True
                continue

            if ":" not in line:
                print("Invalid line in 'Sequences':", line)
                continue

            name, flags = line.split(":", 1)

            if flags.lstrip():
                flags = tuple(map(lambda f: f.strip(), flags.split(",")))
            else:
                flags = ()

            sequence_flags[name] = flags
            sequence_missing.add(name)

    for name, markers in sequences.items():
        print("Exporting sequence", name)

        if "start" not in markers:
            return fail(operator,
                        "Missing start marker for sequence '{}'".format(name))

        if "end" not in markers:
            return fail(operator,
                        "Missing end marker for sequence '{}'".format(name))

        seq = Sequence()
        seq.name = name
        seq.flags = Sequence.AlignedScale

        if name in sequence_flags:
            for part in sequence_flags[name]:
                flag, *data = part.split(" ", 1)
                if data: data = data[0]

                if flag == "cyclic":
                    seq.flags |= Sequence.Cyclic
                elif flag == "blend":
                    seq.flags |= Sequence.Blend
                    seq.priority = int(data)
                else:
                    print("Warning: Unknown flag '{}' (used by sequence '{}')".
                          format(flag, name))

            sequence_missing.remove(name)
        elif sequence_flags_strict:
            return fail(
                operator,
                "Missing 'Sequences' line for sequence '{}'".format(name))

        frame_start = markers["start"].frame
        frame_end = markers["end"].frame

        frame_range = frame_end - frame_start + 1
        frame_step = 1  # TODO: GCD of keyframe spacings

        seq.toolBegin = frame_start
        seq.duration = frame_range * (context.scene.render.fps_base /
                                      context.scene.render.fps)

        seq.numKeyframes = int(math.ceil(float(frame_range) / frame_step))
        seq.firstGroundFrame = len(dsq.ground_translations)
        seq.baseRotation = len(dsq.rotations)
        seq.baseTranslation = len(dsq.translations)
        seq.baseScale = len(dsq.aligned_scales)
        seq.baseObjectState = 0
        seq.baseDecalState = 0
        seq.firstTrigger = len(dsq.triggers)

        seq.rotationMatters = [False] * len(dsq.nodes)
        seq.translationMatters = [False] * len(dsq.nodes)
        seq.scaleMatters = [False] * len(dsq.nodes)
        seq.decalMatters = [False] * len(dsq.nodes)
        seq.iflMatters = [False] * len(dsq.nodes)
        seq.visMatters = [False] * len(dsq.nodes)
        seq.frameMatters = [False] * len(dsq.nodes)
        seq.matFrameMatters = [False] * len(dsq.nodes)

        dsq.sequences.append(seq)

        seq_curves_rotation = []
        seq_curves_translation = []
        seq_curves_scale = []

        for ob in animated_nodes:
            index = node_index[ob]
            fcurves = ob.animation_data.action.fcurves

            if ob.rotation_mode == "QUATERNION":
                curves_rotation = array_from_fcurves(fcurves,
                                                     "rotation_quaternion", 4)
            elif ob.rotation_mode == "XYZ":
                curves_rotation = array_from_fcurves(fcurves, "rotation_euler",
                                                     3)
            else:
                return fail(
                    operator,
                    "Animated node '{}' uses unsupported rotation_mode '{}'".
                    format(ob.name, ob.rotation_mode))

            curves_translation = array_from_fcurves(fcurves, "location", 3)
            curves_scale = array_from_fcurves(fcurves, "scale", 3)

            if curves_rotation and fcurves_keyframe_in_range(
                    curves_rotation, frame_start, frame_end):
                print("rotation matters for", ob.name)
                seq_curves_rotation.append((curves_rotation, ob.rotation_mode))
                seq.rotationMatters[index] = True

            if curves_translation and fcurves_keyframe_in_range(
                    curves_translation, frame_start, frame_end):
                print("translation matters for", ob.name)
                seq_curves_translation.append(curves_translation)
                seq.translationMatters[index] = True

            if curves_scale and fcurves_keyframe_in_range(
                    curves_scale, frame_start, frame_end):
                print("scale matters for", ob.name)
                seq_curves_scale.append(curves_scale)
                seq.scaleMatters[index] = True

        frame_indices = []
        frame_current = frame_start

        while frame_current <= frame_end:
            frame_indices.append(frame_current)

            if frame_current == frame_end:
                break

            frame_current = min(frame_end, frame_current + frame_step)

        for (curves, mode) in seq_curves_rotation:
            for frame in frame_indices:
                if mode == "QUATERNION":
                    r = evaluate_all(curves, frame)
                elif mode == "XYZ":
                    r = Euler(evaluate_all(curves, frame),
                              "XYZ").to_quaternion()
                else:
                    assert false, "unknown rotation_mode after finding matters"
                dsq.rotations.append(Quaternion(r[1], r[2], r[3], -r[0]))

        for curves in seq_curves_translation:
            for frame in frame_indices:
                dsq.translations.append(Vector(evaluate_all(curves, frame)))

        for curves in seq_curves_scale:
            for frame in frame_indices:
                dsq.aligned_scales.append(Vector(evaluate_all(curves, frame)))

    for name in sequence_missing:
        print(
            "Warning: Sequence '{}' exists in flags file, but no markers were found"
            .format(name))

    with open(filepath, "wb") as fd:
        dsq.write(fd)

    with open(filepath + ".txt", "w") as fd:
        dsq.write_dump(fd)

    return {"FINISHED"}
示例#36
0
def nrot(self, n):
    return Euler((radians(self.nrotx) * n[0], radians(self.nroty) * n[1],
                  radians(self.nrotz) * n[2]), 'XYZ')
示例#37
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
示例#38
0
 def getRotation(cls, object, name):
     path = '["AN*Transforms*Rotation*%s"]' % name
     return Euler(getattr(object, paths, (0.0, 0.0, 0.0)), cls.getRotationOrder(object, name))
示例#39
0
    def checkFire(self, tembak):
        now = datetime.datetime.now()
        jarak = now - self.lastTimeOfFire

        if tembak == 2:
            #print("trying to fire weapon {0} with time a : {1} and time b : {2}".format(self.name, str(jarak.seconds), str(self.reloadTime)))
            if self.mag > -1:
                if self.ammo > 0:
                    interval = rTimeLeft(jarak, self.interval)
                    if interval <= 0:
                        projectile = None
                        if self.shootOneByOne == False:
                            for barrel in self.barrelsDeviation:
                                if self.hideBarrelAfterShot == True:
                                    barrel.parent.visible = False
                                #print("dp scene ialah " + self.scene.name + " dengan objek " + self.self.name)
                                #ator dp deviation
                                nx = random.random() * self.deviation
                                nx = nx - self.deviation / 2
                                nz = random.random() * self.deviation
                                nz = nz - self.deviation / 2
                                deviation = Euler((nx, 0.0, nz))
                                #print([nx, ny, nz, self.deviation])
                                na = barrel.parent.worldOrientation
                                #na.rotate(deviation)
                                eul = Vector(na.to_euler()) + Vector(deviation)
                                eul = Euler(eul)
                                barrel.worldOrientation = eul.to_matrix()
                                #cek = deviation, na.to_euler(), barrel.worldOrientation.to_euler()
                                #print(cek)
                                projectile = self.scene.addObject(
                                    self.shell, barrel, self.timeToLive)
                        else:
                            barrel = self.barrelsDeviation[
                                self.currentBarrelIndex]
                            if self.hideBarrelAfterShot == True:
                                barrel.parent.visible = False
                            nx = random.random() * self.deviation
                            nx = nx - self.deviation / 2
                            nz = random.random() * self.deviation
                            nz = nz - self.deviation / 2
                            deviation = Euler((nx, 0.0, nz))
                            na = barrel.parent.worldOrientation
                            eul = Vector(na.to_euler()) + Vector(deviation)
                            eul = Euler(eul)
                            barrel.worldOrientation = eul.to_matrix()
                            #print("dp scene ialah " + self.scene.name + " dengan objek " + self.self.name)
                            projectile = self.scene.addObject(
                                self.shell, barrel, self.timeToLive)
                            '''
							if 'type' in projectile:
								if projectile['type'] == "heatSeekingMissile":
									projectile = KX_SeekingMissile(projectile)
								else:
									projectile = KX_Projectile(projectile)
							else:
								projectile = KX_Projectile(projectile)
							self.ammo -= 1
							#print('dp putput = ' + str(self.output))
							#print("dp velocity = " + str(self.velocity))
							projectile.localLinearVelocity = Vector((self.output.x * self.velocity + self.heldBy.localLinearVelocity.x, self.output.y * self.velocity + self.heldBy.localLinearVelocity.y, self.output.z * self.velocity + self.heldBy.localLinearVelocity.z))
							#print('projectile has been shot with speed = {0}'.format(projectile.localLinearVelocity))
							self.lastTimeOfFire = datetime.datetime.now()
							projectile.shotWith = self.name
							projectile.shotBy = self.heldBy
							projectile.scaling = Vector(self.scale)
							projectile.target = self.target
							'''

                            pb = len(self.barrelsDeviation)
                            if pb > 1:
                                self.currentBarrelIndex += 1
                                if self.currentBarrelIndex > pb - 1:
                                    self.currentBarrelIndex = 0
                                #rint(self.currentBarrelIndex)
                        if projectile != None:
                            if 'type' in projectile:
                                if projectile['type'] == "heatSeekingMissile":
                                    projectile = gameobjects.KX_SeekingMissile(
                                        projectile)
                                    projectile.target = self.lockedTo
                                    projectile.lockOnStatus = self.lockOnStatus
                                else:
                                    projectile = gameobjects.KX_Projectile(
                                        projectile)
                            else:
                                projectile = gameobjects.KX_Projectile(
                                    projectile)
                            self.ammo -= 1
                            projectile.localLinearVelocity += Vector(
                                (self.output.x * self.velocity +
                                 self.heldBy.localLinearVelocity.x,
                                 self.output.y * self.velocity +
                                 self.heldBy.localLinearVelocity.y,
                                 self.output.z * self.velocity +
                                 self.heldBy.localLinearVelocity.z))
                            #print('projectile has been shot with speed = {0}'.format(projectile.localLinearVelocity))
                            projectile.lastVelocity = projectile.worldLinearVelocity
                            self.lastTimeOfFire = datetime.datetime.now()
                            projectile.shotWith = self.name
                            projectile.shotBy = self.heldBy
                            projectile.scaling = Vector(self.scale)
                            self.shootCount += 1
        if self.ammo == 0:
            if self.reloadStatus == "standBy":
                self.reloadStatus = "gonnaReload"

        if self.reloadStatus == "awal":
            self.mag -= 1
            self.reloadStatus = "standBy"
        if self.reloadStatus == "gonnaReload":
            self.lastTimeOfFire = datetime.datetime.now()
            jarak = now - self.lastTimeOfFire
            self.reloadTimeLeft = rTimeLeft(jarak, self.reloadTime)
            self.reloadStatus = "isReloading"
        if self.reloadStatus == "isReloading":
            jarak = now - self.lastTimeOfFire
            self.reloadTimeLeft = rTimeLeft(jarak, self.reloadTime)
            if self.reloadTimeLeft <= 0.0:
                self.reloadStatus = "reloaded"
        if self.reloadStatus == "reloaded":
            if self.mag > 0:
                self.mag -= 1
                self.ammo = self.ammoSize
            if self.mag == 0 and self.ammo == 0:
                self.reloadStatus = "abis"
            else:
                self.reloadStatus = "standBy"
                if self.hideBarrelAfterShot == True:
                    for barrel in self.barrels:
                        barrel.visible = True
示例#40
0
def main():
    # time logging
    global start_time
    start_time = time.time()

    import argparse

    # parse commandline arguments
    log_message(sys.argv)
    parser = argparse.ArgumentParser(
        description='Generate synth dataset images.')
    parser.add_argument('--idx',
                        type=int,
                        help='idx of the requested sequence')
    parser.add_argument('--name',
                        type=str,
                        help='name of the requested sequence')
    parser.add_argument('--ishape',
                        type=int,
                        help='requested cut, according to the stride')
    parser.add_argument('--stride', type=int, help='stride amount, default 50')
    parser.add_argument('--direction',
                        type=str,
                        help='subject direction, default forward')
    parser.add_argument('--subject_id',
                        type=int,
                        help='local subject id, default 0')

    args = parser.parse_args(sys.argv[sys.argv.index("---") + 1:])

    idx = args.idx
    name = args.name
    ishape = args.ishape
    stride = args.stride
    direction = args.direction
    subject_id = args.subject_id

    log_message("input idx: %d" % idx)
    log_message("input name: %s" % name)
    log_message("input ishape: %d" % ishape)
    log_message("input stride: %d" % stride)
    log_message("Subject direction: %s" % direction)
    log_message("Local subject id: %d" % subject_id)

    if idx == None:
        exit(1)
    if ishape == None:
        exit(1)
    if stride == None:
        log_message("WARNING: stride not specified, using default value 50")
        stride = 50

    # import idx info (name, split)
    idx_info = load(open("pkl/idx_info.pickle", 'rb'))
    # get runpass
    (runpass, idx) = divmod(idx, len(idx_info))

    log_message("runpass: %d" % runpass)
    log_message("output idx: %d" % idx)

    for dic in idx_info:
        if dic['name'] == name:
            idx_info = dic
            break
    else:
        idx_info = idx_info[idx]

    log_message("sequence: %s" % idx_info['name'])
    log_message("nb_frames: %f" % idx_info['nb_frames'])

    # import configuration
    log_message("Importing configuration")
    import config
    params = config.load_file('config', 'SYNTH_DATA')

    smpl_data_folder = params['smpl_data_folder']
    smpl_data_filename = params['smpl_data_filename']
    bg_path = params['bg_path']
    resy = params['resy']
    resx = params['resx']
    clothing_option = params['clothing_option']  # grey, nongrey or all
    tmp_path = params['tmp_path']
    output_path = params['output_path']
    output_types = params['output_types']
    stepsize = params['stepsize']
    clipsize = params['clipsize']
    openexr_py2_path = params['openexr_py2_path']

    # compute number of cuts
    nb_ishape = max(
        1, int(np.ceil(
            (idx_info['nb_frames'] - (clipsize - stride)) / stride)))
    log_message("Max ishape: %d" % (nb_ishape - 1))

    if ishape == None:
        exit(1)

    assert (ishape < nb_ishape)

    # name is set given idx
    name = idx_info['name']
    output_path = join(output_path, 'run%d' % runpass, name.replace(" ", ""))
    params['output_path'] = output_path
    tmp_path = join(
        tmp_path,
        'run%d_%s_c%04d' % (runpass, name.replace(" ", ""), (ishape + 1)))
    params['tmp_path'] = tmp_path

    # check if already computed
    #  + clean up existing tmp folders if any
    if exists(tmp_path) and tmp_path != "" and tmp_path != "/":
        os.system('rm -rf %s' % tmp_path)
    rgb_vid_filename = "%s_c%04d.mp4" % (join(output_path, name.replace(
        ' ', '')), (ishape + 1))

    # create tmp directory
    if not exists(tmp_path):
        mkdir_safe(tmp_path)

    # >> don't use random generator before this point <<

    # initialize RNG with seeds from sequence id
    import hashlib
    s = "synth_data:%d:%d:%d" % (idx, runpass, ishape)
    seed_number = int(hashlib.sha1(s.encode('utf-8')).hexdigest(), 16) % (10**
                                                                          8)
    log_message("GENERATED SEED %d from string '%s'" % (seed_number, s))
    random.seed(seed_number)
    np.random.seed(seed_number)

    if (output_types['vblur']):
        vblur_factor = np.random.normal(0.5, 0.5)
        params['vblur_factor'] = vblur_factor

    log_message("Setup Blender")

    # create copy-spher.harm. directory if not exists
    sh_dir = join(tmp_path, 'spher_harm')
    if not exists(sh_dir):
        mkdir_safe(sh_dir)
    sh_dst = join(sh_dir, 'sh_%02d_%05d.osl' % (runpass, idx))
    os.system('cp spher_harm/sh.osl %s' % sh_dst)

    genders = {0: 'male', 1: 'female'}
    # pick random gender
    gender = genders[subject_id % 2]  #choice(genders)

    scene = bpy.data.scenes['Scene']
    scene.render.engine = 'CYCLES'
    bpy.data.materials['Material'].use_nodes = True
    scene.cycles.shading_system = True
    scene.use_nodes = True

    log_message("Listing background images")
    #bg_names = join(bg_path, '%s_img.txt' % idx_info['use_split'])
    bg_names = join(bg_path, 'bg.txt')
    nh_txt_paths = []
    with open(bg_names) as f:
        for line in f:
            nh_txt_paths.append(join(bg_path, line))

    # grab clothing names
    log_message("clothing: %s" % clothing_option)
    with open(join(smpl_data_folder, 'textures',
                   '%s_train.txt' % gender)) as f:
        txt_paths = f.read().splitlines()

    # if using only one source of clothing
    if clothing_option == 'nongrey':
        txt_paths = [k for k in txt_paths if 'nongrey' in k]
    elif clothing_option == 'grey':
        txt_paths = [k for k in txt_paths if 'nongrey' not in k]

    # random clothing texture
    cloth_img_name = txt_paths[subject_id]  #choice(txt_paths)
    cloth_img_name = join(smpl_data_folder, cloth_img_name)
    cloth_img = bpy.data.images.load(cloth_img_name)

    # random background
    bg_img_name = choice(nh_txt_paths)[:-1]
    bg_img = bpy.data.images.load(bg_img_name)

    log_message("Loading parts segmentation")
    beta_stds = np.load(join(smpl_data_folder, ('%s_beta_stds.npy' % gender)))

    log_message("Building materials tree")
    mat_tree = bpy.data.materials['Material'].node_tree
    create_sh_material(mat_tree, sh_dst, cloth_img)
    res_paths = create_composite_nodes(scene.node_tree,
                                       params,
                                       img=bg_img,
                                       idx=idx)

    log_message("Loading smpl data")
    smpl_data = np.load(join(smpl_data_folder, smpl_data_filename))

    log_message("Initializing scene")
    camera_distance = 11.0  #np.random.normal(8.0, 1)
    params['camera_distance'] = camera_distance
    ob, obname, arm_ob, cam_ob = init_scene(scene, params, gender)

    setState0()
    ob.select = True
    bpy.context.scene.objects.active = ob
    segmented_materials = True  #True: 0-24, False: expected to have 0-1 bg/fg

    log_message("Creating materials segmentation")
    # create material segmentation
    if segmented_materials:
        materials = create_segmentation(ob, params)
        prob_dressed = {
            'leftLeg': .5,
            'leftArm': .9,
            'leftHandIndex1': .01,
            'rightShoulder': .8,
            'rightHand': .01,
            'neck': .01,
            'rightToeBase': .9,
            'leftShoulder': .8,
            'leftToeBase': .9,
            'rightForeArm': .5,
            'leftHand': .01,
            'spine': .9,
            'leftFoot': .9,
            'leftUpLeg': .9,
            'rightUpLeg': .9,
            'rightFoot': .9,
            'head': .01,
            'leftForeArm': .5,
            'rightArm': .5,
            'spine1': .9,
            'hips': .9,
            'rightHandIndex1': .01,
            'spine2': .9,
            'rightLeg': .5
        }
    else:
        materials = {'FullBody': bpy.data.materials['Material']}
        prob_dressed = {'FullBody': .6}

    orig_pelvis_loc = None
    random_zrot = 0
    if direction == 'forward':
        random_zrot = -np.pi / 2
        orig_pelvis_loc = (
            arm_ob.matrix_world.copy() *
            arm_ob.pose.bones[obname + '_Pelvis'].head.copy()) - Vector(
                (-1., 0.65, -1.15))
    elif direction == 'backward':
        random_zrot = np.pi / 2
        orig_pelvis_loc = (
            arm_ob.matrix_world.copy() *
            arm_ob.pose.bones[obname + '_Pelvis'].head.copy()) - Vector(
                (-1., 0.65, 2.9))

    orig_cam_loc = cam_ob.location.copy()

    print("CAM LOC:", orig_cam_loc, type(orig_cam_loc))

    # unblocking both the pose and the blendshape limits
    for k in ob.data.shape_keys.key_blocks.keys():
        bpy.data.shape_keys["Key"].key_blocks[k].slider_min = -10
        bpy.data.shape_keys["Key"].key_blocks[k].slider_max = 10

    log_message("Loading body data")
    cmu_parms, fshapes, name = load_body_data(smpl_data,
                                              ob,
                                              obname,
                                              name,
                                              gender=gender)

    log_message("Loaded body data for %s" % name)

    nb_fshapes = len(fshapes)
    #if idx_info['use_split'] == 'train':
    #    fshapes = fshapes[:int(nb_fshapes*0.8)]
    #elif idx_info['use_split'] == 'test':
    #    fshapes = fshapes[int(nb_fshapes*0.8):]

    # pick random real body shape
    shape = fshapes[
        subject_id]  #choice(fshapes) #+random_shape(.5) can add noise
    #shape = random_shape(3.) # random body shape

    # example shapes
    #shape = np.zeros(10) #average
    #shape = np.array([ 2.25176191, -3.7883464 ,  0.46747496,  3.89178988,  2.20098416,  0.26102114, -3.07428093,  0.55708514, -3.94442258, -2.88552087]) #fat

    ndofs = 10

    scene.objects.active = arm_ob
    orig_trans = np.asarray(arm_ob.pose.bones[obname +
                                              '_Pelvis'].location).copy()

    # create output directory
    if not exists(output_path):
        mkdir_safe(output_path)

    # spherical harmonics material needs a script to be loaded and compiled
    scs = []
    for mname, material in materials.items():
        scs.append(material.node_tree.nodes['Script'])
        scs[-1].filepath = sh_dst
        scs[-1].update()

    rgb_dirname = name.replace(" ", "") + '_c%04d.mp4' % (ishape + 1)
    rgb_path = join(tmp_path, rgb_dirname)

    data = cmu_parms[name]

    fbegin = ishape * stepsize * stride
    fend = min(ishape * stepsize * stride + stepsize * clipsize,
               len(data['poses']))

    log_message("Computing how many frames to allocate")
    N = len(data['poses'][fbegin:fend:stepsize])
    log_message("Allocating %d frames in mat file" % N)

    # force recomputation of joint angles unless shape is all zeros
    curr_shape = np.zeros_like(shape)
    nframes = len(data['poses'][::stepsize])

    matfile_info = join(
        output_path,
        name.replace(" ", "") + "_c%04d_info.mat" % (ishape + 1))
    log_message('Working on %s' % matfile_info)

    # allocate
    dict_info = {}
    dict_info['bg'] = np.zeros((N, ), dtype=np.object)  # background image path
    dict_info['camLoc'] = np.empty(3)  # (1, 3)
    dict_info['clipNo'] = ishape + 1
    dict_info['cloth'] = np.zeros(
        (N, ), dtype=np.object)  # clothing texture image path
    dict_info['gender'] = np.empty(N,
                                   dtype='uint8')  # 0 for male, 1 for female
    dict_info['joints2D'] = np.empty(
        (2, 24, N), dtype='float32')  # 2D joint positions in pixel space
    dict_info['joints3D'] = np.empty(
        (3, 24, N), dtype='float32')  # 3D joint positions in world coordinates
    dict_info['light'] = np.empty((9, N), dtype='float32')
    dict_info['pose'] = np.empty(
        (data['poses'][0].size, N),
        dtype='float32')  # joint angles from SMPL (CMU)
    dict_info['sequence'] = name.replace(" ", "") + "_c%04d" % (ishape + 1)
    dict_info['shape'] = np.empty((ndofs, N), dtype='float32')
    dict_info['zrot'] = np.empty(N, dtype='float32')
    dict_info['camDist'] = camera_distance
    dict_info['stride'] = stride

    if name.replace(" ", "").startswith('h36m'):
        dict_info['source'] = 'h36m'
    else:
        dict_info['source'] = 'cmu'

    if (output_types['vblur']):
        dict_info['vblur_factor'] = np.empty(N, dtype='float32')

    # for each clipsize'th frame in the sequence
    get_real_frame = lambda ifr: ifr
    reset_loc = False
    batch_it = 0
    curr_shape = reset_joint_positions(orig_trans, shape, ob, arm_ob, obname,
                                       scene, cam_ob,
                                       smpl_data['regression_verts'],
                                       smpl_data['joint_regressor'])

    arm_ob.animation_data_clear()
    cam_ob.animation_data_clear()

    # create a keyframe animation with pose, translation, blendshapes and camera motion
    # LOOP TO CREATE 3D ANIMATION
    for seq_frame, (pose, trans) in enumerate(
            zip(data['poses'][fbegin:fend:stepsize],
                data['trans'][fbegin:fend:stepsize])):

        iframe = seq_frame
        scene.frame_set(get_real_frame(seq_frame))

        # apply the translation, pose and shape to the character
        apply_trans_pose_shape(Vector(trans), pose, shape, ob, arm_ob, obname,
                               scene, cam_ob, get_real_frame(seq_frame))
        dict_info['shape'][:, iframe] = shape[:ndofs]
        dict_info['pose'][:, iframe] = pose
        dict_info['gender'][iframe] = list(genders)[list(
            genders.values()).index(gender)]
        if (output_types['vblur']):
            dict_info['vblur_factor'][iframe] = vblur_factor

        arm_ob.pose.bones[obname + '_root'].rotation_quaternion = Quaternion(
            Euler((0, 0, random_zrot), 'XYZ'))
        arm_ob.pose.bones[obname + '_root'].keyframe_insert(
            'rotation_quaternion', frame=get_real_frame(seq_frame))
        dict_info['zrot'][iframe] = random_zrot

        scene.update()

        # Bodies centered only in each minibatch of clipsize frames
        if seq_frame == 0 or reset_loc:
            reset_loc = False
            new_pelvis_loc = arm_ob.matrix_world.copy() * arm_ob.pose.bones[
                obname + '_Pelvis'].head.copy()
            cam_ob.location = orig_cam_loc.copy() + (new_pelvis_loc.copy() -
                                                     orig_pelvis_loc.copy())
            cam_ob.keyframe_insert('location', frame=get_real_frame(seq_frame))
            dict_info['camLoc'] = np.array(cam_ob.location)

    scene.node_tree.nodes['Image'].image = bg_img

    for part, material in materials.items():
        material.node_tree.nodes['Vector Math'].inputs[1].default_value[:2] = (
            0, 0)

    # random light
    sh_coeffs = .7 * (2 * np.random.rand(9) - 1)
    sh_coeffs[0] = .5 + .9 * np.random.rand(
    )  # Ambient light (first coeff) needs a minimum  is ambient. Rest is uniformly distributed, higher means brighter.
    sh_coeffs[1] = -.7 * np.random.rand()

    for ish, coeff in enumerate(sh_coeffs):
        for sc in scs:
            sc.inputs[ish + 1].default_value = coeff

    # iterate over the keyframes and render
    # LOOP TO RENDER
    for seq_frame, (pose, trans) in enumerate(
            zip(data['poses'][fbegin:fend:stepsize],
                data['trans'][fbegin:fend:stepsize])):
        scene.frame_set(get_real_frame(seq_frame))
        iframe = seq_frame

        dict_info['bg'][iframe] = bg_img_name
        dict_info['cloth'][iframe] = cloth_img_name
        dict_info['light'][:, iframe] = sh_coeffs

        scene.render.use_antialiasing = False
        scene.render.filepath = join(
            rgb_path, 'Image%04d.png' % get_real_frame(seq_frame))

        log_message("Rendering frame %d" % seq_frame)

        # disable render output
        logfile = '/dev/null'
        open(logfile, 'a').close()
        old = os.dup(1)
        sys.stdout.flush()
        os.close(1)
        os.open(logfile, os.O_WRONLY)

        # Render
        bpy.ops.render.render(write_still=True)

        # disable output redirection
        os.close(1)
        os.dup(old)
        os.close(old)

        # bone locations should be saved after rendering so that the bones are updated
        bone_locs_2D, bone_locs_3D = get_bone_locs(obname, arm_ob, scene,
                                                   cam_ob)
        dict_info['joints2D'][:, :, iframe] = np.transpose(bone_locs_2D)
        dict_info['joints3D'][:, :, iframe] = np.transpose(bone_locs_3D)

        reset_loc = (bone_locs_2D.max(axis=-1) >
                     256).any() or (bone_locs_2D.min(axis=0) < 0).any()
        arm_ob.pose.bones[obname + '_root'].rotation_quaternion = Quaternion(
            (1, 0, 0, 0))

    # save a .blend file for debugging:
    # bpy.ops.wm.save_as_mainfile(filepath=join(tmp_path, 'pre.blend'))

    # save RGB data with ffmpeg (if you don't have h264 codec, you can replace with another one and control the quality with something like -q:v 3)
    cmd_ffmpeg = 'ffmpeg -y -r 30 -i ' '%s' ' -c:v h264 -pix_fmt yuv420p -crf 23 ' '%s_c%04d.mp4' '' % (
        join(rgb_path, 'Image%04d.png'),
        join(output_path, name.replace(' ', '')), (ishape + 1))
    log_message("Generating RGB video (%s)" % cmd_ffmpeg)
    os.system(cmd_ffmpeg)

    if (output_types['vblur']):
        cmd_ffmpeg_vblur = 'ffmpeg -y -r 30 -i ' '%s' ' -c:v h264 -pix_fmt yuv420p -crf 23 -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" ' '%s_c%04d.mp4' '' % (
            join(res_paths['vblur'], 'Image%04d.png'),
            join(output_path,
                 name.replace(' ', '') + '_vblur'), (ishape + 1))
        log_message("Generating vblur video (%s)" % cmd_ffmpeg_vblur)
        os.system(cmd_ffmpeg_vblur)

    if (output_types['fg']):
        cmd_ffmpeg_fg = 'ffmpeg -y -r 30 -i ' '%s' ' -c:v h264 -pix_fmt yuv420p -crf 23 ' '%s_c%04d.mp4' '' % (
            join(res_paths['fg'], 'Image%04d.png'),
            join(output_path,
                 name.replace(' ', '') + '_fg'), (ishape + 1))
        log_message("Generating fg video (%s)" % cmd_ffmpeg_fg)
        os.system(cmd_ffmpeg_fg)

    cmd_tar = 'tar -czvf %s/%s.tar.gz -C %s %s' % (output_path, rgb_dirname,
                                                   tmp_path, rgb_dirname)
    log_message("Tarballing the images (%s)" % cmd_tar)
    os.system(cmd_tar)

    # save annotation excluding png/exr data to _info.mat file
    import scipy.io
    scipy.io.savemat(matfile_info, dict_info, do_compression=True)
def generate(ds_name, tags_list):
    start_time = time.time()

    #check if folder exists in render, if not, create folder
    try:
        os.mkdir("render/" + ds_name)
    except Exception:
        pass
    
    data_storage_path = os.getcwd() + "/render/" + ds_name     
    
    # switch to correct scene
    bpy.context.window.scene = bpy.data.scenes['Real']

    # remove all animation
    for obj in bpy.context.scene.objects:
        obj.animation_data_clear()

    # set up file outputs
    output_node = bpy.data.scenes['Render'].node_tree.nodes["File Output"]
    output_node.base_path = data_storage_path
        
    np.random.seed(5)
    waypoints_dict = {
        'distance': [#0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5
            6,
            3,
            1,
            
            3,
            6,
            
            3,
            1
        ]
    ,
        'offset': [
            (0.25, 0.25),
            (0.5, 0.5),
            (0.75, 0.75),
        
            (0.7, 0.3),
            (0.5, 0.25),
        
            (0.35, 0.5),
            (0.25, 0.5)
        ],
        'background': [
            (0, -90, 0),
            (0, -105, 15),
            (0, -120, 30),
            
            (0, -120, 15),
            (0, -120, 0),
        
            (0, -105, 0),
            (0, -90, 0)
        ],
        'pose': np.random.rand(7, 3) * 360,
        'lighting': np.random.rand(7, 3) * 360
    }

    waypoints = []
    for vals in zip(*waypoints_dict.values()):
        d = dict(zip(waypoints_dict.keys(), vals))
        waypoints.append(starfish.Frame(
            distance=nm_to_bu(d['distance']),
            offset=d['offset'],
            background=Euler(list(map(deg_to_rad, d['background']))),
            pose=Euler(list(map(deg_to_rad, d['pose']))),
            lighting=Euler(list(map(deg_to_rad, d['lighting'])))
        ))

    counts = [300] * 7

    for scene in bpy.data.scenes:
        scene.unit_settings.scale_length = 1 / SCALE

    for i, frame in enumerate(starfish.Sequence.interpolated(waypoints, counts)):
        bpy.context.scene.frame_set(0)
        frame.setup(bpy.data.scenes['Real'], bpy.data.objects["Gateway"], bpy.data.objects["Camera"], bpy.data.objects["Sun"])
    
        #create name for the current image (unique to that image)
        name = str(i).zfill(5)
        output_node.file_slots[0].path = "image_" + "#" + str(name)
        output_node.file_slots[1].path = "mask_" + "#" + str(name)
        
        # render
        bpy.ops.render.render(scene="Render")
        
        # Tag the pictures
        frame.tags = tags_list
        # add metadata to frame
        frame.sequence_name = ds_name

        mask_filepath = os.path.join(output_node.base_path, "mask_0" + str(name) + ".png")
        meta_filepath = os.path.join(output_node.base_path, "meta_0" + str(name) + ".json")

        # run color normalization with labels plus black background
        postprocessing.normalize_mask_colors(mask_filepath, list(LABEL_MAP.values()) + [(0, 0, 0)])

        # get bbox and centroid and add them to metadata
        frame.bboxes = postprocessing.get_bounding_boxes_from_mask(mask_filepath, LABEL_MAP)
        frame.centroids = postprocessing.get_centroids_from_mask(mask_filepath, LABEL_MAP)
    
        with open(meta_filepath, "w") as f:
            f.write(frame.dumps())

    print("===========================================" + "\r")
    time_taken = time.time() - start_time
    print("------Time Taken: %s seconds----------" %(time_taken) + "\r")
    print("Data stored at: " + data_storage_path)
    bpy.ops.wm.quit_blender()
示例#42
0
def createPencil(name,
                 co,
                 segs=12,
                 tipDepth=.1,
                 height=1,
                 diameter=.033,
                 endTipPerc=15,
                 endTipDia=0.0033,
                 sharpCutOffset=0.01,
                 tilt=45,
                 group=None):
    def createMaterialNode(obj, colorVal, matName):
        if (bpy.data.materials.get(matName) == None):
            mat = bpy.data.materials.new(matName)
            if (bpy.context.scene.render.engine == 'CYCLES'):
                mat.use_nodes = True
                defNode = mat.node_tree.nodes[1]
                defNode.inputs[0].default_value = colorVal
            elif (bpy.context.scene.render.engine == 'BLENDER_EEVEE'):
                mat.diffuse_color = colorVal
        else:
            mat = bpy.data.materials[matName]
        obj.data.materials.append(mat)
        return mat

    bm = bmesh.new()
    bmesh.ops.create_cone(bm,
                          cap_ends=True,
                          segments=segs,
                          depth=tipDepth * (100 - endTipPerc) / 100,
                          diameter1=endTipDia,
                          diameter2=diameter)

    up = Vector((0, 0, 1))
    bm.normal_update()

    topFace = [f for f in bm.faces if f.normal.angle(up) < radians(3)][0]
    oldFaces = [f for f in bm.faces]
    info = bmesh.ops.extrude_face_region(bm, geom=[topFace])
    bmesh.ops.translate(
        bm,
        vec=Vector((0, 0, height)),
        verts=[v for v in info["geom"] if isinstance(v, bmesh.types.BMVert)])
    for f in bm.faces:
        if (f not in oldFaces):
            f.material_index = 0
        else:
            f.material_index = 1
    oldFaces = [f for f in bm.faces]

    offsetVerts = [v for i, v in enumerate(topFace.verts) if i % 2 == 0]
    bmesh.ops.translate(bm, vec=(0, 0, sharpCutOffset), verts=offsetVerts)

    info = bmesh.ops.create_cone(bm,
                                 cap_ends=True,
                                 segments=segs * 2,
                                 depth=tipDepth * endTipPerc / 100,
                                 diameter1=0,
                                 diameter2=endTipDia)

    bmesh.ops.translate(bm, vec=(0, 0, -tipDepth * .5), verts=info['verts'])

    for f in bm.faces:
        if (f not in oldFaces):
            f.material_index = 2

    mesh = bpy.data.meshes.new(name)
    pObj = bpy.data.objects.new(name, mesh)
    # ~ bpy.context.scene.collection.objects.link(pObj) #In 2.8 add to group only
    # ~ bpy.context.scene.update()
    depsgraph = bpy.context.evaluated_depsgraph_get()
    depsgraph.update()
    bm.to_mesh(mesh)

    bodyColor = [0.00, 0.35, 0.44, 1.00]
    sharpenedTipColor = [0.80, 0.55, 0.09, 1.00]
    endTipColor = [0.00, 0.00, 0.00, 1.00]
    createMaterialNode(pObj, bodyColor, NEW_DATA_PREFIX + 'BodyMat')
    createMaterialNode(pObj, sharpenedTipColor, NEW_DATA_PREFIX + 'Tip1Mat')
    createMaterialNode(pObj, endTipColor, NEW_DATA_PREFIX + 'Tip2Mat')

    #pObj.data.uv_textures.new() # 2.8 Changed?

    for vert in mesh.vertices:
        vert.co.z += (tipDepth + tipDepth * endTipPerc / 100) / 2

    pObj.rotation_euler = Euler((radians(tilt), 0, 0), 'XYZ')

    if (group != None):
        group.objects.link(pObj)

    return pObj
 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
示例#44
0
        #obj_backup.hide = False
        bpy.context.scene.objects.active = obj_backup
        obj = obj_backup.copy()  # duplicate linked
        obj.data = obj_backup.data.copy(
        )  # optional: make this a real duplicate (not linked)
        obj.name = 'new_2k'
        obj.hide = False
        obj.hide_render = False
        bpy.context.scene.objects.link(obj)  # add to scene

        #    obj.parent.pose.bones['Bone.001'].rotation_quaternion = Euler((np.random.uniform(-180,180),np.random.uniform(-180,180),np.random.uniform(-180,180))).to_quaternion()
        #    obj.parent.pose.bones['Bone.005'].location = loc + Vector((np.random.uniform(-3,3),np.random.uniform(-3,3),np.random.uniform(-5,-3)))
        #        bpy.data.objects['Armature'].pose.bones['Bone.005'].location = Vector((def_a, d, def_c))
        obj.parent.pose.bones["Bone.001"].rotation_mode = 'XYZ'
        obj.parent.pose.bones['Bone.001'].rotation_euler = Euler(
            (np.deg2rad(alpha_range[j, 0]), np.deg2rad(alpha_range[j, 1]),
             np.deg2rad(alpha_range[j, 2])))
        #        break
        applyArmModifier(obj)

        obj.parent.pose.bones['Bone.001'].location = loc
        obj.parent = None
        obj.location = Vector((0, 0, 0))

        rotateTranslate(obj, a, b, g, x, y, z)  #1.5, 2)#4, 10)#std=3

        #        break
        #select and load background image

        bpy.context.scene.render.filepath = outdir + '{}_{:04}.png'.format(
            filename, j)