Ejemplo n.º 1
0
    def create_animation(self, blender_context, ms3d_model, blender_mesh_objects, blender_to_ms3d_bones):
        ##########################
        # setup scene
        blender_scene = blender_context.scene
        ms3d_model.animation_fps = blender_scene.render.fps * blender_scene.render.fps_base
        ms3d_model.number_total_frames = (blender_scene.frame_end - blender_scene.frame_start) + 1
        ms3d_model.current_time = (blender_scene.frame_current - blender_scene.frame_start) / (
            blender_scene.render.fps * blender_scene.render.fps_base
        )

        # return
        ### not ready yet
        for blender_mesh_object in blender_mesh_objects:
            blender_bones = None
            for blender_modifier in blender_mesh_object.modifiers:
                if blender_modifier.type == "ARMATURE" and blender_modifier.object.pose:
                    blender_bones = blender_modifier.object.data.bones
                    break

            for blender_bone_oject in blender_bones:
                ms3d_joint = Ms3dJoint()
                ms3d_joint.__index = len(ms3d_model._joints)

                blender_ms3d_joint = blender_bone_oject.ms3d
                blender_bone = blender_bone_oject

                ms3d_joint.flags = Ms3dUi.flags_to_ms3d(blender_ms3d_joint.flags)
                if blender_ms3d_joint.comment:
                    ms3d_joint._comment_object = Ms3dCommentEx()
                    ms3d_joint._comment_object.comment = blender_ms3d_joint.comment
                    ms3d_joint._comment_object.index = ms3d_joint.__index

                ms3d_joint.joint_ex_object._color = blender_ms3d_joint.color[:]

                if blender_ms3d_joint.name:
                    ms3d_joint.name = blender_ms3d_joint.name
                else:
                    ms3d_joint.name = blender_bone.name

                if blender_bone.parent:
                    if blender_ms3d_joint.name:
                        ms3d_joint.parent_name = blender_bone.parent.ms3d.name
                    else:
                        ms3d_joint.parent_name = blender_bone.parent.name

                    ms3d_joint_vector = blender_bone.head * self.matrix_scaled_coordination_system
                    blender_bone_euler = blender_bone.matrix.to_euler("XZY")
                else:
                    ms3d_joint_vector = blender_bone.head * self.matrix_scaled_coordination_system
                    blender_bone_euler = blender_bone.matrix.to_euler("XZY")
                ms3d_joint._position = ms3d_joint_vector[:]
                ms3d_joint._rotation = (Vector(blender_bone_euler[:]) * self.matrix_scaled_coordination_system)[:]

                ms3d_model._joints.append(ms3d_joint)
                blender_to_ms3d_bones[blender_bone.name] = ms3d_joint
Ejemplo n.º 2
0
    def get_ms3d_material_add_if(self, blender_mesh, ms3d_model,
                                 blender_to_ms3d_materials, blender_index):
        if blender_index < 0 or blender_index >= len(blender_mesh.materials):
            return None

        blender_material = blender_mesh.materials[blender_index]
        ms3d_material = blender_to_ms3d_materials.get(blender_material)
        if ms3d_material is None:
            ms3d_material = Ms3dMaterial()
            ms3d_material.__index = len(ms3d_model.materials)

            blender_ms3d_material = blender_material.ms3d

            if not self.options_use_blender_names \
                    and not self.options_use_blender_materials \
                    and blender_ms3d_material.name:
                ms3d_material.name = blender_ms3d_material.name
            else:
                ms3d_material.name = blender_material.name

            temp_material = None
            if self.options_use_blender_materials:
                temp_material = Ms3dMaterial()
                Ms3dMaterialHelper.copy_from_blender(None, None, temp_material,
                                                     blender_material)
            else:
                temp_material = blender_ms3d_material

            ms3d_material._ambient = temp_material.ambient[:]
            ms3d_material._diffuse = temp_material.diffuse[:]
            ms3d_material._specular = temp_material.specular[:]
            ms3d_material._emissive = temp_material.emissive[:]
            ms3d_material.shininess = temp_material.shininess
            ms3d_material.transparency = temp_material.transparency
            ms3d_material.texture = temp_material.texture
            ms3d_material.alphamap = temp_material.alphamap

            ms3d_material.mode = Ms3dUi.texture_mode_to_ms3d(
                blender_ms3d_material.mode)
            if blender_ms3d_material.comment:
                ms3d_material._comment_object = Ms3dCommentEx()
                ms3d_material._comment_object.comment = \
                        blender_ms3d_material.comment
                ms3d_material._comment_object.index = ms3d_material.__index

            ms3d_model.materials.append(ms3d_material)

            blender_to_ms3d_materials[blender_material] = ms3d_material

        return ms3d_material
Ejemplo n.º 3
0
    def get_ms3d_material_add_if(self, blender_mesh, ms3d_model,
            blender_to_ms3d_materials, blender_index):
        if blender_index < 0 or blender_index >= len(blender_mesh.materials):
            return None

        blender_material = blender_mesh.materials[blender_index]
        ms3d_material = blender_to_ms3d_materials.get(blender_material)
        if ms3d_material is None:
            ms3d_material = Ms3dMaterial()
            ms3d_material.__index = len(ms3d_model.materials)

            blender_ms3d_material = blender_material.ms3d

            if not self.options_use_blender_names \
                    and not self.options_use_blender_materials \
                    and blender_ms3d_material.name:
                ms3d_material.name = blender_ms3d_material.name
            else:
                ms3d_material.name = blender_material.name

            temp_material = None
            if self.options_use_blender_materials:
                temp_material = Ms3dMaterial()
                Ms3dMaterialHelper.copy_from_blender(
                        None, None, temp_material, blender_material)
            else:
                temp_material = blender_ms3d_material

            ms3d_material._ambient = temp_material.ambient[:]
            ms3d_material._diffuse = temp_material.diffuse[:]
            ms3d_material._specular = temp_material.specular[:]
            ms3d_material._emissive = temp_material.emissive[:]
            ms3d_material.shininess = temp_material.shininess
            ms3d_material.transparency = temp_material.transparency
            ms3d_material.texture = temp_material.texture
            ms3d_material.alphamap = temp_material.alphamap

            ms3d_material.mode = Ms3dUi.texture_mode_to_ms3d(
                    blender_ms3d_material.mode)
            if blender_ms3d_material.comment:
                ms3d_material._comment_object = Ms3dCommentEx()
                ms3d_material._comment_object.comment = \
                        blender_ms3d_material.comment
                ms3d_material._comment_object.index = ms3d_material.__index

            ms3d_model.materials.append(ms3d_material)

            blender_to_ms3d_materials[blender_material] = ms3d_material

        return ms3d_material
Ejemplo n.º 4
0
    def get_ms3d_material_add_if(self, blender_mesh, ms3d_model, blender_to_ms3d_materials, blender_index):
        if blender_index < 0 or blender_index >= len(blender_mesh.materials):
            return None

        blender_material = blender_mesh.materials[blender_index]
        ms3d_material = blender_to_ms3d_materials.get(blender_material)
        if ms3d_material is None:
            ms3d_material = Ms3dMaterial()
            ms3d_material.__index = len(ms3d_model.materials)

            blender_ms3d_material = blender_material.ms3d

            if blender_ms3d_material.name:
                ms3d_material.name = blender_ms3d_material.name
            else:
                ms3d_material.name = blender_material.name

            ms3d_material._ambient = blender_ms3d_material.ambient[:]
            ms3d_material._diffuse = blender_ms3d_material.diffuse[:]
            ms3d_material._specular = blender_ms3d_material.specular[:]
            ms3d_material._emissive = blender_ms3d_material.emissive[:]
            ms3d_material.shininess = blender_ms3d_material.shininess
            ms3d_material.transparency = blender_ms3d_material.transparency
            ms3d_material.mode = Ms3dUi.texture_mode_to_ms3d(blender_ms3d_material.mode)
            ms3d_material.texture = blender_ms3d_material.texture
            ms3d_material.alphamap = blender_ms3d_material.alphamap
            if blender_ms3d_material.comment:
                ms3d_material._comment_object = Ms3dCommentEx()
                ms3d_material._comment_object.comment = blender_ms3d_material.comment
                ms3d_material._comment_object.index = ms3d_material.__index

            ms3d_model.materials.append(ms3d_material)

            blender_to_ms3d_materials[blender_material] = ms3d_material

        return ms3d_material
