PLY: code cleanup

Group related and separate unrelated code, rename classes according to PEP8, remove redundant, outdated or misleading comments, greatly simplify UVs and vertex color variable init code.
This commit is contained in:
Mikhail Rachinskiy 2019-10-15 18:57:32 +04:00
parent 11871509f9
commit c584e86e4d
3 changed files with 35 additions and 53 deletions

View File

@ -24,7 +24,7 @@ bl_info = {
"version": (1, 1, 0),
"blender": (2, 82, 0),
"location": "File > Import-Export",
"description": "Import-Export PLY mesh data with UV's and vertex colors",
"description": "Import-Export PLY mesh data with UVs and vertex colors",
"wiki_url": "https://docs.blender.org/manual/en/latest/addons/io_mesh_ply.html",
"support": 'OFFICIAL',
"category": "Import-Export",

View File

@ -34,44 +34,26 @@ def save_mesh(filepath, mesh, use_normals=True, use_uv_coords=True, use_colors=T
def rvec2d(v):
return round(v[0], 6), round(v[1], 6)
has_uv = bool(mesh.uv_layers)
has_vcol = bool(mesh.vertex_colors)
if not has_uv:
if use_uv_coords and mesh.uv_layers:
active_uv_layer = mesh.uv_layers.active.data
else:
use_uv_coords = False
if not has_vcol:
if use_colors and mesh.vertex_colors:
active_col_layer = mesh.vertex_colors.active.data
else:
use_colors = False
if not use_uv_coords:
has_uv = False
if not use_colors:
has_vcol = False
if has_uv:
active_uv_layer = mesh.uv_layers.active
if not active_uv_layer:
use_uv_coords = False
has_uv = False
else:
active_uv_layer = active_uv_layer.data
if has_vcol:
active_col_layer = mesh.vertex_colors.active
if not active_col_layer:
use_colors = False
has_vcol = False
else:
active_col_layer = active_col_layer.data
# in case
color = uvcoord = uvcoord_key = normal = normal_key = None
mesh_verts = mesh.vertices # save a lookup
ply_verts = [] # list of dictionaries
mesh_verts = mesh.vertices
# vdict = {} # (index, normal, uv) -> new index
vdict = [{} for i in range(len(mesh_verts))]
ply_verts = []
ply_faces = [[] for f in range(len(mesh.polygons))]
vert_count = 0
for i, f in enumerate(mesh.polygons):
smooth = not use_normals or f.use_smooth
@ -79,12 +61,12 @@ def save_mesh(filepath, mesh, use_normals=True, use_uv_coords=True, use_colors=T
normal = f.normal[:]
normal_key = rvec3d(normal)
if has_uv:
if use_uv_coords:
uv = [
active_uv_layer[l].uv[:]
for l in range(f.loop_start, f.loop_start + f.loop_total)
]
if has_vcol:
if use_colors:
col = [
active_col_layer[l].color[:]
for l in range(f.loop_start, f.loop_start + f.loop_total)
@ -98,11 +80,11 @@ def save_mesh(filepath, mesh, use_normals=True, use_uv_coords=True, use_colors=T
normal = v.normal[:]
normal_key = rvec3d(normal)
if has_uv:
if use_uv_coords:
uvcoord = uv[j][0], uv[j][1]
uvcoord_key = rvec2d(uvcoord)
if has_vcol:
if use_colors:
color = col[j]
color = (
int(color[0] * 255.0),
@ -115,7 +97,7 @@ def save_mesh(filepath, mesh, use_normals=True, use_uv_coords=True, use_colors=T
vdict_local = vdict[vidx]
pf_vidx = vdict_local.get(key) # Will be None initially
if pf_vidx is None: # same as vdict_local.has_key(key)
if pf_vidx is None: # Same as vdict_local.has_key(key)
pf_vidx = vdict_local[key] = vert_count
ply_verts.append((vidx, normal, uvcoord, color))
vert_count += 1
@ -136,13 +118,11 @@ def save_mesh(filepath, mesh, use_normals=True, use_uv_coords=True, use_colors=T
)
fw(f"element vertex {len(ply_verts)}\n")
fw(
"property float x\n"
"property float y\n"
"property float z\n"
)
if use_normals:
fw(
"property float nx\n"
@ -164,6 +144,7 @@ def save_mesh(filepath, mesh, use_normals=True, use_uv_coords=True, use_colors=T
fw(f"element face {len(mesh.polygons)}\n")
fw("property list uchar uint vertex_indices\n")
fw("end_header\n")
# Vertex data

View File

@ -19,7 +19,7 @@
# <pep8 compliant>
class element_spec(object):
class ElementSpec:
__slots__ = (
"name",
"count",
@ -43,7 +43,7 @@ class element_spec(object):
return -1
class property_spec(object):
class PropertySpec:
__slots__ = (
"name",
"list_type",
@ -102,7 +102,7 @@ class property_spec(object):
return self.read_format(format, 1, self.numeric_type, stream)[0]
class object_spec(object):
class ObjectSpec:
__slots__ = ("specs",)
def __init__(self):
@ -113,15 +113,16 @@ class object_spec(object):
return dict([(i.name, [i.load(format, stream) for j in range(i.count)]) for i in self.specs])
# Longhand for above LC
# answer = {}
# for i in self.specs:
# answer[i.name] = []
# for j in range(i.count):
# if not j % 100 and meshtools.show_progress:
# Blender.Window.DrawProgressBar(float(j) / i.count, 'Loading ' + i.name)
# answer[i.name].append(i.load(format, stream))
# return answer
"""
answer = {}
for i in self.specs:
answer[i.name] = []
for j in range(i.count):
if not j % 100 and meshtools.show_progress:
Blender.Window.DrawProgressBar(float(j) / i.count, 'Loading ' + i.name)
answer[i.name].append(i.load(format, stream))
return answer
"""
def read(filepath):
@ -154,7 +155,7 @@ def read(filepath):
b'double': 'd',
b'string': 's',
}
obj_spec = object_spec()
obj_spec = ObjectSpec()
invalid_ply = (None, None, None)
with open(filepath, 'rb') as plyf:
@ -206,15 +207,15 @@ def read(filepath):
if len(tokens) < 3:
print("Invalid element line")
return invalid_ply
obj_spec.specs.append(element_spec(tokens[1], int(tokens[2])))
obj_spec.specs.append(ElementSpec(tokens[1], int(tokens[2])))
elif tokens[0] == b'property':
if not len(obj_spec.specs):
print("Property without element")
return invalid_ply
if tokens[1] == b'list':
obj_spec.specs[-1].properties.append(property_spec(tokens[4], type_specs[tokens[2]], type_specs[tokens[3]]))
obj_spec.specs[-1].properties.append(PropertySpec(tokens[4], type_specs[tokens[2]], type_specs[tokens[3]]))
else:
obj_spec.specs[-1].properties.append(property_spec(tokens[2], None, type_specs[tokens[1]]))
obj_spec.specs[-1].properties.append(PropertySpec(tokens[2], None, type_specs[tokens[1]]))
if not valid_header:
print("Invalid header ('end_header' line not found!)")
return invalid_ply
@ -373,7 +374,7 @@ def load_ply_mesh(filepath, ply_name):
if texture and uvindices:
pass
# XXX28: add support for using texture.
# TODO add support for using texture.
# import os
# import sys