-
-
-class MaterialAtlas:
- def __init__(self, materials):
- self.render_mode = materials[0].render_mode
- if self.render_mode=='EXTERNAL':
- raise Exception("Material atlas with external render mode does not make sense")
-
- self.shader = materials[0].shader
- if self.shader:
- self.name = "material_atlas_"+os.path.splitext(self.shader)[0]
- else:
- self.name = "material_atlas"
- self.receive_shadows = materials[0].receive_shadows
- self.cast_shadows = (materials[0].shadow_method!='NONE')
- self.materials = materials
- self.material_names = [m.name for m in self.materials]
- for m in self.materials:
- if m.render_mode!=self.render_mode:
- raise Exception("Conflicting render modes in MaterialAtlas constructor")
- if self.render_mode=='CUSTOM' and m.shader!=self.shader:
- raise Exception("Conflicting shaders in MaterialAtlas constructor")
- if m.receive_shadows!=self.receive_shadows or m.shadow_method!=materials[0].shadow_method:
- raise Exception("Conflicting shadow settings in MaterialAtlas constructor")
-
- count = len(self.materials)
- size = 1
- while size*size*2<count:
- size *= 2
- if size*size>=count:
- self.size = (size, size)
- else:
- self.size = (size*2, size)
-
- from .util import get_colormap
-
- cm = get_colormap(True)
- self.base_color_data = ""
- for m in map(Material, self.materials):
- if any(p.texture for p in m.properties):
- raise Exception("Texturing is incompatible with material atlas")
- base_color = [int(cm(c)*255) for c in m.base_color.value]
- self.base_color_data += "\\x{:02X}\\x{:02X}\\x{:02X}\\xFF".format(*base_color)
- self.base_color_data += "\\x00\\x00\\x00\\x00"*(self.size[0]*self.size[1]-count)
-
- def get_material_uv(self, material):
- index = self.material_names.index(material.name)
- x = index%self.size[0]
- y = index//self.size[0]
- return ((x+0.5)/self.size[0], (y+0.5)/self.size[1])
-
-def create_material_atlas(context, material):
- if not material.material_atlas:
- raise Exception("Material is not part of a material atlas")
-
- shader = material.shader
- materials = []
- for m in context.blend_data.materials:
- if m.material_atlas and m.shader==shader:
- materials.append(m)
-
- return MaterialAtlas(materials)