]> git.tdb.fi Git - libs/gl.git/commitdiff
Remove support for material atlases from the Blender exporter
authorMikko Rasa <tdb@tdb.fi>
Thu, 17 Mar 2022 08:46:50 +0000 (10:46 +0200)
committerMikko Rasa <tdb@tdb.fi>
Thu, 17 Mar 2022 09:02:56 +0000 (11:02 +0200)
Support for PBR materials was never added and it's unknown if it even
works anymore.  Baking and vertex colors are better solutions.

blender/io_mspgl/export.py
blender/io_mspgl/export_material.py
blender/io_mspgl/export_object.py
blender/io_mspgl/export_scene.py
blender/io_mspgl/material.py
blender/io_mspgl/mesh.py
blender/io_mspgl/properties.py

index b74fa5300bc86c06af1c5846c36dfa7218849add..95cc556f5504d984291cd45d124fac2dee29fbd3 100644 (file)
@@ -5,10 +5,9 @@ class DataExporter:
                objects = context.context.selected_objects
 
                resources = {}
-               material_atlases = {}
 
                task = ctx.task("Exporting resources", 1.0)
-               dummy_res = self.export_resources(task, objects, resources, material_atlases)
+               dummy_res = self.export_resources(task, objects, resources)
 
                path, base = os.path.split(out_fn)
                base, ext = os.path.splitext(base)
@@ -32,10 +31,7 @@ class DataExporter:
                        for r in refs:
                                r.write_to_file(os.path.join(path, r.name))
 
-       def export_resources(self, ctx, objects, resources, material_atlases):
-               if material_atlases is None:
-                       material_atlases = {}
-
+       def export_resources(self, ctx, objects, resources):
                object_exporter = None
                camera_exporter = None
                armature_exporter = None
@@ -55,7 +51,7 @@ class DataExporter:
                                        if not object_exporter:
                                                from .export_object import ObjectExporter
                                                object_exporter = ObjectExporter()
-                                       object_exporter.export_object_resources(task, obj, resources, material_atlases)
+                                       object_exporter.export_object_resources(task, obj, resources)
                                        res = object_exporter.export_object(obj, resources)
                        elif obj.type=='CAMERA':
                                res_name = obj.name+".camera"
@@ -132,7 +128,7 @@ class ProjectExporter:
 
                task = ctx.task("Exporting resources", 1.0)
                resources = {}
-               dummy_res = data_exporter.export_resources(task, all_objects, resources, None)
+               dummy_res = data_exporter.export_resources(task, all_objects, resources)
 
                task = ctx.task("Exporting scenes", 1.0)
                for s in ordered_scenes:
index aceb6cc0d833ccfb2ab186ff4f4eb017f09cca5c..7f36beeb4016972acf9e72a052fa0c56f79ba010 100644 (file)
@@ -181,42 +181,3 @@ class MaterialExporter:
                shader_res.statements.append(st)
 
                return shader_res
-
-
-class MaterialAtlasExporter:
-       def __init__(self):
-               pass
-
-       def export_technique_resources(self, material_atlas, resources):
-               from .datafile import Resource, Statement, Token
-               base_color_name = material_atlas.name+"_base_color.tex"
-               base_color_res = resources.get(base_color_name)
-               if not base_color_res:
-                       base_color_res = Resource(base_color_name, "texture")
-
-                       base_color_res.statements.append(Statement("type", Token("\\2d")))
-                       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
-
-               sampler_name = "nearest.samp"
-               sampler_res = resources.get(sampler_name)
-               if not sampler_res:
-                       sampler_res = Resource(sampler_name, "sampler")
-
-                       sampler_res.statements.append(Statement("filter", Token('NEAREST')))
-
-                       resources[sampler_name] = sampler_res
-
-               mat_name = material_atlas.name+".mat"
-               if mat_name not in resources:
-                       mat_res = Resource(mat_name, "material")
-                       mat_res.statements.append(Statement("type", Token('pbr')))
-                       mat_res.statements.append(mat_res.create_reference_statement("base_color_map", base_color_res))
-                       mat_res.statements.append(mat_res.create_reference_statement("sampler", sampler_res))
-
-                       resources[mat_name] = mat_res
-
-       def export_technique(self, material_atlas, resources):
-               return create_technique_resource(material_atlas, resources)
index 476927af733619b7ed9754ef3f18f71eae593b4a..989d675837485f121459d9bd130f3f4e6035e320 100644 (file)
@@ -10,45 +10,22 @@ class ObjectExporter:
 
                return lods
 
