mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-14 06:22:24 +00:00
craft-mesh: ignore empty OBJ material assignments
* Ignore empty OBJ material assignments * Preserve empty material resets in OBJ writes Co-authored-by: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> --------- Co-authored-by: NetterSilver <133535268+Silvertree2010@users.noreply.github.com>
This commit is contained in:
1 parent
f759a35db8
commit
e3c6ec4a23
2 files changed
+43
-2
No files matched your search
+19
-2
@@ -236,6 +236,13 @@ impl Reader<'_> {
|
||||
|
||||
fn use_material(&mut self, name: &str) -> Result<()> {
|
||||
self.slot = None;
|
||||
if name.trim().is_empty() {
|
||||
// A bare `usemtl` selects no named material. In particular, do not create a
|
||||
// material with an empty name: callers can map the missing material to their own
|
||||
// default, and writers need not emit a meaningless empty material name.
|
||||
self.material = None;
|
||||
return Ok(());
|
||||
}
|
||||
self.material = match self.material_ids.get(name) {
|
||||
Some(i) => Some(*i),
|
||||
None if self.scene.materials.len() >= self.limits.max_materials => {
|
||||
@@ -518,6 +525,7 @@ pub fn write(scene: &Scene, mtllib: Option<&str>, limits: &Limits) -> Result<Str
|
||||
// OBJ indices run on across objects.
|
||||
let (mut vbase, mut tbase, mut nbase) = (1u64, 1u64, 1u64);
|
||||
let mut smoothing = 0;
|
||||
let mut current_material: Option<Option<usize>> = None;
|
||||
for (index, world) in scene.instances(limits)? {
|
||||
let Some(mesh) = scene.meshes.get(index) else { continue };
|
||||
mesh.validate()?;
|
||||
@@ -546,8 +554,17 @@ pub fn write(scene: &Scene, mtllib: Option<&str>, limits: &Limits) -> Result<Str
|
||||
if !part.name.trim().is_empty() {
|
||||
let _ = writeln!(text, "g {}", part.name.trim().replace(|c: char| c.is_control(), " "));
|
||||
}
|
||||
if let Some(m) = part.material.and_then(|m| materials.get(m)) {
|
||||
let _ = writeln!(text, "usemtl {m}");
|
||||
if current_material != Some(part.material) {
|
||||
match part.material.and_then(|m| materials.get(m)) {
|
||||
Some(m) => {
|
||||
let _ = writeln!(text, "usemtl {m}");
|
||||
}
|
||||
None if current_material.is_some() => {
|
||||
let _ = writeln!(text, "usemtl");
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
current_material = Some(part.material);
|
||||
}
|
||||
if part.smoothing != smoothing {
|
||||
smoothing = part.smoothing;
|
||||
|
||||
@@ -125,6 +125,30 @@ fn objects_groups_quads_and_negative_indices() {
|
||||
assert_eq!((s.meshes.len(), s.meshes[0].name.as_str(), s.meshes[0].parts.len()), (1, "", 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bare_usemtl_does_not_create_an_empty_named_material() {
|
||||
for line in ["usemtl", "usemtl "] {
|
||||
let src = format!("v 0 0 0\nv 1 0 0\nv 0 1 0\n{line}\nf 1 2 3\n");
|
||||
let scene = read(src.as_bytes(), &Limits::default(), &mut |_| None).unwrap();
|
||||
assert!(scene.materials.is_empty(), "{line:?}: {:?}", scene.materials);
|
||||
assert_eq!(scene.meshes.iter().map(Mesh::triangle_count).sum::<usize>(), 1);
|
||||
assert_eq!(scene.meshes[0].parts[0].material, None);
|
||||
scene.validate().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn writing_a_bare_usemtl_preserves_a_material_reset() {
|
||||
let src = b"v 0 0 0\nv 1 0 0\nv 0 1 0\nv 1 1 0\nusemtl Named\nf 1 2 3\nusemtl\nf 2 4 3\n";
|
||||
let scene = read(src, &Limits::default(), &mut no_external).unwrap();
|
||||
assert_eq!(scene.meshes[0].parts.iter().map(|p| p.material).collect::<Vec<_>>(), [Some(0), None]);
|
||||
|
||||
let text = write(&scene, None, &Limits::default()).unwrap();
|
||||
assert!(text.contains("usemtl Named\n") && text.contains("usemtl\nf 2 4 3\n"), "{text}");
|
||||
let roundtrip = read(text.as_bytes(), &Limits::default(), &mut no_external).unwrap();
|
||||
assert_eq!(roundtrip.meshes[0].parts.iter().map(|p| p.material).collect::<Vec<_>>(), [Some(0), None]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn corner_normals_and_smoothing_groups() {
|
||||
let vertices = "v 0 0 0\nv 1 0 0\nv 0 1 0\nv 0 -0.8660254037844386 0.5\n";
|
||||
|
||||
Reference in new issue
Block a user