### Build and serve the ad-hoc viewer Source: https://github.com/ricosjp/truck/blob/master/truck-js/examples/Readme.md Builds the WebAssembly project for the web target using wasm-pack, copies necessary example files into the 'pkg' directory, and then starts a local HTTP server to run the application. ```bash wasm-pack build --target web cp examples/bootstrap.js examples/index.html examples/script.js pkg cd pkg basic-http-server -a 127.0.0.1:8080 ``` -------------------------------- ### Setup Interactive 3D Scene (Rust) Source: https://context7.com/ricosjp/truck/llms.txt Initializes a GPU-accelerated 3D rendering context, including setting up a camera with perspective projection and defining light sources. Requires `truck_platform` and `truck_rendimpl`. ```rust use truck_platform::*; use truck_rendimpl::*; fn main() { // Initialize device handler (GPU context) let device_handler = pollster::block_on(async { DeviceHandler::default_device().await }); // Setup camera let camera = Camera { matrix: Matrix4::look_at_rh( Point3::new(10.0, 10.0, 10.0), // eye position Point3::origin(), // look at target Vector3::unit_y(), // up direction ).invert().unwrap(), projection: ProjectionMethod::Perspective { fovy: Rad(std::f64::consts::PI / 4.0), aspect: 16.0 / 9.0, }, near_clip: 0.1, far_clip: 100.0, }; // Create lights let lights = vec![ Light { position: Point3::new(10.0, 15.0, 10.0), color: Vector3::new(1.0, 1.0, 1.0), light_type: LightType::Point, }, ]; // Create scene let mut scene = Scene::new(device_handler, &camera, &lights); println!("3D scene initialized"); // Add renderable objects to scene... } ``` -------------------------------- ### Install build tools with Cargo Source: https://github.com/ricosjp/truck/blob/master/truck-js/examples/Readme.md Installs wasm-pack for WebAssembly compilation and basic-http-server for local web serving using the Rust package manager, Cargo. ```bash cargo install wasm-pack basic-http-server ``` -------------------------------- ### WebAssembly Shape Building with Truck.js Source: https://context7.com/ricosjp/truck/llms.txt Demonstrates using Truck.js WebAssembly bindings in JavaScript to programmatically build a 3D shape (a cube in this example) by sweeping operations. The generated mesh can then be tessellated and used for WebGL rendering. Requires `truck_js.js`. ```javascript // JavaScript code using truck-js WASM bindings import init, { Vertex, builder_vertex, builder_tsweep, and, or } from './truck_js.js'; async function main() { // Initialize WASM module await init(); // Create a cube using WASM bindings const v = builder_vertex(-0.5, -0.5, -0.5); const e = builder_tsweep(v, 1.0, 0.0, 0.0); // sweep along x const f = builder_tsweep(e, 0.0, 1.0, 0.0); // sweep along y const cube = builder_tsweep(f, 0.0, 0.0, 1.0); // sweep along z // Tessellate for rendering const mesh = cube.triangulation(0.01); // Get mesh data for WebGL rendering const positions = mesh.positions(); const indices = mesh.indices(); const normals = mesh.normals(); console.log(`Generated cube mesh: ${positions.length/3} vertices`); // Render with WebGL... } main(); ``` -------------------------------- ### Export Shape to STEP Format in Rust Source: https://context7.com/ricosjp/truck/llms.txt Writes Truck solid geometry to the STEP file format, enabling interoperability with other CAD systems. This example combines a sphere and a cube using a boolean OR operation and then exports the resulting shape using `truck_stepio::out`. ```rust use truck_modeling::* use truck_stepio::out; fn main() { // Create a complex shape let sphere = builder::sphere(Point3::origin(), 2.0, 32, 16); let cube = builder::cuboid( Point3::new(-1.5, -1.5, -1.5), Point3::new(1.5, 1.5, 1.5) ); // Combine with boolean operation use truck_shapeops::* let shape = or(&sphere, &cube).unwrap(); // Export to STEP file let step_string = out::CompleteStepDisplay::new( out::StepModel::from(&shape), out::StepHeaderDescriptor { originating_system: "Truck CAD Kernel".to_string(), ..Default::default() }, ).to_string(); std::fs::write("shape.step", step_string) .expect("Failed to write STEP file"); println!("Shape exported to STEP format"); } ``` -------------------------------- ### WGSL Shader Implementation for Rendering Source: https://github.com/ricosjp/truck/blob/master/truck-platform/README.md Demonstrates how to create a render object by implementing the 'Rendered' trait in Rust and defining a WGSL shader. The shader should implement the 'main_image' function, which takes fragment coordinates and environment information to draw an image. The 'Environment' struct provides resolution, mouse, and time data. ```wgsl vec4 main_image(coord: vec2, env: Environment); struct Environment { resolution: vec2; // the resolution of the image mouse: vec4; // the mouse information behaving the same as `iMouse` in Shadertoy. time: f32; // the number of seconds since the application started. }; ``` -------------------------------- ### Build Cube by Sweeping in Rust Source: https://context7.com/ricosjp/truck/llms.txt Demonstrates constructing a unit cube solid by sequentially sweeping a vertex into an edge, an edge into a face, and a face into a solid using truck_modeling::builder::tsweep. The resulting cube is serialized to JSON. ```rust use truck_modeling::*; fn main() { // Start with a vertex at (-0.5, -0.5, -0.5) let v = builder::vertex(Point3::new(-0.5, -0.5, -0.5)); // Sweep vertex along x-axis to create an edge let e = builder::tsweep(&v, Vector3::unit_x()); // Sweep edge along y-axis to create a face let f = builder::tsweep(&e, Vector3::unit_y()); // Sweep face along z-axis to create a solid let cube: Solid = builder::tsweep(&f, Vector3::unit_z()); // Serialize to JSON for storage or visualization let json = serde_json::to_vec_pretty(&cube).unwrap(); std::fs::write("cube.json", json).unwrap(); println!("Cube created and saved to cube.json"); } ``` -------------------------------- ### Create Basic Vertex in Rust Source: https://context7.com/ricosjp/truck/llms.txt Demonstrates creating single and multiple 3D vertices using the truck_modeling::builder::vertex and truck_modeling::builder::vertices functions. It also shows how to access a vertex's point coordinates. ```rust use truck_modeling::*; fn main() { // Create a single vertex at coordinates (1.0, 2.0, 3.0) let vertex = builder::vertex(Point3::new(1.0, 2.0, 3.0)); // Create multiple vertices at once let vertices = builder::vertices([ (0.0, 0.0, 0.0), (1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0), ]); // Access vertex position let position = vertex.point(); println!("Vertex at: {:?}", position); } ``` -------------------------------- ### Fragment Shader: Microfacet BRDF for realistic surface rendering Source: https://github.com/ricosjp/truck/blob/master/truck-js/examples/index.html This GLSL fragment shader implements a microfacet Bidirectional Reflectance Distribution Function (BRDF) to simulate realistic surface lighting. It calculates diffuse, specular, and ambient components based on material properties (albedo, roughness, reflectance) and light information, outputting the final pixel color. ```glsl #version 300 es precision highp float; in vec3 vertex_position; in vec2 vertex_uv; in vec3 vertex_normal; uniform vec3 camera_position; uniform vec3 camera_direction; uniform vec3 camera_updirection; uniform vec2 resolution; out vec4 color; // Based on the microfacet theory // cf: https://qiita.com/mebiusbox2/items/e7063c5dfe1424e0d01a struct Light { vec4 position; vec4 color; ivec4 light_type; }; struct Material { vec4 albedo; float roughness; float reflectance; float ambient_ratio; }; // light direction from point to light vec3 light_direction(Light light, vec3 position) { switch(light.light_type[0]) { case 0: return normalize(light.position.xyz - position); default: return light.position.xyz; } } vec3 irradiance(Light light, vec3 position, vec3 normal) { vec3 light_dir = light_direction(light, position); return light.color.xyz * clamp(dot(light_dir, normal), 0.0, 1.0); } vec3 diffuse_brdf(Material material) { return material.albedo.xyz * (1.0 - material.reflectance); } float microfacet_distribution(vec3 middle, vec3 normal, float alpha) { float dotNH = dot(normal, middle); float alpha2 = alpha * alpha; float sqrt_denom = 1.0 - dotNH * dotNH * (1.0 - alpha2); return alpha2 / (sqrt_denom * sqrt_denom); } float schlick_approxy(vec3 vec, vec3 normal, float k) { float dotNV = dot(normal, vec); return dotNV / (dotNV * (1.0 - k) + k); } float geometric_decay(vec3 light_dir, vec3 camera_dir, vec3 normal, float alpha) { float k = alpha / 2.0; return schlick_approxy(light_dir, normal, k) * schlick_approxy(camera_dir, normal, k); } vec3 fresnel(vec3 f0, vec3 middle, vec3 camera_dir) { float c = 1.0 - dot(middle, camera_dir); c = c * c * c * c * c; return f0 + (1.0 - f0) * c; } vec3 specular_brdf(Material material, vec3 camera_dir, vec3 light_dir, vec3 normal) { vec3 specular_color = material.albedo.xyz * material.reflectance; vec3 middle = normalize(camera_dir + light_dir); float alpha = material.roughness * material.roughness; float distribution = microfacet_distribution(middle, normal, alpha); float decay = geometric_decay(light_dir, camera_dir, normal, alpha); vec3 fresnel_color = fresnel(specular_color, middle, camera_dir); float dotCN = clamp(dot(camera_dir, normal), 0.0, 1.0); float dotLN = clamp(dot(light_dir, normal), 0.0, 1.0); float denom = 4.0 * dotCN * dotLN; if (denom < 1.0e-6) { return vec3(0.0, 0.0, 0.0); } return distribution * decay / denom * fresnel_color; } vec3 microfacet_color(vec3 position, vec3 normal, Light light, vec3 camera_dir, Material material) { vec3 light_dir = light_direction(light, position); vec3 irradiance = irradiance(light, position, normal); vec3 diffuse = diffuse_brdf(material); vec3 specular = specular_brdf(material, camera_dir, light_dir, normal); return (diffuse + specular) * irradiance; } vec3 ambient_correction(vec3 pre_color, Material material) { return pre_color * (1.0 - material.ambient_ratio) + material.albedo.xyz * material.ambient_ratio; } void main() { vec3 position = vertex_position; vec2 uv = vertex_uv; vec3 normal = normalize(vertex_normal); uv.y = 1.0 - uv.y; /* discard by texture */ Material mat; mat.albedo = vec4(1); mat.roughness = 0.5; mat.reflectance = 0.5; mat.ambient_ratio = 0.04; Light light; light.position = vec4(camera_position, 1); light.color = vec4(1); light.light_type = ivec4(0); vec3 camera_dir = normalize(camera_position - position); vec3 col = microfacet_color(position, normal, light, camera_dir, mat); col = ambient_correction(col, mat); color = vec4(col, 1.0); } ``` -------------------------------- ### Create NURBS Surface (Rust) Source: https://context7.com/ricosjp/truck/llms.txt Constructs a NURBS surface from a grid of control points. The surface is then evaluated at a specific parameter (u, v) to find a point and its normal. Requires `truck_geometry` and `truck_geotrait`. ```rust use truck_geometry::prelude::*; use truck_geotrait::*; fn main() { // Create 3x3 control point grid let mut control_points = Vec::new(); for i in 0..3 { for j in 0..3 { control_points.push(Point3::new( i as f64, j as f64, ((i + j) % 2) as f64, // Alternating heights )); } } // Create knot vectors (degree 2 in both directions) let u_knot = KnotVec::clamped_uniform(2, 3); let v_knot = KnotVec::clamped_uniform(2, 3); // Create B-spline surface let surface = BSplineSurface::new( (u_knot, v_knot), control_points, ); // Evaluate surface at parameter (u, v) let point = surface.subs(0.5, 0.5); let normal = surface.normal(0.5, 0.5); println!("Surface point at (0.5, 0.5): {:?}", point); println!("Surface normal: {:?}", normal); } ``` -------------------------------- ### Render Polygon Mesh with Material (Rust) Source: https://context7.com/ricosjp/truck/llms.txt Creates a renderable object from a polygon mesh loaded from an OBJ file. It defines physically-based material properties such as albedo, roughness, and reflectance. Requires `truck_platform`, `truck_rendimpl`, and `truck_polymesh`. ```rust use truck_platform::*; use truck_rendimpl::*; use truck_polymesh::obj; fn main() { // Load mesh from OBJ file let mesh = obj::read("model.obj").expect("Failed to load OBJ"); // Initialize rendering context let device_handler = pollster::block_on(DeviceHandler::default_device()); let instance_creator = device_handler.instance_creator(); // Define material properties let material = Material { albedo: Vector4::new(0.8, 0.2, 0.2, 1.0), // Red color roughness: 0.3, // Somewhat smooth reflectance: 0.5, // Moderate reflectivity ambient_ratio: 0.02, // Low ambient light }; // Create polygon state with material let polygon_state = PolygonState { material, backface_culling: true, }; // Create renderable instance let instance = instance_creator.create_instance(&mesh, &polygon_state); println!("Renderable instance created with material"); // Add instance to scene for rendering... } ``` -------------------------------- ### Parse STEP File and Extract Geometry in Rust Source: https://context7.com/ricosjp/truck/llms.txt Reads a STEP CAD file, parses its content using `ruststep`, and extracts geometric and topological data into Truck's internal structures. It iterates through shells, converts them to a compressed format, serializes them to JSON, and generates OBJ meshes for visualization using `truck_stepio` and `truck_meshalgo`. ```rust use truck_stepio::r#in::* use truck_topology::compress::* use truck_meshalgo::prelude::* fn main() { // Read STEP file let step_content = std::fs::read_to_string("input.step") .expect("Failed to read STEP file"); // Parse STEP data let exchange = ruststep::parser::parse(&step_content) .expect("Failed to parse STEP"); // Build table from data section let table = Table::from_data_section(&exchange.data[0]); // Extract all shells for (idx, shell) in table.shell.iter() { // Convert to compressed shell with geometry let compressed_shell = table.to_compressed_shell(shell) .expect(&format!("Failed to convert shell #{}", idx)); // Serialize to JSON let json = serde_json::to_string_pretty(&compressed_shell).unwrap(); std::fs::write(format!("shell-{}.json", idx), json).unwrap(); // Tessellate for visualization let mesh = compressed_shell.robust_triangulation(0.01); let file = std::fs::File::create(format!("shell-{}.obj", idx)).unwrap(); obj::write(&mesh.to_polygon(), file).unwrap(); println!("Extracted and meshed shell #{}", idx); } } ``` -------------------------------- ### Create Torus Primitive Source: https://context7.com/ricosjp/truck/llms.txt Generates a toroidal solid centered at a specified point, defined by its major and minor radii, and the number of divisions along its major and minor circumferences. The torus is exported as a JSON file. ```rust use truck_modeling::*; fn main() { // Create torus centered at origin let center = Point3::origin(); let major_radius = 3.0; // Distance from center to tube center let minor_radius = 1.0; // Tube radius let u_divisions = 32; // Major circle divisions let v_divisions = 16; // Minor circle divisions let torus: Solid = builder::torus( center, major_radius, minor_radius, u_divisions, v_divisions, ); let json = serde_json::to_vec_pretty(&torus).unwrap(); std::fs::write("torus.json", json).unwrap(); println!("Torus created: R={}, r={}", major_radius, minor_radius); } ``` -------------------------------- ### Revolve Profile to Create Solid Source: https://context7.com/ricosjp/truck/llms.txt Creates a solid of revolution by rotating a 2D profile (defined as a face) around a specified axis. The profile is first created in the XZ plane, then revolved around the Z-axis by a given angle. The resulting solid is serialized to JSON. ```rust use truck_modeling::*; fn main() { // Create a rectangular profile in the XZ plane let v0 = builder::vertex(Point3::new(2.0, 0.0, 0.0)); let e0 = builder::tsweep(&v0, Vector3::new(0.0, 0.0, 3.0)); let profile_face: Face = builder::tsweep(&e0, Vector3::new(1.0, 0.0, 0.0)); // Revolve the profile around the Z-axis use std::f64::consts::PI; let revolution: Solid = builder::rsweep( &profile_face, Point3::origin(), // axis point Vector3::unit_z(), // axis direction Rad(2.0 * PI), // angle (full rotation) ); let json = serde_json::to_vec_pretty(&revolution).unwrap(); std::fs::write("revolved.json", json).unwrap(); println!("Solid of revolution created"); } ``` -------------------------------- ### Analyze Mesh Topology and Conditions in Rust Source: https://context7.com/ricosjp/truck/llms.txt Loads an OBJ mesh and analyzes its topological properties, including shell condition (closed, oriented, irregular), edge count, boundary edges, and self-intersections. Requires `truck-meshalgo` and `truck-polymesh` crates. ```rust use truck_meshalgo::analyzers::*; use truck_polymesh::obj; fn main() { // Load mesh let mesh = obj::read("model.obj").expect("Failed to load mesh"); // Check shell condition (closed, orientable, etc.) let condition = mesh.shell_condition(); println!("Shell condition: {:?}", condition); match condition { ShellCondition::Closed => { println!("✓ Mesh is a closed manifold"); } ShellCondition::Oriented => { println!("✓ Mesh is oriented but has boundaries"); } ShellCondition::Irregular => { println!("⚠ Mesh has non-manifold edges or vertices"); } _ => { println!("⚠ Mesh has topological issues"); } } // Analyze connectivity let edges = mesh.edge_iter().count(); let boundaries = mesh.boundary_edges().count(); println!("Total edges: {}", edges); println!("Boundary edges: {}", boundaries); // Check for self-intersections if mesh.has_collision() { println!("⚠ Warning: Mesh has self-intersections"); } else { println!("✓ No self-intersections detected"); } } ``` -------------------------------- ### Create Sphere Primitive Source: https://context7.com/ricosjp/truck/llms.txt Generates a UV-parameterized sphere centered at a specified point with a given radius and divisions for longitude and latitude. The resulting solid is complete with properly oriented faces and can be serialized to JSON. ```rust use truck_modeling::*; fn main() { // Create a sphere at origin with radius 2.0 // usize divisions: 32 meridians, 16 parallels let sphere: Solid = builder::sphere( Point3::origin(), // center 2.0, // radius 32, // u divisions (longitude) 16, // v divisions (latitude) ); // Sphere is a complete solid with properly oriented faces let json = serde_json::to_vec_pretty(&sphere).unwrap(); std::fs::write("sphere.json", json).unwrap(); println!("Sphere with 32x16 divisions created"); } ``` -------------------------------- ### Create Cylinder Primitive Source: https://context7.com/ricosjp/truck/llms.txt Constructs a cylindrical solid between two specified points with a given radius and a number of radial divisions. The resulting cylinder is a complete solid that can be exported to a JSON format. ```rust use truck_modeling::*; fn main() { // Create cylinder from point p0 to p1 let p0 = Point3::new(0.0, 0.0, 0.0); let p1 = Point3::new(0.0, 0.0, 5.0); let radius = 1.5; let divisions = 24; // Number of radial divisions let cylinder: Solid = builder::cylinder(p0, p1, radius, divisions); // Export to JSON let json = serde_json::to_vec_pretty(&cylinder).unwrap(); std::fs::write("cylinder.json", json).unwrap(); println!("Cylinder created with {} divisions", divisions); } ``` -------------------------------- ### Create Line Edge Between Vertices in Rust Source: https://context7.com/ricosjp/truck/llms.txt Shows how to create a linear edge connecting two vertices using truck_modeling::builder::line. It includes evaluating the curve at a specific parameter to find points and tangents. ```rust use truck_modeling::*; fn main() { // Create two vertices let v0 = builder::vertex(Point3::new(0.0, 0.0, 0.0)); let v1 = builder::vertex(Point3::new(5.0, 3.0, 2.0)); // Create a line edge connecting them let line: Edge = builder::line(&v0, &v1); // Evaluate the curve at parameter t let curve = line.oriented_curve(); let midpoint = curve.subs(0.5); // Get point at t=0.5 (middle) let tangent = curve.der(0.5); // Get tangent vector at t=0.5 println!("Midpoint: {:?}", midpoint); println!("Tangent: {:?}", tangent); } ``` -------------------------------- ### Vertex Shader: Transform vertex position with camera parameters Source: https://github.com/ricosjp/truck/blob/master/truck-js/examples/index.html This GLSL vertex shader processes incoming vertex attributes (position, UV, normal) and transforms the vertex position into clip space using camera parameters like position, direction, FOV, and near/far planes. It also outputs interpolated vertex data to the fragment shader. ```glsl #version 300 es in vec3 position; in vec2 uv; in vec3 normal; uniform vec3 camera_position; uniform vec3 camera_direction; uniform vec3 camera_updirection; uniform vec2 resolution; const float camera_fov = 3.141592653 / 4.0; const float camera_near = 0.1; const float camera_far = 10.0; out vec3 vertex_position; out vec2 vertex_uv; out vec3 vertex_normal; vec4 get_vertex_position( in vec3 pos, in vec3 c_pos, in vec3 c_dir, in vec3 c_up, in float c_fov, in float asp, in float c_far, in float c_near ) { vec3 vec = pos - c_pos; float far = 1.0 / tan(c_fov / 2.0); vec3 x_axis = cross(c_dir, c_up); vec3 y_axis = c_up; float depth = dot(c_dir, vec); vec3 h = (vec - depth * c_dir) * far; float u = dot(h, x_axis) / asp; float v = dot(h, y_axis); return vec4(u, v, (depth - c_near) / (c_far - c_near), depth); } void main() { gl_Position = get_vertex_position( position, camera_position, camera_direction, camera_updirection, camera_fov, resolution.x / resolution.y, camera_far, camera_near ); vertex_position = position; vertex_uv = uv; vertex_normal = normal; } ``` -------------------------------- ### Subdivide Mesh for Smoothing in Rust Source: https://context7.com/ricosjp/truck/llms.txt Loads a coarse mesh from an OBJ file, applies Loop subdivision to refine and smooth it, adds smooth normals, cleans up attributes, and saves the resulting refined mesh to a new OBJ file. Requires `truck-meshalgo` and `truck-polymesh` crates. ```rust use truck_meshalgo::filters::*; use truck_polymesh::obj; fn main() { // Load coarse mesh let mut mesh = obj::read("coarse.obj") .expect("Failed to load mesh"); println!("Original mesh: {} vertices, {} faces", mesh.positions().len(), mesh.faces().len()); // Apply Loop subdivision (for triangle meshes) mesh.loop_subdivision(2); // 2 levels of subdivision println!("Subdivided mesh: {} vertices, {} faces", mesh.positions().len(), mesh.faces().len()); // Add smooth normals mesh.add_smooth_normals(0.7, true); // Clean up mesh.put_together_same_attrs(1e-6) .remove_degenerate_faces() .remove_unused_attrs(); // Save refined mesh let output = std::fs::File::create("refined.obj").unwrap(); obj::write(&mesh, output).unwrap(); println!("Refined mesh saved to refined.obj"); } ``` -------------------------------- ### Read and Write OBJ Mesh Files in Rust Source: https://context7.com/ricosjp/truck/llms.txt Reads an OBJ file, performs mesh analysis and processing (merging vertices, removing degenerate faces, adding smooth normals), and writes the processed mesh to a new OBJ file. Requires the `truck-polymesh` and `truck-meshalgo` crates. ```rust use truck_polymesh::{obj, PolygonMesh, StandardVertex}; fn main() -> Result<(), Box> { // Read OBJ file let mesh: PolygonMesh = obj::read("input.obj")?; println!("Loaded mesh:"); println!(" Positions: {}", mesh.positions().len()); println!(" Normals: {}", mesh.normals().as_ref().map_or(0, |n| n.len())); println!(" UVs: {}", mesh.uv_coords().as_ref().map_or(0, |u| u.len())); println!(" Faces: {}", mesh.faces().len()); // Analyze mesh use truck_meshalgo::analyzers::*; let shell_condition = mesh.shell_condition(); println!("Shell condition: {:?}", shell_condition); // Process mesh use truck_meshalgo::filters::*; let mut processed = mesh; processed .put_together_same_attrs(1e-6) // Merge duplicate vertices .remove_degenerate_faces() // Remove invalid faces .remove_unused_attrs() // Clean unused attributes .add_smooth_normals(0.5, true); // Add smooth normals // Write processed mesh let output = std::fs::File::create("output.obj")?; obj::write(&processed, output)?; println!("Processed mesh written to output.obj"); Ok(()) } ``` -------------------------------- ### Create B-Spline Curve (Rust) Source: https://context7.com/ricosjp/truck/llms.txt Defines a B-spline curve using control points and a knot vector. The curve is then evaluated at various parameter values to obtain points and tangents. Requires `truck_geometry` and `truck_geotrait`. ```rust use truck_geometry::prelude::*; use truck_geotrait::*; fn main() { // Define control points let control_points = vec![ Point3::new(0.0, 0.0, 0.0), Point3::new(1.0, 2.0, 0.0), Point3::new(2.0, 2.0, 1.0), Point3::new(3.0, 0.0, 1.0), Point3::new(4.0, 0.0, 0.0), ]; // Create uniform clamped knot vector for degree 3 (cubic) let degree = 3; let knot_vec = KnotVec::clamped_uniform(degree, control_points.len()); // Create B-spline curve let bspline = BSplineCurve::new(knot_vec, control_points); // Evaluate curve at various parameters let param_range = bspline.parameter_range(); for i in 0..=20 { let t = param_range.0 + (param_range.1 - param_range.0) * (i as f64 / 20.0); let point = bspline.subs(t); let tangent = bspline.der(t); println!("t={:.2}: point={:?}, tangent={:?}", t, point, tangent); } } ``` -------------------------------- ### Tessellate Solid to Polygon Mesh in Rust Source: https://context7.com/ricosjp/truck/llms.txt Converts a parametric solid (like a torus) into a triangulated polygon mesh. This is useful for rendering or further analysis. The process involves tessellation with a specified tolerance, adding smooth normals, mesh cleanup, and exporting to an OBJ file using `truck_polymesh`. ```rust use truck_meshalgo::prelude::* use truck_modeling::* use truck_polymesh::obj; fn main() { // Create a torus let torus = builder::torus( Point3::origin(), 3.0, // major radius 1.0, // minor radius 32, // u divisions 16, // v divisions ); // Tessellate to triangle mesh with tolerance 0.01 let mut mesh = torus.triangulation(0.01) .expect("Tessellation failed"); // Add smooth normals for better rendering mesh.add_smooth_normals(0.5, true); // Clean up the mesh mesh.put_together_same_attrs(1e-6) .remove_degenerate_faces() .remove_unused_attrs(); // Export as OBJ file let file = std::fs::File::create("torus.obj").unwrap(); obj::write(&mesh, file).unwrap(); println!("Mesh exported: {} vertices, {} faces", mesh.positions().len(), mesh.faces().len()); } ``` -------------------------------- ### Boolean Union Operation Source: https://context7.com/ricosjp/truck/llms.txt Combines two solids into a single solid representing their union using the `or` function from `truck_shapeops`. This operation requires both input solids to be defined and valid. The result is saved as a JSON file. ```rust use truck_modeling::*; use truck_shapeops::*; fn main() { // Create two overlapping cubes let cube1 = builder::translated( builder::cuboid( Point3::new(-1.0, -1.0, -1.0), Point3::new(1.0, 1.0, 1.0) ), Vector3::new(-0.5, 0.0, 0.0), ); let cube2 = builder::translated( builder::cuboid( Point3::new(-1.0, -1.0, -1.0), Point3::new(1.0, 1.0, 1.0) ), Vector3::new(0.5, 0.0, 0.0), ); // Perform boolean union let union_result = or(&cube1, &cube2).expect("Union operation failed"); let json = serde_json::to_vec_pretty(&union_result).unwrap(); std::fs::write("union.json", json).unwrap(); println!("Union operation completed successfully"); } ``` -------------------------------- ### Create Circular Arc Edge in Rust Source: https://context7.com/ricosjp/truck/llms.txt Illustrates the creation of a circular arc edge between two vertices, passing through a specified transit point, using truck_modeling::builder::circle_arc. The code evaluates points along the arc. ```rust use truck_modeling::*; fn main() { // Create semicircle from (1,0,0) to (-1,0,0) passing through (0,1,0) let v0 = builder::vertex(Point3::new(1.0, 0.0, 0.0)); let v1 = builder::vertex(Point3::new(-1.0, 0.0, 0.0)); let transit = Point3::new(0.0, 1.0, 0.0); let arc: Edge = builder::circle_arc(&v0, &v1, transit); // Evaluate points along the arc let curve = arc.oriented_curve(); for i in 0..=10 { let t = i as f64 / 10.0; let point = curve.subs(t); println!("Arc point at t={}: {:?}", t, point); } } ``` -------------------------------- ### Boolean Difference: Create Hollow Cylinder in Rust Source: https://context7.com/ricosjp/truck/llms.txt Subtracts an inner cylinder from an outer cylinder to create a hollow shape. This operation uses the `truck_shapeops` crate for boolean logic. The resulting geometry is saved as a JSON file. ```rust use truck_modeling::* use truck_shapeops::* fn main() { // Create outer cylinder let outer_cylinder = builder::cylinder( Point3::new(0.0, 0.0, 0.0), Point3::new(0.0, 0.0, 5.0), 2.0, 32, ); // Create inner cylinder to subtract let inner_cylinder = builder::cylinder( Point3::new(0.0, 0.0, -0.5), Point3::new(0.0, 0.0, 5.5), 1.5, 32, ); // Subtract inner from outer using complement and intersection let hollow_cylinder = and( &outer_cylinder, ¬(&inner_cylinder).expect("Complement failed") ).expect("Difference operation failed"); let json = serde_json::to_vec_pretty(&hollow_cylinder).unwrap(); std::fs::write("hollow_cylinder.json", json).unwrap(); println!("Hollow cylinder created"); } ``` -------------------------------- ### Boolean Intersection Operation Source: https://context7.com/ricosjp/truck/llms.txt Computes the intersection of two solids, resulting in a new solid that represents the volume common to both inputs. This is achieved using the `and` function from `truck_shapeops`. The resulting intersection solid is then serialized to JSON. ```rust use truck_modeling::*; use truck_shapeops::*; fn main() { // Create sphere and cube let sphere = builder::sphere(Point3::origin(), 1.5, 32, 16); let cube = builder::cuboid( Point3::new(-1.2, -1.2, -1.2), Point3::new(1.2, 1.2, 1.2) ); // Compute intersection (cube-sphere shape) let intersection = and(&cube, &sphere) .expect("Intersection operation failed"); let json = serde_json::to_vec_pretty(&intersection).unwrap(); std::fs::write("intersection.json", json).unwrap(); println!("Intersection computed"); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.