From 591821c92254b03a64113c077e258d50ff20cca5 Mon Sep 17 00:00:00 2001 From: Campbell Barton <ideasman42@gmail.com> Date: Thu, 26 May 2011 08:45:31 +0000 Subject: [PATCH] added axis settings to 3ds import/export --- io_scene_3ds/__init__.py | 67 +++++++++++++++++++++++++++++++++++--- io_scene_3ds/export_3ds.py | 31 +++++++----------- io_scene_3ds/import_3ds.py | 42 ++++++++++++++++++------ io_scene_fbx/__init__.py | 8 ++--- io_scene_fbx/export_fbx.py | 28 ++++++++-------- 5 files changed, 124 insertions(+), 52 deletions(-) diff --git a/io_scene_3ds/__init__.py b/io_scene_3ds/__init__.py index 4915512a7..8ade71c19 100644 --- a/io_scene_3ds/__init__.py +++ b/io_scene_3ds/__init__.py @@ -42,8 +42,8 @@ if "bpy" in locals(): import bpy -from bpy.props import StringProperty, FloatProperty, BoolProperty -from bpy_extras.io_utils import ImportHelper, ExportHelper +from bpy.props import StringProperty, FloatProperty, BoolProperty, EnumProperty +from bpy_extras.io_utils import ImportHelper, ExportHelper, axis_conversion class Import3DS(bpy.types.Operator, ImportHelper): @@ -58,9 +58,39 @@ class Import3DS(bpy.types.Operator, ImportHelper): use_image_search = BoolProperty(name="Image Search", description="Search subdirectories for any assosiated images (Warning, may be slow)", default=True) use_apply_transform = BoolProperty(name="Apply Transform", description="Workaround for object transformations importing incorrectly", default=True) + global_axis_forward = EnumProperty( + name="Forward", + items=(('X', "X Forward", ""), + ('Y', "Y Forward", ""), + ('Z', "Z Forward", ""), + ('-X', "-X Forward", ""), + ('-Y', "-Y Forward", ""), + ('-Z', "-Z Forward", ""), + ), + default='Y', + ) + + global_axis_up = EnumProperty( + name="Up", + items=(('X', "X Up", ""), + ('Y', "Y Up", ""), + ('Z', "Z Up", ""), + ('-X', "-X Up", ""), + ('-Y', "-Y Up", ""), + ('-Z', "-Z Up", ""), + ), + default='Z', + ) + def execute(self, context): from . import import_3ds - return import_3ds.load(self, context, **self.as_keywords(ignore=("filter_glob",))) + + keywords = self.as_keywords(ignore=("global_axis_forward", "global_axis_up", "filter_glob")) + + global_matrix = axis_conversion(from_forward=self.global_axis_forward, from_up=self.global_axis_up).to_4x4() + keywords["global_matrix"] = global_matrix + + return import_3ds.load(self, context, **keywords) class Export3DS(bpy.types.Operator, ExportHelper): @@ -73,9 +103,38 @@ class Export3DS(bpy.types.Operator, ExportHelper): use_selection = BoolProperty(name="Selection Only", description="Export selected objects only", default=False) + global_axis_forward = EnumProperty( + name="Forward", + items=(('X', "X Forward", ""), + ('Y', "Y Forward", ""), + ('Z', "Z Forward", ""), + ('-X', "-X Forward", ""), + ('-Y', "-Y Forward", ""), + ('-Z', "-Z Forward", ""), + ), + default='Y', + ) + + global_axis_up = EnumProperty( + name="Up", + items=(('X', "X Up", ""), + ('Y', "Y Up", ""), + ('Z', "Z Up", ""), + ('-X', "-X Up", ""), + ('-Y', "-Y Up", ""), + ('-Z', "-Z Up", ""), + ), + default='Z', + ) + def execute(self, context): from . import export_3ds - return export_3ds.save(self, context, **self.as_keywords(ignore=("check_existing", "filter_glob"))) + + keywords = self.as_keywords(ignore=("global_axis_forward", "global_axis_up", "filter_glob", "check_existing")) + global_matrix = axis_conversion(to_forward=self.global_axis_forward, to_up=self.global_axis_up).to_4x4() + keywords["global_matrix"] = global_matrix + + return export_3ds.save(self, context, **keywords) # Add to a menu diff --git a/io_scene_3ds/export_3ds.py b/io_scene_3ds/export_3ds.py index 8def27b16..b9f5d982a 100644 --- a/io_scene_3ds/export_3ds.py +++ b/io_scene_3ds/export_3ds.py @@ -485,11 +485,8 @@ def make_material_chunk(material, image): else: material_chunk.add_subchunk(make_material_subchunk(MATAMBIENT, [a * material.ambient for a in material.diffuse_color])) -# material_chunk.add_subchunk(make_material_subchunk(MATAMBIENT, [a*material.amb for a in material.rgbCol] )) material_chunk.add_subchunk(make_material_subchunk(MATDIFFUSE, material.diffuse_color)) -# material_chunk.add_subchunk(make_material_subchunk(MATDIFFUSE, material.rgbCol)) material_chunk.add_subchunk(make_material_subchunk(MATSPECULAR, material.specular_color)) -# material_chunk.add_subchunk(make_material_subchunk(MATSPECULAR, material.specCol)) images = get_material_images(material) # can be None if image: @@ -522,22 +519,15 @@ def extract_triangles(mesh): If the mesh contains quads, they will be split into triangles.''' tri_list = [] do_uv = len(mesh.uv_textures) -# do_uv = mesh.faceUV - -# if not do_uv: -# face_uv = None img = None for i, face in enumerate(mesh.faces): f_v = face.vertices -# f_v = face.v uf = mesh.uv_textures.active.data[i] if do_uv else None if do_uv: f_uv = uf.uv - # f_uv = (uf.uv1, uf.uv2, uf.uv3, uf.uv4) if face.vertices[3] else (uf.uv1, uf.uv2, uf.uv3) -# f_uv = face.uv img = uf.image if uf else None if img is not None: img = img.name @@ -545,16 +535,13 @@ def extract_triangles(mesh): # if f_v[3] == 0: if len(f_v) == 3: new_tri = tri_wrapper((f_v[0], f_v[1], f_v[2]), face.material_index, img) -# new_tri = tri_wrapper((f_v[0].index, f_v[1].index, f_v[2].index), face.mat, img) if (do_uv): new_tri.faceuvs = uv_key(f_uv[0]), uv_key(f_uv[1]), uv_key(f_uv[2]) tri_list.append(new_tri) else: # it's a quad new_tri = tri_wrapper((f_v[0], f_v[1], f_v[2]), face.material_index, img) -# new_tri = tri_wrapper((f_v[0].index, f_v[1].index, f_v[2].index), face.mat, img) new_tri_2 = tri_wrapper((f_v[0], f_v[2], f_v[3]), face.material_index, img) -# new_tri_2 = tri_wrapper((f_v[0].index, f_v[2].index, f_v[3].index), face.mat, img) if (do_uv): new_tri.faceuvs = uv_key(f_uv[0]), uv_key(f_uv[1]), uv_key(f_uv[2]) @@ -887,11 +874,15 @@ def make_kf_obj_node(obj, name_to_id): """ -def save(operator, context, filepath="", - use_selection=True, - ): +def save(operator, + context, filepath="", + use_selection=True, + global_matrix=None, + ): import bpy + import mathutils + import time from bpy_extras.io_utils import create_derived_objects, free_derived_objects @@ -901,6 +892,9 @@ def save(operator, context, filepath="", time1 = time.clock() # Blender.Window.WaitCursor(1) + if global_matrix is None: + global_matrix = mathutils.Matrix() + if bpy.ops.object.mode_set.poll(): bpy.ops.object.mode_set(mode='OBJECT') @@ -939,8 +933,6 @@ def save(operator, context, filepath="", continue for ob_derived, mat in derived: -# for ob_derived, mat in getDerivedObjects(ob, False): - if ob.type not in ('MESH', 'CURVE', 'SURFACE', 'FONT', 'META'): continue @@ -950,7 +942,7 @@ def save(operator, context, filepath="", data = None if data: - data.transform(mat) + data.transform(global_matrix * mat) # data.transform(mat, recalc_normals=False) mesh_objects.append((ob_derived, data)) mat_ls = data.materials @@ -965,7 +957,6 @@ def save(operator, context, filepath="", for f, uf in zip(data.faces, data.uv_textures.active.data): if mat_ls: mat_index = f.material_index -# mat_index = f.mat if mat_index >= mat_ls_len: mat_index = f.mat = 0 mat = mat_ls[mat_index] diff --git a/io_scene_3ds/import_3ds.py b/io_scene_3ds/import_3ds.py index d66ace47c..f054033d6 100644 --- a/io_scene_3ds/import_3ds.py +++ b/io_scene_3ds/import_3ds.py @@ -339,18 +339,12 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH): ob = bpy.data.objects.new(contextObName, bmesh) object_dictionary[contextObName] = ob SCN.objects.link(ob) - - ''' - if contextMatrix_tx: - ob.setMatrix(contextMatrix_tx) - ''' + importedObjects.append(ob) if contextMatrix_rot: ob.matrix_local = contextMatrix_rot object_matrix[ob] = contextMatrix_rot.copy() - importedObjects.append(ob) - #a spare chunk new_chunk = chunk() temp_chunk = chunk() @@ -667,6 +661,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH): if child is None: child = bpy.data.objects.new(object_name, None) # create an empty object SCN.objects.link(child) + importedObjects.append(child) object_list.append(child) object_parent.append(hierarchy) @@ -779,7 +774,12 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH): ob.data.transform(pivot_matrix) -def load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True, APPLY_MATRIX=True): +def load_3ds(filepath, + context, + IMPORT_CONSTRAIN_BOUNDS=10.0, + IMAGE_SEARCH=True, + APPLY_MATRIX=True, + global_matrix=None): global SCN # XXX @@ -838,6 +838,13 @@ def load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True, me = ob.data me.transform(ob.matrix_local.inverted()) + # print(importedObjects) + if global_matrix: + for ob in importedObjects: + if ob.parent is None: + ob.matrix_world = ob.matrix_world * global_matrix + + # Done DUMMYVERT """ if IMPORT_AS_INSTANCE: @@ -903,6 +910,21 @@ def load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=10.0, IMAGE_SEARCH=True, file.close() -def load(operator, context, filepath="", constrain_size=0.0, use_image_search=True, use_apply_transform=True): - load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=constrain_size, IMAGE_SEARCH=use_image_search, APPLY_MATRIX=use_apply_transform) +def load(operator, + context, + filepath="", + constrain_size=0.0, + use_image_search=True, + use_apply_transform=True, + global_matrix=None, + ): + + load_3ds(filepath, + context, + IMPORT_CONSTRAIN_BOUNDS=constrain_size, + IMAGE_SEARCH=use_image_search, + APPLY_MATRIX=use_apply_transform, + global_matrix=global_matrix, + ) + return {'FINISHED'} diff --git a/io_scene_fbx/__init__.py b/io_scene_fbx/__init__.py index ff87d29bd..48391ac0a 100644 --- a/io_scene_fbx/__init__.py +++ b/io_scene_fbx/__init__.py @@ -138,12 +138,12 @@ class ExportFBX(bpy.types.Operator, ExportHelper): if not self.filepath: raise Exception("filepath not set") - GLOBAL_MATRIX = Matrix() - GLOBAL_MATRIX[0][0] = GLOBAL_MATRIX[1][1] = GLOBAL_MATRIX[2][2] = self.global_scale - GLOBAL_MATRIX = GLOBAL_MATRIX * axis_conversion(to_forward=self.global_axis_forward, to_up=self.global_axis_up).to_4x4() + global_matrix = Matrix() + global_matrix[0][0] = global_matrix[1][1] = global_matrix[2][2] = self.global_scale + global_matrix = global_matrix * axis_conversion(to_forward=self.global_axis_forward, to_up=self.global_axis_up).to_4x4() keywords = self.as_keywords(ignore=("global_axis_forward", "global_axis_up", "global_scale", "check_existing", "filter_glob")) - keywords["GLOBAL_MATRIX"] = GLOBAL_MATRIX + keywords["global_matrix"] = global_matrix from . import export_fbx return export_fbx.save(self, context, **keywords) diff --git a/io_scene_fbx/export_fbx.py b/io_scene_fbx/export_fbx.py index 16789bf9a..fa0b5bfdf 100644 --- a/io_scene_fbx/export_fbx.py +++ b/io_scene_fbx/export_fbx.py @@ -201,7 +201,7 @@ header_comment = \ # This func can be called with just the filepath def save_single(operator, scene, filepath="", - GLOBAL_MATRIX=None, + global_matrix=None, context_objects=None, object_types={'EMPTY', 'CAMERA', 'LAMP', 'ARMATURE', 'MESH'}, mesh_apply_modifiers=True, @@ -219,8 +219,8 @@ def save_single(operator, scene, filepath="", mtx_x90 = Matrix.Rotation(math.pi / 2.0, 3, 'X') mtx4_z90 = Matrix.Rotation(math.pi / 2.0, 4, 'Z') - if GLOBAL_MATRIX is None: - GLOBAL_MATRIX = Matrix() + if global_matrix is None: + global_matrix = Matrix() # Use this for working out paths relative to the export location base_src = os.path.dirname(bpy.data.filepath) @@ -348,9 +348,9 @@ def save_single(operator, scene, filepath="", self.fbxGroupNames = [] self.fbxParent = None # set later on IF the parent is in the selection. if matrixWorld: - self.matrixWorld = GLOBAL_MATRIX * matrixWorld + self.matrixWorld = global_matrix * matrixWorld else: - self.matrixWorld = GLOBAL_MATRIX * ob.matrix_world + self.matrixWorld = global_matrix * ob.matrix_world self.__anim_poselist = {} # we should only access this @@ -362,24 +362,24 @@ def save_single(operator, scene, filepath="", def setPoseFrame(self, f, fake=False): if fake: - # annoying, have to clear GLOBAL_MATRIX - self.__anim_poselist[f] = self.matrixWorld * GLOBAL_MATRIX.inverted() + # annoying, have to clear global_matrix + self.__anim_poselist[f] = global_matrix * self.matrixWorld else: self.__anim_poselist[f] = self.blenObject.matrix_world.copy() def getAnimParRelMatrix(self, frame): if self.fbxParent: - #return (self.__anim_poselist[frame] * self.fbxParent.__anim_poselist[frame].inverted() ) * GLOBAL_MATRIX - return (GLOBAL_MATRIX * self.fbxParent.__anim_poselist[frame]).inverted() * (GLOBAL_MATRIX * self.__anim_poselist[frame]) + #return (self.__anim_poselist[frame] * self.fbxParent.__anim_poselist[frame].inverted() ) * global_matrix + return (global_matrix * self.fbxParent.__anim_poselist[frame]).inverted() * (global_matrix * self.__anim_poselist[frame]) else: - return GLOBAL_MATRIX * self.__anim_poselist[frame] + return global_matrix * self.__anim_poselist[frame] def getAnimParRelMatrixRot(self, frame): obj_type = self.blenObject.type if self.fbxParent: - matrix_rot = ((GLOBAL_MATRIX * self.fbxParent.__anim_poselist[frame]).inverted() * (GLOBAL_MATRIX * self.__anim_poselist[frame])).to_3x3() + matrix_rot = ((global_matrix * self.fbxParent.__anim_poselist[frame]).inverted() * (global_matrix * self.__anim_poselist[frame])).to_3x3() else: - matrix_rot = (GLOBAL_MATRIX * self.__anim_poselist[frame]).to_3x3() + matrix_rot = (global_matrix * self.__anim_poselist[frame]).to_3x3() # Lamps need to be rotated if obj_type == 'LAMP': @@ -465,7 +465,7 @@ def save_single(operator, scene, filepath="", scale = tuple(scale) else: # This is bad because we need the parent relative matrix from the fbx parent (if we have one), dont use anymore - #if ob and not matrix: matrix = ob.matrix_world * GLOBAL_MATRIX + #if ob and not matrix: matrix = ob.matrix_world * global_matrix if ob and not matrix: raise Exception("error: this should never happen!") @@ -937,7 +937,7 @@ def save_single(operator, scene, filepath="", do_light = not (light.use_only_shadow or (not light.use_diffuse and not light.use_specular)) do_shadow = (light.shadow_method in ('RAY_SHADOW', 'BUFFER_SHADOW')) - scale = abs(GLOBAL_MATRIX.to_scale()[0]) # scale is always uniform in this case + scale = abs(global_matrix.to_scale()[0]) # scale is always uniform in this case file.write('\n\t\t\tProperty: "LightType", "enum", "",%i' % light_type) file.write('\n\t\t\tProperty: "CastLightOnObject", "bool", "",1') -- GitLab