Ejemplo n.º 5
0
    def create_animation(self, blender_context, ms3d_model, blender_mesh_object):
        ##########################
        # setup scene
        blender_scene = blender_context.scene
        blender_scene.render.fps = ms3d_model.animation_fps
        if ms3d_model.animation_fps:
            blender_scene.render.fps_base = (blender_scene.render.fps /
                    ms3d_model.animation_fps)

        blender_scene.frame_start = 1
        blender_scene.frame_end = (ms3d_model.number_total_frames
                + blender_scene.frame_start) - 1
        blender_scene.frame_current = (ms3d_model.current_time
                * ms3d_model.animation_fps)

        ##########################
        if not ms3d_model.joints:
            return

        ##########################
        ms3d_armature_name = "{}.a".format(ms3d_model.name)
        ms3d_action_name = "{}.act".format(ms3d_model.name)

        ##########################
        # create new blender_armature_object
        blender_armature = blender_context.blend_data.armatures.new(
                ms3d_armature_name)
        blender_armature.ms3d.name = ms3d_model.name
        blender_armature.draw_type = 'STICK'
        blender_armature.show_axes = True
        blender_armature.use_auto_ik = True
        blender_armature_object = blender_context.blend_data.objects.new(
                ms3d_armature_name, blender_armature)
        blender_scene.objects.link(blender_armature_object)
        #blender_armature_object.location = blender_scene.cursor_location
        blender_armature_object.show_x_ray = True

        ##########################
        # create new modifier
        blender_modifier = blender_mesh_object.modifiers.new(
                ms3d_armature_name, type='ARMATURE')
        blender_modifier.show_expanded = False
        blender_modifier.use_vertex_groups = True
        blender_modifier.use_bone_envelopes = False
        blender_modifier.object = blender_armature_object

        ##########################
        # prepare for vertex groups
        ms3d_to_blender_vertex_groups = {}
        for ms3d_vertex_index, ms3d_vertex in enumerate(ms3d_model.vertices):
            # prepare for later use for blender vertex group
            if ms3d_vertex.bone_id != Ms3dSpec.NONE_VERTEX_BONE_ID:
                if ms3d_vertex.vertex_ex_object \
                        and ( \
                        ms3d_vertex.vertex_ex_object.bone_ids[0] != \
                                Ms3dSpec.NONE_VERTEX_BONE_ID \
                        or ms3d_vertex.vertex_ex_object.bone_ids[1] != \
                                Ms3dSpec.NONE_VERTEX_BONE_ID \
                        or ms3d_vertex.vertex_ex_object.bone_ids[2] != \
                                Ms3dSpec.NONE_VERTEX_BONE_ID \
                        ):
                    ms3d_vertex_group_ids_weights = []
                    ms3d_vertex_group_ids_weights.append(
                            (ms3d_vertex.bone_id,
                            float(ms3d_vertex.vertex_ex_object.weights[0] % 101) / 100.0,
                            ))
                    if ms3d_vertex.vertex_ex_object.bone_ids[0] != \
                            Ms3dSpec.NONE_VERTEX_BONE_ID:
                        ms3d_vertex_group_ids_weights.append(
                                (ms3d_vertex.vertex_ex_object.bone_ids[0],
                                float(ms3d_vertex.vertex_ex_object.weights[1] % 101) / 100.0
                                ))
                    if ms3d_vertex.vertex_ex_object.bone_ids[1] != \
                            Ms3dSpec.NONE_VERTEX_BONE_ID:
                        ms3d_vertex_group_ids_weights.append(
                                (ms3d_vertex.vertex_ex_object.bone_ids[1],
                                float(ms3d_vertex.vertex_ex_object.weights[2] % 101) / 100.0
                                ))
                    if ms3d_vertex.vertex_ex_object.bone_ids[2] != \
                            Ms3dSpec.NONE_VERTEX_BONE_ID:
                        ms3d_vertex_group_ids_weights.append(
                                (ms3d_vertex.vertex_ex_object.bone_ids[2],
                                1.0 -
                                float((ms3d_vertex.vertex_ex_object.weights[0] % 101)
                                + (ms3d_vertex.vertex_ex_object.weights[1] % 101)
                                + (ms3d_vertex.vertex_ex_object.weights[2] % 101)) / 100.0
                                ))

                else:
                    ms3d_vertex_group_ids_weights = [(ms3d_vertex.bone_id, 1.0), ]

                for ms3d_vertex_group_id_weight in ms3d_vertex_group_ids_weights:
                    ms3d_vertex_group_id = ms3d_vertex_group_id_weight[0]
                    blender_vertex_weight = ms3d_vertex_group_id_weight[1]
                    blender_vertex_group = ms3d_to_blender_vertex_groups.get(
                            ms3d_vertex_group_id)
                    if blender_vertex_group is None:
                        ms3d_to_blender_vertex_groups[ms3d_vertex_group_id] \
                                = blender_vertex_group = []
                    blender_vertex_group.append((ms3d_vertex_index,
                            blender_vertex_weight))

        ##########################
        # blender stuff:
        # create all vertex groups to be used for bones
        for ms3d_bone_id, blender_vertex_index_weight_list \
                in ms3d_to_blender_vertex_groups.items():
            ms3d_name = ms3d_model.joints[ms3d_bone_id].name
            blender_vertex_group = blender_mesh_object.vertex_groups.new(
                    ms3d_name)
            for blender_vertex_id_weight in blender_vertex_index_weight_list:
                blender_vertex_index = blender_vertex_id_weight[0]
                blender_vertex_weight = blender_vertex_id_weight[1]
                blender_vertex_group.add((blender_vertex_index, ),
                        blender_vertex_weight, 'ADD')

        ##########################
        # bring joints in the correct order
        ms3d_joints_ordered = []
        self.build_ms3d_joint_dependency_order(ms3d_model.joints,
                ms3d_joints_ordered)

        ##########################
        # prepare joint data for later use
        ms3d_joint_by_name = {}
        for ms3d_joint in ms3d_joints_ordered:
            item = ms3d_joint_by_name.get(ms3d_joint.name)
            if item is None:
                ms3d_joint.__children = []
                ms3d_joint_by_name[ms3d_joint.name] = ms3d_joint

            matrix_local_rot = (Matrix.Rotation(ms3d_joint.rotation[2], 4, 'Z')
                    * Matrix.Rotation(ms3d_joint.rotation[1], 4, 'Y')
                    ) * Matrix.Rotation(ms3d_joint.rotation[0], 4, 'X')
            matrix_local = Matrix.Translation(Vector(ms3d_joint.position)
                    ) * matrix_local_rot

            ms3d_joint.__matrix_local_rot = matrix_local_rot
            ms3d_joint.__matrix_global_rot = matrix_local_rot
            ms3d_joint.__matrix_local = matrix_local
            ms3d_joint.__matrix_global = matrix_local

            if ms3d_joint.parent_name:
                ms3d_joint_parent = ms3d_joint_by_name.get(
                        ms3d_joint.parent_name)
                if ms3d_joint_parent is not None:
                    ms3d_joint_parent.__children.append(ms3d_joint)

                    matrix_global = ms3d_joint_parent.__matrix_global \
                            * matrix_local
                    ms3d_joint.__matrix_global = matrix_global

                    matrix_global_rot = ms3d_joint_parent.__matrix_global_rot \
                            * matrix_local_rot
                    ms3d_joint.__matrix_global_rot = matrix_global_rot

        ##########################
        # ms3d_joint to blender_edit_bone
        if ms3d_model.model_ex_object and not self.options_use_joint_size:
            joint_length = ms3d_model.model_ex_object.joint_size
        else:
            joint_length = self.options_joint_size
        if joint_length < 0.01:
            joint_length = 0.01

        blender_scene.objects.active = blender_armature_object
        enable_edit_mode(True, blender_context)
        for ms3d_joint in ms3d_joints_ordered:
            blender_edit_bone = blender_armature.edit_bones.new(ms3d_joint.name)
            blender_edit_bone.use_connect = False
            blender_edit_bone.use_inherit_rotation = True
            blender_edit_bone.use_inherit_scale = True
            blender_edit_bone.use_local_location = True
            blender_armature.edit_bones.active = blender_edit_bone

            ms3d_joint = ms3d_joint_by_name[ms3d_joint.name]
            ms3d_joint_vector = ms3d_joint.__matrix_global * Vector()

            blender_edit_bone.head \
                    = self.geometry_correction(ms3d_joint_vector)

            vector_tail_end_up = ms3d_joint.__matrix_global_rot * Vector((0,1,0))
            vector_tail_end_dir = ms3d_joint.__matrix_global_rot * Vector((0,0,1))
            vector_tail_end_up.normalize()
            vector_tail_end_dir.normalize()
            blender_edit_bone.tail = blender_edit_bone.head \
                    + self.geometry_correction(
                    vector_tail_end_dir * joint_length)
            blender_edit_bone.align_roll(self.geometry_correction(
                    vector_tail_end_up))

            if ms3d_joint.parent_name:
                ms3d_joint_parent = ms3d_joint_by_name[ms3d_joint.parent_name]
                blender_edit_bone_parent = ms3d_joint_parent.blender_edit_bone
                blender_edit_bone.parent = blender_edit_bone_parent

            ms3d_joint.blender_bone_name = blender_edit_bone.name
            ms3d_joint.blender_edit_bone = blender_edit_bone
        enable_edit_mode(False, blender_context)

        if self.options_use_joint_to_bones:
            enable_edit_mode(True, blender_context)
            for ms3d_joint in ms3d_joints_ordered:
                blender_edit_bone = blender_armature.edit_bones[ms3d_joint.name]
                if blender_edit_bone.children:
                    new_length = 0.0
                    for child_bone in blender_edit_bone.children:
                        length = (child_bone.head - blender_edit_bone.head).length
                        if new_length <= 0 or length < new_length:
                            new_length = length
                    if new_length >= 0.01:
                        direction = blender_edit_bone.tail - blender_edit_bone.head
                        direction.normalize()
                        blender_edit_bone.tail = blender_edit_bone.head + (direction * new_length)
            enable_edit_mode(False, blender_context)

        ##########################
        # post process bones
        enable_edit_mode(False, blender_context)
        for ms3d_joint_name, ms3d_joint in ms3d_joint_by_name.items():
            blender_bone = blender_armature.bones.get(
                    ms3d_joint.blender_bone_name)
            if blender_bone is None:
                continue

            blender_bone.ms3d.name = ms3d_joint.name
            blender_bone.ms3d.flags = Ms3dUi.flags_from_ms3d(ms3d_joint.flags)

            ms3d_joint_ex = ms3d_joint.joint_ex_object
            if ms3d_joint_ex is not None:
                blender_bone.ms3d.color = ms3d_joint_ex.color

            ms3d_comment = ms3d_joint.comment_object
            if ms3d_comment is not None:
                blender_bone.ms3d.comment = ms3d_comment.comment

        ##########################
        if not self.options_use_animation:
            return blender_armature_object


        ##########################
        # process pose bones
        enable_pose_mode(True, blender_context)

        blender_action = blender_context.blend_data.actions.new(ms3d_action_name)
        if blender_armature_object.animation_data is None:
            blender_armature_object.animation_data_create()
        blender_armature_object.animation_data.action = blender_action

        ##########################
        # transition between keys may be incorrect
        # because of the gimbal-lock problem!
        # http://www.youtube.com/watch?v=zc8b2Jo7mno
        # http://www.youtube.com/watch?v=rrUCBOlJdt4
        # you can fix it manually by selecting the affected keyframes
        # and allpy the following option to it:
        # "Graph Editor -> Key -> Discontinuity (Euler) Filter"
        # ==> "bpy.ops.graph.euler_filter()"
        # but this option is only available for Euler rotation f-curves!
        #
        for ms3d_joint_name, ms3d_joint in ms3d_joint_by_name.items():
            blender_pose_bone = blender_armature_object.pose.bones.get(
                    ms3d_joint.blender_bone_name)
            if blender_pose_bone is None:
                continue

            data_path = blender_pose_bone.path_from_id('location')
            fcurve_location_x = blender_action.fcurves.new(data_path, index=0)
            fcurve_location_y = blender_action.fcurves.new(data_path, index=1)
            fcurve_location_z = blender_action.fcurves.new(data_path, index=2)
            for translation_key_frames in ms3d_joint.translation_key_frames:
                frame = (translation_key_frames.time * ms3d_model.animation_fps)
                matrix_local = Matrix.Translation(
                        Vector(translation_key_frames.position))
                v = (matrix_local) * Vector()
                fcurve_location_x.keyframe_points.insert(frame, -v[0])
                fcurve_location_y.keyframe_points.insert(frame, v[2])
                fcurve_location_z.keyframe_points.insert(frame, v[1])

            if self.options_use_quaternion_rotation:
                blender_pose_bone.rotation_mode = 'QUATERNION'
                data_path = blender_pose_bone.path_from_id("rotation_quaternion")
                fcurve_rotation_w = blender_action.fcurves.new(data_path, index=0)
                fcurve_rotation_x = blender_action.fcurves.new(data_path, index=1)
                fcurve_rotation_y = blender_action.fcurves.new(data_path, index=2)
                fcurve_rotation_z = blender_action.fcurves.new(data_path, index=3)
                for rotation_key_frames in ms3d_joint.rotation_key_frames:
                    frame = (rotation_key_frames.time * ms3d_model.animation_fps)
                    matrix_local_rot = (
                            Matrix.Rotation(
                                    rotation_key_frames.rotation[2], 4, 'Y')
                            * Matrix.Rotation(
                                    rotation_key_frames.rotation[1], 4, 'Z')
                            ) * Matrix.Rotation(
                                    -rotation_key_frames.rotation[0], 4, 'X')
                    q = (matrix_local_rot).to_quaternion()
                    fcurve_rotation_w.keyframe_points.insert(frame, q.w)
                    fcurve_rotation_x.keyframe_points.insert(frame, q.x)
                    fcurve_rotation_y.keyframe_points.insert(frame, q.y)
                    fcurve_rotation_z.keyframe_points.insert(frame, q.z)
            else:
                blender_pose_bone.rotation_mode = 'XZY'
                data_path = blender_pose_bone.path_from_id("rotation_euler")
                fcurve_rotation_x = blender_action.fcurves.new(data_path, index=0)
                fcurve_rotation_y = blender_action.fcurves.new(data_path, index=1)
                fcurve_rotation_z = blender_action.fcurves.new(data_path, index=2)
                for rotation_key_frames in ms3d_joint.rotation_key_frames:
                    frame = (rotation_key_frames.time * ms3d_model.animation_fps)
                    fcurve_rotation_x.keyframe_points.insert(
                            frame, -rotation_key_frames.rotation[0])
                    fcurve_rotation_y.keyframe_points.insert(
                            frame, rotation_key_frames.rotation[2])
                    fcurve_rotation_z.keyframe_points.insert(
                            frame, rotation_key_frames.rotation[1])

        enable_pose_mode(False, blender_context)

        return blender_armature_object
