return Statement(prop.keyword, prop.value)
-class MaterialMapExporter:
+class MaterialAtlasExporter:
def __init__(self):
pass
- def export_technique_resources(self, material_map, resources):
+ def export_technique_resources(self, material_atlas, resources):
from .datafile import Resource, Statement, Token
- base_color_name = material_map.name+"_base_color.tex2d"
+ base_color_name = material_atlas.name+"_base_color.tex2d"
base_color_res = resources.get(base_color_name)
if not base_color_res:
base_color_res = Resource(base_color_name, "texture2d")
- base_color_res.statements.append(Statement("storage", Token('SRGB_ALPHA'), *material_map.size))
- base_color_res.statements.append(Statement("raw_data", material_map.base_color_data))
+ base_color_res.statements.append(Statement("storage", Token('SRGB_ALPHA'), *material_atlas.size))
+ base_color_res.statements.append(Statement("raw_data", material_atlas.base_color_data))
resources[base_color_name] = base_color_res
resources[sampler_name] = sampler_res
- mat_name = material_map.name+".mat"
+ mat_name = material_atlas.name+".mat"
if mat_name not in resources:
mat_res = Resource(mat_name, "material")
st = Statement("pbr")
resources[mat_name] = mat_res
- def export_technique(self, material_map, *, resources):
- return create_technique_resource(material_map, resources)
+ def export_technique(self, material_atlas, *, resources):
+ return create_technique_resource(material_atlas, resources)
material_export.use_textures = self.use_textures
return material_export
- def create_material_map_exporter(self):
- from .export_material import MaterialMapExporter
- material_map_export = MaterialMapExporter()
- return material_map_export
+ def create_material_atlas_exporter(self):
+ from .export_material import MaterialAtlasExporter
+ material_atlas_export = MaterialAtlasExporter()
+ return material_atlas_export
def export_to_file(self, context, out_fn):
if self.export_all:
progress.pop_task()
- def export_object_resources(self, context, obj, resources, progress, material_maps=None):
- if material_maps is None:
- material_maps = {}
+ def export_object_resources(self, context, obj, resources, progress, material_atlass=None):
+ if material_atlass is None:
+ material_atlass = {}
lods = self.collect_object_lods(obj)
from .mesh import create_mesh_from_object
- from .material import create_material_map
+ from .material import create_material_atlas
mesh_export = self.create_mesh_exporter()
material_export = self.create_material_exporter()
- material_map_export = self.create_material_map_exporter()
+ material_atlas_export = self.create_material_atlas_exporter()
for i, l in enumerate(lods):
lod_index = l.lod_index if l.lod_for_parent else 0
progress.push_task_slice("LOD {}".format(lod_index), i, len(lods))
- material_map = None
- mapped_count = sum(m.render_mode!='EXTERNAL' and m.material_map for m in l.data.materials if m)
- if mapped_count:
+ material_atlas = None
+ atlas_flags = [m.render_mode!='EXTERNAL' and m.material_atlas for m in l.data.materials if m]
+ if any(atlas_flags):
mmk = lambda m: m.shader if m.render_mode=='CUSTOM' else ""
- material_map_key = mmk(l.data.materials[0])
- key_mismatch = any(mmk(m)!=material_map_key for m in l.data.materials)
- if mapped_count!=len(l.data.materials) or key_mismatch:
+ material_atlas_key = mmk(l.data.materials[0])
+ key_mismatch = any(mmk(m)!=material_atlas_key for m in l.data.materials)
+ if not all(atlas_flags) or key_mismatch:
raise Exception("Conflicting settings in object materials")
- if material_map_key in material_maps:
- material_map = material_maps[material_map_key]
+ if material_atlas_key in material_atlass:
+ material_atlas = material_atlass[material_atlas_key]
else:
- material_map = create_material_map(context, l.data.materials[0])
- material_maps[material_map_key] = material_map
+ material_atlas = create_material_atlas(context, l.data.materials[0])
+ material_atlass[material_atlas_key] = material_atlas
- tech_name = "{}.tech".format(material_map.name)
+ tech_name = "{}.tech".format(material_atlas.name)
if tech_name not in resources:
- material_map_export.export_technique_resources(material_map, resources)
- resources[tech_name] = material_map_export.export_technique(material_map, resources=resources)
+ material_atlas_export.export_technique_resources(material_atlas, resources)
+ resources[tech_name] = material_atlas_export.export_technique(material_atlas, resources=resources)
elif l.material_slots and l.material_slots[0].material:
material = l.material_slots[0].material
if material.render_mode!='EXTERNAL':
mesh_name = l.data.name+".mesh"
if mesh_name not in resources:
- mesh = create_mesh_from_object(context, l, progress, material_map=material_map)
+ mesh = create_mesh_from_object(context, l, progress, material_atlas=material_atlas)
mesh_res = mesh_export.export_mesh(context, mesh, progress)
resources[mesh_name] = mesh_res
if material:
if material.render_mode=='EXTERNAL':
tech_name = material.technique
- elif material.material_map:
- tech_name = "material_map_{}.tech".format(os.path.splitext(material.technique)[0])
+ elif material.material_atlas:
+ tech_name = "material_atlas_{}.tech".format(os.path.splitext(material.technique)[0])
else:
tech_name = material.name+".tech"
else:
object_export = ObjectExporter()
object_export.single_file = False
- material_maps = {}
+ material_atlass = {}
for i, o in enumerate(objs):
progress.push_task_slice(o.name, i, len(objs))
- object_export.export_object_resources(context, o, resources, progress, material_maps=material_maps)
+ object_export.export_object_resources(context, o, resources, progress, material_atlass=material_atlass)
obj_name = o.name+".object"
resources[obj_name] = object_export.export_object(context, o, progress, resources=resources)
progress.pop_task()
return prop
-class MaterialMap:
+class MaterialAtlas:
def __init__(self, materials):
self.render_mode = materials[0].render_mode
if self.render_mode=='EXTERNAL':
- raise Exception("Material map with external render mode does not make sense")
+ raise Exception("Material atlas with external render mode does not make sense")
self.shader = materials[0].shader
if self.shader:
- self.name = "material_map_"+os.path.splitext(self.shader)[0]
+ self.name = "material_atlas_"+os.path.splitext(self.shader)[0]
else:
- self.name = "material_map"
+ self.name = "material_atlas"
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 MaterialMap constructor")
+ raise Exception("Conflicting render modes in MaterialAtlas constructor")
if self.render_mode=='CUSTOM' and m.shader!=self.shader:
- raise Exception("Conflicting shaders in MaterialMap constructor")
+ raise Exception("Conflicting shaders in MaterialAtlas constructor")
count = len(self.materials)
size = 1
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 map")
+ 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)
y = index//self.size[0]
return ((x+0.5)/self.size[0], (y+0.5)/self.size[1])
-def create_material_map(context, material):
- if not material.material_map:
- raise Exception("Material is not part of a material map")
+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_map and m.shader==shader:
+ if m.material_atlas and m.shader==shader:
materials.append(m)
- mat_map = MaterialMap(materials)
+ mat_map = MaterialAtlas(materials)
return mat_map
# Merge materials and form a lookup from source material indices to the
# merged material list
- material_map = []
+ material_atlas = []
for m in other.materials:
if m in self.materials:
- material_map.append(self.materials.index(m))
+ material_atlas.append(self.materials.index(m))
else:
- material_map.append(len(self.materials))
+ material_atlas.append(len(self.materials))
self.materials.append(m)
# Append data and adjust indices where necessary. Since the data is
f.index += offset
f.loop_indices = range(f.loop_indices.start+offset, f.loop_indices.stop+offset)
if other.materials:
- f.material_index = material_map[f.material_index]
+ f.material_index = material_atlas[f.material_index]
offset = len(self.edges)
self.edges += other.edges
for g in v.groups:
g.group = group_index_map[g.group]
- def apply_material_map(self, material_map):
+ def apply_material_atlas(self, material_atlas):
for m in self.materials:
- if m.name not in material_map.material_names:
- raise Exception("Material map is not compatible with Mesh")
+ if m.name not in material_atlas.material_names:
+ raise Exception("Material atlas is not compatible with Mesh")
if self.use_uv=='NONE':
return
- layer = UvLayer("material_map")
+ layer = UvLayer("material_atlas")
if self.use_uv=='UNIT0':
self.uv_layers = [layer]
layer.unit = 0
layer.uvs = [(0.0, 0.0)]*len(self.loops)
for f in self.faces:
- uv = material_map.get_material_uv(self.materials[f.material_index])
+ uv = material_atlas.get_material_uv(self.materials[f.material_index])
for i in f.loop_indices:
layer.uvs[i] = uv
e.key = make_edge_key(e.vertices[0].index, e.vertices[1].index)
-def create_mesh_from_object(context, obj, progress, *, material_map=None):
+def create_mesh_from_object(context, obj, progress, *, material_atlas=None):
if obj.type!="MESH":
raise Exception("Object is not a mesh")
mesh.name = obj.data.name
- if material_map:
- mesh.apply_material_map(material_map)
+ if material_atlas:
+ mesh.apply_material_atlas(material_atlas)
progress.set_task("Triangulating", 0.2, 0.3)
mesh.prepare_triangles(progress)
if mat.array_atlas:
self.layout.prop(mat, "array_layer")
if mat.render_mode!='EXTERNAL':
- self.layout.prop(mat, "material_map")
+ self.layout.prop(mat, "material_atlas")
class MspGLTextureNodeProperties(bpy.types.Panel):
bl_idname = "NODE_PT_mspgl_properties"
bpy.types.Material.shader = bpy.props.StringProperty(name="Custom shader", description="Name of an external technique to use for rendering")
bpy.types.Material.array_atlas = bpy.props.BoolProperty(name="Texture array atlas", description="The material is stored in a texture array")
bpy.types.Material.array_layer = bpy.props.IntProperty("Texture array layer", description="Layer of the texture array atlas to use")
- bpy.types.Material.material_map = bpy.props.BoolProperty(name="Material map", description="Make this material part of a material map")
+ bpy.types.Material.material_atlas = bpy.props.BoolProperty(name="Material atlas", description="Make this material part of a material atlas")
bpy.types.ShaderNodeTexImage.default_filter = bpy.props.BoolProperty(name="Default filter", description="Let the loading program determine filtering options")
bpy.types.ShaderNodeTexImage.use_mipmap = bpy.props.BoolProperty(name="Use mipmaps", description="Use mipmaps (automatically generated) for the texture", default=True)