8 return 1.055*(l**(1/2.4))-0.055
10 def get_colormap(srgb):
19 return os.path.split(fp)[1]
26 self.show_progress = True
27 self.use_strips = True
28 self.use_degen_tris = False
30 self.separate_mesh = False
31 self.separate_tech = False
32 self.shared_resources = True
33 self.export_lods = True
35 def compute_bounding_sphere(self, obj):
36 p1 = max(((v.co, v.co.length) for v in obj.data.vertices), key=lambda x:x[1])[0]
37 p2 = max(((v.co, (v.co-p1).length) for v in obj.data.vertices), key=lambda x:x[1])[0]
39 radius = (p1-p2).length/2
40 for v in obj.data.vertices:
43 center += d*(1-radius/d.length)/2
44 radius = (radius+d.length)/2
48 def collect_object_lods(self, obj):
51 lods += sorted([c for c in obj.children if c.lod_for_parent], key=(lambda l: l.lod_index))
52 for i, l in enumerate(lods):
53 if i>0 and l.lod_index!=i:
54 raise Exception("Inconsistent LOD indices")
58 def create_mesh_exporter(self):
59 from .export_mesh import MeshExporter
60 mesh_export = MeshExporter()
61 mesh_export.use_strips = self.use_strips
62 mesh_export.use_degen_tris = self.use_degen_tris
65 def export_to_file(self, context, out_fn):
66 obj = context.active_object
68 from .util import Progress
69 progress = Progress(self.show_progress and context)
71 path, base = os.path.split(out_fn)
72 base = os.path.splitext(base)[0]
75 self.export_object_resources(context, obj, resources, progress)
77 obj_res = self.export_object(context, obj, progress, resources=resources)
78 refs = obj_res.collect_references()
79 if not self.shared_resources:
82 ext = os.path.splitext(r.name)[1]
83 n = numbers.get(ext, 0)
85 r.name = "{}_{}{}".format(base, n, ext)
91 with open(os.path.join(path, r.name), "w") as out_file:
92 for s in r.statements:
93 s.write_to_file(out_file)
95 with open(out_fn, "w") as out_file:
96 for s in obj_res.statements:
97 s.write_to_file(out_file)
99 def export_object_resources(self, context, obj, resources, progress):
100 lods = self.collect_object_lods(obj)
102 from .mesh import create_mesh_from_object
103 mesh_export = self.create_mesh_exporter()
105 for i, l in enumerate(lods):
106 lod_index = l.lod_index if l.lod_for_parent else 0
107 progress.push_task_slice("LOD {}".format(lod_index), i, len(lods))
109 mesh_name = l.data.name+".mesh"
110 if mesh_name not in resources:
111 mesh = create_mesh_from_object(context, l, progress)
112 mesh_res = mesh_export.export_mesh(context, mesh, progress)
113 resources[mesh_name] = mesh_res
116 if l.material_slots and l.material_slots[0].material:
117 material = l.material_slots[0].material
118 mat_name = material.name+".mat"
119 if mat_name not in resources:
120 resources[mat_name] = self.export_material(material)
122 tech_name = (material.name if material else l.name)+".tech"
123 if tech_name not in resources:
124 resources[tech_name] = self.export_object_technique(l, resources=resources)
128 def export_object(self, context, obj, progress, *, resources=None):
129 if resources is None:
131 self.export_object_resources(context, obj, resources, progress)
133 lods = self.collect_object_lods(obj)
135 from .datafile import Resource, Statement
136 obj_res = Resource(obj.name+".object")
137 statements = obj_res.statements
139 center, radius = self.compute_bounding_sphere(obj)
140 statements.append(Statement("bounding_sphere_hint", *center, radius))
143 prev_tech = (None, None)
144 for i, l in enumerate(lods):
147 if l.data.name!=prev_mesh:
148 mesh_res = resources[l.data.name+".mesh"]
149 if self.separate_mesh:
150 lod_st.append(obj_res.create_reference_statement("mesh", mesh_res))
152 lod_st.append(obj_res.create_embed_statement("mesh", mesh_res))
154 prev_mesh = l.data.name
157 if l.material_slots and l.material_slots[0].material:
158 mat_name = l.material_slots[0].material.name
160 tech = (l.technique, mat_name)
162 tech_res = resources[(mat_name or l.name)+".tech"]
165 lod_st.append(obj_res.create_embed_statement("technique", tech_res))
167 lod_st.append(Statement("technique", l.technique))
168 elif self.separate_tech:
169 lod_st.append(obj_res.create_reference_statement("technique", tech_res))
171 lod_st.append(obj_res.create_embed_statement("technique", tech_res))
176 st = Statement("level_of_detail", i)
178 statements.append(st)
182 progress.set_progress(1.0)
186 def export_object_technique(self, obj, *, resources):
188 if obj.material_slots:
189 material = obj.material_slots[0].material
191 from .datafile import Resource, Statement, Token
192 tech_res = Resource((material.name if material else obj.name)+".tech")
196 mat_res = resources[material.name+".mat"]
199 if not obj.inherit_tech:
202 st = Statement("inherit", obj.technique)
204 for slot in material.texture_slots:
205 if slot and slot.texture.type=="IMAGE":
206 name = image_name(slot.texture.image)
207 if slot.use_map_color_diffuse:
208 st.sub.append(Statement("texture", "diffuse_map", name))
209 elif slot.use_map_normal:
210 st.sub.append(Statement("texture", "normal_map", name))
211 if obj.override_material:
212 st.sub.append(tech_res.create_reference_statement("material", "surface", mat_res))
213 tech_res.statements.append(st)
217 pass_st = Statement("pass", "")
219 pass_st.sub.append(tech_res.create_embed_statement("material", mat_res))
221 if self.textures!="NONE":
223 for slot in material.texture_slots:
224 if slot and slot.texture.type=="IMAGE" and slot.use_map_color_diffuse:
225 diffuse_tex = slot.texture
229 st = Statement("texunit", 0)
230 if self.textures=="INLINE":
231 ss = Statement("texture2d")
232 ss.sub.append(Statement("min_filter", Token("LINEAR")))
233 ss.sub.append(Statement("storage", Token("RGBA"), tex.image.size[0], tex.image.size[1]))
235 for p in tex.image.pixels:
236 texdata += "\\x%02X"%int(p*255)
237 ss.sub.append(Statement("raw_data", texdata))
240 st.sub.append(Statement("texture", image_name(tex.image)))
241 pass_st.sub.append(st)
242 tech_res.statements.append(pass_st)
246 def export_material(self, material):
247 from .datafile import Resource, Statement
248 mat_res = Resource(material.name+".mat")
249 statements = mat_res.statements
251 cm = get_colormap(material.srgb_colors)
252 if any(s.use_map_color_diffuse for s in material.texture_slots if s):
253 statements.append(Statement("diffuse", 1.0, 1.0, 1.0, 1.0))
254 amb = cm(material.ambient)
255 statements.append(Statement("ambient", amb, amb, amb, 1.0))
257 diff = material.diffuse_color*material.diffuse_intensity
258 statements.append(Statement("diffuse", cm(diff.r), cm(diff.g), cm(diff.b), 1.0))
259 amb = diff*material.ambient
260 statements.append(Statement("ambient", cm(amb.r), cm(amb.g), cm(amb.b), 1.0))
261 spec = material.specular_color*material.specular_intensity
262 statements.append(Statement("specular", cm(spec.r), cm(spec.g), cm(spec.g), 1.0))
263 statements.append(Statement("shininess", material.specular_hardness))