Ejemplo n.º 6
0
    def create_geometry(self, blender_context, ms3d_model):
        ##########################
        # blender stuff:
        # create a blender Mesh
        blender_mesh = blender_context.blend_data.meshes.new(
                "{}.m".format(ms3d_model.name))
        blender_mesh.ms3d.name = ms3d_model.name

        ms3d_comment = ms3d_model.comment_object
        if ms3d_comment is not None:
            blender_mesh.ms3d.comment = ms3d_comment.comment
        ms3d_model_ex = ms3d_model.model_ex_object
        if ms3d_model_ex is not None:
            blender_mesh.ms3d.joint_size = ms3d_model_ex.joint_size
            blender_mesh.ms3d.alpha_ref = ms3d_model_ex.alpha_ref
            blender_mesh.ms3d.transparency_mode \
                    = Ms3dUi.transparency_mode_from_ms3d(
                            ms3d_model_ex.transparency_mode)

        ##########################
        # blender stuff:
        # link to blender object
        blender_mesh_object = blender_context.blend_data.objects.new(
                "{}.m".format(ms3d_model.name), blender_mesh)

        ##########################
        # blender stuff:
        # create edge split modifire, to make sharp edges visible
        blender_modifier = get_edge_split_modifier_add_if(blender_mesh_object)

        ##########################
        # blender stuff:
        # link to blender scene
        blender_scene = blender_context.scene
        blender_scene.objects.link(blender_mesh_object)
        #blender_mesh_object.location = blender_scene.cursor_location
        enable_edit_mode(False, blender_context)
        select_all(False)
        blender_mesh_object.select = True
        blender_scene.objects.active = blender_mesh_object

        ##########################
        # take this as active object after import
        self.active_object = blender_mesh_object

        ##########################
        # blender stuff:
        # create all (ms3d) groups
        ms3d_to_blender_group_index = {}
        blender_group_manager = blender_mesh.ms3d
        for ms3d_group_index, ms3d_group in enumerate(ms3d_model.groups):
            blender_group = blender_group_manager.create_group()
            blender_group.name = ms3d_group.name
            blender_group.flags = Ms3dUi.flags_from_ms3d(ms3d_group.flags)
            blender_group.material_index = ms3d_group.material_index

            ms3d_comment = ms3d_group.comment_object
            if ms3d_comment is not None:
                blender_group.comment = ms3d_comment.comment

            # translation dictionary
            ms3d_to_blender_group_index[ms3d_group_index] = blender_group.id

        ####################################################
        # begin BMesh stuff
        #

        ##########################
        # BMesh stuff:
        # create an empty BMesh
        bm = bmesh.new()

        ##########################
        # BMesh stuff:
        # create new Layers for custom data per "mesh face"
        layer_texture = bm.faces.layers.tex.get(
                ms3d_str['OBJECT_LAYER_TEXTURE'])
        if layer_texture is None:
            layer_texture = bm.faces.layers.tex.new(
                    ms3d_str['OBJECT_LAYER_TEXTURE'])

        layer_smoothing_group = bm.faces.layers.int.get(
                ms3d_str['OBJECT_LAYER_SMOOTHING_GROUP'])
        if layer_smoothing_group is None:
            layer_smoothing_group = bm.faces.layers.int.new(
                    ms3d_str['OBJECT_LAYER_SMOOTHING_GROUP'])

        layer_group = bm.faces.layers.int.get(
                ms3d_str['OBJECT_LAYER_GROUP'])
        if layer_group is None:
            layer_group = bm.faces.layers.int.new(
                    ms3d_str['OBJECT_LAYER_GROUP'])

        ##########################
        # BMesh stuff:
        # create new Layers for custom data per "face vertex"
        layer_uv = bm.loops.layers.uv.get(ms3d_str['OBJECT_LAYER_UV'])
        if layer_uv is None:
            layer_uv = bm.loops.layers.uv.new(ms3d_str['OBJECT_LAYER_UV'])

        ##########################
        # BMesh stuff:
        # create new Layers for custom data per "vertex"
        layer_extra = bm.verts.layers.int.get(ms3d_str['OBJECT_LAYER_EXTRA'])
        if layer_extra is None:
            layer_extra = bm.verts.layers.int.new(ms3d_str['OBJECT_LAYER_EXTRA'])

        ##########################
        # BMesh stuff:
        # create all vertices
        for ms3d_vertex_index, ms3d_vertex in enumerate(ms3d_model.vertices):
            bmv = bm.verts.new(self.geometry_correction(ms3d_vertex.vertex))

            if layer_extra and ms3d_vertex.vertex_ex_object and \
                    (isinstance(ms3d_vertex.vertex_ex_object, Ms3dVertexEx2) \
                    or isinstance(ms3d_vertex.vertex_ex_object, Ms3dVertexEx3)):

                #bmv[layer_extra] = ms3d_vertex.vertex_ex_object.extra
                # bm.verts.layers.int does only support signed int32
                # convert unsigned int32 to signed int32 (little-endian)
                unsigned_int32 = ms3d_vertex.vertex_ex_object.extra
                bytes_int32 = unsigned_int32.to_bytes(
                        4, byteorder='little', signed=False)
                signed_int32 = int.from_bytes(
                        bytes_int32, byteorder='little', signed=True)
                bmv[layer_extra] = signed_int32

        ##########################
        # blender stuff (uses BMesh stuff):
        # create all materials / image textures
        ms3d_to_blender_material = {}
        for ms3d_material_index, ms3d_material in enumerate(
                ms3d_model.materials):
            blender_material = blender_context.blend_data.materials.new(
                    ms3d_material.name)

            # custom datas
            blender_material.ms3d.name = ms3d_material.name
            blender_material.ms3d.ambient = ms3d_material.ambient
            blender_material.ms3d.diffuse = ms3d_material.diffuse
            blender_material.ms3d.specular = ms3d_material.specular
            blender_material.ms3d.emissive = ms3d_material.emissive
            blender_material.ms3d.shininess = ms3d_material.shininess
            blender_material.ms3d.transparency = ms3d_material.transparency
            blender_material.ms3d.mode = Ms3dUi.texture_mode_from_ms3d(
                    ms3d_material.mode)

            if ms3d_material.texture:
                blender_material.ms3d.texture = ms3d_material.texture

            if ms3d_material.alphamap:
                blender_material.ms3d.alphamap = ms3d_material.alphamap

            ms3d_comment = ms3d_material.comment_object
            if ms3d_comment is not None:
                blender_material.ms3d.comment = ms3d_comment.comment

            # blender datas
            blender_material.ambient = (
                    (ms3d_material.ambient[0]
                    + ms3d_material.ambient[1]
                    + ms3d_material.ambient[2]) / 3.0)

            blender_material.diffuse_color[0] = ms3d_material.diffuse[0]
            blender_material.diffuse_color[1] = ms3d_material.diffuse[1]
            blender_material.diffuse_color[2] = ms3d_material.diffuse[2]

            blender_material.specular_color[0] = ms3d_material.specular[0]
            blender_material.specular_color[1] = ms3d_material.specular[1]
            blender_material.specular_color[2] = ms3d_material.specular[2]

            blender_material.emit = (
                    (ms3d_material.emissive[0]
                    + ms3d_material.emissive[1]
                    + ms3d_material.emissive[2]) / 3.0)

            blender_material.specular_hardness = ms3d_material.shininess * 4.0
            blender_material.alpha = 1.0 - ms3d_material.transparency

            # diffuse texture
            if ms3d_material.texture:
                dir_name_diffuse = self.directory_name
                file_name_diffuse = path.split(ms3d_material.texture)[1]
                blender_image_diffuse = load_image(
                        file_name_diffuse, dir_name_diffuse)
                blender_texture_diffuse = \
                        blender_context.blend_data.textures.new(
                        name=file_name_diffuse, type='IMAGE')
                blender_texture_diffuse.image = blender_image_diffuse
                blender_texture_slot_diffuse \
                        = blender_material.texture_slots.add()
                blender_texture_slot_diffuse.texture = blender_texture_diffuse
                blender_texture_slot_diffuse.texture_coords = 'UV'
                blender_texture_slot_diffuse.uv_layer = layer_uv.name
                blender_texture_slot_diffuse.use_map_color_diffuse = True
                blender_texture_slot_diffuse.use_map_alpha = False
                if blender_image_diffuse is not None:
                    self.has_textures = True
            else:
                blender_image_diffuse = None

            # alpha texture
            if ms3d_material.alphamap:
                dir_name_alpha = self.directory_name
                file_name_alpha = path.split(ms3d_material.alphamap)[1]
                blender_image_alpha = load_image(
                        file_name_alpha, dir_name_alpha)
                blender_texture_alpha = blender_context.blend_data.textures.new(
                        name=file_name_alpha, type='IMAGE')
                blender_texture_alpha.image = blender_image_alpha
                blender_texture_slot_alpha \
                        = blender_material.texture_slots.add()
                blender_texture_slot_alpha.texture = blender_texture_alpha
                blender_texture_slot_alpha.texture_coords = 'UV'
                blender_texture_slot_alpha.uv_layer = layer_uv.name
                blender_texture_slot_alpha.use_map_color_diffuse = False
                blender_texture_slot_alpha.use_map_alpha = True
                blender_texture_slot_alpha.use_rgb_to_intensity = True
                blender_material.alpha = 0
                blender_material.specular_alpha = 0

            # append blender material to blender mesh, to be linked to
            blender_mesh.materials.append(blender_material)

            # translation dictionary
            ms3d_to_blender_material[ms3d_material_index] \
                    = blender_image_diffuse

        ##########################
        # BMesh stuff:
        # create all triangles
        length_verts = len(bm.verts)
        vertex_extra_index = length_verts
        blender_invalide_normal = Vector()
        smoothing_group_blender_faces = {}
        for ms3d_triangle_index, ms3d_triangle in enumerate(
                ms3d_model.triangles):
            bmv_list = []
            bmf_normal = Vector()

            for index, vert_index in enumerate(ms3d_triangle.vertex_indices):
                if vert_index < 0 or vert_index >= length_verts:
                    continue
                bmv = bm.verts[vert_index]

                blender_normal = self.geometry_correction(
                        ms3d_triangle.vertex_normals[index])
                if bmv.normal == blender_invalide_normal:
                    bmv.normal = blender_normal
                elif bmv.normal != blender_normal \
                        and self.options_use_extended_normal_handling:
                    ## search for an already created extra vertex
                    bmv_new = None
                    for vert_index_candidat in range(
                            vertex_extra_index, length_verts):
                        bmv_candidat = bm.verts[vert_index_candidat]
                        if bmv_candidat.co == bmv.co \
                                and bmv_candidat.normal == blender_normal:
                            bmv_new = bmv_candidat
                            vert_index = vert_index_candidat
                            break

                    ## if not exists, create one in blender and ms3d as well
                    if bmv_new is None:
                        ms3d_model.vertices.append(
                                ms3d_model.vertices[vert_index])
                        bmv_new = bm.verts.new(bmv.co)
                        bmv_new.normal = blender_normal
                        bmv_new[layer_extra] = bmv[layer_extra]
                        vert_index = length_verts
                        length_verts += 1
                        if self.report and self.options_verbose in Ms3dUi.VERBOSE_NORMAL:
                            self.report({'WARNING', 'INFO'},
                                    ms3d_str['WARNING_IMPORT_EXTRA_VERTEX_NORMAL'].format(
                                    bmv.normal, blender_normal))
                    bmv = bmv_new

                if [[x] for x in bmv_list if x == bmv]:
                    if self.report and self.options_verbose in Ms3dUi.VERBOSE_NORMAL:
                        self.report(
                                {'WARNING', 'INFO'},
                                ms3d_str['WARNING_IMPORT_SKIP_VERTEX_DOUBLE'].format(
                                        ms3d_triangle_index))
                    continue
                bmv_list.append(bmv)
                bmf_normal += bmv.normal

            if len(bmv_list) < 3:
                if self.report and self.options_verbose in Ms3dUi.VERBOSE_NORMAL:
                    self.report(
                            {'WARNING', 'INFO'},
                            ms3d_str['WARNING_IMPORT_SKIP_LESS_VERTICES'].format(
                                    ms3d_triangle_index))
                continue

            bmf_normal.normalize()

            bmf = bm.faces.get(bmv_list)
            if bmf is not None:
                if self.report and self.options_verbose in Ms3dUi.VERBOSE_NORMAL:
                    self.report(
                            {'WARNING', 'INFO'},
                            ms3d_str['WARNING_IMPORT_SKIP_FACE_DOUBLE'].format(
                                    ms3d_triangle_index))
                continue

            bmf = bm.faces.new(bmv_list)
            bmf.normal = bmf_normal

            # blender uv custom data per "face vertex"
            bmf.loops[0][layer_uv].uv = Vector(
                    (ms3d_triangle.s[0], 1.0 - ms3d_triangle.t[0]))
            bmf.loops[1][layer_uv].uv = Vector(
                    (ms3d_triangle.s[1], 1.0 - ms3d_triangle.t[1]))
            bmf.loops[2][layer_uv].uv = Vector(
                    (ms3d_triangle.s[2], 1.0 - ms3d_triangle.t[2]))

            # ms3d custom data per "mesh face"
            bmf[layer_smoothing_group] = ms3d_triangle.smoothing_group

            blender_group_id = ms3d_to_blender_group_index.get(
                    ms3d_triangle.group_index)
            if blender_group_id is not None:
                bmf[layer_group] = blender_group_id

            if ms3d_triangle.group_index >= 0 \
                    and ms3d_triangle.group_index < len(ms3d_model.groups):
                ms3d_material_index \
                        = ms3d_model.groups[ms3d_triangle.group_index].material_index
                if ms3d_material_index != Ms3dSpec.NONE_GROUP_MATERIAL_INDEX:
                    bmf.material_index = ms3d_material_index
                    # apply diffuse texture image to face, to be visible in 3d view
                    bmf[layer_texture].image = ms3d_to_blender_material.get(
                            ms3d_material_index)

            # helper dictionary for post-processing smoothing_groups
            smoothing_group_blender_face = smoothing_group_blender_faces.get(
                    ms3d_triangle.smoothing_group)
            if smoothing_group_blender_face is None:
                smoothing_group_blender_face = []
                smoothing_group_blender_faces[ms3d_triangle.smoothing_group] \
                        = smoothing_group_blender_face
            smoothing_group_blender_face.append(bmf)

        ##########################
        # BMesh stuff:
        # create all sharp edges for blender to make smoothing_groups visible
        for ms3d_smoothing_group_index, blender_face_list \
                in smoothing_group_blender_faces.items():
            edge_dict = {}
            for bmf in blender_face_list:
                bmf.smooth = True
                for bme in bmf.edges:
                    if edge_dict.get(bme) is None:
                        edge_dict[bme] = 0
                    else:
                        edge_dict[bme] += 1
                    bme.seam = (edge_dict[bme] == 0)
                    bme.smooth = (edge_dict[bme] != 0)

        ##########################
        # BMesh stuff:
        # finally tranfer BMesh to Mesh
        bm.to_mesh(blender_mesh)
        bm.free()


        #
        # end BMesh stuff
        ####################################################

        blender_mesh.validate(self.options_verbose in Ms3dUi.VERBOSE_MAXIMAL)

        return blender_mesh_object
