From: Mikko Rasa Date: Thu, 17 Mar 2022 10:17:48 +0000 (+0200) Subject: Further refactoring of instance handling in the Blender exporter X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=6c881bc1ee3c0af5c1bb4b3794dcb23ba096ac12 Further refactoring of instance handling in the Blender exporter --- diff --git a/blender/io_mspgl/export.py b/blender/io_mspgl/export.py index 95cc556f..238f8c4d 100644 --- a/blender/io_mspgl/export.py +++ b/blender/io_mspgl/export.py @@ -105,7 +105,7 @@ class ProjectExporter: all_objects = [] for s in scenes.values(): - all_objects += s.prototypes + all_objects += [p.object for p in s.prototypes] all_objects += s.lights if s.camera: all_objects.append(s.camera) diff --git a/blender/io_mspgl/export_scene.py b/blender/io_mspgl/export_scene.py index e7759e9c..a42d8180 100644 --- a/blender/io_mspgl/export_scene.py +++ b/blender/io_mspgl/export_scene.py @@ -33,7 +33,7 @@ class SceneExporter: from .export import DataExporter data_exporter = DataExporter() - data_exporter.export_resources(ctx, scene.prototypes, resources) + data_exporter.export_resources(ctx, [p.object for p in scene.prototypes], resources) def export_scene(self, scene, resources): from .datafile import Resource, Statement, Token @@ -73,23 +73,28 @@ class SceneExporter: if i.name: st.append(i.name) - ss = Statement("transform") + st.sub.append(self.create_transform_statement(i)) + statements.append(st) - loc = i.matrix_world.to_translation() - ss.sub.append(Statement("position", *tuple(loc))) + def create_transform_statement(self, instance): + from .datafile import Statement - quat = i.matrix_world.to_quaternion() - if i.rotation_mode in ('XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'): - angles = [a*180/math.pi for a in quat.to_euler()] - ss.sub.append(Statement("euler", *angles)); - else: - ss.sub.append(Statement("rotation", quat.angle*180/math.pi, *tuple(quat.axis))) + st = Statement("transform") - scale = i.matrix_world.to_scale() - ss.sub.append(Statement("scale", *tuple(scale))) + loc = instance.matrix_world.to_translation() + st.sub.append(Statement("position", *tuple(loc))) - st.sub.append(ss) - statements.append(st) + quat = instance.matrix_world.to_quaternion() + if instance.rotation_mode in ('XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'): + angles = [a*180/math.pi for a in quat.to_euler()] + st.sub.append(Statement("euler", *angles)); + else: + st.sub.append(Statement("rotation", quat.angle*180/math.pi, *tuple(quat.axis))) + + scale = instance.matrix_world.to_scale() + st.sub.append(Statement("scale", *tuple(scale))) + + return st def export_sequence_resources(self, scene, resources): from .datafile import Resource, Statement, Token @@ -151,8 +156,8 @@ class SceneExporter: use_shadow = True shadowed_lights += [l.data for l in s.lights if l.data.use_shadow] for i in itertools.chain(s.instances, s.blended_instances): - p = i.prototype - if p.material_slots and p.material_slots[0].material and p.material_slots[0].material.shadow_method!='NONE': + o = i.prototype.object + if o.material_slots and o.material_slots[0].material and o.material_slots[0].material.shadow_method!='NONE': shadow_casters.append(i) s = s.background_set @@ -290,7 +295,7 @@ class SceneExporter: def compute_bounding_sphere(self, instances): points = [] for i in instances: - points += [i.matrix_world@mathutils.Vector(c) for c in i.prototype.bound_box] + points += [i.matrix_world@mathutils.Vector(c) for c in i.prototype.object.bound_box] from .util import compute_bounding_sphere return compute_bounding_sphere(points) diff --git a/blender/io_mspgl/scene.py b/blender/io_mspgl/scene.py index 4cb6be5b..cb62a1b0 100644 --- a/blender/io_mspgl/scene.py +++ b/blender/io_mspgl/scene.py @@ -10,18 +10,24 @@ def is_same_object(obj1, obj2): return True -class Instance: +class ObjectPrototype: + def __init__(self, obj): + self.name = obj.name + self.object = obj + self.instances = [] + self.use_array = False + +class ObjectInstance: def __init__(self, obj, prototype): if type(obj)==bpy.types.DepsgraphObjectInstance: self.name = None self.matrix_world = mathutils.Matrix(obj.matrix_world) - self.rotation_mode = prototype.rotation_mode - self.prototype = bpy.data.objects[prototype.name] + self.rotation_mode = prototype.object.rotation_mode else: self.name = obj.name self.matrix_world = obj.matrix_world self.rotation_mode = obj.rotation_mode - self.prototype = prototype + self.prototype = prototype class Scene: def __init__(self, scene, obj_filter=None): @@ -64,9 +70,10 @@ class Scene: if obj_filter: objects = list(filter(obj_filter, objects)) + proto_map = {} for o in objects: if o.type=='MESH': - self.add_instance(Instance(o, o)) + self.add_instance(o, o, proto_map) elif o.type=='LIGHT': self.lights.append(o) if o.data.use_shadow: @@ -74,36 +81,33 @@ class Scene: for i in scene.view_layers[0].depsgraph.object_instances: if i.is_instance and i.object.type=='MESH': - self.add_instance(Instance(i, i.object)) + self.add_instance(i, bpy.data.objects[i.object.name], proto_map) + + def add_instance(self, obj, proto_obj, proto_map): + prototype = proto_map.get(proto_obj) + if not prototype: + for p in proto_map.values(): + if is_same_object(proto_obj, p.object): + prototype = p + break + + if not prototype: + prototype = ObjectPrototype(proto_obj) + self.prototypes.append(prototype) + + proto_map[proto_obj] = prototype - proto_map = {} - for i in itertools.chain(self.instances, self.blended_instances): - p = proto_map.get(i.prototype) - if p: - i.prototype = p - else: - found = False - for p in proto_map.values(): - if is_same_object(i.prototype, p): - proto_map[i.prototype] = p - i.prototype = p - found = True - break - - if not found: - proto_map[i.prototype] = i.prototype - self.prototypes.append(i.prototype) - - def add_instance(self, instance): - obj = instance.prototype instance_list = self.instances - if obj.material_slots and obj.material_slots[0].material: - mat = obj.material_slots[0].material + if proto_obj.material_slots and proto_obj.material_slots[0].material: + mat = proto_obj.material_slots[0].material if mat.blend_method=='BLEND': instance_list = self.blended_instances if mat.image_based_lighting: self.use_ibl = True + + instance = ObjectInstance(obj, prototype) instance_list.append(instance) + prototype.instances.append(instance) def get_chain(self): result = []