-       def export_object_resources(self, ctx, obj, resources, material_atlases):
-               if material_atlases is None:
-                       material_atlases = {}
-
+       def export_object_resources(self, ctx, obj, resources):
                lods = self.collect_object_lods(obj)
 
                from .export_mesh import MeshExporter
-               from .export_material import MaterialAtlasExporter, MaterialExporter
+               from .export_material import MaterialExporter
                from .mesh import create_mesh_from_object
-               from .material import Material, create_material_atlas
+               from .material import Material
                mesh_export = MeshExporter()
                material_export = MaterialExporter()
-               material_atlas_export = MaterialAtlasExporter()
 
                ctx.set_slices(len(lods))
                for l in lods:
                        lod_index = l.lod_index if l.lod_for_parent else 0
                        task = ctx.next_slice("LOD {}".format(lod_index))
 
-                       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_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("Invalid configuration on object {}: Mixed material atlas state")
-
-                               if material_atlas_key in material_atlases:
-                                       material_atlas = material_atlases[material_atlas_key]
-                               else:
-                                       material_atlas = create_material_atlas(task.context, l.data.materials[0])
-                                       material_atlases[material_atlas_key] = material_atlas
-
-                               tech_name = "{}.tech".format(material_atlas.name)
-                               if tech_name not in resources:
-                                       material_atlas_export.export_technique_resources(material_atlas, resources)
-                                       resources[tech_name] = material_atlas_export.export_technique(material_atlas, resources)
-                       elif l.material_slots and l.material_slots[0].material:
+                       if l.material_slots and l.material_slots[0].material:
                                material = l.material_slots[0].material
                                subtask = task.task(material, 0.1)
                                if material.render_mode!='EXTERNAL':
@@ -63,7 +40,7 @@ class ObjectExporter:
                        mesh_name = l.data.name+".mesh"
                        if mesh_name not in resources:
                                subtask = task.task(l.data, 1.0)
-                               mesh = create_mesh_from_object(subtask, l, material_atlas)
+                               mesh = create_mesh_from_object(subtask, l)
                                mesh_res = mesh_export.export_mesh(subtask, mesh)
                                resources[mesh_name] = mesh_res
 
@@ -98,8 +75,6 @@ class ObjectExporter:
                        if material:
                                if material.render_mode=='EXTERNAL':
                                        tech_name = material.technique
-                               elif material.material_atlas:
-                                       tech_name = "material_atlas_{}.tech".format(os.path.splitext(material.technique)[0])
                                else:
                                        tech_name = material.name+".tech"
                        else:
index 861286ff4f2a2e54631093004e1a4ced14b8141e..e7759e9c4c8a775e6aff2f9879fb6c6d30eacb98 100644 (file)
@@ -33,7 +33,7 @@ class SceneExporter:
                from .export import DataExporter
                data_exporter = DataExporter()
 
-               data_exporter.export_resources(ctx, scene.prototypes, resources, None)
+               data_exporter.export_resources(ctx, scene.prototypes, resources)
 
        def export_scene(self, scene, resources):
                from .datafile import Resource, Statement, Token
index e92aee2f3e55303c0ddc25461316221e865c7df1..ff145515db5febe6cdf1a518237e5a7d186d1e77 100644 (file)
@@ -296,70 +296,3 @@ class Material:
                        prop = MaterialProperty(*args)
                self.properties.append(prop)
                return prop
-
-
-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")
-
-               if self.render_mode=='CUSTOM':
-                       self.render_methods = materials[0].render_methods
-               else:
-                       self.render_methods = None
-               if self.render_methods:
-                       self.name = "material_atlas_"+os.path.splitext(self.render_methods[0].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]
-               self.uniforms = None
-               method_hash = compute_render_method_hash(self)
-               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 compute_render_method_hash(m)!=method_hash:
-                               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")
-
-       method_hash = compute_render_method_hash(material)
-       materials = []
-       for m in context.blend_data.materials:
-               if m.material_atlas and compute_render_method_hash(m)==method_hash:
-                       materials.append(m)
-
-       return MaterialAtlas(materials)
index 3b1c74dfbec9675403226a3435fed354ffed7ef8..bf5d108ba5e27caa68c9767638702aca3b9ea7d6 100644 (file)
@@ -257,12 +257,12 @@ class Mesh:
 
                # Merge materials and form a lookup from source material indices to the
                # merged material list
