From 63fb923b0081a81310409dd34780bab73bf77ea4 Mon Sep 17 00:00:00 2001 From: Sebastian Sille Date: Sun, 26 Mar 2023 20:03:11 +0200 Subject: [PATCH 01/11] io_scene_3ds: Update for Blender 3.x Changed Version Material and texture bsdf shader support Added face and point flags Added material shading method Added emission strength Signed-off-by: Sebastian Sille --- io_scene_3ds/io_scene_3ds.zip | Bin 0 -> 111243 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 io_scene_3ds/io_scene_3ds.zip diff --git a/io_scene_3ds/io_scene_3ds.zip b/io_scene_3ds/io_scene_3ds.zip new file mode 100644 index 0000000000000000000000000000000000000000..7d77b48897af9c675c55a35e2841f8b6afe09cdd GIT binary patch literal 111243 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%0AmN#)MGm?au3^2o`22_>+QIlc` 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 literal 0 HcmV?d00001 -- 2.30.2 From 1e5872a009ec80cf7bd9a737fd6047da3db3a7c2 Mon Sep 17 00:00:00 2001 From: Sebastian Sille Date: Sun, 26 Mar 2023 20:07:09 +0200 Subject: [PATCH 02/11] =?UTF-8?q?=E2=80=9Eio=5Fscene=5F3ds/io=5Fscene=5F3d?= =?UTF-8?q?s.zip=E2=80=9C=20l=C3=B6schen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- io_scene_3ds/io_scene_3ds.zip | Bin 111243 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 io_scene_3ds/io_scene_3ds.zip diff --git a/io_scene_3ds/io_scene_3ds.zip b/io_scene_3ds/io_scene_3ds.zip deleted file mode 100644 index 7d77b48897af9c675c55a35e2841f8b6afe09cdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111243 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%0AmN#)MGm?au3^2o`22_>+QIlc` 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 -- 2.30.2 From e7964887195f7b730a53c333fd56c571add47376 Mon Sep 17 00:00:00 2001 From: Sebastian Sille Date: Sun, 26 Mar 2023 20:19:25 +0200 Subject: [PATCH 03/11] nrgsille-patch-1 just merging the patches Pull Request: https://projects.blender.org/blender/blender-addons/pulls/104506 --- io_scene_3ds/__init__.py | 175 +++++ io_scene_3ds/export_3ds.py | 1454 ++++++++++++++++++++++++++++++++++++ io_scene_3ds/import_3ds.py | 1271 +++++++++++++++++++++++++++++++ 3 files changed, 2900 insertions(+) create mode 100644 io_scene_3ds/__init__.py create mode 100644 io_scene_3ds/export_3ds.py create mode 100644 io_scene_3ds/import_3ds.py diff --git a/io_scene_3ds/__init__.py b/io_scene_3ds/__init__.py new file mode 100644 index 000000000..9430ca410 --- /dev/null +++ b/io_scene_3ds/__init__.py @@ -0,0 +1,175 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +from bpy_extras.io_utils import ( + ImportHelper, + ExportHelper, + orientation_helper, + axis_conversion, +) +from bpy.props import ( + BoolProperty, + EnumProperty, + FloatProperty, + StringProperty, +) +import bpy +bl_info = { + "name": "Autodesk 3DS format", + "author": "Bob Holcomb, Campbell Barton, Andreas Atteneder, Sebastian Schrand", + "version": (2, 3, 1), + "blender": (3, 0, 0), + "location": "File > Import", + "description": "Import 3DS, meshes, uvs, materials, textures, " + "cameras & lamps", + "warning": "Images must be in file folder", + "doc_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/" + "Scripts/Import-Export/Autodesk_3DS", + "category": "Import-Export", +} + +if "bpy" in locals(): + import importlib + if "import_3ds" in locals(): + importlib.reload(import_3ds) + if "export_3ds" in locals(): + importlib.reload(export_3ds) + + +@orientation_helper(axis_forward='Y', axis_up='Z') +class Import3DS(bpy.types.Operator, ImportHelper): + """Import from 3DS file format (.3ds)""" + bl_idname = "import_scene.autodesk_3ds" + bl_label = 'Import 3DS' + bl_options = {'UNDO'} + + filename_ext = ".3ds" + filter_glob: StringProperty(default="*.3ds", options={'HIDDEN'}) + + constrain_size: FloatProperty( + name="Size Constraint", + description="Scale the model by 10 until it reaches the " + "size constraint (0 to disable)", + min=0.0, max=1000.0, + soft_min=0.0, soft_max=1000.0, + default=10.0, + ) + use_image_search: BoolProperty( + name="Image Search", + description="Search subdirectories for any associated images " + "(Warning, may be slow)", + default=True, + ) + use_apply_transform: BoolProperty( + name="Apply Transform", + description="Workaround for object transformations " + "importing incorrectly", + default=True, + ) + + read_keyframe: bpy.props.BoolProperty( + name="Read Keyframe", + description="Read the keyframe data", + default=True, + ) + + def execute(self, context): + from . import import_3ds + + keywords = self.as_keywords(ignore=("axis_forward", + "axis_up", + "filter_glob", + )) + + global_matrix = axis_conversion(from_forward=self.axis_forward, + from_up=self.axis_up, + ).to_4x4() + keywords["global_matrix"] = global_matrix + + return import_3ds.load(self, context, **keywords) + + +@orientation_helper(axis_forward='Y', axis_up='Z') +class Export3DS(bpy.types.Operator, ExportHelper): + """Export to 3DS file format (.3ds)""" + bl_idname = "export_scene.autodesk_3ds" + bl_label = 'Export 3DS' + + filename_ext = ".3ds" + filter_glob: StringProperty( + default="*.3ds", + options={'HIDDEN'}, + ) + + use_selection: BoolProperty( + name="Selection Only", + description="Export selected objects only", + default=False, + ) + + def execute(self, context): + from . import export_3ds + + keywords = self.as_keywords(ignore=("axis_forward", + "axis_up", + "filter_glob", + "check_existing", + )) + global_matrix = axis_conversion(to_forward=self.axis_forward, + to_up=self.axis_up, + ).to_4x4() + keywords["global_matrix"] = global_matrix + + return export_3ds.save(self, context, **keywords) + + +# Add to a menu +def menu_func_export(self, context): + self.layout.operator(Export3DS.bl_idname, text="3D Studio (.3ds)") + + +def menu_func_import(self, context): + self.layout.operator(Import3DS.bl_idname, text="3D Studio (.3ds)") + + +def register(): + bpy.utils.register_class(Import3DS) + bpy.utils.register_class(Export3DS) + + bpy.types.TOPBAR_MT_file_import.append(menu_func_import) + bpy.types.TOPBAR_MT_file_export.append(menu_func_export) + + +def unregister(): + bpy.utils.unregister_class(Import3DS) + bpy.utils.unregister_class(Export3DS) + + bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) + +# NOTES: +# why add 1 extra vertex? and remove it when done? - +# "Answer - eekadoodle - would need to re-order UV's without this since face +# order isnt always what we give blender, BMesh will solve :D" +# +# disabled scaling to size, this requires exposing bb (easy) and understanding +# how it works (needs some time) + + +if __name__ == "__main__": + register() diff --git a/io_scene_3ds/export_3ds.py b/io_scene_3ds/export_3ds.py new file mode 100644 index 000000000..e7dda764e --- /dev/null +++ b/io_scene_3ds/export_3ds.py @@ -0,0 +1,1454 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# Script copyright (C) Bob Holcomb +# Contributors: Campbell Barton, Bob Holcomb, Richard Lärkäng, Damien McGinnes, Mark Stijnman, Sebastian Sille + +""" +Exporting is based on 3ds loader from www.gametutorials.com(Thanks DigiBen) and using information +from the lib3ds project (http://lib3ds.sourceforge.net/) sourcecode. +""" + +import bpy +import math +import struct +import mathutils +import bpy_extras +from bpy_extras import node_shader_utils + +###################################################### +# Data Structures +###################################################### + +# Some of the chunks that we will export +# ----- Primary Chunk, at the beginning of each file +PRIMARY = 0x4D4D + +# ------ Main Chunks +VERSION = 0x0002 # This gives the version of the .3ds file +KFDATA = 0xB000 # This is the header for all of the key frame info + +# ------ sub defines of OBJECTINFO +OBJECTINFO = 0x3D3D # Main mesh object chunk before the material and object information +MESHVERSION = 0x3D3E # This gives the version of the mesh +AMBIENTLIGHT = 0x2100 # The color of the ambient light +MATERIAL = 45055 # 0xAFFF // This stored the texture info +OBJECT = 16384 # 0x4000 // This stores the faces, vertices, etc... + +# >------ sub defines of MATERIAL +MATNAME = 0xA000 # This holds the material name +MATAMBIENT = 0xA010 # Ambient color of the object/material +MATDIFFUSE = 0xA020 # This holds the color of the object/material +MATSPECULAR = 0xA030 # Specular color of the object/material +MATSHINESS = 0xA040 # Specular intensity of the object/material (percent) +MATSHIN2 = 0xA041 # Reflection of the object/material (percent) +MATSHIN3 = 0xA042 # metallic/mirror of the object/material (percent) +MATTRANS = 0xA050 # Transparency value (100-OpacityValue) (percent) +MATSELFILPCT = 0xA084 # Self illumination strength (percent) +MATSHADING = 0xA100 # Material shading method + +MAT_DIFFUSEMAP = 0xA200 # This is a header for a new diffuse texture +MAT_SPECMAP = 0xA204 # head for specularity map +MAT_OPACMAP = 0xA210 # head for opacity map +MAT_REFLMAP = 0xA220 # head for reflect map +MAT_BUMPMAP = 0xA230 # head for normal map +MAT_BUMP_PERCENT = 0xA252 # Normalmap strength (percent) +MAT_TEX2MAP = 0xA33A # head for secondary texture +MAT_SHINMAP = 0xA33C # head for roughness map +MAT_SELFIMAP = 0xA33D # head for emission map + +# >------ sub defines of MAT_MAP +MATMAPFILE = 0xA300 # This holds the file name of a texture +MAT_MAP_TILING = 0xa351 # 2nd bit (from LSB) is mirror UV flag +MAT_MAP_TEXBLUR = 0xA353 # Texture blurring factor +MAT_MAP_USCALE = 0xA354 # U axis scaling +MAT_MAP_VSCALE = 0xA356 # V axis scaling +MAT_MAP_UOFFSET = 0xA358 # U axis offset +MAT_MAP_VOFFSET = 0xA35A # V axis offset +MAT_MAP_ANG = 0xA35C # UV rotation around the z-axis in rad +MAP_COL1 = 0xA360 # Tint Color1 +MAP_COL2 = 0xA362 # Tint Color2 +MAP_RCOL = 0xA364 # Red tint +MAP_GCOL = 0xA366 # Green tint +MAP_BCOL = 0xA368 # Blue tint + +RGB = 0x0010 # RGB float +RGB1 = 0x0011 # RGB Color1 +RGB2 = 0x0012 # RGB Color2 +PCT = 0x0030 # Percent chunk +MASTERSCALE = 0x0100 # Master scale factor + +# >------ sub defines of OBJECT +OBJECT_MESH = 0x4100 # This lets us know that we are reading a new object +OBJECT_LIGHT = 0x4600 # This lets us know we are reading a light object +OBJECT_CAMERA = 0x4700 # This lets us know we are reading a camera object + +# >------ Sub defines of LIGHT +LIGHT_MULTIPLIER = 0x465B # The light energy factor +LIGHT_SPOTLIGHT = 0x4610 # The target of a spotlight +LIGHT_SPOTROLL = 0x4656 # The roll angle of the spot + +# >------ sub defines of CAMERA +OBJECT_CAM_RANGES = 0x4720 # The camera range values + +# >------ sub defines of OBJECT_MESH +OBJECT_VERTICES = 0x4110 # The objects vertices +OBJECT_VERTFLAGS = 0x4111 # The objects vertex flags +OBJECT_FACES = 0x4120 # The objects faces +OBJECT_MATERIAL = 0x4130 # This is found if the object has a material, either texture map or color +OBJECT_UV = 0x4140 # The UV texture coordinates +OBJECT_SMOOTH = 0x4150 # The objects smooth groups +OBJECT_TRANS_MATRIX = 0x4160 # The Object Matrix + +# >------ sub defines of KFDATA +KFDATA_KFHDR = 0xB00A +KFDATA_KFSEG = 0xB008 +KFDATA_KFCURTIME = 0xB009 +KFDATA_OBJECT_NODE_TAG = 0xB002 + +# >------ sub defines of OBJECT_NODE_TAG +OBJECT_NODE_ID = 0xB030 +OBJECT_NODE_HDR = 0xB010 +OBJECT_PIVOT = 0xB013 +OBJECT_INSTANCE_NAME = 0xB011 +POS_TRACK_TAG = 0xB020 +ROT_TRACK_TAG = 0xB021 +SCL_TRACK_TAG = 0xB022 + + +# So 3ds max can open files, limit names to 12 in length +# this is very annoying for filenames! +name_unique = [] # stores str, ascii only +name_mapping = {} # stores {orig: byte} mapping + + +def sane_name(name): + name_fixed = name_mapping.get(name) + if name_fixed is not None: + return name_fixed + + # strip non ascii chars + new_name_clean = new_name = name.encode("ASCII", "replace").decode("ASCII")[:12] + i = 0 + + while new_name in name_unique: + new_name = new_name_clean + ".%.3d" % i + i += 1 + + # note, appending the 'str' version. + name_unique.append(new_name) + name_mapping[name] = new_name = new_name.encode("ASCII", "replace") + return new_name + + +def uv_key(uv): + return round(uv[0], 6), round(uv[1], 6) + + +# size defines: +SZ_SHORT = 2 +SZ_INT = 4 +SZ_FLOAT = 4 + + +class _3ds_ushort(object): + """Class representing a short (2-byte integer) for a 3ds file. + *** This looks like an unsigned short H is unsigned from the struct docs - Cam***""" + __slots__ = ("value", ) + + def __init__(self, val=0): + self.value = val + + def get_size(self): + return SZ_SHORT + + def write(self, file): + file.write(struct.pack("= ma_ls_len: + ma_index = f.material_index = 0 + ma = ma_ls[ma_index] + ma_name = None if ma is None else ma.name + # else there already set to none + + img = get_uv_image(ma) + img_name = None if img is None else img.name + + materialDict.setdefault((ma_name, img_name), (ma, img)) + + else: + for ma in ma_ls: + if ma: # material may be None so check its not. + materialDict.setdefault((ma.name, None), (ma, None)) + + # Why 0 Why! + for f in data.polygons: + if f.material_index >= ma_ls_len: + f.material_index = 0 + + # ob_derived_eval.to_mesh_clear() + + #if free: + # free_derived_objects(ob) + + # Make material chunks for all materials used in the meshes: + for ma_image in materialDict.values(): + object_info.add_subchunk(make_material_chunk(ma_image[0], ma_image[1])) + + # Give all objects a unique ID and build a dictionary from object name to object id: + translation = {} # collect translation for transformation matrix + #name_to_id = {} + for ob, data, matrix in mesh_objects: + translation[ob.name] = ob.location + #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, 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(ob, mesh, matrix, materialDict, translation)) + + # 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) + #blender_mesh.vertices = None + + i += i + + # 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 + ''' + + # Create light object chunks + for ob in light_objects: + object_chunk = _3ds_chunk(OBJECT) + light_chunk = _3ds_chunk(OBJECT_LIGHT) + color_float_chunk = _3ds_chunk(RGB) + energy_factor = _3ds_chunk(LIGHT_MULTIPLIER) + object_chunk.add_variable("light", _3ds_string(sane_name(ob.name))) + light_chunk.add_variable("location", _3ds_point_3d(ob.location)) + color_float_chunk.add_variable("color", _3ds_float_color(ob.data.color)) + energy_factor.add_variable("energy", _3ds_float(ob.data.energy * .001)) + light_chunk.add_subchunk(color_float_chunk) + light_chunk.add_subchunk(energy_factor) + + if ob.data.type == 'SPOT': + cone_angle = math.degrees(ob.data.spot_size) + hotspot = cone_angle - (ob.data.spot_blend * math.floor(cone_angle)) + hypo = math.copysign(math.sqrt(pow(ob.location[0], 2) + pow(ob.location[1], 2)), ob.location[1]) + pos_x = ob.location[0] + (ob.location[1] * math.tan(ob.rotation_euler[2])) + pos_y = ob.location[1] + (ob.location[0] * math.tan(math.radians(90) - ob.rotation_euler[2])) + pos_z = hypo * math.tan(math.radians(90) - ob.rotation_euler[0]) + spotlight_chunk = _3ds_chunk(LIGHT_SPOTLIGHT) + spot_roll_chunk = _3ds_chunk(LIGHT_SPOTROLL) + spotlight_chunk.add_variable("target", _3ds_point_3d((pos_x, pos_y, pos_z))) + spotlight_chunk.add_variable("hotspot", _3ds_float(round(hotspot, 4))) + spotlight_chunk.add_variable("angle", _3ds_float(round(cone_angle, 4))) + spot_roll_chunk.add_variable("roll", _3ds_float(round(ob.rotation_euler[1], 6))) + spotlight_chunk.add_subchunk(spot_roll_chunk) + light_chunk.add_subchunk(spotlight_chunk) + + # Add light to object info + object_chunk.add_subchunk(light_chunk) + object_info.add_subchunk(object_chunk) + + # Create camera object chunks + for ob in camera_objects: + object_chunk = _3ds_chunk(OBJECT) + camera_chunk = _3ds_chunk(OBJECT_CAMERA) + diagonal = math.copysign(math.sqrt(pow(ob.location[0], 2) + pow(ob.location[1], 2)), ob.location[1]) + focus_x = ob.location[0] + (ob.location[1] * math.tan(ob.rotation_euler[2])) + focus_y = ob.location[1] + (ob.location[0] * math.tan(math.radians(90) - ob.rotation_euler[2])) + focus_z = diagonal * math.tan(math.radians(90) - ob.rotation_euler[0]) + object_chunk.add_variable("camera", _3ds_string(sane_name(ob.name))) + camera_chunk.add_variable("location", _3ds_point_3d(ob.location)) + camera_chunk.add_variable("target", _3ds_point_3d((focus_x, focus_y, focus_z))) + camera_chunk.add_variable("roll", _3ds_float(round(ob.rotation_euler[1], 6))) + camera_chunk.add_variable("lens", _3ds_float(ob.data.lens)) + object_chunk.add_subchunk(camera_chunk) + object_info.add_subchunk(object_chunk) + + # 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: + # Blender.Window.WaitCursor(0) + print("3ds export time: %.2f" % (time.time() - duration)) + + # Debugging only: dump the chunk hierarchy: + # primary.dump() + + return {'FINISHED'} diff --git a/io_scene_3ds/import_3ds.py b/io_scene_3ds/import_3ds.py new file mode 100644 index 000000000..833c43a48 --- /dev/null +++ b/io_scene_3ds/import_3ds.py @@ -0,0 +1,1271 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# Script copyright (C) Bob Holcomb +# Contributors: Bob Holcomb, Richard L?rk?ng, Damien McGinnes, Sebastian Sille +# Campbell Barton, Mario Lapin, Dominique Lorre, Andreas Atteneder + +import os +import time +import struct +import bpy +import math +import mathutils +from bpy_extras.node_shader_utils import PrincipledBSDFWrapper + +BOUNDS_3DS = [] + + +###################################################### +# Data Structures +###################################################### + +# Some of the chunks that we will see +# ----- Primary Chunk, at the beginning of each file +PRIMARY = 0x4D4D + +# ------ Main Chunks +OBJECTINFO = 0x3D3D # This gives the version of the mesh and is found right before the material and object information +VERSION = 0x0002 # This gives the version of the .3ds file +EDITKEYFRAME = 0xB000 # This is the header for all of the key frame info + +# ------ Data Chunks, used for various attributes +PERCENTAGE_SHORT = 0x30 +PERCENTAGE_FLOAT = 0x31 + +# ------ sub defines of OBJECTINFO +MATERIAL = 0xAFFF # This stored the texture info +OBJECT = 0x4000 # This stores the faces, vertices, etc... + +# >------ sub defines of MATERIAL +# ------ sub defines of MATERIAL_BLOCK +MAT_NAME = 0xA000 # This holds the material name +MAT_AMBIENT = 0xA010 # Ambient color of the object/material +MAT_DIFFUSE = 0xA020 # This holds the color of the object/material +MAT_SPECULAR = 0xA030 # Specular color of the object/material +MAT_SHINESS = 0xA040 # Roughness of the object/material (percent) +MAT_SHIN2 = 0xA041 # Shininess of the object/material (percent) +MAT_SHIN3 = 0xA042 # Reflection of the object/material (percent) +MAT_TRANSPARENCY = 0xA050 # Transparency value of material (percent) +MAT_SELF_ILLUM = 0xA080 # Self Illumination value of material +MAT_SELF_ILPCT = 0xA084 # Self illumination strength (percent) +MAT_WIRE = 0xA085 # Only render's wireframe +MAT_SHADING = 0xA100 # Material shading method + +MAT_TEXTURE_MAP = 0xA200 # This is a header for a new texture map +MAT_SPECULAR_MAP = 0xA204 # This is a header for a new specular map +MAT_OPACITY_MAP = 0xA210 # This is a header for a new opacity map +MAT_REFLECTION_MAP = 0xA220 # This is a header for a new reflection map +MAT_BUMP_MAP = 0xA230 # This is a header for a new bump map +MAT_BUMP_PERCENT = 0xA252 # Normalmap strength (percent) +MAT_TEX2_MAP = 0xA33A # This is a header for a secondary texture +MAT_SHIN_MAP = 0xA33C # This is a header for a new roughness map +MAT_SELFI_MAP = 0xA33D # This is a header for a new emission map +MAT_MAP_FILEPATH = 0xA300 # This holds the file name of the texture + +MAT_MAP_TILING = 0xa351 # 2nd bit (from LSB) is mirror UV flag +MAT_MAP_USCALE = 0xA354 # U axis scaling +MAT_MAP_VSCALE = 0xA356 # V axis scaling +MAT_MAP_UOFFSET = 0xA358 # U axis offset +MAT_MAP_VOFFSET = 0xA35A # V axis offset +MAT_MAP_ANG = 0xA35C # UV rotation around the z-axis in rad +MAT_MAP_COL1 = 0xA360 # Map Color1 +MAT_MAP_COL2 = 0xA362 # Map Color2 +MAT_MAP_RCOL = 0xA364 # Red mapping +MAT_MAP_GCOL = 0xA366 # Green mapping +MAT_MAP_BCOL = 0xA368 # Blue mapping +MAT_FLOAT_COLOR = 0x0010 # color defined as 3 floats +MAT_24BIT_COLOR = 0x0011 # color defined as 3 bytes + +# >------ sub defines of OBJECT +OBJECT_MESH = 0x4100 # This lets us know that we are reading a new object +OBJECT_LIGHT = 0x4600 # This lets un know we are reading a light object +OBJECT_LIGHT_SPOT = 0x4610 # The light is a spotloght. +OBJECT_LIGHT_OFF = 0x4620 # The light off. +OBJECT_LIGHT_ATTENUATE = 0x4625 +OBJECT_LIGHT_RAYSHADE = 0x4627 +OBJECT_LIGHT_SHADOWED = 0x4630 +OBJECT_LIGHT_LOCAL_SHADOW = 0x4640 +OBJECT_LIGHT_LOCAL_SHADOW2 = 0x4641 +OBJECT_LIGHT_SEE_CONE = 0x4650 +OBJECT_LIGHT_SPOT_RECTANGULAR = 0x4651 +OBJECT_LIGHT_SPOT_OVERSHOOT = 0x4652 +OBJECT_LIGHT_SPOT_PROJECTOR = 0x4653 +OBJECT_LIGHT_EXCLUDE = 0x4654 +OBJECT_LIGHT_RANGE = 0x4655 +OBJECT_LIGHT_ROLL = 0x4656 +OBJECT_LIGHT_SPOT_ASPECT = 0x4657 +OBJECT_LIGHT_RAY_BIAS = 0x4658 +OBJECT_LIGHT_INNER_RANGE = 0x4659 +OBJECT_LIGHT_OUTER_RANGE = 0x465A +OBJECT_LIGHT_MULTIPLIER = 0x465B +OBJECT_LIGHT_AMBIENT_LIGHT = 0x4680 + +OBJECT_CAMERA = 0x4700 # This lets un know we are reading a camera object + +# >------ sub defines of CAMERA +OBJECT_CAM_RANGES = 0x4720 # The camera range values + +# >------ sub defines of OBJECT_MESH +OBJECT_VERTICES = 0x4110 # The objects vertices +OBJECT_VERTFLAGS = 0x4111 # The objects vertex flags +OBJECT_FACES = 0x4120 # The objects faces +OBJECT_MATERIAL = 0x4130 # This is found if the object has a material, either texture map or color +OBJECT_UV = 0x4140 # The UV texture coordinates +OBJECT_SMOOTH = 0x4150 # The Object smooth groups +OBJECT_TRANS_MATRIX = 0x4160 # The Object Matrix + +# >------ sub defines of EDITKEYFRAME +KFDATA_AMBIENT = 0xB001 +KFDATA_OBJECT = 0xB002 +KFDATA_CAMERA = 0xB003 +KFDATA_TARGET = 0xB004 +KFDATA_LIGHT = 0xB005 +KFDATA_L_TARGET = 0xB006 +KFDATA_SPOTLIGHT = 0xB007 +KFDATA_KFSEG = 0xB008 +# KFDATA_CURTIME = 0xB009 +# KFDATA_KFHDR = 0xB00A +# >------ sub defines of KEYFRAME_NODE +OBJECT_NODE_HDR = 0xB010 +OBJECT_INSTANCE_NAME = 0xB011 +# OBJECT_PRESCALE = 0xB012 +OBJECT_PIVOT = 0xB013 +# OBJECT_BOUNDBOX = 0xB014 +# MORPH_SMOOTH = 0xB015 +POS_TRACK_TAG = 0xB020 +ROT_TRACK_TAG = 0xB021 +SCL_TRACK_TAG = 0xB022 +FOV_TRACK_TAG = 0xB023 +ROLL_TRACK_TAG = 0xB024 +COL_TRACK_TAG = 0xB025 +# MORPH_TRACK_TAG = 0xB026 +# HOTSPOT_TRACK_TAG = 0xB027 +# FALLOFF_TRACK_TAG = 0xB028 +# HIDE_TRACK_TAG = 0xB029 +# OBJECT_NODE_ID = 0xB030 + +ROOT_OBJECT = 0xFFFF + +global scn +scn = None + +object_dictionary = {} +object_matrix = {} + + +class Chunk: + __slots__ = ( + "ID", + "length", + "bytes_read", + ) + # we don't read in the bytes_read, we compute that + binary_format = " 0: + bmesh.polygons[f].use_smooth = True + + if contextMatrix: + ob.matrix_local = contextMatrix + object_matrix[ob] = contextMatrix.copy() + + # a spare chunk + new_chunk = Chunk() + temp_chunk = Chunk() + + CreateBlenderObject = False + CreateLightObject = False + CreateCameraObject = False + + def read_float_color(temp_chunk): + temp_data = file.read(SZ_3FLOAT) + temp_chunk.bytes_read += SZ_3FLOAT + return [float(col) for col in struct.unpack('<3f', temp_data)] + + def read_float(temp_chunk): + temp_data = file.read(SZ_FLOAT) + temp_chunk.bytes_read += SZ_FLOAT + return struct.unpack(' 3: + print('\tNon-Fatal Error: Version greater than 3, may not load correctly: ', version) + + # is it an object info chunk? + elif new_chunk.ID == OBJECTINFO: + process_next_chunk(context, file, new_chunk, imported_objects, IMAGE_SEARCH, KEYFRAME) + + # keep track of how much we read in the main chunk + new_chunk.bytes_read += temp_chunk.bytes_read + + # is it an object chunk? + elif new_chunk.ID == OBJECT: + + if CreateBlenderObject: + putContextMesh( + context, + contextMesh_vertls, + contextMesh_facels, + contextMesh_flag, + contextMeshMaterials, + contextMesh_smooth, + ) + contextMesh_vertls = [] + contextMesh_facels = [] + contextMeshMaterials = [] + contextMesh_flag = None + contextMesh_smooth = None + contextMeshUV = None + # Reset matrix + contextMatrix = None + + CreateBlenderObject = True + contextObName, read_str_len = read_string(file) + new_chunk.bytes_read += read_str_len + + # is it a material chunk? + elif new_chunk.ID == MATERIAL: + contextMaterial = bpy.data.materials.new('Material') + contextWrapper = PrincipledBSDFWrapper(contextMaterial, is_readonly=False, use_nodes=False) + + elif new_chunk.ID == MAT_NAME: + material_name, read_str_len = read_string(file) + + # plus one for the null character that ended the string + new_chunk.bytes_read += read_str_len + contextMaterial.name = material_name.rstrip() # remove trailing whitespace + MATDICT[material_name] = contextMaterial + + elif new_chunk.ID == MAT_AMBIENT: + read_chunk(file, temp_chunk) + # only available color is emission color + if temp_chunk.ID == MAT_FLOAT_COLOR: + contextMaterial.line_color[:3] = read_float_color(temp_chunk) + elif temp_chunk.ID == MAT_24BIT_COLOR: + contextMaterial.line_color[:3] = read_byte_color(temp_chunk) + else: + skip_to_end(file, temp_chunk) + new_chunk.bytes_read += temp_chunk.bytes_read + + elif new_chunk.ID == MAT_DIFFUSE: + read_chunk(file, temp_chunk) + if temp_chunk.ID == MAT_FLOAT_COLOR: + contextMaterial.diffuse_color[:3] = read_float_color(temp_chunk) + elif temp_chunk.ID == MAT_24BIT_COLOR: + contextMaterial.diffuse_color[:3] = read_byte_color(temp_chunk) + else: + skip_to_end(file, temp_chunk) + new_chunk.bytes_read += temp_chunk.bytes_read + + elif new_chunk.ID == MAT_SPECULAR: + read_chunk(file, temp_chunk) + # Specular color is available + if temp_chunk.ID == MAT_FLOAT_COLOR: + contextMaterial.specular_color = read_float_color(temp_chunk) + elif temp_chunk.ID == MAT_24BIT_COLOR: + contextMaterial.specular_color = read_byte_color(temp_chunk) + else: + skip_to_end(file, temp_chunk) + new_chunk.bytes_read += temp_chunk.bytes_read + + elif new_chunk.ID == MAT_SHINESS: + read_chunk(file, temp_chunk) + if temp_chunk.ID == PERCENTAGE_SHORT: + temp_data = file.read(SZ_U_SHORT) + temp_chunk.bytes_read += SZ_U_SHORT + contextMaterial.roughness = 1 - (float(struct.unpack('= 2: + contextWrapper.use_nodes = True + contextWrapper.emission_color = contextMaterial.line_color[:3] + contextWrapper.emission_strength = contextMaterial.line_priority / 100 + contextWrapper.base_color = contextMaterial.diffuse_color[:3] + contextWrapper.specular = contextMaterial.specular_intensity + contextWrapper.roughness = contextMaterial.roughness + contextWrapper.metallic = contextMaterial.metallic + contextWrapper.alpha = contextMaterial.diffuse_color[3] + contextWrapper.use_nodes = False + if shading >= 3: + contextWrapper.use_nodes = True + + elif new_chunk.ID == MAT_TEXTURE_MAP: + read_texture(new_chunk, temp_chunk, "Diffuse", "COLOR") + + elif new_chunk.ID == MAT_SPECULAR_MAP: + read_texture(new_chunk, temp_chunk, "Specular", "SPECULARITY") + + elif new_chunk.ID == MAT_OPACITY_MAP: + contextMaterial.blend_method = 'BLEND' + read_texture(new_chunk, temp_chunk, "Opacity", "ALPHA") + + elif new_chunk.ID == MAT_REFLECTION_MAP: + read_texture(new_chunk, temp_chunk, "Reflect", "METALLIC") + + elif new_chunk.ID == MAT_BUMP_MAP: + read_texture(new_chunk, temp_chunk, "Bump", "NORMAL") + + elif new_chunk.ID == MAT_BUMP_PERCENT: + read_chunk(file, temp_chunk) + if temp_chunk.ID == PERCENTAGE_SHORT: + temp_data = file.read(SZ_U_SHORT) + temp_chunk.bytes_read += SZ_U_SHORT + contextWrapper.normalmap_strength = (float(struct.unpack(' value: + axis_min[axis] = value + if axis_max[axis] < value: + axis_max[axis] = value + + # Scale objects + max_axis = max(axis_max[0] - axis_min[0], + axis_max[1] - axis_min[1], + axis_max[2] - axis_min[2]) + scale = 1.0 + + while global_clamp_size < max_axis * scale: + scale = scale / 10.0 + + scale_mat = mathutils.Matrix.Scale(scale, 4) + + for obj in imported_objects: + if obj.parent is None: + obj.matrix_world = scale_mat @ obj.matrix_world + + # Select all new objects. + print(" done in %.4f sec." % (time.time() - time1)) + file.close() + + +def load(operator, + context, + filepath="", + constrain_size=0.0, + use_image_search=True, + read_keyframe=True, + use_apply_transform=True, + global_matrix=None, + ): + + load_3ds(filepath, + context, + IMPORT_CONSTRAIN_BOUNDS=constrain_size, + IMAGE_SEARCH=use_image_search, + KEYFRAME=read_keyframe, + APPLY_MATRIX=use_apply_transform, + global_matrix=global_matrix, + ) + + return {'FINISHED'} -- 2.30.2 From 81b53f784bad24d88b8abb4a13717ec0a100517c Mon Sep 17 00:00:00 2001 From: Sebastian Sille Date: Mon, 27 Mar 2023 00:02:15 +0200 Subject: [PATCH 04/11] io_scene_3ds: Update for Blender 3.x Changed Version Signed-off-by: Sebastian Sille --- io_scene_3ds/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/io_scene_3ds/__init__.py b/io_scene_3ds/__init__.py index 9430ca410..9bf20f540 100644 --- a/io_scene_3ds/__init__.py +++ b/io_scene_3ds/__init__.py @@ -32,7 +32,7 @@ import bpy bl_info = { "name": "Autodesk 3DS format", "author": "Bob Holcomb, Campbell Barton, Andreas Atteneder, Sebastian Schrand", - "version": (2, 3, 1), + "version": (2, 3, 2), "blender": (3, 0, 0), "location": "File > Import", "description": "Import 3DS, meshes, uvs, materials, textures, " -- 2.30.2 From 31d1a49b2e516dfef7f12b86460a03fd8b7f3a2d Mon Sep 17 00:00:00 2001 From: Sebastian Sille Date: Mon, 27 Mar 2023 00:03:42 +0200 Subject: [PATCH 05/11] io_scene_3ds: Inverted roughness Inverted roughness to match with 3ds shininess Signed-off-by: Sebastian Sille --- io_scene_3ds/export_3ds.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/io_scene_3ds/export_3ds.py b/io_scene_3ds/export_3ds.py index e7dda764e..55053222a 100644 --- a/io_scene_3ds/export_3ds.py +++ b/io_scene_3ds/export_3ds.py @@ -668,7 +668,7 @@ def make_material_chunk(material, image): material_chunk.add_subchunk(make_material_subchunk(MATAMBIENT, wrap.emission_color[:3])) material_chunk.add_subchunk(make_material_subchunk(MATDIFFUSE, wrap.base_color[:3])) material_chunk.add_subchunk(make_material_subchunk(MATSPECULAR, material.specular_color[:])) - material_chunk.add_subchunk(make_percent_subchunk(MATSHINESS, wrap.roughness)) + material_chunk.add_subchunk(make_percent_subchunk(MATSHINESS, 1 - wrap.roughness)) material_chunk.add_subchunk(make_percent_subchunk(MATSHIN2, wrap.specular)) material_chunk.add_subchunk(make_percent_subchunk(MATSHIN3, wrap.metallic)) material_chunk.add_subchunk(make_percent_subchunk(MATTRANS, 1 - wrap.alpha)) @@ -716,7 +716,7 @@ def make_material_chunk(material, image): if wrap.roughness_texture: roughness = [wrap.roughness_texture] - r_pct = material.roughness + r_pct = 1 - material.roughness matmap = make_material_texture_chunk(MAT_SHINMAP, roughness, r_pct) if matmap: material_chunk.add_subchunk(matmap) @@ -749,7 +749,7 @@ def make_material_chunk(material, image): material_chunk.add_subchunk(make_material_subchunk(MATAMBIENT, material.line_color[:3])) material_chunk.add_subchunk(make_material_subchunk(MATDIFFUSE, material.diffuse_color[:3])) material_chunk.add_subchunk(make_material_subchunk(MATSPECULAR, material.specular_color[:])) - material_chunk.add_subchunk(make_percent_subchunk(MATSHINESS, material.roughness)) + material_chunk.add_subchunk(make_percent_subchunk(MATSHINESS, 1 - material.roughness)) material_chunk.add_subchunk(make_percent_subchunk(MATSHIN2, material.specular_intensity)) material_chunk.add_subchunk(make_percent_subchunk(MATSHIN3, material.metallic)) material_chunk.add_subchunk(make_percent_subchunk(MATTRANS, 1 - material.diffuse_color[3])) -- 2.30.2 From 389eda1897f4b71059d0be48776c18f0df7ec9cc Mon Sep 17 00:00:00 2001 From: Sebastian Sille Date: Mon, 27 Mar 2023 00:07:42 +0200 Subject: [PATCH 06/11] io_scene_3ds: Remove trailing space some cleanup Signed-off-by: Sebastian Sille --- io_scene_3ds/import_3ds.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/io_scene_3ds/import_3ds.py b/io_scene_3ds/import_3ds.py index 833c43a48..118a78a55 100644 --- a/io_scene_3ds/import_3ds.py +++ b/io_scene_3ds/import_3ds.py @@ -168,7 +168,6 @@ scn = None object_dictionary = {} object_matrix = {} - class Chunk: __slots__ = ( "ID", @@ -189,7 +188,6 @@ class Chunk: print('length: ', self.length) print('bytes_read: ', self.bytes_read) - def read_chunk(file, chunk): temp_data = file.read(struct.calcsize(chunk.binary_format)) data = struct.unpack(chunk.binary_format, temp_data) @@ -201,7 +199,6 @@ def read_chunk(file, chunk): # if debugging # chunk.dump() - def read_string(file): # read in the characters till we get a null character s = [] @@ -220,7 +217,6 @@ def read_string(file): # IMPORT ###################################################### - def process_next_object_chunk(file, previous_chunk): new_chunk = Chunk() @@ -228,14 +224,12 @@ def process_next_object_chunk(file, previous_chunk): # read the next chunk read_chunk(file, new_chunk) - def skip_to_end(file, skip_chunk): buffer_size = skip_chunk.length - skip_chunk.bytes_read binary_format = "%ic" % buffer_size file.read(struct.calcsize(binary_format)) skip_chunk.bytes_read += buffer_size - def add_texture_to_material(image, contextWrapper, pct, extend, alpha, scale, offset, angle, tintcolor, mapto): shader = contextWrapper.node_principled_bsdf nodetree = contextWrapper.material.node_tree @@ -322,7 +316,6 @@ def add_texture_to_material(image, contextWrapper, pct, extend, alpha, scale, of shader.location = (300, 300) contextWrapper._grid_to_location(1, 0, dst_node=contextWrapper.node_out, ref_node=shader) - def process_next_chunk(context, file, previous_chunk, imported_objects, IMAGE_SEARCH, KEYFRAME): from bpy_extras.image_utils import load_image @@ -1114,7 +1107,6 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, IMAGE_SE #pivot_matrix = mathutils.Matrix.Translation(pivot_matrix.to_3x3() @ -pivot) ob.data.transform(pivot_matrix) - def load_3ds(filepath, context, IMPORT_CONSTRAIN_BOUNDS=10.0, @@ -1123,7 +1115,6 @@ def load_3ds(filepath, APPLY_MATRIX=True, global_matrix=None): # global SCN - # XXX # if BPyMessages.Error_NoFile(filepath): # return @@ -1248,7 +1239,6 @@ def load_3ds(filepath, print(" done in %.4f sec." % (time.time() - time1)) file.close() - def load(operator, context, filepath="", -- 2.30.2 From 4f31fe5ac7de0732d0bba67fecbb8b037ac0d1d9 Mon Sep 17 00:00:00 2001 From: Sebastian Sille Date: Mon, 27 Mar 2023 12:04:03 +0200 Subject: [PATCH 07/11] io_scene_3ds: Added face and point flags changed vertex loop order if tri loop ends with zero Signed-off-by: Sebastian Sille --- io_scene_3ds/export_3ds.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/io_scene_3ds/export_3ds.py b/io_scene_3ds/export_3ds.py index 55053222a..09752b153 100644 --- a/io_scene_3ds/export_3ds.py +++ b/io_scene_3ds/export_3ds.py @@ -791,7 +791,7 @@ def extract_triangles(mesh): img = None for i, face in enumerate(mesh.loop_triangles): f_v = face.vertices - v1, v2, v3 = f_v[0], f_v[1], f_v[2] + v1, v2, v3 = f_v uf = mesh.uv_layers.active.data if do_uv else None if do_uv: @@ -800,7 +800,7 @@ def extract_triangles(mesh): img = get_uv_image(ma) if uf else None if img is not None: img = img.name - uv1, uv2, uv3 = f_uv[0], f_uv[1], f_uv[2] + uv1, uv2, uv3 = f_uv """Flag 0x1 sets CA edge visible, Flag 0x2 sets BC edge visible, Flag 0x4 sets AB edge visible Flag 0x8 indicates a U axis texture wrap and Flag 0x10 indicates a V axis texture wrap -- 2.30.2 From 1af6eb3394fc779a5b79005724618475faca184d Mon Sep 17 00:00:00 2001 From: Sebastian Sille Date: Mon, 27 Mar 2023 12:11:14 +0200 Subject: [PATCH 08/11] io_scene_3ds: Auto smooth after sharp and smoothflag import enabled autosmooth after importing smoothgroups and edge flags Signed-off-by: Sebastian Sille --- io_scene_3ds/import_3ds.py | 1 + 1 file changed, 1 insertion(+) diff --git a/io_scene_3ds/import_3ds.py b/io_scene_3ds/import_3ds.py index 118a78a55..b0846e0a5 100644 --- a/io_scene_3ds/import_3ds.py +++ b/io_scene_3ds/import_3ds.py @@ -452,6 +452,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, IMAGE_SE smoothface = myContextMesh_smooth[f] if smoothface > 0: bmesh.polygons[f].use_smooth = True + bmesh.use_auto_smooth = True if contextMatrix: ob.matrix_local = contextMatrix -- 2.30.2 From cfc0a3984fd4c160b4b732238f0cccbbe36dc35a Mon Sep 17 00:00:00 2001 From: Sebastian Sille Date: Mon, 27 Mar 2023 12:38:43 +0200 Subject: [PATCH 09/11] io_scene_3ds: Update for Blender 3.x Added warning that filenames are limited to DOS 8.3 format Signed-off-by: Sebastian Sille --- io_scene_3ds/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/io_scene_3ds/__init__.py b/io_scene_3ds/__init__.py index 9bf20f540..42283693e 100644 --- a/io_scene_3ds/__init__.py +++ b/io_scene_3ds/__init__.py @@ -37,7 +37,8 @@ bl_info = { "location": "File > Import", "description": "Import 3DS, meshes, uvs, materials, textures, " "cameras & lamps", - "warning": "Images must be in file folder", + "warning": "Images must be in file folder, " + "filename is limited to DOS 8.3 format", "doc_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/" "Scripts/Import-Export/Autodesk_3DS", "category": "Import-Export", -- 2.30.2 From 52b28788f1406c8aaad2a0a99eac5aedd1b5ff41 Mon Sep 17 00:00:00 2001 From: Sebastian Sille Date: Tue, 28 Mar 2023 12:08:39 +0200 Subject: [PATCH 10/11] io_scene_3ds: Added face and point flags changed vertex loop order if tri loop ends with zero Signed-off-by: Sebastian Sille --- io_scene_3ds/export_3ds.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/io_scene_3ds/export_3ds.py b/io_scene_3ds/export_3ds.py index 09752b153..69d907033 100644 --- a/io_scene_3ds/export_3ds.py +++ b/io_scene_3ds/export_3ds.py @@ -803,14 +803,17 @@ def extract_triangles(mesh): uv1, uv2, uv3 = f_uv """Flag 0x1 sets CA edge visible, Flag 0x2 sets BC edge visible, Flag 0x4 sets AB edge visible - Flag 0x8 indicates a U axis texture wrap and Flag 0x10 indicates a V axis texture wrap + Flag 0x8 indicates a U axis texture wrap seam and Flag 0x10 indicates a V axis texture wrap seam In Blender we use the edge CA, BC, and AB flags for sharp edges flags""" a_b = mesh.edges[mesh.loops[face.loops[0]].edge_index] b_c = mesh.edges[mesh.loops[face.loops[1]].edge_index] c_a = mesh.edges[mesh.loops[face.loops[2]].edge_index] if v3 == 0: + v1, v2, v3 = v3, v1, v2 a_b, b_c, c_a = c_a, a_b, b_c + if do_uv: + uv1, uv2, uv3 = uv3, uv1, uv2 faceflag = 0 if c_a.use_edge_sharp: @@ -822,11 +825,7 @@ def extract_triangles(mesh): smoothgroup = polygroup[face.polygon_index] - if len(f_v)==3: - if v3 == 0: - v1, v2, v3 = v3, v1, v2 - if do_uv: - uv1, uv2, uv3 = uv3, uv1, uv2 + if len(f_v)==3: new_tri = tri_wrapper((v1, v2, v3), face.material_index, img) if (do_uv): new_tri.faceuvs = uv_key(uv1), uv_key(uv2), uv_key(uv3) -- 2.30.2 From 0d64fbee551108deeaadff48f348414674cce6d4 Mon Sep 17 00:00:00 2001 From: Sebastian Sille Date: Tue, 28 Mar 2023 12:10:09 +0200 Subject: [PATCH 11/11] io_scene_3ds: Update for Blender 3.x Added warning that filenames are limited to DOS 8.3 format Signed-off-by: Sebastian Sille --- io_scene_3ds/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/io_scene_3ds/__init__.py b/io_scene_3ds/__init__.py index 42283693e..4cd1ce86c 100644 --- a/io_scene_3ds/__init__.py +++ b/io_scene_3ds/__init__.py @@ -38,7 +38,7 @@ bl_info = { "description": "Import 3DS, meshes, uvs, materials, textures, " "cameras & lamps", "warning": "Images must be in file folder, " - "filename is limited to DOS 8.3 format", + "filenames are limited to DOS 8.3 format", "doc_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/" "Scripts/Import-Export/Autodesk_3DS", "category": "Import-Export", -- 2.30.2