use std::fs;
use std::process;
use rust_usd::{Mesh, Stage};
const ASSET: &str = "examples/variants.usda";
const EDIT_LAYER: &str = "examples/paint_edits_paint.usda";
const PRIM_PATH: &str = "/Cube";
fn main() {
let _ = fs::remove_file(EDIT_LAYER);
let asset_bytes_before = fs::read(ASSET).expect("variants.usda missing");
let stage = Stage::open_for_painting(ASSET, EDIT_LAYER).unwrap_or_else(|e| {
eprintln!("open_for_painting failed: {}", e.what());
process::exit(1);
});
println!("edit target → {}", stage.edit_layer_path());
let prim = stage.prim_at_path(PRIM_PATH).unwrap_or_else(|| {
eprintln!("prim {} not found", PRIM_PATH);
process::exit(1);
});
let mesh = prim.as_mesh().unwrap_or_else(|| {
eprintln!("{} is not a mesh", PRIM_PATH);
process::exit(1);
});
let point_count = mesh.points().len() / 3;
println!("painting on {} ({} verts)", mesh.prim_path(), point_count);
let wear: Vec<f32> = (0..point_count)
.map(|i| i as f32 / (point_count.max(1) as f32 - 1.0).max(1.0))
.collect();
assert!(mesh.create_primvar_float("wear", &wear, "vertex"));
println!("authored primvars:wear = {:?}", wear);
let dust: Vec<f32> = (0..point_count)
.flat_map(|i| {
let t = i as f32 / (point_count.max(1) as f32 - 1.0).max(1.0);
[0.5 + 0.5 * t, 0.4, 0.3 - 0.3 * t]
})
.collect();
assert!(mesh.create_primvar_color3f("dustColor", &dust, "vertex"));
println!(
"authored primvars:dustColor ({} components / {} colors)",
dust.len(),
dust.len() / 3
);
stage.save_edit_layer();
println!("saved {}", EDIT_LAYER);
let reopened = Stage::open(EDIT_LAYER).expect("reopen failed");
let reprim = reopened.prim_at_path(PRIM_PATH).expect("prim missing on reopen");
let remesh = reprim.as_mesh().expect("not a mesh on reopen");
println!("\nprimvars on {} after reopen:", PRIM_PATH);
for name in remesh.primvar_names() {
if let Some(pv) = remesh.primvar(&name) {
print_primvar(&name, &pv, &remesh);
}
}
println!(
"\nnormals interpolation on /World/Cube of test.usda: {}",
Stage::open("examples/test.usda")
.expect("test.usda")
.prim_at_path("/World/Cube")
.and_then(|p| p.as_mesh())
.map(|m| m.normals_interpolation())
.unwrap_or_else(|| "<none>".into())
);
let asset_bytes_after = fs::read(ASSET).expect("variants.usda gone");
if asset_bytes_before == asset_bytes_after {
println!("\nverified {} is byte-identical to its original", ASSET);
} else {
eprintln!("ASSET WAS MUTATED — this should never happen");
process::exit(2);
}
}
fn print_primvar(name: &str, pv: &rust_usd::Primvar, _mesh: &Mesh) {
let type_name = pv.type_name();
let interp = pv.interpolation();
let header = format!(" {:<14} type={:<12} interp={}", name, type_name, interp);
match type_name.as_str() {
"float[]" => {
let v = pv.as_float_array();
println!("{} values={:?}", header, v);
}
"color3f[]" | "float3[]" | "vector3f[]" => {
let v = pv.as_vec3f_array();
let chunks: Vec<String> = v
.chunks_exact(3)
.map(|c| format!("({:.3},{:.3},{:.3})", c[0], c[1], c[2]))
.collect();
println!("{} values=[{}]", header, chunks.join(", "));
}
"float2[]" | "texCoord2f[]" => {
let v = pv.as_vec2f_array();
let chunks: Vec<String> = v
.chunks_exact(2)
.map(|c| format!("({:.3},{:.3})", c[0], c[1]))
.collect();
println!("{} values=[{}]", header, chunks.join(", "));
}
"int[]" => {
let v = pv.as_int_array();
println!("{} values={:?}", header, v);
}
_ => {
println!("{} (unhandled type)", header);
}
}
}