Ejemplo n.º 7
0
    def create_animation(self, blender_context, ms3d_model,
                         blender_mesh_objects, blender_to_ms3d_bones):
        ##########################
        # setup scene
        blender_scene = blender_context.scene

        if not self.options_use_animation:
            ms3d_model.animation_fps = 24
            ms3d_model.number_total_frames = 1
            ms3d_model.current_time = 0
            return

        frame_start = blender_scene.frame_start
        frame_end = blender_scene.frame_end
        frame_total = (frame_end - frame_start) + 1
        frame_step = blender_scene.frame_step
        frame_offset = 0

        fps = blender_scene.render.fps * blender_scene.render.fps_base
        time_base = 1.0 / fps

        base_bone_correction = Matrix.Rotation(pi / 2, 4, 'Z')

        for blender_mesh_object in blender_mesh_objects:
            blender_bones = None
            blender_action = None
            blender_nla_tracks = None

            # note: only one armature modifier/parent will be handled.
            #   if the parent is an armature, it will be handled irrespective
            #   of existence of any armature modifier

            # question: maybe it is better to handle
            #   all existing armature sources (parent / modifier)
            #   as a merged animation...
            #   what is best practice in case of multiple animation sources?

            # take parent to account if it is an armature
            if blender_mesh_object.parent and \
                    blender_mesh_object.parent_type == 'ARMATURE' and \
                    blender_mesh_object.parent.pose:
                blender_bones = blender_mesh_object.parent.data.bones
                blender_pose_bones = blender_mesh_object.parent.pose.bones
                if blender_mesh_object.parent.animation_data:
                    blender_action = \
                            blender_mesh_object.parent.animation_data.action
                    blender_nla_tracks = \
                            blender_mesh_object.parent.animation_data.nla_tracks

                # apply transform
                if self.options_apply_transform:
                    matrix_transform = blender_mesh_object.parent.matrix_basis
                else:
                    matrix_transform = 1

            # search for animation modifier
            else:
                for blender_modifier in blender_mesh_object.modifiers:
                    if blender_modifier.type == 'ARMATURE' \
                            and blender_modifier.object.pose:
                        blender_bones = blender_modifier.object.data.bones
                        blender_pose_bones = blender_modifier.object.pose.bones
                        if blender_modifier.object.animation_data:
                            blender_action = \
                                    blender_modifier.object.animation_data.action
                            blender_nla_tracks = \
                                    blender_modifier.object.animation_data.nla_tracks

                        # apply transform
                        if self.options_apply_transform:
                            matrix_transform = blender_modifier.object.matrix_basis
                        else:
                            matrix_transform = 1

                        break

            # skip animation/bone handling, if no animation data is available
            if blender_bones is None \
                    and (blender_action is None and blender_nla_tracks is None):
                continue

            ##########################
            # bones
            blender_bones_ordered = []
            self.build_blender_bone_dependency_order(blender_bones,
                                                     blender_bones_ordered)
            for blender_bone_name in blender_bones_ordered:
                blender_bone_oject = blender_bones[blender_bone_name]
                ms3d_joint = Ms3dJoint()
                ms3d_joint.__index = len(ms3d_model._joints)

                blender_bone_ms3d = blender_bone_oject.ms3d
                blender_bone = blender_bone_oject

                ms3d_joint.flags = Ms3dUi.flags_to_ms3d(
                    blender_bone_ms3d.flags)
                if blender_bone_ms3d.comment:
                    ms3d_joint._comment_object = Ms3dCommentEx()
                    ms3d_joint._comment_object.comment = \
                            blender_bone_ms3d.comment
                    ms3d_joint._comment_object.index = ms3d_joint.__index

                ms3d_joint.joint_ex_object._color = blender_bone_ms3d.color[:]

                ms3d_joint.name = blender_bone.name

                if blender_bone.parent:
                    ms3d_joint.parent_name = blender_bone.parent.name
                    ms3d_joint.__matrix = matrix_difference(
                        matrix_transform * blender_bone.matrix_local,
                        matrix_transform * blender_bone.parent.matrix_local)
                else:
                    ms3d_joint.__matrix = base_bone_correction \
                            * matrix_transform * blender_bone.matrix_local

                mat = ms3d_joint.__matrix
                loc = mat.to_translation()
                rot = mat.to_euler('XZY')
                ms3d_joint._position = self.joint_correction(loc)
                ms3d_joint._rotation = self.joint_correction(rot)

                ms3d_model._joints.append(ms3d_joint)
                blender_to_ms3d_bones[blender_bone.name] = ms3d_joint

            ##########################
            # animation
            frames = None
            frames_location = set()
            frames_rotation = set()
            frames_scale = set()

            if blender_action:
                self.fill_keyframe_sets(blender_action.fcurves,
                                        frames_location, frames_rotation,
                                        frames_scale, 0)

            if blender_nla_tracks:
                for nla_track in blender_nla_tracks:
                    if nla_track.mute:
                        continue
                    for strip in nla_track.strips:
                        if strip.mute:
                            continue
                        frame_correction = strip.frame_start \
                                - strip.action_frame_start
                        self.fill_keyframe_sets(strip.action.fcurves,
                                                frames_location,
                                                frames_rotation, frames_scale,
                                                frame_correction)

            frames = set(frames_location)
            frames = frames.union(frames_rotation)
            frames = frames.union(frames_scale)

            if not self.options_shrink_to_keys:
                frames = frames.intersection(
                    range(blender_scene.frame_start,
                          blender_scene.frame_end + 1))

            frames_sorted = list(frames)
            frames_sorted.sort()

            if self.options_shrink_to_keys and len(frames_sorted) >= 2:
                frame_start = frames_sorted[0]
                frame_end = frames_sorted[len(frames_sorted) - 1]
                frame_total = (frame_end - frame_start) + 1
                frame_offset = frame_start - 1

            if self.options_bake_each_frame:
                frames_sorted = range(int(frame_start), int(frame_end + 1),
                                      int(frame_step))

            frame_temp = blender_scene.frame_current

            for current_frame in frames_sorted:
                blender_scene.frame_set(current_frame)

                current_time = (current_frame - frame_offset) * time_base
                for blender_bone_name in blender_bones_ordered:
                    blender_bone = blender_bones[blender_bone_name]
                    blender_pose_bone = blender_pose_bones[blender_bone_name]
                    ms3d_joint = blender_to_ms3d_bones[blender_bone_name]

                    m1 = blender_bone.matrix_local.inverted()
                    if blender_pose_bone.parent:
                        m2 = blender_pose_bone.parent.matrix_channel.inverted()
                    else:
                        m2 = 1
                    m3 = blender_pose_bone.matrix.copy()
                    m = ((m1 * m2) * m3)
                    loc = m.to_translation()
                    rot = m.to_euler('XZY')

                    ms3d_joint.translation_key_frames.append(
                        Ms3dTranslationKeyframe(current_time,
                                                self.joint_correction(loc)))
                    ms3d_joint.rotation_key_frames.append(
                        Ms3dRotationKeyframe(current_time,
                                             self.joint_correction(rot)))

            blender_scene.frame_set(frame_temp)

        ms3d_model.animation_fps = fps
        if ms3d_model.number_joints > 0:
            ms3d_model.number_total_frames = int(frame_total)
            ms3d_model.current_time = ((blender_scene.frame_current \
                    - blender_scene.frame_start) + 1) * time_base
        else:
            ms3d_model.number_total_frames = 1
            ms3d_model.current_time = 0
