max_strip_len = bpy.props.IntProperty(name="Max strip length", description="Maximum length for a triangle strip", default=1024, min=4, max=16384)
optimize_cache = bpy.props.BoolProperty(name="Optimize cache", description="Optimize element order for vertex cache", default=True)
cache_size = bpy.props.IntProperty(name="Cache size", description="Simulated vertex cache size used in optimization", default=64, min=8, max=1024)
- export_lines = bpy.props.BoolProperty(name="Export lines", description="Export edges without faces as lines", default=False)
- export_uv = bpy.props.EnumProperty(name="Export UV", description="Export UV coordinates", default="UNIT0",
- items=(("NONE", "None", "No UV coordinates are exported"),
- ("UNIT0", "Unit 0", "UV coordinates for unit 0 are exported"),
- ("ALL", "All", "All UV coordinates are exported")))
- tbn_vecs = bpy.props.BoolProperty(name="TBN vectors", description="Compute tangent and binormal vectors for vertices", default=False)
- tbn_uvtex = bpy.props.StringProperty(name="TBN UV layer", description="UV layer to use as basis for TBN vectors", default="")
compound = bpy.props.BoolProperty(name="Compound", description="Combine all selected objects into one for exporting", default=False)
- smoothing = bpy.props.EnumProperty(name="Smoothing", description="Smoothing method to use", default="MSPGL",
- items=(("NONE", "None", "No smoothing"),
- ("BLENDER", "Blender", "Use Blender's vertex normals"),
- ("MSPGL", "MspGL", "Compute vertex normals internally")))
- export_groups = bpy.props.BoolProperty(name="Vertex groups", description="Export vertex groups and weights", default=False)
def draw(self, context):
col = self.layout.column()
- col.prop(self, "export_lines")
col.prop(self, "compound")
- col.prop(self, "smoothing")
- col.prop(self, "export_groups")
self.general_col = col
self.layout.separator()
self.layout.separator()
- col = self.layout.column()
- col.label("Texturing")
- col.prop(self, "export_uv")
- col.prop(self, "tbn_vecs")
- col.prop(self, "tbn_uvtex")
- self.texturing_col = col
-
- self.layout.separator()
-
col = self.layout.column()
col.label("Vertex cache")
col.prop(self, "optimize_cache")
items=(("NONE", "None", "Ignore textures"),
("REF", "Referenced", "Reference external data"),
("INLINE", "Inline", "Embed textures in the object")))
- material_tex = bpy.props.BoolProperty(name="Material texture", description="Generate a texture based on material colors", default=False)
- srgb_colors = bpy.props.BoolProperty(name="sRGB colors", description="Export material colors as sRGB instead of linear", default=True)
separate_mesh = bpy.props.BoolProperty(name="Separate mesh", description="Write mesh data into a separate file", default=False)
shared_mesh = bpy.props.BoolProperty(name="Shared mesh", description="Use mesh name for mesh file to enable sharing", default=True)
col = self.general_col
col.prop(self, "external_tech")
col.prop(self, "export_lods")
-
- col = self.texturing_col
col.prop(self, "textures")
- col.prop(self, "material_tex")
- col.prop(self, "srgb_colors")
self.layout.separator();
self.max_strip_len = 1024
self.optimize_cache = True
self.cache_size = 64
- self.export_lines = False
- self.export_uv = "UNIT0"
- self.tbn_vecs = False
- self.tbn_uvtex = ""
self.compound = False
self.material_tex = False
- self.smoothing = "MSPGL"
- self.export_groups = False
- self.max_groups = 2
def stripify(self, mesh, progress=None):
for f in mesh.faces:
for o, m in objs:
if o.data.winding_test:
winding_test = True
+ if o.material_tex:
+ self.material_tex = True
bmesh = o.to_mesh(context.scene, True, "PREVIEW")
bmeshes.append(bmesh)
me = Mesh(bmesh)
if progress:
progress.set_task("Smoothing", 0.05, 0.35)
- if self.smoothing=="NONE":
+ if mesh.smoothing=="NONE":
mesh.flatten_faces()
mesh.split_smooth(progress)
- if self.smoothing!="BLENDER":
+ if mesh.smoothing!="BLENDER":
mesh.compute_normals()
- if self.export_groups:
- mesh.sort_vertex_groups(self.max_groups)
+ if mesh.vertex_groups:
+ mesh.sort_vertex_groups(mesh.max_groups_per_vertex)
# Create a mapping from vertex group indices to bone indices
first_obj = objs[0][0]
texunits = []
force_unit0 = False
- if mesh.uv_layers and (self.export_uv!="NONE" or self.material_tex):
+ if mesh.uv_layers and (mesh.use_uv!="NONE" or self.material_tex):
# Figure out which UV layers to export
- if self.export_uv=="ALL":
+ if mesh.use_uv=="ALL":
texunits = range(len(mesh.uv_layers))
elif self.material_tex:
# The material UV layer is always the last one
texunits = [(i, mesh.uv_layers[i]) for i in texunits]
texunits = [u for u in texunits if not u[1].hidden]
- if self.tbn_vecs:
+ if mesh.tbn_vecs:
# TBN coordinates must be generated before vertices are split by any other layer
uv_names = [u.name for i, u in texunits]
- if self.tbn_uvtex in uv_names:
- tbn_index = uv_names.index(self.tbn_uvtex)
+ if mesh.tbn_uvtex in uv_names:
+ tbn_index = uv_names.index(mesh.tbn_uvtex)
unit = texunits[tbn_index]
del texunits[tbn_index]
texunits.insert(0, unit)
if progress:
progress.set_task("Splitting UVs", 0.35+0.3*i/len(texunits), 0.35+0.3*(i+1)/len(texunits))
mesh.split_uv(i, progress)
- if self.tbn_vecs and u.name==self.tbn_uvtex:
+ if mesh.tbn_vecs and u.name==mesh.tbn_uvtex:
mesh.compute_uv()
mesh.compute_tbn(i)
fmt.append("TEXCOORD"+size)
else:
fmt.append("TEXCOORD%s_%d"%(size, u.unit))
- if self.tbn_vecs:
+ if mesh.tbn_vecs:
fmt += ["TANGENT3", "BINORMAL3"]
- if self.export_groups:
- fmt.append("ATTRIB%d_5"%(self.max_groups*2))
+ if mesh.vertex_groups:
+ fmt.append("ATTRIB%d_5"%(mesh.max_groups_per_vertex*2))
fmt.append("VERTEX3")
out_file.begin("vertices", *fmt)
normal = None
else:
out_file.write("multitexcoord"+size, u.unit, *v.uvs[i])
uvs[i] = v.uvs[i]
- if self.tbn_vecs:
+ if mesh.tbn_vecs:
if v.tan!=tan:
out_file.write("tangent3", *v.tan)
tan = v.tan
if v.bino!=bino:
out_file.write("binormal3", *v.bino)
bino = v.bino
- if self.export_groups:
- group_attr = [(group_index_map[g.group], g.weight*v.group_weight_scale) for g in v.groups[:self.max_groups]]
- while len(group_attr)<self.max_groups:
+ if mesh.vertex_groups:
+ group_attr = [(group_index_map[g.group], g.weight*v.group_weight_scale) for g in v.groups[:mesh.max_groups_per_vertex]]
+ while len(group_attr)<mesh.max_groups_per_vertex:
group_attr.append((0, 0.0))
group_attr = list(itertools.chain(*group_attr))
if group_attr!=group:
out_file.write("indices", f.vertices[0].index, f.vertices[i-1].index, f.vertices[i].index)
out_file.end()
- if self.export_lines and mesh.lines:
+ if mesh.use_lines and mesh.lines:
out_file.begin("batch", "LINES")
for l in mesh.lines:
out_file.write("indices", l.vertices[0].index, l.vertices[1].index)
else:
return 1.055*(l**(1/2.4))-0.055
+def get_colormap(srgb):
+ if srgb:
+ return linear_to_srgb
+ else:
+ return lambda x: x
+
def image_name(i):
fp = i.filepath
if fp:
class ObjectExporter:
def __init__(self):
- self.material_tex = False
- self.srgb_colors = True
self.textures = "REF"
self.separate_mesh = False
self.shared_mesh = True
return mesh
def export_object_technique(self, obj, mesh, out_file, lod_index):
- if self.srgb_colors:
- self.colormap = linear_to_srgb
- else:
- self.colormap = lambda x: x
-
material = None
if obj.material_slots:
material = obj.material_slots[0].material
out_file.write("technique", '"{}"'.format(name))
else:
out_file.begin("technique")
- self.export_technique_definition(material, mesh, out_file)
+ self.export_technique_definition(material, obj.material_tex, mesh, out_file)
out_file.end()
- def export_technique_definition(self, material, mesh, out_file):
+ def export_technique_definition(self, material, material_tex, mesh, out_file):
out_file.begin("pass", '""')
if material:
- cm = self.colormap
-
- if self.material_tex:
+ if material_tex:
out_file.begin("material")
out_file.write("diffuse", 1.0, 1.0, 1.0, 1.0)
out_file.end()
out_file.write("storage", "RGB", len(mesh.materials), 1)
texdata = '"'
for m in mesh.materials:
- color = [int(cm(c)*255) for c in m.diffuse_color*mat.diffuse_intensity]
+ cm = get_colormap(m.srgb_colors)
+ color = [int(cm(c)*255) for c in m.diffuse_color*m.diffuse_intensity]
texdata += "\\x%02X\\x%02X\\x%02X"%tuple(color)
texdata += '"'
out_file.write("raw_data", texdata)
out_file.end()
def export_material(self, mat, out_file):
- cm = self.colormap
+ cm = get_colormap(mat.srgb_colors)
if any((s and s.use_map_color_diffuse) for s in mat.texture_slots):
out_file.write("diffuse", 1.0, 1.0, 1.0, 1.0)
amb = cm(mat.ambient)
mesh = context.active_object.data
self.layout.prop(mesh, "winding_test")
+ self.layout.prop(mesh, "smoothing")
+
+ self.layout.separator()
+
+ col = self.layout.column()
+ col.label("Data selection")
+ col.prop(mesh, "use_lines")
+ col.prop(mesh, "vertex_groups")
+ col.prop(mesh, "max_groups_per_vertex")
+
+ self.layout.separator()
+
+ col = self.layout.column()
+ col.label("Texturing")
+ col.prop(mesh, "use_uv")
+ col.prop(mesh, "tbn_vecs")
+ col.prop(mesh, "tbn_uvtex")
class MspGLObjectProperties(bpy.types.Panel):
bl_idname = "OBJECT_PT_mspgl_properties"
self.layout.prop(obj, "inherit_tech");
if obj.inherit_tech:
self.layout.prop(obj, "override_material");
+ self.layout.prop(obj, "material_tex")
self.layout.prop(obj, "compound");
self.layout.prop(obj, "lod_for_parent")
if obj.lod_for_parent:
if not mat:
return
+ self.layout.prop(mat, "srgb_colors")
self.layout.prop(mat, "array_atlas");
if mat.array_atlas:
self.layout.prop(mat, "array_layer");
def register_properties():
bpy.types.Mesh.winding_test = bpy.props.BoolProperty(name="Winding test", description="Perform winding test to skip back faces")
+ bpy.types.Mesh.smoothing = bpy.props.EnumProperty(name="Smoothing", description="Smoothing method to use", default="MSPGL",
+ items=(("NONE", "None", "No smoothing"),
+ ("BLENDER", "Blender", "Use Blender's vertex normals"),
+ ("MSPGL", "MspGL", "Compute vertex normals internally")))
+ bpy.types.Mesh.use_lines = bpy.props.BoolProperty(name="Include lines", description="Include edges without faces as lines", default=False)
+ bpy.types.Mesh.vertex_groups = bpy.props.BoolProperty(name="Vertex groups", description="Include vertex groups and weights", default=False)
+ bpy.types.Mesh.max_groups_per_vertex = bpy.props.IntProperty(name="Max groups", description="Maximum amount of groups per vertex", min=1, max=4, default=2)
+ bpy.types.Mesh.use_uv = bpy.props.EnumProperty(name="Use UV", description="Use UV coordinates", default="UNIT0",
+ items=(("NONE", "None", "Ignore all UV coordinates"),
+ ("UNIT0", "Unit 0", "Use UV coordinates for unit 0"),
+ ("ALL", "All", "Use all UV coordinates")))
+ bpy.types.Mesh.tbn_vecs = bpy.props.BoolProperty(name="TBN vectors", description="Compute tangent and binormal vectors for vertices", default=False)
+ bpy.types.Mesh.tbn_uvtex = bpy.props.StringProperty(name="TBN UV layer", description="UV layer to use as basis for TBN vectors", default="")
+
bpy.types.Object.technique = bpy.props.StringProperty(name="Technique", description="Name of the technique to use for rendering")
bpy.types.Object.inherit_tech = bpy.props.BoolProperty(name="Inherit technique", description="Inherit from the technique to customize textures")
bpy.types.Object.override_material = bpy.props.BoolProperty(name="Override material", description="Override material in the inherited technique as well", default=True)
+ bpy.types.Object.material_tex = bpy.props.BoolProperty(name="Material texture", description="Generate a texture based on material colors", default=False)
bpy.types.Object.compound = bpy.props.BoolProperty(name="Compound with parent", description="Join this object to its parent when exporting")
bpy.types.Object.lod_for_parent = bpy.props.BoolProperty(name="LoD for parent", description="This object is a level of detail for its parent")
- bpy.types.Object.lod_index = bpy.props.IntProperty(name="LoD index", description="Index of the level of detail", min=1, default=1)
+ bpy.types.Object.lod_index = bpy.props.IntProperty(name="LoD index", description="Index of the level of detail", min=1, max=16, default=1)
+
+ bpy.types.Material.srgb_colors = bpy.props.BoolProperty(name="sRGB colors", description="Export material colors as sRGB instead of linear", default=True)
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")