-               material_atlas = []
+               material_lookup = []
                for m in other.materials:
                        if m in self.materials:
-                               material_atlas.append(self.materials.index(m))
+                               material_lookup.append(self.materials.index(m))
                        else:
-                               material_atlas.append(len(self.materials))
+                               material_lookup.append(len(self.materials))
                                self.materials.append(m)
 
                # Append data and adjust indices where necessary.  Since the data is
@@ -293,7 +293,7 @@ class Mesh:
                        f.index += offset
                        f.loop_indices = range(f.loop_indices.start+offset, f.loop_indices.stop+offset)
                        if other.materials:
-                               f.material_index = material_atlas[f.material_index]
+                               f.material_index = material_lookup[f.material_index]
 
                offset = len(self.edges)
                self.edges += other.edges
@@ -411,30 +411,6 @@ class Mesh:
                                for g in v.groups:
                                        g.group = group_index_map[g.group]
 
-       def apply_material_atlas(self, material_atlas):
-               for m in self.materials:
-                       if m.name not in material_atlas.material_names:
-                               raise Exception("Material atlas {} is not compatible with Mesh {}".format(material_atlas.name, self.name))
-
-               if self.use_uv=='NONE':
-                       return
-
-               layer = UvLayer("material_atlas")
-               if self.use_uv=='UNIT0':
-                       self.uv_layers = [layer]
-                       layer.unit = 0
-               else:
-                       self.uv_layers.append(layer)
-                       used_units = [u.unit for u in self.uv_layers]
-                       layer.unit = next(i for i in itertools.count() if i not in used_units)
-                       self.uv_layers.sort(key=lambda u: u.unit)
-
-               layer.uvs = [(0.0, 0.0)]*len(self.loops)
-               for f in self.faces:
-                       uv = material_atlas.get_material_uv(self.materials[f.material_index])
-                       for i in f.loop_indices:
-                               layer.uvs[i] = uv
-
        def prepare_uv(self, task):
                # Form a list of UV layers referenced by materials with the array atlas
                # property set
@@ -793,7 +769,7 @@ class Mesh:
                        e.key = make_edge_key(e.vertices[0].index, e.vertices[1].index)
 
 
-def create_mesh_from_object(ctx, obj, material_atlas):
+def create_mesh_from_object(ctx, obj):
        if obj.type!="MESH":
                raise Exception("Object {} is not a mesh".format(obj.name))
 
@@ -838,9 +814,6 @@ def create_mesh_from_object(ctx, obj, material_atlas):
 
        mesh.name = obj.data.name
 
-       if material_atlas:
-               mesh.apply_material_atlas(material_atlas)
-
        task = ctx.task("Triangulating", 0.3)
        mesh.prepare_triangles(task)
        task = ctx.task("Smoothing", 0.5)
index 9b00a76c27f5c238e05ff9f17904ba9aef34bd79..a5a24274dc648b0bc28a951a23361627098d1c93 100644 (file)
@@ -119,8 +119,6 @@ class MspGLMaterialProperties(bpy.types.Panel):
                self.layout.prop(mat, "array_atlas")
                if mat.array_atlas:
                        self.layout.prop(mat, "array_layer")
-               if mat.render_mode!='EXTERNAL':
-                       self.layout.prop(mat, "material_atlas")
                if mat.render_mode=='CUSTOM':
                        self.layout.separator()
                        self.layout.label(text="Uniform values")
@@ -272,7 +270,6 @@ def register_properties():
        bpy.types.Material.image_based_lighting = bpy.props.BoolProperty(name="Image based lighting", description="Use an environment map for ambient lighting", default=False)
        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_atlas = bpy.props.BoolProperty(name="Material atlas", description="Make this material part of a material atlas")
        bpy.types.Material.uniforms = bpy.props.CollectionProperty(type=MspGLUniform, name="Uniforms", description="Uniform variables to add to the technique")
        bpy.types.Material.active_uniform_index = bpy.props.IntProperty("Active uniform index")