Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugenio Pignataro <info@oscurart.com.ar>2020-04-09 23:02:50 +0300
committerEugenio Pignataro <info@oscurart.com.ar>2020-04-09 23:02:50 +0300
commit2e88f2ed403d2c1e287d77d94a9f6e268cdbac95 (patch)
treec60f617857df6db07b53bcdff7f38910267e11df
parent0c453127e1257381300cd01c1c75dbdb79581a8d (diff)
New Feature: Add uv info. Texel, image gain, and more
-rw-r--r--oscurart_tools/__init__.py7
-rw-r--r--oscurart_tools/mesh/print_uv_stats.py125
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