use opensubdiv_petite::far::{
AdaptiveRefinementOptions, EndCapType, PatchTable, PatchTableOptions, PrimvarRefiner,
TopologyDescriptor, TopologyRefiner, TopologyRefinerOptions,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let vertex_positions = vec![
[-0.5, -0.5, -0.5], [0.5, -0.5, -0.5], [-0.5, 0.5, -0.5], [0.5, 0.5, -0.5], [-0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [-0.5, -0.5, 0.5], [0.5, -0.5, 0.5], ];
let face_vertex_counts = vec![4, 4, 4, 4, 4, 4];
let face_vertex_indices = vec![
0, 1, 3, 2, 2, 3, 5, 4, 4, 5, 7, 6, 6, 7, 1, 0, 0, 2, 4, 6, 1, 7, 5, 3, ];
let descriptor = TopologyDescriptor::new(
vertex_positions.len(),
&face_vertex_counts,
&face_vertex_indices,
)?;
let refiner_options = TopologyRefinerOptions::default();
let mut refiner = TopologyRefiner::new(descriptor, refiner_options)?;
let mut adaptive_options = AdaptiveRefinementOptions::default();
adaptive_options.isolation_level = 3;
refiner.refine_adaptive(adaptive_options, &[]);
println!("Refinement complete. Max level: {}", refiner.max_level());
let patch_options = PatchTableOptions::new().end_cap_type(EndCapType::BSplineBasis);
let patch_table = PatchTable::new(&refiner, Some(patch_options))?;
println!(
"Patch table created with {} patches",
patch_table.patch_count()
);
let primvar_refiner = PrimvarRefiner::new(&refiner)?;
let mut all_vertices = Vec::with_capacity(refiner.vertex_count_all_levels());
all_vertices.extend_from_slice(&vertex_positions);
println!("Added {} base vertices", vertex_positions.len());
for level in 1..refiner.refinement_levels() {
let prev_level = refiner.level(level - 1).unwrap();
let prev_count = prev_level.vertex_count();
let src_start = all_vertices.len() - prev_count;
let src_data: Vec<f32> = all_vertices[src_start..]
.iter()
.flat_map(|v| v.iter().copied())
.collect();
println!(
"Level {}: interpolating from {} vertices",
level, prev_count
);
if let Some(refined) = primvar_refiner.interpolate(level, 3, &src_data) {
let level_vertices: Vec<[f32; 3]> = refined
.chunks_exact(3)
.map(|chunk| [chunk[0], chunk[1], chunk[2]])
.collect();
println!(" Generated {} vertices", level_vertices.len());
all_vertices.extend_from_slice(&level_vertices);
}
}
println!("Total vertices after refinement: {}", all_vertices.len());
let num_local_points = patch_table.local_point_count();
println!("Patch table has {} local points", num_local_points);
if num_local_points > 0 {
if let Some(stencil_table) = patch_table.local_point_stencil_table() {
println!("Stencil table info:");
println!(" Number of stencils: {}", stencil_table.len());
let control_vertex_count = stencil_table.control_vertex_count();
println!(" Control vertex count: {}", control_vertex_count);
println!(" Current vertex buffer size: {}", all_vertices.len());
if control_vertex_count == 0 {
println!("INFO: Stencil table appears to be for local points only");
println!(
" It expects refined vertices as input (count: {})",
all_vertices.len()
);
println!(
"\nApplying stencils to compute {} local points...",
num_local_points
);
for dim in 0..3 {
let dim_name = ["X", "Y", "Z"][dim];
let src_dim: Vec<f32> = all_vertices.iter().map(|v| v[dim]).collect();
println!(
" Processing dimension {} with {} source values",
dim_name,
src_dim.len()
);
let dst_dim = stencil_table.update_values(&src_dim, None, None);
println!(" Generated {} local point values", dst_dim.len());
if dst_dim.len() != num_local_points {
println!(
" WARNING: Expected {} local points but got {}",
num_local_points,
dst_dim.len()
);
}
}
println!("\nSuccessfully computed local points!");
} else if control_vertex_count != all_vertices.len() {
println!(
"ERROR: Stencil table expects {} control vertices but we have {}",
control_vertex_count,
all_vertices.len()
);
println!("This mismatch indicates a problem with vertex buffer construction!");
return Err("Vertex count mismatch".into());
} else {
println!("\nApplying stencils for dimension 0...");
let src_dim: Vec<f32> = all_vertices.iter().map(|v| v[0]).collect();
println!(" Source array size: {}", src_dim.len());
let dst_dim = stencil_table.update_values(&src_dim, None, None);
println!(" Output array size: {}", dst_dim.len());
println!("Successfully applied stencils!");
}
} else {
println!("No local point stencil table available");
}
} else {
println!("No local points in patch table");
}
Ok(())
}