$fn=64; // --- Parameters --- pot_diameter = 33.5; // Citadel paint pots are ~33.5mm clearance = 1.5; // Extra clearance for easy insertion hole_depth = 15; // Depth of the pot recess rows = 4; // Number of stepped rows cols = 5; // Number of pots per row step_height = 25; // Vertical rise per row step_depth = 40; // Depth of each step wall_thickness = 3; // Outer and divider wall thickness base_thickness = 3; // Minimum thickness under the lowest pot cutout_width = 20; // Width of the front viewing cutout // --- Derived Variables --- actual_diameter = pot_diameter + clearance; spacing_x = actual_diameter + wall_thickness; rack_width = cols * spacing_x + wall_thickness; // --- Main Assembly --- difference() { // Main stepped body union() { for (r = [0 : rows - 1]) { overlap = (r < rows - 1) ? 0.1 : 0; // Ensure manifold union translate([0, r * step_depth, 0]) cube([ rack_width, step_depth + overlap, base_thickness + hole_depth + (r * step_height) ]); } } // Subtractions for pots and cutouts for (r = [0 : rows - 1]) { for (c = [0 : cols - 1]) { x_pos = wall_thickness + (actual_diameter / 2) + (c * spacing_x); y_pos = (r * step_depth) + (step_depth / 2); z_pos = base_thickness + (r * step_height); translate([x_pos, y_pos, z_pos]) { // Pot recess cylinder(h = hole_depth + 1, d = actual_diameter); // Front cutout for label visibility and grabbing translate([-cutout_width / 2, -step_depth / 2 - 1, 0]) cube([cutout_width, step_depth / 2 + 1, hole_depth + 1]); } } } }