forked from franMarz/TexTools-Blender
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathop_color_convert_texture.py
153 lines (113 loc) · 4.51 KB
/
op_color_convert_texture.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import bpy
import bmesh
import operator
import math
from mathutils import Vector
from collections import defaultdict
from . import utilities_color
from . import utilities_bake
from . import utilities_ui
material_prefix = "TT_atlas_"
gamma = 2.2
class op(bpy.types.Operator):
bl_idname = "uv.textools_color_convert_to_texture"
bl_label = "Pack Texture"
bl_description = "Pack ID Colors into single texture and UVs"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
if not bpy.context.active_object:
return False
if bpy.context.active_object not in bpy.context.selected_objects:
return False
if len(bpy.context.selected_objects) != 1:
return False
if bpy.context.active_object.type != 'MESH':
return False
#Only in UV editor mode
if bpy.context.area.type != 'IMAGE_EDITOR':
return False
return True
def execute(self, context):
pack_texture(self, context)
return {'FINISHED'}
def pack_texture(self, context):
obj = bpy.context.active_object
name = material_prefix+obj.name
if obj.mode != 'OBJECT':
bpy.ops.object.mode_set(mode='OBJECT')
# Determine size
size_pixel = 8
size_square = math.ceil(math.sqrt( context.scene.texToolsSettings.color_ID_count ))
size_image = size_square * size_pixel
size_image_pow = int(math.pow(2, math.ceil(math.log(size_image, 2))))
# Maximize pixel size
size_pixel = math.floor(size_image_pow/size_square)
print("{0} colors = {1} x {1} = ({2}pix) {3} x {3} | {4} x {4}".format(
context.scene.texToolsSettings.color_ID_count,
size_square,
size_pixel,
size_image,
size_image_pow
))
# Create image
image = bpy.data.images.new(name, width=size_image_pow, height=size_image_pow)
pixels = [None] * size_image_pow * size_image_pow
# Black pixels
for x in range(size_image_pow):
for y in range(size_image_pow):
pixels[(y * size_image_pow) + x] = [0, 0, 0, 1]
# Pixels
for c in range(context.scene.texToolsSettings.color_ID_count):
x = c % size_square
y = math.floor(c/size_square)
color = utilities_color.get_color(c).copy()
for i in range(3):
color[i] = pow(color[i] , 1.0/gamma)
for sx in range(size_pixel):
for sy in range(size_pixel):
_x = x*size_pixel + sx
_y = y*size_pixel + sy
pixels[(_y * size_image_pow) + _x] = [color[0], color[1], color[2], 1]
# flatten list & assign pixels
pixels = [chan for px in pixels for chan in px]
image.pixels = pixels
# Set background image
for area in bpy.context.screen.areas:
if area.type == 'IMAGE_EDITOR':
area.spaces[0].image = image
# Edit mesh
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE')
bpy.ops.mesh.select_all(action='SELECT')
# bpy.ops.uv.smart_project(angle_limit=1)
bpy.ops.uv.unwrap(method='ANGLE_BASED', margin=0.0078)
bm = bmesh.from_edit_mesh(bpy.context.active_object.data)
uv_layers = bm.loops.layers.uv.verify();
for face in bm.faces:
index = face.material_index
# Get UV coordinates for index
x = index%size_square
y = math.floor(index/size_square)
x*= (size_pixel / size_image_pow)
y*= (size_pixel / size_image_pow)
x+= size_pixel/size_image_pow/2
y+= size_pixel/size_image_pow/2
for loop in face.loops:
loop[uv_layers].uv = (x, y)
# Remove Slots & add one
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.uv.textools_color_clear()
bpy.ops.object.material_slot_add()
#Create material with image
obj.material_slots[0].material = utilities_bake.get_image_material(image)
#Display UVs
bpy.ops.object.mode_set(mode='EDIT')
# Switch textured shading
for area in bpy.context.screen.areas:
if area.type == 'VIEW_3D':
for space in area.spaces:
if space.type == 'VIEW_3D':
space.shading.type = 'MATERIAL'
bpy.ops.ui.textools_popup('INVOKE_DEFAULT', message="Packed texture with {} color IDs".format( context.scene.texToolsSettings.color_ID_count ))
bpy.utils.register_class(op)