return center, radius
- def make_external_name(self, base_name, resource_name, ext, index):
- if self.shared_resources:
- return resource_name+ext
- elif lod_index>0:
- return "{}_lod{}{}".format(base_name, lod_index, ext)
- else:
- return base_name+ext
+ def collect_object_lods(self, obj):
+ lods = [obj]
+ if self.export_lods:
+ lods += sorted([c for c in obj.children if c.lod_for_parent], key=(lambda l: l.lod_index))
+ for i, l in enumerate(lods):
+ if i>0 and l.lod_index!=i:
+ raise Exception("Inconsistent LOD indices")
+
+ return lods
def create_mesh_exporter(self):
from .export_mesh import MeshExporter
path, base = os.path.split(out_fn)
base = os.path.splitext(base)[0]
- meshes = self.export_object_meshes(context, obj, progress, base_name=base)
- if self.separate_mesh:
- for name, st in meshes.items():
- with open(os.path.join(path, name), "w") as out_file:
- for s in st:
- s.write_to_file(out_file)
-
- if self.separate_tech:
- lods = [obj]
- if self.export_lods:
- lods += [c for c in obj.children if c.lod_for_parent]
-
- for l in lods:
- lod_index = l.lod_index if l.lod_for_parent else 0
-
- material = None
- if obj.material_slots:
- material = obj.material_slots[0].material
-
- if not l.technique:
- tech_name = self.make_external_name(base, material.name, ".tech", lod_index)
- st = self.export_object_technique(l, base_name=base)
- with open(os.path.join(path, tech_name), "w") as out_file:
- for s in st:
- s.write_to_file(out_file)
- elif material and l.override_material:
- mat_name = self.make_external_name(base, material.name, ".mat", lod_index)
- st = self.export_material(material)
- with open(os.path.join(path, mat_name), "w") as out_file:
- for s in st:
- s.write_to_file(out_file)
-
- statements = self.export_object(context, obj, progress, meshes=meshes, base_name=base)
+ resources = {}
+ self.export_object_resources(context, obj, resources, progress)
+
+ obj_res = self.export_object(context, obj, progress, resources=resources)
+ refs = obj_res.collect_references()
+ if not self.shared_resources:
+ numbers = {}
+ for r in refs:
+ ext = os.path.splitext(r.name)[1]
+ n = numbers.get(ext, 0)
+ if n>0:
+ r.name = "{}_{}{}".format(base, n, ext)
+ else:
+ r.name = base+ext
+ numbers[ext] = n+1
+
+ for r in refs:
+ with open(os.path.join(path, r.name), "w") as out_file:
+ for s in r.statements:
+ s.write_to_file(out_file)
with open(out_fn, "w") as out_file:
- for s in statements:
+ for s in obj_res.statements:
s.write_to_file(out_file)
- def export_object_meshes(self, context, obj, progress, *, base_name=None):
- if base_name is None:
- base_name = obj.name
-
- lods = [obj]
- if self.export_lods:
- lods += [c for c in obj.children if c.lod_for_parent]
+ def export_object_resources(self, context, obj, resources, progress):
+ lods = self.collect_object_lods(obj)
from .mesh import create_mesh_from_object
mesh_export = self.create_mesh_exporter()
- meshes = {}
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))
- mesh_name = self.make_external_name(base_name, l.data.name, ".mesh", lod_index)
- if mesh_name not in meshes:
+ mesh_name = l.data.name+".mesh"
+ if mesh_name not in resources:
mesh = create_mesh_from_object(context, l, progress)
- meshes[mesh_name] = mesh_export.export_mesh(context, mesh, progress)
+ mesh_res = mesh_export.export_mesh(context, mesh, progress)
+ resources[mesh_name] = mesh_res
- progress.pop_task()
+ material = None
+ if l.material_slots and l.material_slots[0].material:
+ material = l.material_slots[0].material
+ mat_name = material.name+".mat"
+ if mat_name not in resources:
+ resources[mat_name] = self.export_material(material)
- return meshes
+ tech_name = (material.name if material else l.name)+".tech"
+ if tech_name not in resources:
+ resources[tech_name] = self.export_object_technique(l, resources=resources)
- def export_object(self, context, obj, progress, *, meshes=None, base_name=None):
- if base_name is None:
- base_name = obj.name
+ progress.pop_task()
- if meshes is None:
- meshes = self.export_object_meshes(context, obj, progress, base_name=base_name)
+ def export_object(self, context, obj, progress, *, resources=None):
+ if resources is None:
+ resources = {}
+ self.export_object_resources(context, obj, resources, progress)
- lods = [obj]
- for c in obj.children:
- if c.lod_for_parent:
- if c.lod_index>=len(lods):
- lods += [None]*(c.lod_index+1-len(lods))
- lods[c.lod_index] = c
+ lods = self.collect_object_lods(obj)
- from .datafile import Statement
- statements = []
+ from .datafile import Resource, Statement
+ obj_res = Resource(obj.name+".object")
+ statements = obj_res.statements
center, radius = self.compute_bounding_sphere(obj)
statements.append(Statement("bounding_sphere_hint", *center, radius))
lod_st = []
if l.data.name!=prev_mesh:
- mesh_name = self.make_external_name(base_name, l.data.name, ".mesh", i)
+ mesh_res = resources[l.data.name+".mesh"]
if self.separate_mesh:
- lod_st.append(Statement("mesh", mesh_name))
+ lod_st.append(obj_res.create_reference_statement("mesh", mesh_res))
else:
- st = Statement("mesh")
- st.sub = meshes[mesh_name]
- lod_st.append(st)
+ lod_st.append(obj_res.create_embed_statement("mesh", mesh_res))
prev_mesh = l.data.name
tech = (l.technique, mat_name)
if tech!=prev_tech:
- tech_name = self.make_external_name(base_name, mat_name or l.name, ".tech", i)
+ tech_res = resources[(mat_name or l.name)+".tech"]
if l.technique:
if l.inherit_tech:
- st = Statement("technique")
- st.sub = self.export_object_technique(l, base_name=base_name)
- lod_st.append(st)
+ lod_st.append(obj_res.create_embed_statement("technique", tech_res))
else:
lod_st.append(Statement("technique", l.technique))
elif self.separate_tech:
- lod_st.append(Statement("technique", tech_name))
+ lod_st.append(obj_res.create_reference_statement("technique", tech_res))
else:
- st = Statement("technique")
- st.sub = self.export_object_technique(l, base_name=base_name)
- lod_st.append(st)
+ lod_st.append(obj_res.create_embed_statement("technique", tech_res))
prev_tech = tech
progress.set_progress(1.0)
- return statements
-
- def export_object_technique(self, obj, *, base_name=None):
- if base_name is None:
- base_name = obj.name
+ return obj_res
+ def export_object_technique(self, obj, *, resources):
material = None
if obj.material_slots:
material = obj.material_slots[0].material
- from .datafile import Statement, Token
- statements = []
+ from .datafile import Resource, Statement, Token
+ tech_res = Resource((material.name if material else obj.name)+".tech")
+
+ mat_res = None
+ if material:
+ mat_res = resources[material.name+".mat"]
if obj.technique:
if not obj.inherit_tech:
- return []
+ return tech_res
st = Statement("inherit", obj.technique)
if material:
elif slot.use_map_normal:
st.sub.append(Statement("texture", "normal_map", name))
if obj.override_material:
- mat_name = self.make_external_name(base_name, material.name, ".mat", obj.lod_index)
- st.sub.append(Statement("material", "surface", mat_name))
- statements.append(st)
+ st.sub.append(tech_res.create_reference_statement("material", "surface", mat_res))
+ tech_res.statements.append(st)
- return statements
+ return tech_res
pass_st = Statement("pass", "")
if material:
- st = Statement("material")
- st.sub = self.export_material(material)
- pass_st.sub.append(st)
+ pass_st.sub.append(tech_res.create_embed_statement("material", mat_res))
if self.textures!="NONE":
diffuse_tex = None
elif tex.image:
st.sub.append(Statement("texture", image_name(tex.image)))
pass_st.sub.append(st)
- statements.append(pass_st)
+ tech_res.statements.append(pass_st)
- return statements
+ return tech_res
def export_material(self, material):
- from .datafile import Statement
- statements = []
+ from .datafile import Resource, Statement
+ mat_res = Resource(material.name+".mat")
+ statements = mat_res.statements
cm = get_colormap(material.srgb_colors)
if any(s.use_map_color_diffuse for s in material.texture_slots if s):
statements.append(Statement("specular", cm(spec.r), cm(spec.g), cm(spec.g), 1.0))
statements.append(Statement("shininess", material.specular_hardness))
- return statements
+ return mat_res
from .util import Progress
progress = Progress(self.show_progress and context)
- from .export_object import ObjectExporter
- object_export = ObjectExporter()
+ resources = {}
+ self.export_scene_resources(context, unique_objects, resources, progress)
+
+ scene_res = self.export_scene(context, objs, progress, prototypes=object_prototypes, resources=resources)
+ refs = scene_res.collect_references()
from .datafile import Statement
if self.resource_collection:
+ keywords = { ".mat": "material",
+ ".mesh": "mesh",
+ ".object": "object",
+ ".tech": "technique" }
with open(os.path.join(path, base+"_resources.mdc"), "w") as res_out:
- for i, o in enumerate(unique_objects):
- progress.push_task_slice(o.name, i, len(unique_objects))
- st = Statement("object", "{}.object".format(o.name))
- st.sub = object_export.export_object(context, o, progress)
+ for r in refs:
+ st = Statement(keywords[os.path.splitext(r.name)[1]], r.name)
+ st.sub = r.statements
st.write_to_file(res_out)
- progress.pop_task()
else:
res_dir = os.path.join(path, base+"_resources")
if not os.path.exists(res_dir):
os.makedirs(res_dir)
- for i, o in enumerate(unique_objects):
- progress.push_task_slice(o.name, i, len(unique_objects))
- st = object_export.export_object(context, o, progress)
- with open(os.path.join(res_dir, o.name+".object"), "w") as obj_out:
- for s in st:
- s.write_to_file(obj_out)
- progress.pop_task()
-
- statements = self.export_scene(context, objs, progress, prototypes=object_prototypes)
+ for r in refs:
+ with open(os.path.join(res_dir, r.name), "w") as res_out:
+ for s in r.statements:
+ s.write_to_file(res_out)
with open(out_fn, "w") as out_file:
- for s in statements:
+ for s in scene_res.statements:
s.write_to_file(out_file)
- def export_scene(self, context, objs, progress, *, prototypes=None):
- from .datafile import Statement
- statements = []
+ def export_scene_resources(self, context, objs, resources, progress):
+ from .export_object import ObjectExporter
+ object_export = ObjectExporter()
+ object_export.separate_mesh = True
+ object_export.separate_tech = True
+
+ for i, o in enumerate(objs):
+ progress.push_task_slice(o.name, i, len(objs))
+ object_export.export_object_resources(context, o, resources, progress)
+ obj_name = o.name+".object"
+ resources[obj_name] = object_export.export_object(context, o, progress, resources=resources)
+ progress.pop_task()
+
+ def export_scene(self, context, objs, progress, *, prototypes, resources):
+ from .datafile import Resource, Statement
+ scene_res = Resource("scene.scene")
for o in objs:
- st = Statement("object", "{}.object".format(prototypes[o.name].name))
+ obj_res = resources[prototypes[o.name].name+".object"]
+ st = scene_res.create_reference_statement("object", obj_res)
# XXX Parent relationships screw up the location and rotation
st.sub.append(Statement("position", o.location[0], o.location[1], o.location[2]))
if o.rotation_mode=="AXIS_ANGLE":
axis = q.axis
st.sub.append(Statement("rotation", angle*180/math.pi, axis[0], axis[1], axis[2]))
st.sub.append(Statement("scale", o.scale[0], o.scale[1], o.scale[2]))
- statements.append(st)
+ scene_res.statements.append(st)
progress.set_progress(1.0)
- return statements
+ return scene_res