$fn = 64; // --- Parameters --- // Outer radius of the tray (center to corner) tray_radius = 90; // Total height of the tray tray_height = 35; // Thickness of the outer walls wall_thickness = 4; // Thickness of the bottom base (felt is glued on top of this flat surface) base_thickness = 3; // Radius of the rounded corners corner_radius = 8; // Number of sides (8 = octagon, 6 = hexagon) num_sides = 8; // --- Main Model --- difference() { // Outer shell tray_profile(tray_radius, tray_height, corner_radius); // Inner hollow area for rolling // Z-translation leaves the base intact, Z-height + 1 ensures a clean manifold cut at the top translate([0, 0, base_thickness]) tray_profile( r = tray_radius - wall_thickness, h = tray_height + 1, cr = max(0.1, corner_radius - wall_thickness) ); } // --- Modules --- // Generates a rounded polygonal profile using a hull of cylinders module tray_profile(r, h, cr) { hull() { for(i = [0 : num_sides - 1]) { rotate([0, 0, i * (360 / num_sides)]) translate([r - cr, 0, 0]) cylinder(r = cr, h = h); } } }