3
11

io_scene_3ds: Added face and point flags #11

Merged
Sebastian Sille merged 3 commits from :main into main 2023-03-26 19:29:34 +02:00
3 changed files with 54 additions and 35 deletions

View File

@ -32,7 +32,7 @@ import bpy
bl_info = { bl_info = {
"name": "Autodesk 3DS format", "name": "Autodesk 3DS format",
"author": "Bob Holcomb, Campbell Barton, Andreas Atteneder, Sebastian Schrand", "author": "Bob Holcomb, Campbell Barton, Andreas Atteneder, Sebastian Schrand",
"version": (2, 2, 0), "version": (2, 3, 1),
"blender": (3, 0, 0), "blender": (3, 0, 0),
"location": "File > Import", "location": "File > Import",
"description": "Import 3DS, meshes, uvs, materials, textures, " "description": "Import 3DS, meshes, uvs, materials, textures, "

View File

@ -108,6 +108,7 @@ OBJECT_CAM_RANGES = 0x4720 # The camera range values
# >------ sub defines of OBJECT_MESH # >------ sub defines of OBJECT_MESH
OBJECT_VERTICES = 0x4110 # The objects vertices OBJECT_VERTICES = 0x4110 # The objects vertices
OBJECT_VERTFLAGS = 0x4111 # The objects vertex flags
OBJECT_FACES = 0x4120 # The objects faces OBJECT_FACES = 0x4120 # The objects faces
OBJECT_MATERIAL = 0x4130 # This is found if the object has a material, either texture map or color 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_UV = 0x4140 # The UV texture coordinates
@ -327,10 +328,11 @@ class _3ds_rgb_color(object):
class _3ds_face(object): class _3ds_face(object):
"""Class representing a face for a 3ds file.""" """Class representing a face for a 3ds file."""
__slots__ = ("vindex", ) __slots__ = ("vindex", "flag")
def __init__(self, vindex): def __init__(self, vindex, flag):
self.vindex = vindex self.vindex = vindex
self.flag = flag
def get_size(self): def get_size(self):
return 4 * SZ_SHORT return 4 * SZ_SHORT
@ -339,11 +341,11 @@ class _3ds_face(object):
# catch this problem # catch this problem
def write(self, file): def write(self, file):
# The last zero is only used by 3d studio # The last short is used for face flags
file.write(struct.pack("<4H", self.vindex[0], self.vindex[1], self.vindex[2], 0)) file.write(struct.pack("<4H", self.vindex[0], self.vindex[1], self.vindex[2], self.flag))
def __str__(self): def __str__(self):
return "[%d %d %d]" % (self.vindex[0], self.vindex[1], self.vindex[2]) return "[%d %d %d %d]" % (self.vindex[0], self.vindex[1], self.vindex[2], self.flag)
class _3ds_array(object): class _3ds_array(object):
@ -763,17 +765,17 @@ def make_material_chunk(material, image):
class tri_wrapper(object): class tri_wrapper(object):
"""Class representing a triangle. """Class representing a triangle.
Used when converting faces to triangles""" Used when converting faces to triangles"""
__slots__ = "vertex_index", "ma", "image", "faceuvs", "offset", "group" __slots__ = "vertex_index", "ma", "image", "faceuvs", "offset", "flag", "group"
def __init__(self, vindex=(0, 0, 0), ma=None, image=None, faceuvs=None, group=0): def __init__(self, vindex=(0, 0, 0), ma=None, image=None, faceuvs=None, flag=0, group=0):
self.vertex_index = vindex self.vertex_index = vindex
self.ma = ma self.ma = ma
self.image = image self.image = image
self.faceuvs = faceuvs self.faceuvs = faceuvs
self.offset = [0, 0, 0] # offset indices self.offset = [0, 0, 0] # offset indices
self.flag = flag
self.group = group self.group = group
@ -789,7 +791,7 @@ def extract_triangles(mesh):
img = None img = None
for i, face in enumerate(mesh.loop_triangles): for i, face in enumerate(mesh.loop_triangles):
f_v = face.vertices f_v = face.vertices
v1, v2, v3 = f_v[0], f_v[1], f_v[2]
uf = mesh.uv_layers.active.data if do_uv else None uf = mesh.uv_layers.active.data if do_uv else None
if do_uv: if do_uv:
@ -798,13 +800,37 @@ def extract_triangles(mesh):
img = get_uv_image(ma) if uf else None img = get_uv_image(ma) if uf else None
if img is not None: if img is not None:
img = img.name img = img.name
uv1, uv2, uv3 = f_uv[0], f_uv[1], f_uv[2]
"""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
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:
a_b, b_c, c_a = c_a, a_b, b_c
faceflag = 0
if c_a.use_edge_sharp:
faceflag = faceflag + 0x1
if b_c.use_edge_sharp:
faceflag = faceflag + 0x2
if a_b.use_edge_sharp:
faceflag = faceflag + 0x4
smoothgroup = polygroup[face.polygon_index] smoothgroup = polygroup[face.polygon_index]
if len(f_v)==3: if len(f_v)==3:
new_tri = tri_wrapper((f_v[0], f_v[1], f_v[2]), face.material_index, img) if v3 == 0:
v1, v2, v3 = v3, v1, v2
if do_uv:
uv1, uv2, uv3 = uv3, uv1, uv2
new_tri = tri_wrapper((v1, v2, v3), face.material_index, img)
if (do_uv): if (do_uv):
new_tri.faceuvs = uv_key(f_uv[0]), uv_key(f_uv[1]), uv_key(f_uv[2]) new_tri.faceuvs = uv_key(uv1), uv_key(uv2), uv_key(uv3)
new_tri.flag = faceflag
new_tri.group = smoothgroup if face.use_smooth else 0 new_tri.group = smoothgroup if face.use_smooth else 0
tri_list.append(new_tri) tri_list.append(new_tri)
@ -813,7 +839,6 @@ def extract_triangles(mesh):
def remove_face_uv(verts, tri_list): def remove_face_uv(verts, tri_list):
"""Remove face UV coordinates from a list of triangles. """Remove face UV coordinates from a list of triangles.
Since 3ds files only support one pair of uv coordinates for each vertex, face uv coordinates Since 3ds files only support one pair of uv coordinates for each vertex, face uv coordinates
need to be converted to vertex uv coordinates. That means that vertices need to be duplicated when need to be converted to vertex uv coordinates. That means that vertices need to be duplicated when
there are multiple uv coordinates per vertex.""" there are multiple uv coordinates per vertex."""
@ -896,8 +921,7 @@ def make_faces_chunk(tri_list, mesh, materialDict):
# Gather materials used in this mesh - mat/image pairs # Gather materials used in this mesh - mat/image pairs
unique_mats = {} unique_mats = {}
for i, tri in enumerate(tri_list): for i, tri in enumerate(tri_list):
face_list.add(_3ds_face(tri.vertex_index, tri.flag))
face_list.add(_3ds_face(tri.vertex_index))
if materials: if materials:
ma = materials[tri.ma] ma = materials[tri.ma]
@ -927,7 +951,6 @@ def make_faces_chunk(tri_list, mesh, materialDict):
face_chunk.add_subchunk(obj_material_chunk) face_chunk.add_subchunk(obj_material_chunk)
else: else:
obj_material_faces = [] obj_material_faces = []
obj_material_names = [] obj_material_names = []
for m in materials: for m in materials:
@ -937,7 +960,7 @@ def make_faces_chunk(tri_list, mesh, materialDict):
n_materials = len(obj_material_names) n_materials = len(obj_material_names)
for i, tri in enumerate(tri_list): for i, tri in enumerate(tri_list):
face_list.add(_3ds_face(tri.vertex_index)) face_list.add(_3ds_face(tri.vertex_index, tri.flag))
if (tri.ma < n_materials): if (tri.ma < n_materials):
obj_material_faces[tri.ma].add(_3ds_ushort(i)) obj_material_faces[tri.ma].add(_3ds_ushort(i))

View File

@ -400,15 +400,6 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, IMAGE_SE
for fidx in faces: for fidx in faces:
bmesh.polygons[fidx].material_index = mat_idx bmesh.polygons[fidx].material_index = mat_idx
# if uv_faces and img:
# for fidx in faces:
# bmesh.polygons[fidx].material_index = mat_idx
# # TODO: How to restore this?
# # uv_faces[fidx].image = img
# else:
# for fidx in faces:
# bmesh.polygons[fidx].material_index = mat_idx
if uv_faces: if uv_faces:
uvl = bmesh.uv_layers.active.data[:] uvl = bmesh.uv_layers.active.data[:]
for fidx, pl in enumerate(bmesh.polygons): for fidx, pl in enumerate(bmesh.polygons):
@ -433,13 +424,16 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, IMAGE_SE
imported_objects.append(ob) imported_objects.append(ob)
if myContextMesh_flag: if myContextMesh_flag:
# Bit 0 (0x1) sets edge CA visible, Bit 1 (0x2) sets edge BC visible and Bit 2 (0x4) sets the edge AB visible # Bit 0 (0x1) sets edge CA visible, Bit 1 (0x2) sets edge BC visible and Bit 2 (0x4) sets edge AB visible
# In Blender we use sharp edges for those flags # In Blender we use sharp edges for those flags
for lt, tri in enumerate(bmesh.loop_triangles): for f, pl in enumerate(bmesh.polygons):
faceflag = myContextMesh_flag[lt] face = myContextMesh_facels[f]
edge_ca = bmesh.edges[bmesh.loops[tri.loops[2]].edge_index] faceflag = myContextMesh_flag[f]
edge_bc = bmesh.edges[bmesh.loops[tri.loops[1]].edge_index] edge_ab = bmesh.edges[bmesh.loops[pl.loop_start].edge_index]
edge_ab = bmesh.edges[bmesh.loops[tri.loops[0]].edge_index] edge_bc = bmesh.edges[bmesh.loops[pl.loop_start + 1].edge_index]
edge_ca = bmesh.edges[bmesh.loops[pl.loop_start + 2].edge_index]
if face[2] == 0:
edge_ab, edge_bc, edge_ca = edge_ca, edge_ab, edge_bc
if faceflag == 1: if faceflag == 1:
edge_ca.use_edge_sharp = True edge_ca.use_edge_sharp = True
elif faceflag == 2: elif faceflag == 2:
@ -455,8 +449,10 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, IMAGE_SE
elif faceflag == 6: elif faceflag == 6:
edge_bc.use_edge_sharp = True edge_bc.use_edge_sharp = True
edge_ab.use_edge_sharp = True edge_ab.use_edge_sharp = True
elif faceflag >= 7: elif faceflag == 7:
pass edge_bc.use_edge_sharp = True
edge_ab.use_edge_sharp = True
edge_ca.use_edge_sharp = True
if myContextMesh_smooth: if myContextMesh_smooth:
for f, pl in enumerate(bmesh.polygons): for f, pl in enumerate(bmesh.polygons):