in native/src/work_asset/export.rs [71:159]
fn export_variant_mapping(&self, root: &mut Root, variant_ix_lookup: &HashMap<usize, Tag>) -> Result<Metadata> {
let mut image_sizer = ImageSizes::new(&self);
// for each mesh...
for (m_ix, mesh) in root.meshes.iter_mut().enumerate() {
// and for each of that mesh's primitives...
for (p_ix, primitive) in mesh.primitives.iter_mut().enumerate() {
// retrieve the mapping of tag->material_key
let variant_mapping = self.variant_mapping(m_ix, p_ix);
// prepare to build the mapping of tag->material_ix
let mut tag_to_ix = HashMap::new();
// loop over the (tag, key) entries in that mapping...
for (tag, material_key) in variant_mapping.iter() {
// map the material key to a glTF material index...
if let Some(material_ix) = self.material_ix(material_key) {
if *tag == self.default_tag {
// there may be a mapping for the default tag, but if so the primitive
// must have a default material too, and they must match, and we do
// not keep or count it – it's treated elsewhere further down
if let Some(default_material_ix) = primitive.material {
if default_material_ix.value() == material_ix {
continue;
}
return Err(format!(
"Huh? Default material {} != variant map entry {} of default tag {}.",
default_material_ix,
material_ix, self.default_tag
));
}
return Err(format!(
"Huh? No default material, but variant map entry {} of default tag {} ",
material_ix, self.default_tag
));
}
// place it into the tag->material_ix mapping
tag_to_ix.insert(tag.to_owned(), material_ix);
// and update metadata
image_sizer.accumulate_material(material_ix, true);
image_sizer.accumulate_tagged_material(material_ix, tag);
} else {
return Err(format!("Huh? Non-existent meld key: {}", material_key));
}
}
// now handle the primitive's default material, if any
if let Some(default_material_ix) = primitive.material {
let default_material_ix = default_material_ix.value();
let is_variational = !tag_to_ix.is_empty();
image_sizer.accumulate_material(default_material_ix, is_variational);
image_sizer.accumulate_tagged_material(default_material_ix, &self.default_tag);
if is_variational {
// only map the default tag if there's other tags already in the mapping
tag_to_ix.insert(self.default_tag.clone(), default_material_ix);
}
};
extension::write_variant_map(primitive, &tag_to_ix, &variant_ix_lookup)?;
}
}
// ask metadata sizer to count up all the totals
let (total_image_size, variational_image_size, per_tag_image_size) = image_sizer.count()?;
// use it to create an authoritative set of all variational tags
let tags: HashSet<Tag> = per_tag_image_size.keys().cloned().collect();
// use it also to create the Tag->AssetSize mapping
let per_tag_sizes: HashMap<Tag, AssetSizes> = tags
.iter()
.map(|tag| (tag.to_owned(), AssetSizes::new(per_tag_image_size[tag])))
.collect();
// finally construct & return the Metadata structure
Ok(Metadata {
tags,
total_sizes: AssetSizes {
texture_bytes: total_image_size,
},
variational_sizes: AssetSizes {
texture_bytes: variational_image_size,
},
per_tag_sizes,
})
}