Ejemplo n.º 8
0
    def create_geometry(self, blender_context, ms3d_model,
                        blender_mesh_objects, blender_to_ms3d_bones):
        blender_scene = blender_context.scene

        blender_to_ms3d_vertices = {}
        blender_to_ms3d_triangles = {}
        blender_to_ms3d_groups = {}
        blender_to_ms3d_materials = {}

        for blender_mesh_object in blender_mesh_objects:
            blender_mesh = blender_mesh_object.data

            ms3d_model._model_ex_object.joint_size = \
                    blender_mesh.ms3d.joint_size
            ms3d_model._model_ex_object.alpha_ref = blender_mesh.ms3d.alpha_ref
            ms3d_model._model_ex_object.transparency_mode = \
                    Ms3dUi.transparency_mode_to_ms3d(
                    blender_mesh.ms3d.transparency_mode)

            if blender_mesh.ms3d.comment:
                ms3d_model._comment_object = Ms3dComment(
                    blender_mesh.ms3d.comment)

            ##########################
            # prepare ms3d groups if available
            # works only for exporting active object
            ##EXPORT_ACTIVE_ONLY:
            for ms3d_local_group_index, blender_ms3d_group in enumerate(
                    blender_mesh.ms3d.groups):
                ms3d_group = Ms3dGroup()
                ms3d_group.__index = len(ms3d_model._groups)
                ms3d_group.name = blender_ms3d_group.name
                ms3d_group.flags = Ms3dUi.flags_to_ms3d(
                    blender_ms3d_group.flags)
                if blender_ms3d_group.comment:
                    ms3d_group._comment_object = Ms3dCommentEx()
                    ms3d_group._comment_object.comment = \
                            blender_ms3d_group.comment
                    ms3d_group._comment_object.index = len(ms3d_model._groups)
                ms3d_group.material_index = None  # to mark as not set
                ms3d_model._groups.append(ms3d_group)
                blender_to_ms3d_groups[blender_ms3d_group.id] = ms3d_group

            ##########################
            # i have to use BMesh, because there are several custom data stored.
            # BMesh doesn't support quads_convert_to_tris()
            # so, i use that very ugly way:
            # create a complete copy of mesh and bend object data
            # to be able to apply operations to it.

            # temporary, create a full heavy copy of the model
            # (object, mesh, modifiers)
            blender_mesh_temp = blender_mesh_object.data.copy()
            blender_mesh_object_temp = blender_mesh_object.copy()
            blender_mesh_object_temp.data = blender_mesh_temp
            blender_scene.objects.link(blender_mesh_object_temp)
            blender_scene.objects.active = blender_mesh_object_temp

            # apply transform
            if self.options_apply_transform:
                matrix_transform = blender_mesh_object_temp.matrix_basis
            else:
                matrix_transform = 1

            # apply modifiers
            for modifier in blender_mesh_object_temp.modifiers:
                if self.options_apply_modifiers:
                    # disable only armature modifiers and only,
                    # when use_animation is enabled
                    if  self.options_use_animation \
                            and modifier.type in {'ARMATURE', }:
                        modifier.show_viewport = False
                        modifier.show_render = False
                else:
                    # disable all modifiers,
                    # to be able to add and apply triangulate modifier later
                    modifier.show_viewport = False
                    modifier.show_render = False

            # convert to tris by using the triangulate modifier
            blender_mesh_object_temp.modifiers.new("temp", 'TRIANGULATE')
            blender_mesh_temp = blender_mesh_object_temp.to_mesh(
                blender_scene, True, self.options_apply_modifiers_mode)

            enable_edit_mode(True, blender_context)
            bm = bmesh.new()
            bm.from_mesh(blender_mesh_temp)

            layer_texture = bm.faces.layers.tex.get(
                ms3d_str['OBJECT_LAYER_TEXTURE'])
            if layer_texture is None:
                layer_texture = bm.faces.layers.tex.new(
                    ms3d_str['OBJECT_LAYER_TEXTURE'])

            layer_smoothing_group = bm.faces.layers.int.get(
                ms3d_str['OBJECT_LAYER_SMOOTHING_GROUP'])
            if layer_smoothing_group is None:
                layer_smoothing_group = bm.faces.layers.int.new(
                    ms3d_str['OBJECT_LAYER_SMOOTHING_GROUP'])

            layer_group = bm.faces.layers.int.get(
                ms3d_str['OBJECT_LAYER_GROUP'])
            if layer_group is None:
                layer_group = bm.faces.layers.int.new(
                    ms3d_str['OBJECT_LAYER_GROUP'])

            layer_uv = bm.loops.layers.uv.get(ms3d_str['OBJECT_LAYER_UV'])
            if layer_uv is None:
                if bm.loops.layers.uv:
                    layer_uv = bm.loops.layers.uv[0]
                else:
                    layer_uv = bm.loops.layers.uv.new(
                        ms3d_str['OBJECT_LAYER_UV'])

            layer_deform = bm.verts.layers.deform.active

            layer_extra = bm.verts.layers.int.get(
                ms3d_str['OBJECT_LAYER_EXTRA'])
            if layer_extra is None:
                layer_extra = bm.verts.layers.int.new(
                    ms3d_str['OBJECT_LAYER_EXTRA'])

            ##########################
            # handle vertices
            for bmv in bm.verts:
                item = blender_to_ms3d_vertices.get(bmv)
                if item is None:
                    index = len(ms3d_model._vertices)
                    ms3d_vertex = Ms3dVertex()
                    ms3d_vertex.__index = index

                    ms3d_vertex._vertex = self.geometry_correction(
                        matrix_transform * bmv.co)

                    if self.options_use_animation and layer_deform:
                        blender_vertex_group_ids = bmv[layer_deform]
                        if blender_vertex_group_ids:
                            bone_weights = {}
                            for blender_index, blender_weight \
                                    in blender_vertex_group_ids.items():
                                ms3d_joint = blender_to_ms3d_bones.get(
                                        blender_mesh_object_temp.vertex_groups[\
                                                blender_index].name)
                                if ms3d_joint:
                                    weight = bone_weights.get(
                                        ms3d_joint.__index)
                                    if not weight:
                                        weight = 0
                                    bone_weights[
                                        ms3d_joint.
                                        __index] = weight + blender_weight

                            # sort (bone_id: weight) according its weights
                            # to skip only less important weights in the next pass
                            bone_weights_sorted = sorted(
                                bone_weights.items(),
                                key=lambda item: item[1],
                                reverse=True)

                            count = 0
                            bone_ids = []
                            weights = []
                            for ms3d_index, blender_weight \
                                    in bone_weights_sorted:

                                if count == 0:
                                    ms3d_vertex.bone_id = ms3d_index
                                    weights.append(blender_weight)
                                elif count == 1:
                                    bone_ids.append(ms3d_index)
                                    weights.append(blender_weight)
                                elif count == 2:
                                    bone_ids.append(ms3d_index)
                                    weights.append(blender_weight)
                                elif count == 3:
                                    bone_ids.append(ms3d_index)
                                    if self.report and self.options_verbose in Ms3dUi.VERBOSE_NORMAL:
                                        self.report(
                                            {'WARNING', 'INFO'}, ms3d_str[
                                                'WARNING_EXPORT_SKIP_WEIGHT'])
                                else:
                                    # only first three weights will be supported / four bones
                                    if self.report and self.options_verbose in Ms3dUi.VERBOSE_NORMAL:
                                        self.report({
                                            'WARNING', 'INFO'
                                        }, ms3d_str[
                                            'WARNING_EXPORT_SKIP_WEIGHT_EX'])
                                    break
                                count += 1

                            # normalize weights to 100%
                            if self.options_normalize_weights:
                                weight_sum = 0.0
                                for weight in weights:
                                    weight_sum += weight

                                if weight_sum > 0.0:
                                    weight_normalize = 1.0 / weight_sum
                                else:
                                    weight_normalize = 1.0

                                weight_sum = 100
                                for index, weight in enumerate(weights):
                                    if index >= count - 1 or index >= 2:
                                        # take the full rest instead of calculate,
                                        # that should fill up to exactly 100%
                                        # (in some cases it is only 99% bacaus of roulding errors)
                                        weights[index] = int(weight_sum)
                                        break
                                    normalized_weight = int(
                                        weight * weight_normalize * 100)
                                    weights[index] = normalized_weight
                                    weight_sum -= normalized_weight

                            # fill up missing values
                            while len(bone_ids) < 3:
                                bone_ids.append(
                                    Ms3dSpec.DEFAULT_VERTEX_BONE_ID)
                            while len(weights) < 3:
                                weights.append(0)

                            ms3d_vertex._vertex_ex_object._bone_ids = \
                                    tuple(bone_ids)
                            ms3d_vertex._vertex_ex_object._weights = \
                                    tuple(weights)

                    if layer_extra:
                        #ms3d_vertex._vertex_ex_object.extra = bmv[layer_extra]
                        # bm.verts.layers.int does only support signed int32
                        # convert signed int32 to unsigned int32 (little-endian)
                        signed_int32 = bmv[layer_extra]
                        bytes_int32 = signed_int32.to_bytes(4,
                                                            byteorder='little',
                                                            signed=True)
                        unsigned_int32 = int.from_bytes(bytes_int32,
                                                        byteorder='little',
                                                        signed=False)
                        ms3d_vertex._vertex_ex_object.extra = unsigned_int32

                    ms3d_model._vertices.append(ms3d_vertex)
                    blender_to_ms3d_vertices[bmv] = ms3d_vertex

            ##########################
            # handle faces / tris
            for bmf in bm.faces:
                item = blender_to_ms3d_triangles.get(bmf)
                if item is None:
                    index = len(ms3d_model._triangles)
                    ms3d_triangle = Ms3dTriangle()
                    ms3d_triangle.__index = index
                    bmv0 = bmf.verts[0]
                    bmv1 = bmf.verts[1]
                    bmv2 = bmf.verts[2]
                    ms3d_vertex0 = blender_to_ms3d_vertices[bmv0]
                    ms3d_vertex1 = blender_to_ms3d_vertices[bmv1]
                    ms3d_vertex2 = blender_to_ms3d_vertices[bmv2]
                    ms3d_vertex0.reference_count += 1
                    ms3d_vertex1.reference_count += 1
                    ms3d_vertex2.reference_count += 1
                    ms3d_triangle._vertex_indices = (
                        ms3d_vertex0.__index,
                        ms3d_vertex1.__index,
                        ms3d_vertex2.__index,
                    )
                    ms3d_triangle._vertex_normals = (
                        self.geometry_correction(bmv0.normal),
                        self.geometry_correction(bmv1.normal),
                        self.geometry_correction(bmv2.normal),
                    )
                    ms3d_triangle._s = (
                        bmf.loops[0][layer_uv].uv.x,
                        bmf.loops[1][layer_uv].uv.x,
                        bmf.loops[2][layer_uv].uv.x,
                    )
                    ms3d_triangle._t = (
                        1.0 - bmf.loops[0][layer_uv].uv.y,
                        1.0 - bmf.loops[1][layer_uv].uv.y,
                        1.0 - bmf.loops[2][layer_uv].uv.y,
                    )

                    ms3d_triangle.smoothing_group = bmf[layer_smoothing_group]
                    ms3d_model._triangles.append(ms3d_triangle)

                    ms3d_material = self.get_ms3d_material_add_if(
                        blender_mesh, ms3d_model, blender_to_ms3d_materials,
                        bmf.material_index)
                    ms3d_group = blender_to_ms3d_groups.get(bmf[layer_group])

                    ##EXPORT_ACTIVE_ONLY:
                    if ms3d_group is not None:
                        if ms3d_material is None:
                            ms3d_group.material_index = \
                                    Ms3dSpec.DEFAULT_GROUP_MATERIAL_INDEX
                        else:
                            if ms3d_group.material_index is None:
                                ms3d_group.material_index = \
                                        ms3d_material.__index
                            else:
                                if ms3d_group.material_index != \
                                        ms3d_material.__index:
                                    ms3d_group = \
                                            self.get_ms3d_group_by_material_add_if(
                                            ms3d_model, ms3d_material)
                    else:
                        if ms3d_material is not None:
                            ms3d_group = self.get_ms3d_group_by_material_add_if(
                                ms3d_model, ms3d_material)
                        else:
                            ms3d_group = self.get_ms3d_group_default_material_add_if(
                                ms3d_model)

                    if ms3d_group is not None:
                        ms3d_group._triangle_indices.append(
                            ms3d_triangle.__index)
                        ms3d_triangle.group_index = ms3d_group.__index

                    blender_to_ms3d_triangles[bmf] = ms3d_triangle

            if bm is not None:
                bm.free()

            enable_edit_mode(False, blender_context)

            ##########################
            # remove the temporary data
            blender_scene.objects.unlink(blender_mesh_object_temp)
            if blender_mesh_temp is not None:
                blender_mesh_temp.user_clear()
                blender_context.blend_data.meshes.remove(blender_mesh_temp)
            blender_mesh_temp = None
            if blender_mesh_object_temp is not None:
                blender_mesh_temp = blender_mesh_object_temp.data.user_clear()
                blender_mesh_object_temp.user_clear()
                blender_context.blend_data.objects.remove(
                    blender_mesh_object_temp)
            if blender_mesh_temp is not None:
                blender_mesh_temp.user_clear()
                blender_context.blend_data.meshes.remove(blender_mesh_temp)
Ejemplo n.º 9
0
    def create_animation(self, blender_context, ms3d_model,
            blender_mesh_objects, blender_to_ms3d_bones):
        ##########################
        # setup scene
        blender_scene = blender_context.scene

        if not self.options_use_animation:
            ms3d_model.animation_fps = 24
            ms3d_model.number_total_frames = 1
            ms3d_model.current_time = 0
            return

        frame_start = blender_scene.frame_start
        frame_end = blender_scene.frame_end
        frame_total = (frame_end - frame_start) + 1
        frame_step = blender_scene.frame_step
        frame_offset = 0

        fps = blender_scene.render.fps * blender_scene.render.fps_base
        time_base = 1.0 / fps

        base_bone_correction = Matrix.Rotation(pi / 2, 4, 'Z')

        for blender_mesh_object in blender_mesh_objects:
            blender_bones = None
            blender_action = None
            blender_nla_tracks = None
            for blender_modifier in blender_mesh_object.modifiers:
                if blender_modifier.type == 'ARMATURE' \
                        and blender_modifier.object.pose:
                    blender_bones = blender_modifier.object.data.bones
                    blender_pose_bones = blender_modifier.object.pose.bones
                    if blender_modifier.object.animation_data:
                        blender_action = \
                                blender_modifier.object.animation_data.action
                        blender_nla_tracks = \
                                blender_modifier.object.animation_data.nla_tracks

                    # apply transform
                    if self.options_apply_transform:
                        matrix_transform = blender_modifier.object.matrix_basis
                    else:
                        matrix_transform = 1

                    break

            if blender_bones is None \
                    and (blender_action is None and blender_nla_tracks is None):
                continue

            ##########################
            # bones
            blender_bones_ordered = []
            self.build_blender_bone_dependency_order(
                    blender_bones, blender_bones_ordered)
            for blender_bone_name in blender_bones_ordered:
                blender_bone_oject = blender_bones[blender_bone_name]
                ms3d_joint = Ms3dJoint()
                ms3d_joint.__index = len(ms3d_model._joints)

                blender_bone_ms3d = blender_bone_oject.ms3d
                blender_bone = blender_bone_oject

                ms3d_joint.flags = Ms3dUi.flags_to_ms3d(blender_bone_ms3d.flags)
                if blender_bone_ms3d.comment:
                    ms3d_joint._comment_object = Ms3dCommentEx()
                    ms3d_joint._comment_object.comment = \
                            blender_bone_ms3d.comment
                    ms3d_joint._comment_object.index = ms3d_joint.__index

                ms3d_joint.joint_ex_object._color = blender_bone_ms3d.color[:]

                ms3d_joint.name = blender_bone.name

                if blender_bone.parent:
                    ms3d_joint.parent_name = blender_bone.parent.name
                    ms3d_joint.__matrix = matrix_difference(
                            matrix_transform * blender_bone.matrix_local,
                            matrix_transform * blender_bone.parent.matrix_local)
                else:
                    ms3d_joint.__matrix = base_bone_correction \
                            * matrix_transform * blender_bone.matrix_local

                mat = ms3d_joint.__matrix
                loc = mat.to_translation()
                rot = mat.to_euler('XZY')
                ms3d_joint._position = self.joint_correction(loc)
                ms3d_joint._rotation = self.joint_correction(rot)

                ms3d_model._joints.append(ms3d_joint)
                blender_to_ms3d_bones[blender_bone.name] = ms3d_joint

            ##########################
            # animation
            frames = None
            frames_location = set()
            frames_rotation = set()
            frames_scale = set()

            if blender_action:
                self.fill_keyframe_sets(
                        blender_action.fcurves,
                        frames_location, frames_rotation, frames_scale,
                        0)

            if blender_nla_tracks:
                for nla_track in blender_nla_tracks:
                    if nla_track.mute:
                        continue
                    for strip in nla_track.strips:
                        if strip.mute:
                            continue
                        frame_correction = strip.frame_start \
                                - strip.action_frame_start
                        self.fill_keyframe_sets(
                                strip.action.fcurves,
                                frames_location, frames_rotation, frames_scale,
                                frame_correction)

            frames = set(frames_location)
            frames = frames.union(frames_rotation)
            frames = frames.union(frames_scale)

            if not self.options_shrink_to_keys:
                frames = frames.intersection(range(
                        blender_scene.frame_start, blender_scene.frame_end + 1))

            frames_sorted = list(frames)
            frames_sorted.sort()

            if self.options_shrink_to_keys and len(frames_sorted) >= 2:
                frame_start = frames_sorted[0]
                frame_end = frames_sorted[len(frames_sorted)-1]
                frame_total = (frame_end - frame_start) + 1
                frame_offset = frame_start - 1

            if self.options_bake_each_frame:
                frames_sorted = range(int(frame_start), int(frame_end + 1),
                        int(frame_step))

            frame_temp = blender_scene.frame_current

            for current_frame in frames_sorted:
                blender_scene.frame_set(current_frame)

                current_time = (current_frame - frame_offset) * time_base
                for blender_bone_name in blender_bones_ordered:
                    blender_bone = blender_bones[blender_bone_name]
                    blender_pose_bone = blender_pose_bones[blender_bone_name]
                    ms3d_joint = blender_to_ms3d_bones[blender_bone_name]

                    m1 = blender_bone.matrix_local.inverted()
                    if blender_pose_bone.parent:
                        m2 = blender_pose_bone.parent.matrix_channel.inverted()
                    else:
                        m2 = 1
                    m3 = blender_pose_bone.matrix.copy()
                    m = ((m1 * m2) * m3)
                    loc = m.to_translation()
                    rot = m.to_euler('XZY')

                    ms3d_joint.translation_key_frames.append(
                            Ms3dTranslationKeyframe(
                                    current_time, self.joint_correction(loc)
                                    )
                            )
                    ms3d_joint.rotation_key_frames.append(
                            Ms3dRotationKeyframe(
                                    current_time, self.joint_correction(rot)
                                    )
                            )

            blender_scene.frame_set(frame_temp)

        ms3d_model.animation_fps = fps
        if ms3d_model.number_joints > 0:
            ms3d_model.number_total_frames = int(frame_total)
            ms3d_model.current_time = ((blender_scene.frame_current \
                    - blender_scene.frame_start) + 1) * time_base
        else:
            ms3d_model.number_total_frames = 1
            ms3d_model.current_time = 0
