use std::f64::consts::PI;use ranim::{ anims::{camera::CameraFrameAnim, morph::MorphAnim}, color::palettes::manim, glam::DVec3, items::mesh::{MeshItem, Sphere, Surface}, prelude::*, utils::rate_functions::{linear, smooth},};/// Comprehensive mesh morphing demo: sphere -> torus -> disc -> sphere#[scene]#[wasm_demo_doc]#[output(dir = "./output/mesh_morph")]fn mesh_morph(r: &mut RanimScene) { // Setup camera let phi = 70.0 * PI / 180.0; let theta = 30.0 * PI / 180.0; let distance = 8.0; let mut cam = CameraFrame::from_spherical(phi, theta, distance); cam.fovy = 50.0 * PI / 180.0; // Create meshes with better colors from manim palette let sphere_surface = Sphere::new(2.0) .with_fill_color(manim::BLUE_D) // Deep blue .with_resolution((50, 30)); let mut sphere = surface_to_mesh(Surface::from(sphere_surface)); let torus_surface = create_torus_shape(2.0, 0.8, (50, 30)); let mut torus = surface_to_mesh(torus_surface); torus.set_fill_color(manim::TEAL_D); // Teal for torus let disc_surface = create_disc_shape(2.5, (50, 30)); let mut disc = surface_to_mesh(disc_surface); disc.set_fill_color(manim::PURPLE_D); // Purple for disc let sphere_red_surface = Sphere::new(2.0) .with_fill_color(manim::MAROON_D) // Deep red .with_resolution((50, 30)); let sphere_red = surface_to_mesh(Surface::from(sphere_red_surface)); let mut mesh_sequence = seq![ sphere .morph_to(torus.clone()) .with_duration(2.5) .with_rate_func(smooth) ]; mesh_sequence.hold(0.5).push( torus .morph_to(disc.clone()) .with_duration(2.5) .with_rate_func(smooth), ); mesh_sequence.hold(0.5).push( disc.morph_to(sphere_red) .with_duration(2.5) .with_rate_func(smooth), ); let total_secs = 9.0; let camera = cam .orbit(DVec3::ZERO, 2.0) .with_duration(total_secs) .with_rate_func(linear); mesh_sequence.hold_to(total_secs); r.play(camera); r.play(mesh_sequence); // Add preview captures at key moments r.insert_time_mark(2.5, TimeMark::Capture("preview_torus.png".to_string())); r.insert_time_mark(5.5, TimeMark::Capture("preview_disc.png".to_string()));}/// Convert Surface to MeshItemfn surface_to_mesh(surface: Surface) -> MeshItem { let points: Vec<DVec3> = surface.vertices.clone(); // Build MeshItem manually let mut mesh = MeshItem::from_indexed_vertices(points, surface.triangle_indices.clone()); // Set colors by iterating through surface colors and using set_fill_color // Since we can't directly access vertex_colors from outside, we'll just use the first color if let Some(first_color) = surface.vertex_colors.first() { mesh.set_fill_color(*first_color); } mesh}/// Create a torus-like shapefn create_torus_shape(major_radius: f64, minor_radius: f64, resolution: (u32, u32)) -> Surface { Surface::from_uv_func( |u, v| { let theta = u * 2.0 * PI; let phi = v * 2.0 * PI; let x = (major_radius + minor_radius * phi.cos()) * theta.cos(); let y = (major_radius + minor_radius * phi.cos()) * theta.sin(); let z = minor_radius * phi.sin(); DVec3::new(x, y, z) }, (0.0, 1.0), (0.0, 1.0), resolution, )}/// Create a flattened disc-like shapefn create_disc_shape(radius: f64, resolution: (u32, u32)) -> Surface { Surface::from_uv_func( |u, v| { let theta = u * 2.0 * PI; let r = v * radius; let x = r * theta.cos(); let y = r * theta.sin(); let z = 0.3 * (1.0 - v) * (u * 4.0 * PI).sin(); // Small wave pattern DVec3::new(x, y, z) }, (0.0, 1.0), (0.0, 1.0), resolution, )}