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 = {
"name": "Autodesk 3DS format",
"author": "Bob Holcomb, Campbell Barton, Andreas Atteneder, Sebastian Schrand",
"version": (2, 2, 0),
"version": (2, 3, 1),
"blender": (3, 0, 0),
"location": "File > Import",
"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
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
@ -327,10 +328,11 @@ class _3ds_rgb_color(object):
class _3ds_face(object):
"""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.flag = flag
def get_size(self):
return 4 * SZ_SHORT
@ -339,11 +341,11 @@ class _3ds_face(object):
# catch this problem
def write(self, file):
# The last zero is only used by 3d studio
file.write(struct.pack("<4H", self.vindex[0], self.vindex[1], self.vindex[2], 0))
# The last short is used for face flags
file.write(struct.pack("<4H", self.vindex[0], self.vindex[1], self.vindex[2], self.flag))
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):
@ -763,17 +765,17 @@ def make_material_chunk(material, image):
class tri_wrapper(object):
"""Class representing a triangle.
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.ma = ma
self.image = image
self.faceuvs = faceuvs
self.offset = [0, 0, 0] # offset indices
self.flag = flag
self.group = group
@ -789,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]
uf = mesh.uv_layers.active.data if do_uv else None
if do_uv:
@ -798,13 +800,37 @@ 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]
"""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]
if len(f_v) == 3:
new_tri = tri_wrapper((f_v[0], f_v[1], f_v[2]), face.material_index, img)
if len(f_v)==3:
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):
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
tri_list.append(new_tri)
@ -813,7 +839,6 @@ def extract_triangles(mesh):
def remove_face_uv(verts, tri_list):
"""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
need to be converted to vertex uv coordinates. That means that vertices need to be duplicated when
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
unique_mats = {}
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 materials:
ma = materials[tri.ma]
@ -927,7 +951,6 @@ def make_faces_chunk(tri_list, mesh, materialDict):
face_chunk.add_subchunk(obj_material_chunk)
else:
obj_material_faces = []
obj_material_names = []
for m in materials:
@ -937,7 +960,7 @@ def make_faces_chunk(tri_list, mesh, materialDict):
n_materials = len(obj_material_names)
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):
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:
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:
uvl = bmesh.uv_layers.active.data[:]
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)
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
for lt, tri in enumerate(bmesh.loop_triangles):
faceflag = myContextMesh_flag[lt]
edge_ca = bmesh.edges[bmesh.loops[tri.loops[2]].edge_index]
edge_bc = bmesh.edges[bmesh.loops[tri.loops[1]].edge_index]
edge_ab = bmesh.edges[bmesh.loops[tri.loops[0]].edge_index]
for f, pl in enumerate(bmesh.polygons):
face = myContextMesh_facels[f]
faceflag = myContextMesh_flag[f]
edge_ab = bmesh.edges[bmesh.loops[pl.loop_start].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:
edge_ca.use_edge_sharp = True
elif faceflag == 2:
@ -455,8 +449,10 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, IMAGE_SE
elif faceflag == 6:
edge_bc.use_edge_sharp = True
edge_ab.use_edge_sharp = True
elif faceflag >= 7:
pass
elif faceflag == 7:
edge_bc.use_edge_sharp = True
edge_ab.use_edge_sharp = True
edge_ca.use_edge_sharp = True
if myContextMesh_smooth:
for f, pl in enumerate(bmesh.polygons):