Last active
August 16, 2021 14:44
-
-
Save Tiim/ef4925c64cb177a61fdf8176cab7a2db to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import bpy | |
import os | |
import re | |
from bpy_extras import io_utils | |
from zipfile import ZipFile | |
EXPORT_SINGLE = False # Only export the selected Collection and not seperate files | |
ENABLE_ZIP = True | |
dir = os.path.dirname(bpy.data.filepath) | |
texture_dir = None | |
if os.path.basename(dir) == 'project': | |
print("Photogrammetry file structure detected!") | |
dir = os.path.join(dir, '..', 'models', '4-other-formats') | |
texture_dir = os.path.join(os.path.dirname(bpy.data.filepath), '..', 'textures_pkg') | |
else: | |
print("No special folder structure detected!") | |
dir = os.path.join(dir, 'export') | |
texture_dir = os.path.join(os.path.dirname(bpy.data.filepath), 'textures_pkg') | |
def simple_slug(str): | |
return re.sub('\W', '_', str.lower()) | |
def copy_imgs(images, folder): | |
copy_set = set() | |
for t in images: | |
io_utils.path_reference(t.filepath, os.path.dirname(bpy.data.filepath), folder, | |
"COPY", "", copy_set, t.library) | |
io_utils.path_reference_copy(copy_set) | |
def select(obj_or_col, select): | |
if type(obj_or_col) == bpy.types.Collection: | |
for obj in obj_or_col.all_objects: | |
obj.select_set(select) | |
else: | |
obj = obj_or_col | |
obj.select_set(select) | |
def zip_folder(name, path, folder): | |
if not ENABLE_ZIP: | |
return | |
print("Zipping folder", folder) | |
with ZipFile(os.path.join(path, name + '.zip'), 'w') as zipObj: | |
for folder, subfolders, filenames in os.walk(folder): | |
for file in filenames: | |
file_path = os.path.join(folder, file) | |
zipObj.write(file_path, os.path.basename(file_path)) | |
def export_obj(object, dir, tex, name_ext=''): | |
odir = os.path.join(dir, object.name, 'obj') | |
os.makedirs(odir, exist_ok=True) | |
file = os.path.join(odir,object.name+name_ext+'.obj') | |
select(object, True) | |
bpy.ops.export_scene.obj(filepath=file, check_existing=False, use_selection=True, path_mode='COPY'); | |
select(object, False) | |
zip_folder(object.name + name_ext + '-obj', dir, odir) | |
def export_fbx(object, dir, tex, name_ext=''): | |
file = os.path.join(dir,object.name+name_ext+'.fbx') | |
select(object, True) | |
bpy.ops.export_scene.fbx(filepath=file, check_existing=False, use_selection=True, path_mode='COPY', embed_textures=True); | |
select(object, False) | |
def export_dae(object, dir, tex, name_ext=''): | |
odir = os.path.join(dir, object.name, 'dae') | |
os.makedirs(odir, exist_ok=True) | |
file = os.path.join(odir,object.name+name_ext+'.dae') | |
select(object, True) | |
bpy.ops.wm.collada_export(filepath=file, check_existing=False, selected=True, use_texture_copies=True); | |
select(object, False) | |
copy_imgs(tex, odir) | |
zip_folder(object.name + name_ext + '-dae', dir, odir) | |
def export_abc(object, dir, tex, name_ext=''): | |
odir = os.path.join(dir, object.name, 'abc') | |
os.makedirs(odir, exist_ok=True) | |
file = os.path.join(odir,object.name+name_ext+'.abc') | |
select(object, True) | |
bpy.ops.wm.alembic_export(filepath=file, check_existing=False, selected=True); | |
select(object, False) | |
copy_imgs(tex, odir) | |
zip_folder(object.name + name_ext + '-abc', dir, odir) | |
def set_subsurf(obj_or_col, set = True ): | |
if type(obj_or_col) == bpy.types.Collection: | |
old = [] | |
for i, object in enumerate(obj_or_col.all_objects): | |
if type(set) == bool: | |
old.append(set_subsurf(object, set)) | |
else: | |
old.append(set_subsurf(object, set[i])) | |
return old | |
object = obj_or_col | |
if len(object.modifiers) != 1 or object.modifiers[0].type != 'SUBSURF': | |
return | |
subsurf = object.modifiers[0] | |
old_show_viewport = subsurf.show_viewport | |
old_show_render = subsurf.show_render | |
if type(set) == tuple: | |
subsurf.show_viewport = set[0] | |
subsurf.show_render = set[1] | |
else: | |
subsurf.show_viewport = set | |
subsurf.show_render = set | |
return (old_show_viewport, old_show_render) | |
def has_subsurf(obj_or_col): | |
if type(obj_or_col) == bpy.types.Collection: | |
for object in obj_or_col.all_objects: | |
if len(object.modifiers) == 1 and object.modifiers[0].type == 'SUBSURF' and (object.modifiers[0].show_render or object.modifiers[0].show_viewport): | |
return True | |
else: | |
object = obj_or_col | |
if len(object.modifiers) == 1 and object.modifiers[0].type == 'SUBSURF' and (object.modifiers[0].show_render or object.modifiers[0].show_viewport): | |
return True | |
return False | |
def process_textures(obj_or_col): | |
principled = None | |
if type(obj_or_col) == bpy.types.Collection: | |
tex = [] | |
for obj in obj_or_col.all_objects: | |
tex.extend(process_textures(obj)) | |
return tex | |
object = obj_or_col | |
for node in object.active_material.node_tree.nodes.values(): | |
#print(node.bl_idname) | |
if node.bl_idname == 'ShaderNodeBsdfPrincipled': | |
principled = node | |
if principled is None: | |
return | |
tex_dir = os.path.join(texture_dir, object.name) | |
textures = [] | |
for inp in principled.inputs: | |
if len(inp.links) != 1: | |
continue | |
node = inp.links[0].from_node | |
if node.bl_idname == 'ShaderNodeNormalMap': | |
node = node.inputs.values()[1].links[0].from_node | |
if node.bl_idname != 'ShaderNodeTexImage': | |
continue | |
image = node.image | |
image.pack() | |
new_name = object.name +'_'+ simple_slug(inp.name) | |
image_path = os.path.join(tex_dir, new_name + os.path.splitext(image.filepath_raw)[1] ) | |
os.makedirs(os.path.dirname(image_path), exist_ok = True) | |
print("Save img:", image.name, image_path) | |
image.save_render(image_path) | |
image.filepath_raw = image_path | |
image.name = new_name | |
textures.append(image) | |
zip_folder(object.name + '-textures', texture_dir, tex_dir) | |
return textures | |
exporters = [export_obj, export_fbx, export_dae, export_abc] | |
def main(): | |
objects = [] | |
if EXPORT_SINGLE: | |
objects = [bpy.context.collection] | |
else: | |
objects = bpy.context.selected_objects | |
bpy.ops.object.select_all(action='DESELECT') | |
if len(objects) < 1 or objects[0] is None: | |
print("ERR: No objects or collections selected") | |
return | |
for object in objects: | |
tex = process_textures(object) | |
if has_subsurf(object): | |
old = set_subsurf(object, set=False) | |
for export in exporters: export(object, dir, tex) | |
set_subsurf(object, set=True) | |
for export in exporters: export(object, dir, tex, name_ext='_subsurf') | |
set_subsurf(object, set=old) | |
else: | |
for export in exporters: export(object, dir, tex) | |
print("Done") | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment