Got images working
- does not do UVs yet - is able to pack images using a split algorithm. I think I broke the size finding though for the output canvas. - does not combine materials after packing
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
from pathlib import Path
|
||||
import bpy
|
||||
import re
|
||||
import os
|
||||
from typing import List, Tuple, Optional
|
||||
from bpy.types import Material, Operator, Context, Object, Image
|
||||
from ..core.register import register_wrap
|
||||
from ..core.properties import material_list_bool, SceneMatClass
|
||||
from ..core.packer.rectangle_packer import MaterialImageList, BinPacker
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def scale_images_to_largest(images:list[Image]) -> set:
|
||||
print([image.name for image in images])
|
||||
x: int=0
|
||||
y: int=0
|
||||
for image in images:
|
||||
x = max(x,image.size[0])
|
||||
y = max(y,image.size[1])
|
||||
print(x,y)
|
||||
|
||||
for image in images:
|
||||
image.scale(width=int(x), height=int(y))
|
||||
|
||||
return x,y
|
||||
|
||||
def MaterialImageList_to_Image_list(classitem: MaterialImageList) -> list[Image]:
|
||||
list_of_images: list[Image] = []
|
||||
|
||||
list_of_images.append(classitem.albedo)
|
||||
list_of_images.append(classitem.normal)
|
||||
list_of_images.append(classitem.emission)
|
||||
list_of_images.append(classitem.ambient_occlusion)
|
||||
list_of_images.append(classitem.height)
|
||||
|
||||
return list_of_images
|
||||
|
||||
|
||||
def get_material_images_from_scene(context: Context) -> list[MaterialImageList]:
|
||||
mat: SceneMatClass = None
|
||||
material_image_list: list[MaterialImageList] = []
|
||||
for mat in context.scene.materials:
|
||||
new_mat_image_item: MaterialImageList = MaterialImageList()
|
||||
try:
|
||||
new_mat_image_item.albedo = bpy.data.images[mat.mat.texture_atlas_albedo]
|
||||
except Exception as e:
|
||||
name: str = mat.mat.name+"_albedo_replacement"
|
||||
if name in bpy.data.images:
|
||||
bpy.data.images.remove(image=bpy.data.images[name],do_unlink=True)
|
||||
new_mat_image_item.albedo = bpy.data.images.new(name=name,width=32,height=32, alpha=True)
|
||||
try:
|
||||
new_mat_image_item.normal = bpy.data.images[mat.mat.texture_atlas_normal]
|
||||
except Exception:
|
||||
name: str = mat.mat.name+"_normal_replacement"
|
||||
if name in bpy.data.images:
|
||||
bpy.data.images.remove(image=bpy.data.images[name],do_unlink=True)
|
||||
new_mat_image_item.normal = bpy.data.images.new(name=name,width=32,height=32, alpha=True)
|
||||
try:
|
||||
new_mat_image_item.emission = bpy.data.images[mat.mat.texture_atlas_emission]
|
||||
except Exception:
|
||||
name: str = mat.mat.name+"_emission_replacement"
|
||||
if name in bpy.data.images:
|
||||
bpy.data.images.remove(image=bpy.data.images[name],do_unlink=True)
|
||||
new_mat_image_item.emission = bpy.data.images.new(name=name,width=32,height=32, alpha=True)
|
||||
|
||||
try:
|
||||
new_mat_image_item.ambient_occlusion = bpy.data.images[mat.mat.texture_atlas_ambient_occlusion]
|
||||
except Exception:
|
||||
name: str = mat.mat.name+"_ambient_occlusion_replacement"
|
||||
if name in bpy.data.images:
|
||||
bpy.data.images.remove(image=bpy.data.images[name],do_unlink=True)
|
||||
new_mat_image_item.ambient_occlusion = bpy.data.images.new(name=name,width=32,height=32, alpha=True)
|
||||
try:
|
||||
new_mat_image_item.height = bpy.data.images[mat.mat.texture_atlas_height]
|
||||
except Exception:
|
||||
name: str = mat.mat.name+"_height_replacement"
|
||||
if name in bpy.data.images:
|
||||
bpy.data.images.remove(image=bpy.data.images[name],do_unlink=True)
|
||||
new_mat_image_item.height = bpy.data.images.new(name=name,width=32,height=32, alpha=True)
|
||||
material_image_list.append(new_mat_image_item)
|
||||
return material_image_list
|
||||
|
||||
|
||||
def prep_images_in_scene(context: Context) -> list[MaterialImageList]:
|
||||
preped_images: list[MaterialImageList] = get_material_images_from_scene(context)
|
||||
for MaterialImageClass in preped_images:
|
||||
ImageList: list[Image] = MaterialImageList_to_Image_list(MaterialImageClass)
|
||||
|
||||
MaterialImageClass.w, MaterialImageClass.h = scale_images_to_largest(ImageList)
|
||||
|
||||
|
||||
|
||||
return preped_images
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@register_wrap
|
||||
class Atlas_Materials(Operator):
|
||||
|
||||
bl_idname = "avatar_toolkit.atlas_materials"
|
||||
bl_label = "Atlas Materials"
|
||||
bl_description = "Atlas materials to optimize the model"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context: Context) -> bool:
|
||||
return context.scene.texture_atlas_Has_Mat_List_Shown
|
||||
|
||||
def execute(self, context: Context) -> set:
|
||||
try:
|
||||
mat_images: list[MaterialImageList] = prep_images_in_scene(context)
|
||||
|
||||
packer: BinPacker = BinPacker(mat_images)
|
||||
|
||||
mat_images = packer.fit()
|
||||
|
||||
|
||||
size: list[int] = [max([matimg.fit.w + matimg.albedo.size[0] for matimg in mat_images]),
|
||||
max([matimg.fit.h + matimg.albedo.size[1] for matimg in mat_images])]
|
||||
print([matimg.fit.w + matimg.albedo.size[1] for matimg in mat_images])
|
||||
|
||||
for type in ["albedo","normal", "emission","ambient_occlusion","height"]:
|
||||
new_image_name: str= "Atlas_"+type+"_"+bpy.context.scene.name+"_"+Path(bpy.data.filepath).stem
|
||||
|
||||
print("Processing "+type+" atlas image")
|
||||
|
||||
if new_image_name in bpy.data.images:
|
||||
bpy.data.images.remove(bpy.data.images[new_image_name])
|
||||
|
||||
canvas: Image = bpy.data.images.new(name=new_image_name, width=int(size[0]),height=int(size[1]), alpha=True)
|
||||
c_w = canvas.size[0]
|
||||
c_h = canvas.size[1]
|
||||
canvas_pixels: list[float] = list(canvas.pixels[:])
|
||||
for mat in mat_images:
|
||||
x: int = int(mat.fit.x)
|
||||
y: int = int(mat.fit.y)
|
||||
w: int = int(mat.albedo.size[0])
|
||||
h: int = int(mat.albedo.size[1])
|
||||
|
||||
image_var: Image = eval("mat."+type)
|
||||
|
||||
image_pixels: list[float] = list(image_var.pixels[:])
|
||||
|
||||
print("writing image \""+image_var.name+"\" to canvas.")
|
||||
print("x: \""+str(x)+"\" "+"y: \""+str(y)+"\" "+"w: \""+str(w)+"\" "+"h: \""+str(h)+"\" ")
|
||||
for k in range(0,h):
|
||||
for i in range(0, w):
|
||||
for channel in range(0,4):
|
||||
canvas_pixels[
|
||||
int((((k+y)*c_w)
|
||||
+
|
||||
(i+x))*4)
|
||||
+int(channel)
|
||||
] = image_pixels[
|
||||
int((
|
||||
(k*w)
|
||||
+i)*4)
|
||||
+int(channel)]
|
||||
|
||||
canvas.pixels[:] = canvas_pixels[:]
|
||||
canvas.save(filepath=os.path.join(os.path.dirname(bpy.data.filepath),new_image_name+".png"))
|
||||
return {"FINISHED"}
|
||||
except Exception as e:
|
||||
raise e
|
||||
return {"FINISHED"}
|
||||
|
||||
Reference in New Issue
Block a user