Ejemplo n.º 10
0
    def create_geometry(self, blender_context, ms3d_model, blender_mesh_objects, blender_to_ms3d_bones):
        blender_scene = blender_context.scene

        blender_to_ms3d_vertices = {}
        blender_to_ms3d_triangles = {}
        blender_to_ms3d_groups = {}
        blender_to_ms3d_materials = {}

        for blender_mesh_object in blender_mesh_objects:
            blender_mesh = blender_mesh_object.data

            ms3d_model._model_ex_object.joint_size = \
                    blender_mesh.ms3d.joint_size
            ms3d_model._model_ex_object.alpha_ref = blender_mesh.ms3d.alpha_ref
            ms3d_model._model_ex_object.transparency_mode = \
                    Ms3dUi.transparency_mode_to_ms3d(
                    blender_mesh.ms3d.transparency_mode)

            if blender_mesh.ms3d.comment:
                ms3d_model._comment_object = Ms3dComment(blender_mesh.ms3d.comment)

            ##########################
            # prepare ms3d groups if available
            # works only for exporting active object
            ##EXPORT_ACTIVE_ONLY:
            for ms3d_local_group_index, blender_ms3d_group in enumerate(
                    blender_mesh.ms3d.groups):
                ms3d_group = Ms3dGroup()
                ms3d_group.__index = len(ms3d_model._groups)
                ms3d_group.name = blender_ms3d_group.name
                ms3d_group.flags = Ms3dUi.flags_to_ms3d(blender_ms3d_group.flags)
                if blender_ms3d_group.comment:
                    ms3d_group._comment_object = Ms3dCommentEx()
                    ms3d_group._comment_object.comment = \
                            blender_ms3d_group.comment
                    ms3d_group._comment_object.index = len(ms3d_model._groups)
                ms3d_group.material_index = None # to mark as not setted
                ms3d_model._groups.append(ms3d_group)
                blender_to_ms3d_groups[blender_ms3d_group.id] = ms3d_group

            ##########################
            # i have to use BMesh, because there are several custom data stored.
            # BMesh doesn't support quads_convert_to_tris()
            # so, i use that very ugly way:
            # create a complete copy of mesh and bend object data
            # to be able to apply operations to it.

            # temporary, create a full heavy copy of the model
            # (object, mesh, modifiers)
            blender_mesh_temp = blender_mesh_object.data.copy()
            blender_mesh_object_temp = blender_mesh_object.copy()
            blender_mesh_object_temp.data = blender_mesh_temp
            blender_scene.objects.link(blender_mesh_object_temp)
            blender_scene.objects.active = blender_mesh_object_temp

            # apply transform
            if self.options_apply_transform:
                matrix_transform = blender_mesh_object_temp.matrix_basis
            else:
                matrix_transform = 1

            # apply modifiers
            for modifier in blender_mesh_object_temp.modifiers:
                if self.options_apply_modifiers:
                    # disable only armature modifiers and only,
                    # when use_animation is enabled
                    if  self.options_use_animation \
                            and modifier.type in {'ARMATURE', }:
                        modifier.show_viewport = False
                        modifier.show_render = False
                else:
                    # disable all modifiers,
                    # to be able to add and apply triangulate modifier later
                    modifier.show_viewport = False
                    modifier.show_render = False

            # convert to tris by using the triangulate modifier
            blender_mesh_object_temp.modifiers.new("temp", 'TRIANGULATE')
            blender_mesh_temp = blender_mesh_object_temp.to_mesh(
                    blender_scene,
                    True,
                    self.options_apply_modifiers_mode)

            enable_edit_mode(True, blender_context)
            bm = bmesh.new()
            bm.from_mesh(blender_mesh_temp)

            layer_texture = bm.faces.layers.tex.get(
                    ms3d_str['OBJECT_LAYER_TEXTURE'])
            if layer_texture is None:
                layer_texture = bm.faces.layers.tex.new(
                        ms3d_str['OBJECT_LAYER_TEXTURE'])

            layer_smoothing_group = bm.faces.layers.int.get(
                    ms3d_str['OBJECT_LAYER_SMOOTHING_GROUP'])
            if layer_smoothing_group is None:
                layer_smoothing_group = bm.faces.layers.int.new(
                        ms3d_str['OBJECT_LAYER_SMOOTHING_GROUP'])

            layer_group = bm.faces.layers.int.get(
                    ms3d_str['OBJECT_LAYER_GROUP'])
            if layer_group is None:
                layer_group = bm.faces.layers.int.new(
                        ms3d_str['OBJECT_LAYER_GROUP'])

            layer_uv = bm.loops.layers.uv.get(ms3d_str['OBJECT_LAYER_UV'])
            if layer_uv is None:
                if bm.loops.layers.uv:
                    layer_uv = bm.loops.layers.uv[0]
                else:
                    layer_uv = bm.loops.layers.uv.new(
                            ms3d_str['OBJECT_LAYER_UV'])

            layer_deform = bm.verts.layers.deform.active

            layer_extra = bm.verts.layers.int.get(ms3d_str['OBJECT_LAYER_EXTRA'])
            if layer_extra is None:
                layer_extra = bm.verts.layers.int.new(
                        ms3d_str['OBJECT_LAYER_EXTRA'])


            ##########################
            # handle vertices
            for bmv in bm.verts:
                item = blender_to_ms3d_vertices.get(bmv)
                if item is None:
                    index = len(ms3d_model._vertices)
                    ms3d_vertex = Ms3dVertex()
                    ms3d_vertex.__index = index

                    ms3d_vertex._vertex = self.geometry_correction(
                            matrix_transform * bmv.co)

                    if self.options_use_animation and layer_deform:
                        blender_vertex_group_ids = bmv[layer_deform]
                        if blender_vertex_group_ids:
                            bone_weights = {}
                            for blender_index, blender_weight \
                                    in blender_vertex_group_ids.items():
                                ms3d_joint = blender_to_ms3d_bones.get(
                                        blender_mesh_object_temp.vertex_groups[\
                                                blender_index].name)
                                if ms3d_joint:
                                    weight = bone_weights.get(ms3d_joint.__index)
                                    if not weight:
                                        weight = 0
                                    bone_weights[ms3d_joint.__index] = weight + blender_weight

                            # sort (bone_id: weight) according its weights
                            # to skip only less important weights in the next pass
                            bone_weights_sorted = sorted(bone_weights.items(), key=lambda item: item[1], reverse=True)

                            count = 0
                            bone_ids = []
                            weights = []
                            for ms3d_index, blender_weight \
                                    in bone_weights_sorted:

                                if count == 0:
                                    ms3d_vertex.bone_id = ms3d_index
                                    weights.append(blender_weight)
                                elif count == 1:
                                    bone_ids.append(ms3d_index)
                                    weights.append(blender_weight)
                                elif count == 2:
                                    bone_ids.append(ms3d_index)
                                    weights.append(blender_weight)
                                elif count == 3:
                                    bone_ids.append(ms3d_index)
                                    if self.report and self.options_verbose in Ms3dUi.VERBOSE_NORMAL:
                                        self.report(
                                                {'WARNING', 'INFO'},
                                                ms3d_str['WARNING_EXPORT_SKIP_WEIGHT'])
                                else:
                                    # only first three weights will be supported / four bones
                                    if self.report and self.options_verbose in Ms3dUi.VERBOSE_NORMAL:
                                        self.report(
                                                {'WARNING', 'INFO'},
                                                ms3d_str['WARNING_EXPORT_SKIP_WEIGHT_EX'])
                                    break
                                count += 1

                            # normalize weights to 100%
                            if self.options_normalize_weights:
                                weight_sum = 0.0
                                for weight in weights:
                                    weight_sum += weight

                                if weight_sum > 0.0:
                                    weight_normalize = 1.0 / weight_sum
                                else:
                                    weight_normalize = 1.0

                                weight_sum = 100
                                for index, weight in enumerate(weights):
                                    if index >= count-1 or index >= 2:
                                        # take the full rest instead of calculate,
                                        # that should fill up to exactly 100%
                                        # (in some cases it is only 99% bacaus of roulding errors)
                                        weights[index] = int(weight_sum)
                                        break
                                    normalized_weight = int(weight * weight_normalize * 100)
                                    weights[index] = normalized_weight
                                    weight_sum -= normalized_weight

                            # fill up missing values
                            while len(bone_ids) < 3:
                                bone_ids.append(Ms3dSpec.DEFAULT_VERTEX_BONE_ID)
                            while len(weights) < 3:
                                weights.append(0)

                            ms3d_vertex._vertex_ex_object._bone_ids = \
                                    tuple(bone_ids)
                            ms3d_vertex._vertex_ex_object._weights = \
                                    tuple(weights)

                    if layer_extra:
                        #ms3d_vertex._vertex_ex_object.extra = bmv[layer_extra]
                        # bm.verts.layers.int does only support signed int32
                        # convert signed int32 to unsigned int32 (little-endian)
                        signed_int32 = bmv[layer_extra]
                        bytes_int32 = signed_int32.to_bytes(
                                4, byteorder='little', signed=True)
                        unsigned_int32 = int.from_bytes(
                                bytes_int32, byteorder='little', signed=False)
                        ms3d_vertex._vertex_ex_object.extra = unsigned_int32

                    ms3d_model._vertices.append(ms3d_vertex)
                    blender_to_ms3d_vertices[bmv] = ms3d_vertex

            ##########################
            # handle faces / tris
            for bmf in bm.faces:
                item = blender_to_ms3d_triangles.get(bmf)
                if item is None:
                    index = len(ms3d_model._triangles)
                    ms3d_triangle = Ms3dTriangle()
                    ms3d_triangle.__index = index
                    bmv0 = bmf.verts[0]
                    bmv1 = bmf.verts[1]
                    bmv2 = bmf.verts[2]
                    ms3d_vertex0 = blender_to_ms3d_vertices[bmv0]
                    ms3d_vertex1 = blender_to_ms3d_vertices[bmv1]
                    ms3d_vertex2 = blender_to_ms3d_vertices[bmv2]
                    ms3d_vertex0.reference_count += 1
                    ms3d_vertex1.reference_count += 1
                    ms3d_vertex2.reference_count += 1
                    ms3d_triangle._vertex_indices = (
                            ms3d_vertex0.__index,
                            ms3d_vertex1.__index,
                            ms3d_vertex2.__index,
                            )
                    ms3d_triangle._vertex_normals = (
                            self.geometry_correction(bmv0.normal),
                            self.geometry_correction(bmv1.normal),
                            self.geometry_correction(bmv2.normal),
                            )
                    ms3d_triangle._s = (
                            bmf.loops[0][layer_uv].uv.x,
                            bmf.loops[1][layer_uv].uv.x,
                            bmf.loops[2][layer_uv].uv.x,
                            )
                    ms3d_triangle._t = (
                            1.0 - bmf.loops[0][layer_uv].uv.y,
                            1.0 - bmf.loops[1][layer_uv].uv.y,
                            1.0 - bmf.loops[2][layer_uv].uv.y,
                            )

                    ms3d_triangle.smoothing_group = bmf[layer_smoothing_group]
                    ms3d_model._triangles.append(ms3d_triangle)

                    ms3d_material = self.get_ms3d_material_add_if(
                            blender_mesh, ms3d_model,
                            blender_to_ms3d_materials, bmf.material_index)
                    ms3d_group = blender_to_ms3d_groups.get(bmf[layer_group])

                    ##EXPORT_ACTIVE_ONLY:
                    if ms3d_group is not None:
                        if ms3d_material is None:
                            ms3d_group.material_index = \
                                    Ms3dSpec.DEFAULT_GROUP_MATERIAL_INDEX
                        else:
                            if ms3d_group.material_index is None:
                                ms3d_group.material_index = \
                                        ms3d_material.__index
                            else:
                                if ms3d_group.material_index != \
                                        ms3d_material.__index:
                                    ms3d_group = \
                                            self.get_ms3d_group_by_material_add_if(
                                            ms3d_model, ms3d_material)
                    else:
                        if ms3d_material is not None:
                            ms3d_group = self.get_ms3d_group_by_material_add_if(
                                    ms3d_model, ms3d_material)
                        else:
                            ms3d_group = self.get_ms3d_group_default_material_add_if(
                                    ms3d_model)

                    if ms3d_group is not None:
                        ms3d_group._triangle_indices.append(
                                ms3d_triangle.__index)
                        ms3d_triangle.group_index = ms3d_group.__index

                    blender_to_ms3d_triangles[bmf] = ms3d_triangle

            if bm is not None:
                bm.free()

            enable_edit_mode(False, blender_context)

            ##########################
            # remove the temporary data
            blender_scene.objects.unlink(blender_mesh_object_temp)
            if blender_mesh_temp is not None:
                blender_mesh_temp.user_clear()
                blender_context.blend_data.meshes.remove(blender_mesh_temp)
            blender_mesh_temp = None
            if blender_mesh_object_temp is not None:
                blender_mesh_temp = blender_mesh_object_temp.data.user_clear()
                blender_mesh_object_temp.user_clear()
                blender_context.blend_data.objects.remove(
                        blender_mesh_object_temp)
            if blender_mesh_temp is not None:
                blender_mesh_temp.user_clear()
                blender_context.blend_data.meshes.remove(blender_mesh_temp)
