diff options
author | Eugenio Pignataro <info@oscurart.com.ar> | 2020-04-09 23:02:50 +0300 |
---|---|---|
committer | Eugenio Pignataro <info@oscurart.com.ar> | 2020-04-09 23:02:50 +0300 |
commit | 2e88f2ed403d2c1e287d77d94a9f6e268cdbac95 (patch) | |
tree | c60f617857df6db07b53bcdff7f38910267e11df | |
parent | 0c453127e1257381300cd01c1c75dbdb79581a8d (diff) |
New Feature: Add uv info. Texel, image gain, and more
-rw-r--r-- | oscurart_tools/__init__.py | 7 | ||||
-rw-r--r-- | oscurart_tools/mesh/print_uv_stats.py | 125 |
2 files changed, 131 insertions, 1 deletions
diff --git a/oscurart_tools/__init__.py b/oscurart_tools/__init__.py index 26c07c2d..0d340cc8 100644 --- a/oscurart_tools/__init__.py +++ b/oscurart_tools/__init__.py @@ -51,6 +51,7 @@ from oscurart_tools.render import render_tokens from oscurart_tools.render import batch_maker from oscurart_tools.render import material_overrides from oscurart_tools.mesh import flipped_uvs +from oscurart_tools.mesh import print_uv_stats from bpy.types import ( AddonPreferences, @@ -75,12 +76,14 @@ class VIEW3D_MT_edit_mesh_oscurarttools(Menu): layout.operator("mesh.uv_island_copy") layout.operator("mesh.uv_island_paste") layout.operator("mesh.select_doubles") + layout.operator("mesh.print_uv_stats") layout.separator() layout.operator("image.reload_images_osc") layout.operator("file.save_incremental_backup") layout.operator("file.collect_all_images") layout.operator("file.create_batch_maker_osc") + def menu_funcMesh(self, context): self.layout.menu("VIEW3D_MT_edit_mesh_oscurarttools") self.layout.separator() @@ -121,6 +124,7 @@ class VIEW3D_MT_object_oscurarttools(Menu): layout.operator("object.search_and_select_osc") layout.operator("object.shape_key_to_objects_osc") layout.operator("mesh.apply_linked_meshes") + layout.operator("mesh.print_uv_stats") layout.separator() layout.operator("image.reload_images_osc") layout.operator("file.save_incremental_backup") @@ -160,7 +164,8 @@ classes = ( material_overrides.OscOverridesUp, material_overrides.OscOverridesDown, material_overrides.OscOverridesKill, - flipped_uvs.selectFlippedUvs + flipped_uvs.selectFlippedUvs, + print_uv_stats.uvStats ) def register(): diff --git a/oscurart_tools/mesh/print_uv_stats.py b/oscurart_tools/mesh/print_uv_stats.py new file mode 100644 index 00000000..7488456d --- /dev/null +++ b/oscurart_tools/mesh/print_uv_stats.py @@ -0,0 +1,125 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + + + +import bpy +import bmesh +from mathutils.geometry import area_tri +from math import sqrt +from math import pow + + +def setImageRes(object): + global pixels + mat = object.material_slots[object.active_material_index].material + if mat.node_tree.nodes.active.type in ["TEX_IMAGE"]: + pixels = [mat.node_tree.nodes.active.image.size[0] ,mat.node_tree.nodes.active.image.size[1] ] + return(True) + + else: + print("Please select image node first") + return(False) + + +def makeTessellate(actObj): + global bm_tess + ob = actObj + me = ob.data + bm = bmesh.new() + bm.from_mesh(me) + bmesh.ops.triangulate(bm, faces=bm.faces[:]) + bm_tess = bpy.data.meshes.new("Tris") + bm.to_mesh(bm_tess) + + +def calcArea(): + global totalArea + totalArea = 0 + for poly in bm_tess.polygons: + uno = bm_tess.uv_layers.active.data[poly.loop_indices[0]].uv + dos = bm_tess.uv_layers.active.data[poly.loop_indices[1]].uv + tres = bm_tess.uv_layers.active.data[poly.loop_indices[2]].uv + area = area_tri(uno, dos, tres) + totalArea += area + + bpy.data.meshes.remove( + bm_tess, + do_unlink=True, + do_id_user=True, + do_ui_user=True) + + +def calcMeshArea(ob): + global GlobLog + polyArea = 0 + for poly in ob.data.polygons: + polyArea += poly.area + ta = "UvGain: %s%s || " % (round(totalArea * 100),"%") + ma = "MeshArea: %s || " % (polyArea) + pg = "PixelsGain: %s || " % (round(totalArea * (pixels[0] * pixels[1]))) + pl = "PixelsLost: %s || " % ((pixels[0]*pixels[1]) - round(totalArea * (pixels[0] * pixels[1]))) + tx = "Texel: %s pix/meter" % (round(sqrt(totalArea * pixels[0] * pixels[1] / polyArea))) + GlobLog = ta+ma+pg+pl+tx + + + + +class uvStats(bpy.types.Operator): + """Print Uv Stats""" + bl_idname = "mesh.print_uv_stats" + bl_label = "Print Uv Stats" + bl_options = {'REGISTER'} + + @classmethod + def poll(cls, context): + return context.active_object is not None + + def execute(self, context): + if round( + bpy.context.object.scale.x, + 2) == 1 and round( + bpy.context.object.scale.y, + 2) == 1 and round( + bpy.context.object.scale.x, + 2) == 1: + if setImageRes(bpy.context.object): + makeTessellate(bpy.context.object) + calcArea() + calcMeshArea(bpy.context.object) + else: + print("Warning: Non Uniform Scale Object") + + copyOb = bpy.context.object.copy() + copyMe = bpy.context.object.data.copy() + bpy.context.scene.collection.objects.link(copyOb) + copyOb.data = copyMe + bpy.ops.object.select_all(action="DESELECT") + copyOb.select_set(1) + bpy.ops.object.transform_apply() + + if setImageRes(copyOb): + makeTessellate(copyOb) + calcArea() + calcMeshArea(copyOb) + + bpy.data.objects.remove(copyOb) + bpy.data.meshes.remove(copyMe) + + self.report({'INFO'}, GlobLog) + return {'FINISHED'}
\ No newline at end of file |