Skip to content
Snippets Groups Projects
export_3ds.py 37.8 KiB
Newer Older
  • Learn to ignore specific revisions
  •     # Initialize the main chunk (primary):
        primary = _3ds_chunk(PRIMARY)
        # Add version chunk:
        version_chunk = _3ds_chunk(VERSION)
    
        version_chunk.add_variable("version", _3ds_uint(3))
    
        primary.add_subchunk(version_chunk)
    
        # init main object info chunk:
        object_info = _3ds_chunk(OBJECTINFO)
    
        ''' # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX
        # init main key frame data chunk:
        kfdata = make_kfdata()
        '''
    
        # Make a list of all materials used in the selected meshes (use a dictionary,
        # each material is added once):
        materialDict = {}
        mesh_objects = []
    
        if use_selection:
            objects = (ob for ob in scene.objects if ob.is_visible(scene) and ob.select)
        else:
            objects = (ob for ob in scene.objects if ob.is_visible(scene))
    
        for ob in objects:
    
            # get derived objects
            free, derived = create_derived_objects(scene, ob)
    
            if derived is None:
                continue
    
            for ob_derived, mat in derived:
    
                if ob.type not in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META'}:
    
                    data = ob_derived.to_mesh(scene, True, 'PREVIEW')
    
                    matrix = global_matrix * mat
                    data.transform(matrix)
                    mesh_objects.append((ob_derived, data, matrix))
    
                    mat_ls = data.materials
                    mat_ls_len = len(mat_ls)
    
                    # get material/image tuples.
    
                    if data.tessface_uv_textures:
    
                        for f, uf in zip(data.tessfaces, data.tessface_uv_textures.active.data):
    
                            if mat_ls:
                                mat_index = f.material_index
                                if mat_index >= mat_ls_len:
                                    mat_index = f.mat = 0
                                mat = mat_ls[mat_index]
    
                                mat_name = None if mat is None else mat.name
    
                            # else there already set to none
    
                            img = uf.image
    
                            img_name = None if img is None else img.name
    
                            materialDict.setdefault((mat_name, img_name), (mat, img))
    
                            if mat:  # material may be None so check its not.
                                materialDict.setdefault((mat.name, None), (mat, None))
    
                        for f in data.tessfaces:
    
                            if f.material_index >= mat_ls_len:
                                f.material_index = 0
    
            if free:
                free_derived_objects(ob)
    
        # Make material chunks for all materials used in the meshes:
        for mat_and_image in materialDict.values():
            object_info.add_subchunk(make_material_chunk(mat_and_image[0], mat_and_image[1]))
    
        # Give all objects a unique ID and build a dictionary from object name to object id:
        """
        name_to_id = {}
        for ob, data in mesh_objects:
            name_to_id[ob.name]= len(name_to_id)
        #for ob in empty_objects:
    
        #    name_to_id[ob.name]= len(name_to_id)
    
        """
    
        # Create object chunks for all meshes:
        i = 0
    
        for ob, blender_mesh, matrix in mesh_objects:
    
            # create a new object chunk
            object_chunk = _3ds_chunk(OBJECT)
    
            # set the object name
            object_chunk.add_variable("name", _3ds_string(sane_name(ob.name)))
    
            # make a mesh chunk out of the mesh:
    
            object_chunk.add_subchunk(make_mesh_chunk(blender_mesh, matrix, materialDict))
    
    
            # ensure the mesh has no over sized arrays
            # skip ones that do!, otherwise we cant write since the array size wont
            # fit into USHORT.
            if object_chunk.validate():
                object_info.add_subchunk(object_chunk)
            else:
                operator.report({'WARNING'}, "Object %r can't be written into a 3DS file")
    
    
            ''' # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX
            # make a kf object node for the object:
            kfdata.add_subchunk(make_kf_obj_node(ob, name_to_id))
            '''
    
            if not blender_mesh.users:
                bpy.data.meshes.remove(blender_mesh)
    
    
        # Create chunks for all empties:
        ''' # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX
        for ob in empty_objects:
            # Empties only require a kf object node:
            kfdata.add_subchunk(make_kf_obj_node(ob, name_to_id))
            pass
        '''
    
        # Add main object info chunk to primary chunk:
        primary.add_subchunk(object_info)
    
        ''' # COMMENTED OUT FOR 2.42 RELEASE!! CRASHES 3DS MAX
        # Add main keyframe data chunk to primary chunk:
        primary.add_subchunk(kfdata)
        '''
    
        # At this point, the chunk hierarchy is completely built.
    
        # Check the size:
        primary.get_size()
        # Open the file for writing:
        file = open(filepath, 'wb')
    
        # Recursively write the chunks to file:
        primary.write(file)
    
        # Close the file:
        file.close()
    
        # Clear name mapping vars, could make locals too
    
        del name_unique[:]
    
        name_mapping.clear()
    
        # Debugging only: report the exporting time:
    
        print("3ds export time: %.2f" % (time.clock() - time1))
    
        # Debugging only: dump the chunk hierarchy:
        #primary.dump()