Ejemplo n.º 11
0
    def create_geometry(self, blender_context, ms3d_model, blender_mesh_objects, blender_to_ms3d_bones):
        blender_scene = blender_context.scene

        blender_to_ms3d_vertices = {}
        blender_to_ms3d_triangles = {}
        blender_to_ms3d_groups = {}
        blender_to_ms3d_materials = {}

        for blender_mesh_object in blender_mesh_objects:
            blender_mesh = blender_mesh_object.data

            ##########################
            # prepare ms3d groups if available
            # works only for exporting active object
            ##EXPORT_ACTIVE_ONLY:
            for ms3d_local_group_index, blender_ms3d_group in enumerate(blender_mesh.ms3d.groups):
                ms3d_group = Ms3dGroup()
                ms3d_group.__index = len(ms3d_model._groups)
                ms3d_group.name = blender_ms3d_group.name
                ms3d_group.flags = Ms3dUi.flags_to_ms3d(blender_ms3d_group.flags)
                if blender_ms3d_group.comment:
                    ms3d_group._comment_object = Ms3dCommentEx()
                    ms3d_group._comment_object.comment = blender_ms3d_group.comment
                    ms3d_group._comment_object.index = len(ms3d_model._groups)
                ms3d_group.material_index = None  # to mark as not setted
                ms3d_model._groups.append(ms3d_group)
                blender_to_ms3d_groups[blender_ms3d_group.id] = ms3d_group

            ##########################
            # i have to use BMesh, because there are several custom data stored.
            # BMesh doesn't support quads_convert_to_tris()
            # so, i use that very ugly way:
            # create a complete copy of mesh and bend object data
            # to be able to apply operations to it.

            # get a temporary mesh with applied modifiers
            if self.options.prop_apply_modifier:
                blender_mesh_temp = blender_mesh_object.to_mesh(
                    blender_scene, self.options.prop_apply_modifier, self.options.prop_apply_modifier_mode
                )
            else:
                blender_mesh_temp = blender_mesh_object.data.copy()

            # assign temporary mesh as new object data
            blender_mesh_object.data = blender_mesh_temp

            # convert to tris
            enable_edit_mode(True)
            select_all(True)
            if ops.mesh.quads_convert_to_tris.poll():
                ops.mesh.quads_convert_to_tris()
            enable_edit_mode(False)

            enable_edit_mode(True)
            bm = bmesh.from_edit_mesh(blender_mesh_temp)

            layer_texture = bm.faces.layers.tex.get(ms3d_str["OBJECT_LAYER_TEXTURE"])
            if layer_texture is None:
                layer_texture = bm.faces.layers.tex.new(ms3d_str["OBJECT_LAYER_TEXTURE"])

            layer_smoothing_group = bm.faces.layers.int.get(ms3d_str["OBJECT_LAYER_SMOOTHING_GROUP"])
            if layer_smoothing_group is None:
                layer_smoothing_group = bm.faces.layers.int.new(ms3d_str["OBJECT_LAYER_SMOOTHING_GROUP"])

            layer_group = bm.faces.layers.int.get(ms3d_str["OBJECT_LAYER_GROUP"])
            if layer_group is None:
                layer_group = bm.faces.layers.int.new(ms3d_str["OBJECT_LAYER_GROUP"])

            layer_uv = bm.loops.layers.uv.get(ms3d_str["OBJECT_LAYER_UV"])
            if layer_uv is None:
                if bm.loops.layers.uv:
                    layer_uv = bm.loops.layers.uv[0]
                else:
                    layer_uv = bm.loops.layers.uv.new(ms3d_str["OBJECT_LAYER_UV"])

            layer_deform = bm.verts.layers.deform.active

            ##########################
            # handle vertices
            for bmv in bm.verts:
                item = blender_to_ms3d_vertices.get(bmv)
                if item is None:
                    index = len(ms3d_model._vertices)
                    ms3d_vertex = Ms3dVertex()
                    ms3d_vertex.__index = index
                    ms3d_vertex._vertex = (
                        self.matrix_scaled_coordination_system * (bmv.co + blender_mesh_object.location)
                    )[:]

                    if layer_deform:
                        blender_vertex_group_ids = bmv[layer_deform]
                        if blender_vertex_group_ids:
                            temp_weight = 0
                            count = 0
                            for blender_index, blender_weight in blender_vertex_group_ids.items():
                                ms3d_joint = blender_to_ms3d_bones.get(
                                    blender_mesh_object.vertex_groups[blender_index].name
                                )
                                if ms3d_joint:
                                    if count == 0:
                                        ms3d_vertex.bone_id = ms3d_joint.__index
                                        temp_weight = blender_weight
                                    elif count == 1:
                                        ms3d_vertex._vertex_ex_object.bone_ids[0] = ms3d_joint.__index
                                        ms3d_vertex._vertex_ex_object.weights[0] = temp_weight * 100
                                        ms3d_vertex._vertex_ex_object.weights[1] = blender_weight * 100
                                    elif count == 2:
                                        ms3d_vertex._vertex_ex_object.bone_ids[1] = ms3d_joint.__index
                                        ms3d_vertex._vertex_ex_object.weights[2] = blender_weight * 100
                                    # elif count == 3:
                                    #    ms3d_vertex._vertex_ex_object.bone_ids[2] = ms3d_joint.__index

                                # only first three weights will be supported
                                count += 1
                                if count > 3:
                                    break

                    ms3d_model._vertices.append(ms3d_vertex)
                    blender_to_ms3d_vertices[bmv] = ms3d_vertex

            ##########################
            # handle faces / tris
            for bmf in bm.faces:
                item = blender_to_ms3d_triangles.get(bmf)
                if item is None:
                    index = len(ms3d_model._triangles)
                    ms3d_triangle = Ms3dTriangle()
                    ms3d_triangle.__index = index
                    bmv0 = bmf.verts[0]
                    bmv1 = bmf.verts[1]
                    bmv2 = bmf.verts[2]
                    ms3d_vertex0 = blender_to_ms3d_vertices[bmv0]
                    ms3d_vertex1 = blender_to_ms3d_vertices[bmv1]
                    ms3d_vertex2 = blender_to_ms3d_vertices[bmv2]
                    ms3d_vertex0.reference_count += 1
                    ms3d_vertex1.reference_count += 1
                    ms3d_vertex2.reference_count += 1
                    ms3d_triangle._vertex_indices = (ms3d_vertex0.__index, ms3d_vertex1.__index, ms3d_vertex2.__index)
                    ms3d_triangle._vertex_normals = (
                        (self.matrix_coordination_system * bmv0.normal)[:],
                        (self.matrix_coordination_system * bmv1.normal)[:],
                        (self.matrix_coordination_system * bmv2.normal)[:],
                    )
                    ms3d_triangle._s = (
                        bmf.loops[0][layer_uv].uv.x,
                        bmf.loops[1][layer_uv].uv.x,
                        bmf.loops[2][layer_uv].uv.x,
                    )
                    ms3d_triangle._t = (
                        1.0 - bmf.loops[0][layer_uv].uv.y,
                        1.0 - bmf.loops[1][layer_uv].uv.y,
                        1.0 - bmf.loops[2][layer_uv].uv.y,
                    )

                    ms3d_triangle.smoothing_group = bmf[layer_smoothing_group]
                    ms3d_model._triangles.append(ms3d_triangle)

                    ms3d_material = self.get_ms3d_material_add_if(
                        blender_mesh, ms3d_model, blender_to_ms3d_materials, bmf.material_index
                    )
                    ms3d_group = blender_to_ms3d_groups.get(bmf[layer_group])

                    ##EXPORT_ACTIVE_ONLY:
                    if ms3d_group is not None:
                        if ms3d_material is None:
                            ms3d_group.material_index = Ms3dSpec.DEFAULT_GROUP_MATERIAL_INDEX
                        else:
                            if ms3d_group.material_index is None:
                                ms3d_group.material_index = ms3d_material.__index
                            else:
                                if ms3d_group.material_index != ms3d_material.__index:
                                    ms3d_group = self.get_ms3d_group_by_material_add_if(ms3d_model, ms3d_material)
                    else:
                        if ms3d_material is not None:
                            ms3d_group = self.get_ms3d_group_by_material_add_if(ms3d_model, ms3d_material)
                        else:
                            ms3d_group = self.get_ms3d_group_default_material_add_if(ms3d_model)

                    if ms3d_group is not None:
                        ms3d_group._triangle_indices.append(ms3d_triangle.__index)
                        ms3d_triangle.group_index = ms3d_group.__index

                    blender_to_ms3d_triangles[bmf] = ms3d_triangle

            if bm is not None:
                bm.free()

            enable_edit_mode(False)

            ##########################
            # restore original object data
            blender_mesh_object.data = blender_mesh

            ##########################
            # remove the temporary data
            if blender_mesh_temp is not None:
                blender_mesh_temp.user_clear()
                blender_context.blend_data.meshes.remove(blender_mesh_temp)
