Skip to content
Snippets Groups Projects
Commit c584e86e authored by Mikhail Rachinskiy's avatar Mikhail Rachinskiy
Browse files

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.
parent 11871509
No related branches found
No related tags found
No related merge requests found
...@@ -24,7 +24,7 @@ bl_info = { ...@@ -24,7 +24,7 @@ bl_info = {
"version": (1, 1, 0), "version": (1, 1, 0),
"blender": (2, 82, 0), "blender": (2, 82, 0),
"location": "File > Import-Export", "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", "wiki_url": "https://docs.blender.org/manual/en/latest/addons/io_mesh_ply.html",
"support": 'OFFICIAL', "support": 'OFFICIAL',
"category": "Import-Export", "category": "Import-Export",
......
...@@ -34,44 +34,26 @@ def save_mesh(filepath, mesh, use_normals=True, use_uv_coords=True, use_colors=T ...@@ -34,44 +34,26 @@ def save_mesh(filepath, mesh, use_normals=True, use_uv_coords=True, use_colors=T
def rvec2d(v): def rvec2d(v):
return round(v[0], 6), round(v[1], 6) return round(v[0], 6), round(v[1], 6)
has_uv = bool(mesh.uv_layers) if use_uv_coords and mesh.uv_layers:
has_vcol = bool(mesh.vertex_colors) active_uv_layer = mesh.uv_layers.active.data
else:
if not has_uv:
use_uv_coords = False use_uv_coords = False
if not has_vcol:
use_colors = False
if not use_uv_coords: if use_colors and mesh.vertex_colors:
has_uv = False active_col_layer = mesh.vertex_colors.active.data
if not use_colors: else:
has_vcol = False use_colors = 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 # in case
color = uvcoord = uvcoord_key = normal = normal_key = None color = uvcoord = uvcoord_key = normal = normal_key = None
mesh_verts = mesh.vertices # save a lookup mesh_verts = mesh.vertices
ply_verts = [] # list of dictionaries
# vdict = {} # (index, normal, uv) -> new index # vdict = {} # (index, normal, uv) -> new index
vdict = [{} for i in range(len(mesh_verts))] vdict = [{} for i in range(len(mesh_verts))]
ply_verts = []
ply_faces = [[] for f in range(len(mesh.polygons))] ply_faces = [[] for f in range(len(mesh.polygons))]
vert_count = 0 vert_count = 0
for i, f in enumerate(mesh.polygons): for i, f in enumerate(mesh.polygons):
smooth = not use_normals or f.use_smooth 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 ...@@ -79,12 +61,12 @@ def save_mesh(filepath, mesh, use_normals=True, use_uv_coords=True, use_colors=T
normal = f.normal[:] normal = f.normal[:]
normal_key = rvec3d(normal) normal_key = rvec3d(normal)
if has_uv: if use_uv_coords:
uv = [ uv = [
active_uv_layer[l].uv[:] active_uv_layer[l].uv[:]
for l in range(f.loop_start, f.loop_start + f.loop_total) for l in range(f.loop_start, f.loop_start + f.loop_total)
] ]
if has_vcol: if use_colors:
col = [ col = [
active_col_layer[l].color[:] active_col_layer[l].color[:]
for l in range(f.loop_start, f.loop_start + f.loop_total) 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 ...@@ -98,11 +80,11 @@ def save_mesh(filepath, mesh, use_normals=True, use_uv_coords=True, use_colors=T
normal = v.normal[:] normal = v.normal[:]
normal_key = rvec3d(normal) normal_key = rvec3d(normal)
if has_uv: if use_uv_coords:
uvcoord = uv[j][0], uv[j][1] uvcoord = uv[j][0], uv[j][1]
uvcoord_key = rvec2d(uvcoord) uvcoord_key = rvec2d(uvcoord)
if has_vcol: if use_colors:
color = col[j] color = col[j]
color = ( color = (
int(color[0] * 255.0), int(color[0] * 255.0),
...@@ -115,7 +97,7 @@ def save_mesh(filepath, mesh, use_normals=True, use_uv_coords=True, use_colors=T ...@@ -115,7 +97,7 @@ def save_mesh(filepath, mesh, use_normals=True, use_uv_coords=True, use_colors=T
vdict_local = vdict[vidx] vdict_local = vdict[vidx]
pf_vidx = vdict_local.get(key) # Will be None initially 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 pf_vidx = vdict_local[key] = vert_count
ply_verts.append((vidx, normal, uvcoord, color)) ply_verts.append((vidx, normal, uvcoord, color))
vert_count += 1 vert_count += 1
...@@ -136,13 +118,11 @@ def save_mesh(filepath, mesh, use_normals=True, use_uv_coords=True, use_colors=T ...@@ -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(f"element vertex {len(ply_verts)}\n")
fw( fw(
"property float x\n" "property float x\n"
"property float y\n" "property float y\n"
"property float z\n" "property float z\n"
) )
if use_normals: if use_normals:
fw( fw(
"property float nx\n" "property float nx\n"
...@@ -164,6 +144,7 @@ def save_mesh(filepath, mesh, use_normals=True, use_uv_coords=True, use_colors=T ...@@ -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(f"element face {len(mesh.polygons)}\n")
fw("property list uchar uint vertex_indices\n") fw("property list uchar uint vertex_indices\n")
fw("end_header\n") fw("end_header\n")
# Vertex data # Vertex data
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
# <pep8 compliant> # <pep8 compliant>
class element_spec(object): class ElementSpec:
__slots__ = ( __slots__ = (
"name", "name",
"count", "count",
...@@ -43,7 +43,7 @@ class element_spec(object): ...@@ -43,7 +43,7 @@ class element_spec(object):
return -1 return -1
class property_spec(object): class PropertySpec:
__slots__ = ( __slots__ = (
"name", "name",
"list_type", "list_type",
...@@ -102,7 +102,7 @@ class property_spec(object): ...@@ -102,7 +102,7 @@ class property_spec(object):
return self.read_format(format, 1, self.numeric_type, stream)[0] return self.read_format(format, 1, self.numeric_type, stream)[0]
class object_spec(object): class ObjectSpec:
__slots__ = ("specs",) __slots__ = ("specs",)
def __init__(self): def __init__(self):
...@@ -113,15 +113,16 @@ class object_spec(object): ...@@ -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]) return dict([(i.name, [i.load(format, stream) for j in range(i.count)]) for i in self.specs])
# Longhand for above LC # Longhand for above LC
"""
# answer = {} answer = {}
# for i in self.specs: for i in self.specs:
# answer[i.name] = [] answer[i.name] = []
# for j in range(i.count): for j in range(i.count):
# if not j % 100 and meshtools.show_progress: if not j % 100 and meshtools.show_progress:
# Blender.Window.DrawProgressBar(float(j) / i.count, 'Loading ' + i.name) Blender.Window.DrawProgressBar(float(j) / i.count, 'Loading ' + i.name)
# answer[i.name].append(i.load(format, stream)) answer[i.name].append(i.load(format, stream))
# return answer return answer
"""
def read(filepath): def read(filepath):
...@@ -154,7 +155,7 @@ def read(filepath): ...@@ -154,7 +155,7 @@ def read(filepath):
b'double': 'd', b'double': 'd',
b'string': 's', b'string': 's',
} }
obj_spec = object_spec() obj_spec = ObjectSpec()
invalid_ply = (None, None, None) invalid_ply = (None, None, None)
with open(filepath, 'rb') as plyf: with open(filepath, 'rb') as plyf:
...@@ -206,15 +207,15 @@ def read(filepath): ...@@ -206,15 +207,15 @@ def read(filepath):
if len(tokens) < 3: if len(tokens) < 3:
print("Invalid element line") print("Invalid element line")
return invalid_ply 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': elif tokens[0] == b'property':
if not len(obj_spec.specs): if not len(obj_spec.specs):
print("Property without element") print("Property without element")
return invalid_ply return invalid_ply
if tokens[1] == b'list': 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: 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: if not valid_header:
print("Invalid header ('end_header' line not found!)") print("Invalid header ('end_header' line not found!)")
return invalid_ply return invalid_ply
...@@ -373,7 +374,7 @@ def load_ply_mesh(filepath, ply_name): ...@@ -373,7 +374,7 @@ def load_ply_mesh(filepath, ply_name):
if texture and uvindices: if texture and uvindices:
pass pass
# XXX28: add support for using texture. # TODO add support for using texture.
# import os # import os
# import sys # import sys
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment