diff --git a/io_scene_3ds/export_3ds.py b/io_scene_3ds/export_3ds.py index c9e731508..6a8dcb207 100644 --- a/io_scene_3ds/export_3ds.py +++ b/io_scene_3ds/export_3ds.py @@ -85,7 +85,10 @@ 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 +LIGHT_SPOT_ROLL = 0x4656 # Light spot roll angle +LIGHT_SPOT_SHADOWED = 0x4630 # Light spot shadow flag +LIGHT_SPOT_SEE_CONE = 0x4650 # Light spot show cone flag +LIGHT_SPOT_RECTANGLE = 0x4651 # Light spot rectangle flag # >------ sub defines of CAMERA OBJECT_CAM_RANGES = 0x4720 # The camera range values @@ -106,13 +109,29 @@ 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 +AMBIENT_NODE_TAG = 0xB001 # Ambient node tag +OBJECT_NODE_TAG = 0xB002 # Object tree tag +CAMERA_NODE_TAG = 0xB003 # Camera object tag +TARGET_NODE_TAG = 0xB004 # Camera target tag +LIGHT_NODE_TAG = 0xB005 # Light object tag +LTARGET_NODE_TAG = 0xB006 # Light target tag +SPOT_NODE_TAG = 0xB007 # Spotlight tag +OBJECT_NODE_ID = 0xB030 # Object hierachy ID +OBJECT_NODE_HDR = 0xB010 # Hierachy tree header +OBJECT_INSTANCE_NAME = 0xB011 # Object instance name +OBJECT_PIVOT = 0xB013 # Object pivot position +OBJECT_BOUNDBOX = 0xB014 # Object boundbox +OBJECT_MORPH_SMOOTH = 0xB015 # Object smooth angle +POS_TRACK_TAG = 0xB020 # Position transform tag +ROT_TRACK_TAG = 0xB021 # Rotation transform tag +SCL_TRACK_TAG = 0xB022 # Scale transform tag +FOV_TRACK_TAG = 0xB023 # Field of view tag +ROLL_TRACK_TAG = 0xB024 # Roll transform tag +COL_TRACK_TAG = 0xB025 # Color transform tag +HOTSPOT_TRACK_TAG = 0xB027 # Hotspot transform tag +FALLOFF_TRACK_TAG = 0xB028 # Falloff transform tag + +ROOT_OBJECT = 0xFFFF # Root object # So 3ds max can open files, limit names to 12 in length @@ -120,7 +139,6 @@ SCL_TRACK_TAG = 0xB022 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: @@ -143,13 +161,11 @@ def sane_name(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***""" @@ -1362,7 +1378,7 @@ def save(operator, 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)) + energy_factor.add_variable("energy", _3ds_float(ob.data.energy * 0.001)) light_chunk.add_subchunk(color_float_chunk) light_chunk.add_subchunk(energy_factor) @@ -1374,12 +1390,18 @@ def save(operator, 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) + spot_roll_chunk = _3ds_chunk(LIGHT_SPOT_ROLL) 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) + if ob.data.show_cone: + spot_cone_chunk = _3ds_chunk(LIGHT_SPOT_SEE_CONE) + spotlight_chunk.add_subchunk(spot_cone_chunk) + if ob.data.use_square: + spot_square_chunk = _3ds_chunk(LIGHT_SPOT_RECTANGLE) + spotlight_chunk.add_subchunk(spot_square_chunk) light_chunk.add_subchunk(spotlight_chunk) # Add light to object info diff --git a/io_scene_3ds/import_3ds.py b/io_scene_3ds/import_3ds.py index 14fdd6acf..88155a3aa 100644 --- a/io_scene_3ds/import_3ds.py +++ b/io_scene_3ds/import_3ds.py @@ -76,30 +76,32 @@ MAT_MAP_BCOL = 0xA368 # Blue mapping # >------ 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_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_SPOTLIGHT = 0x4610 # The target of a spotlight +LIGHT_OFF = 0x4620 # The light is off +LIGHT_ATTENUATE = 0x4625 # Light attenuate flag +LIGHT_RAYSHADE = 0x4627 # Light rayshading flag +LIGHT_SPOT_SHADOWED = 0x4630 # Light spot shadow flag +LIGHT_LOCAL_SHADOW = 0x4640 # Light shadow values 1 +LIGHT_LOCAL_SHADOW2 = 0x4641 # Light shadow values 2 +LIGHT_SPOT_SEE_CONE = 0x4650 # Light spot cone flag +LIGHT_SPOT_RECTANGLE = 0x4651 # Light spot rectangle flag +LIGHT_SPOT_OVERSHOOT = 0x4652 # Light spot overshoot flag +LIGHT_SPOT_PROJECTOR = 0x4653 # Light spot bitmap name +LIGHT_EXCLUDE = 0x4654 # Light excluded objects +LIGHT_RANGE = 0x4655 # Light range +LIGHT_SPOT_ROLL = 0x4656 # The roll angle of the spot +LIGHT_SPOT_ASPECT = 0x4657 # Light spot aspect flag +LIGHT_RAY_BIAS = 0x4658 # Light ray bias value +LIGHT_INNER_RANGE = 0x4659 # The light inner range +LIGHT_OUTER_RANGE = 0x465A # The light outer range +LIGHT_MULTIPLIER = 0x465B # The light energy factor +LIGHT_AMBIENT_LIGHT = 0x4680 # Light ambient flag # >------ sub defines of CAMERA -OBJECT_CAMERA = 0x4700 # This lets un know we are reading a camera object OBJECT_CAM_RANGES = 0x4720 # The camera range values # >------ sub defines of OBJECT_MESH @@ -112,15 +114,15 @@ 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_AMBIENT = 0xB001 # Keyframe ambient node +KFDATA_OBJECT = 0xB002 # Keyframe object node +KFDATA_CAMERA = 0xB003 # Keyframe camera node +KFDATA_TARGET = 0xB004 # Keyframe target node +KFDATA_LIGHT = 0xB005 # Keyframe light node +KFDATA_LTARGET = 0xB006 # Keyframe light target node +KFDATA_SPOTLIGHT = 0xB007 # Keyframe spotlight node +KFDATA_KFSEG = 0xB008 # Keyframe start and stop +KFDATA_CURTIME = 0xB009 # Keyframe current frame # KFDATA_KFHDR = 0xB00A # >------ sub defines of KEYFRAME_NODE @@ -903,12 +905,12 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI temp_data = file.read(SZ_3FLOAT) contextLamp.data.color = struct.unpack('<3f', temp_data) new_chunk.bytes_read += SZ_3FLOAT - elif CreateLightObject and new_chunk.ID == OBJECT_LIGHT_MULTIPLIER: # Intensity + elif CreateLightObject and new_chunk.ID == LIGHT_MULTIPLIER: # Intensity temp_data = file.read(SZ_FLOAT) contextLamp.data.energy = (float(struct.unpack('f', temp_data)[0]) * 1000) new_chunk.bytes_read += SZ_FLOAT - elif CreateLightObject and new_chunk.ID == OBJECT_LIGHT_SPOT: # Spotlight + elif CreateLightObject and new_chunk.ID == LIGHT_SPOTLIGHT: # Spotlight temp_data = file.read(SZ_3FLOAT) contextLamp.data.type = 'SPOT' spot = mathutils.Vector(struct.unpack('<3f', temp_data)) @@ -927,10 +929,16 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI contextLamp.data.spot_size = math.radians(beam_angle) contextLamp.data.spot_blend = (1.0 - (hotspot / beam_angle)) * 2 new_chunk.bytes_read += SZ_FLOAT - elif CreateLightObject and new_chunk.ID == OBJECT_LIGHT_ROLL: # Roll + elif CreateLightObject and new_chunk.ID == LIGHT_SPOT_ROLL: # Roll temp_data = file.read(SZ_FLOAT) contextLamp.rotation_euler[1] = float(struct.unpack('f', temp_data)[0]) new_chunk.bytes_read += SZ_FLOAT + elif CreateLightObject and new_chunk.ID == LIGHT_SPOT_SHADOWED: # Shadow + newLight.use_shadow = True + elif CreateLightObject and new_chunk.ID == LIGHT_SPOT_SEE_CONE: # Cone + newLight.show_cone = True + elif CreateLightObject and new_chunk.ID == LIGHT_SPOT_RECTANGLE: # Square + newLight.use_square = True elif contextObName and new_chunk.ID == OBJECT_CAMERA and CreateCameraObject is False: # Basic camera support camera = bpy.data.cameras.new("Camera") @@ -954,7 +962,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI contextCamera.rotation_euler[2] = -1 * (math.radians(90) - math.acos(cam[0] / focus)) new_chunk.bytes_read += SZ_FLOAT temp_data = file.read(SZ_FLOAT) - contextCamera.data.lens = float(struct.unpack('f', temp_data)[0]) + contextCamera.data.lens = float(struct.unpack('f', temp_data)[0]) # Focus new_chunk.bytes_read += SZ_FLOAT contextMatrix = None # Reset matrix CreateBlenderObject = False @@ -981,7 +989,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI # including these here means their OB_NODE_HDR are scanned # another object is being processed - elif new_chunk.ID in {KFDATA_AMBIENT, KFDATA_OBJECT, KFDATA_CAMERA, KFDATA_LIGHT}: + elif new_chunk.ID in {KFDATA_AMBIENT, KFDATA_OBJECT, KFDATA_CAMERA, KFDATA_LIGHT, KFDATA_SPOTLIGHT}: object_id = ROOT_OBJECT tracking = 'OBJECT' child = None