Ejemplo n.º 12
0
    def create_geometry(self, blender_context, ms3d_model):
        ##########################
        # blender stuff:
        # create a blender Mesh
        blender_mesh = blender_context.blend_data.meshes.new(
                ms3d_model.name + ".m")
        blender_mesh.ms3d.name = ms3d_model.name

        ms3d_comment = ms3d_model.comment_object
        if ms3d_comment is not None:
            blender_mesh.ms3d.comment = ms3d_comment.comment
        ms3d_model_ex = ms3d_model.model_ex_object
        if ms3d_model_ex is not None:
            blender_mesh.ms3d.joint_size = ms3d_model_ex.joint_size
            blender_mesh.ms3d.alpha_ref = ms3d_model_ex.alpha_ref
            blender_mesh.ms3d.transparency_mode \
                    = Ms3dUi.transparency_mode_from_ms3d(
                            ms3d_model_ex.transparency_mode)

        ##########################
        # blender stuff:
        # link to blender object
        blender_mesh_object = blender_context.blend_data.objects.new(
                ms3d_model.name + ".m", blender_mesh)

        ##########################
        # blender stuff:
        # create edge split modifire, to make sharp edges visible
        blender_modifier = get_edge_split_modifier_add_if(blender_mesh_object)

        ##########################
        # blender stuff:
        # link to blender scene
        blender_scene = blender_context.scene
        blender_scene.objects.link(blender_mesh_object)
        #blender_mesh_object.location = blender_scene.cursor_location
        enable_edit_mode(False)
        select_all(False)
        blender_mesh_object.select = True
        blender_scene.objects.active = blender_mesh_object

        ##########################
        # blender stuff:
        # create all (ms3d) groups
        ms3d_to_blender_group_index = {}
        blender_group_manager = blender_mesh.ms3d
        for ms3d_group_index, ms3d_group in enumerate(ms3d_model.groups):
            blender_group = blender_group_manager.create_group()
            blender_group.name = ms3d_group.name
            blender_group.flags = Ms3dUi.flags_from_ms3d(ms3d_group.flags)
            blender_group.material_index = ms3d_group.material_index

            ms3d_comment = ms3d_group.comment_object
            if ms3d_comment is not None:
                blender_group.comment = ms3d_comment.comment

            # translation dictionary
            ms3d_to_blender_group_index[ms3d_group_index] = blender_group.id

        ####################################################
        # begin BMesh stuff
        #

        ##########################
        # BMesh stuff:
        # create an empty BMesh
        bm = bmesh.new()

        ##########################
        # BMesh stuff:
        # create new Layers for custom data per "mesh face"
        layer_texture = bm.faces.layers.tex.get(
                ms3d_str['OBJECT_LAYER_TEXTURE'])
        if layer_texture is None:
            layer_texture = bm.faces.layers.tex.new(
                    ms3d_str['OBJECT_LAYER_TEXTURE'])

        layer_smoothing_group = bm.faces.layers.int.get(
                ms3d_str['OBJECT_LAYER_SMOOTHING_GROUP'])
        if layer_smoothing_group is None:
            layer_smoothing_group = bm.faces.layers.int.new(
                    ms3d_str['OBJECT_LAYER_SMOOTHING_GROUP'])

        layer_group = bm.faces.layers.int.get(
                ms3d_str['OBJECT_LAYER_GROUP'])
        if layer_group is None:
            layer_group = bm.faces.layers.int.new(
                    ms3d_str['OBJECT_LAYER_GROUP'])

        ##########################
        # BMesh stuff:
        # create new Layers for custom data per "face vertex"
        layer_uv = bm.loops.layers.uv.get(ms3d_str['OBJECT_LAYER_UV'])
        if layer_uv is None:
            layer_uv = bm.loops.layers.uv.new(ms3d_str['OBJECT_LAYER_UV'])

        ##########################
        # BMesh stuff:
        # create all vertices
        for ms3d_vertex_index, ms3d_vertex in enumerate(ms3d_model.vertices):
            bmv = bm.verts.new(
                    self.matrix_scaled_coordination_system
                    * Vector(ms3d_vertex.vertex))

        ##########################
        # blender stuff (uses BMesh stuff):
        # create all materials / image textures
        ms3d_to_blender_material = {}
        for ms3d_material_index, ms3d_material in enumerate(
                ms3d_model.materials):
            blender_material = blender_context.blend_data.materials.new(
                    ms3d_material.name)

            # custom datas
            blender_material.ms3d.name = ms3d_material.name
            blender_material.ms3d.ambient = ms3d_material.ambient
            blender_material.ms3d.diffuse = ms3d_material.diffuse
            blender_material.ms3d.specular = ms3d_material.specular
            blender_material.ms3d.emissive = ms3d_material.emissive
            blender_material.ms3d.shininess = ms3d_material.shininess
            blender_material.ms3d.transparency = ms3d_material.transparency
            blender_material.ms3d.mode = Ms3dUi.texture_mode_from_ms3d(
                    ms3d_material.mode)

            if ms3d_material.texture:
                blender_material.ms3d.texture = ms3d_material.texture

            if ms3d_material.alphamap:
                blender_material.ms3d.alphamap = ms3d_material.alphamap

            ms3d_comment = ms3d_material.comment_object
            if ms3d_comment is not None:
                blender_material.ms3d.comment = ms3d_comment.comment

            # blender datas
            blender_material.ambient = ((
                    (ms3d_material.ambient[0]
                    + ms3d_material.ambient[1]
                    + ms3d_material.ambient[2]) / 3.0)
                    * ms3d_material.ambient[3])

            blender_material.diffuse_color[0] = ms3d_material.diffuse[0]
            blender_material.diffuse_color[1] = ms3d_material.diffuse[1]
            blender_material.diffuse_color[2] = ms3d_material.diffuse[2]
            blender_material.diffuse_intensity = ms3d_material.diffuse[3]

            blender_material.specular_color[0] = ms3d_material.specular[0]
            blender_material.specular_color[1] = ms3d_material.specular[1]
            blender_material.specular_color[2] = ms3d_material.specular[2]
            blender_material.specular_intensity = ms3d_material.specular[3]

            blender_material.emit = ((
                    (ms3d_material.emissive[0]
                    + ms3d_material.emissive[1]
                    + ms3d_material.emissive[2]) / 3.0)
                    * ms3d_material.emissive[3])

            blender_material.specular_hardness = ms3d_material.shininess * 2.0

            if (ms3d_material.transparency):
                blender_material.use_transparency = True
                blender_material.alpha = ms3d_material.transparency
                blender_material.specular_alpha = blender_material.alpha

            if (blender_material.game_settings):
                blender_material.game_settings.use_backface_culling = False
                blender_material.game_settings.alpha_blend = 'ALPHA'

            # diffuse texture
            if ms3d_material.texture:
                dir_name_diffuse = self.filepath_splitted[0]
                file_name_diffuse = path.split(ms3d_material.texture)[1]
                blender_image_diffuse = load_image(
                        file_name_diffuse, dir_name_diffuse)
                blender_texture_diffuse = blender_context.blend_data.textures.new(
                        name=file_name_diffuse, type='IMAGE')
                blender_texture_diffuse.image = blender_image_diffuse
                blender_texture_slot_diffuse \
                        = blender_material.texture_slots.add()
                blender_texture_slot_diffuse.texture = blender_texture_diffuse
                blender_texture_slot_diffuse.texture_coords = 'UV'
                blender_texture_slot_diffuse.uv_layer = layer_uv.name
                blender_texture_slot_diffuse.use_map_color_diffuse = True
                blender_texture_slot_diffuse.use_map_alpha = False
                if blender_image_diffuse is not None:
                    self.has_textures = True
            else:
                blender_image_diffuse = None

            # alpha texture
            if ms3d_material.alphamap:
                dir_name_alpha = self.filepath_splitted[0]
                file_name_alpha = path.split(ms3d_material.alphamap)[1]
                blender_image_alpha = load_image(
                        file_name_alpha, dir_name_alpha)
                blender_texture_alpha = blender_context.blend_data.textures.new(
                        name=file_name_alpha, type='IMAGE')
                blender_texture_alpha.image = blender_image_alpha
                blender_texture_slot_alpha \
                        = blender_material.texture_slots.add()
                blender_texture_slot_alpha.texture = blender_texture_alpha
                blender_texture_slot_alpha.texture_coords = 'UV'
                blender_texture_slot_alpha.uv_layer = layer_uv.name
                blender_texture_slot_alpha.use_map_color_diffuse = False
                blender_texture_slot_alpha.use_map_alpha = True
                blender_texture_slot_alpha.use_rgb_to_intensity = True
                blender_material.alpha = 0
                blender_material.specular_alpha = 0

            # append blender material to blender mesh, to be linked to
            blender_mesh.materials.append(blender_material)

            # translation dictionary
            ms3d_to_blender_material[ms3d_material_index] \
                    = blender_image_diffuse

        ##########################
        # BMesh stuff:
        # create all triangles
        smoothing_group_blender_faces = {}
        for ms3d_triangle_index, ms3d_triangle in enumerate(
                ms3d_model.triangles):
            bmv_list = []
            for vert_index in ms3d_triangle.vertex_indices:
                bmv = bm.verts[vert_index]
                if [[x] for x in bmv_list if x == bmv]:
                    self.options.report(
                            {'WARNING', 'INFO'},
                            ms3d_str['WARNING_IMPORT_SKIP_VERTEX_DOUBLE'].format(
                                    ms3d_triangle_index))
                    continue
                bmv_list.append(bmv)

            if len(bmv_list) < 3:
                self.options.report(
                        {'WARNING', 'INFO'},
                        ms3d_str['WARNING_IMPORT_SKIP_LESS_VERTICES'].format(
                                ms3d_triangle_index))
                continue
            bmf = bm.faces.get(bmv_list)
            if bmf is not None:
                self.options.report(
                        {'WARNING', 'INFO'},
                        ms3d_str['WARNING_IMPORT_SKIP_FACE_DOUBLE'].format(
                                ms3d_triangle_index))
                continue

            bmf = bm.faces.new(bmv_list)

            # blender uv custom data per "face vertex"
            bmf.loops[0][layer_uv].uv = Vector(
                    (ms3d_triangle.s[0], 1.0 - ms3d_triangle.t[0]))
            bmf.loops[1][layer_uv].uv = Vector(
                    (ms3d_triangle.s[1], 1.0 - ms3d_triangle.t[1]))
            bmf.loops[2][layer_uv].uv = Vector(
                    (ms3d_triangle.s[2], 1.0 - ms3d_triangle.t[2]))

            # ms3d custom data per "mesh face"
            bmf[layer_smoothing_group] = ms3d_triangle.smoothing_group

            blender_group_id = ms3d_to_blender_group_index.get(
                    ms3d_triangle.group_index)
            if blender_group_id is not None:
                bmf[layer_group] = blender_group_id

            if ms3d_triangle.group_index >= 0 \
                    and ms3d_triangle.group_index < len(ms3d_model.groups):
                ms3d_material_index \
                        = ms3d_model.groups[ms3d_triangle.group_index].material_index
                if ms3d_material_index != Ms3dSpec.NONE_GROUP_MATERIAL_INDEX:
                    # BMFace.material_index expects...
                    # index of material in types.Mesh.materials,
                    # not index of material in blender_context.blend_data.materials!
                    bmf.material_index = ms3d_material_index

                    # apply diffuse texture image to face, to be visible in 3d view
                    bmf[layer_texture].image = ms3d_to_blender_material.get(
                            ms3d_material_index)
                else:
                    # set material index to highes possible index
                    # - in most cases there is no maretial assigned ;)
                    bmf.material_index = 32766
                    pass

            # helper dictionary for post-processing smoothing_groups
            smoothing_group_blender_face = smoothing_group_blender_faces.get(
                    ms3d_triangle.smoothing_group)
            if smoothing_group_blender_face is None:
                smoothing_group_blender_face = []
                smoothing_group_blender_faces[ms3d_triangle.smoothing_group] \
                        = smoothing_group_blender_face
            smoothing_group_blender_face.append(bmf)

        ##########################
        # BMesh stuff:
        # create all sharp edges for blender to make smoothing_groups visible
        for ms3d_smoothing_group_index, blender_face_list \
                in smoothing_group_blender_faces.items():
            edge_dict = {}
            for bmf in blender_face_list:
                bmf.smooth = True
                for bme in bmf.edges:
                    if edge_dict.get(bme) is None:
                        edge_dict[bme] = 0
                    else:
                        edge_dict[bme] += 1
                    bme.seam = (edge_dict[bme] == 0)
                    bme.smooth = (edge_dict[bme] != 0)

        ##########################
        # BMesh stuff:
        # finally tranfer BMesh to Mesh
        bm.to_mesh(blender_mesh)
        bm.free()


        #
        # end BMesh stuff
        ####################################################

        return blender_mesh_object