$fn = 64; // --- Parameters --- bottle_diameter = 26.0; // Vallejo bottles are ~24.5mm, 26mm gives comfortable clearance columns = 5; // Number of bottles across (X axis) rows = 3; // Number of tiers (Y axis) wall_thickness = 2.0; // Thickness of structural walls row_spacing = 2.0; // Extra Y-spacing between rows for easier grabbing hole_depth = 15.0; // Depth of the bottle cutouts base_thickness = 2.0; // Thickness of the floor under each bottle step_height = 20.0; // Z-height increase per tier // --- Calculated Variables --- pitch_x = bottle_diameter + wall_thickness; pitch_y = bottle_diameter + wall_thickness + row_spacing; total_width = columns * pitch_x + wall_thickness; // --- Geometry --- difference() { union() { // Horizontal shelves for (r = [0 : rows - 1]) { translate([0, r * pitch_y, r * step_height]) cube([total_width, pitch_y + wall_thickness, hole_depth + base_thickness]); } // Vertical risers (supports the shelves from the floor, leaving the underside hollow) for (r = [1 : rows - 1]) { translate([0, r * pitch_y, 0]) cube([total_width, wall_thickness, r * step_height + 0.1]); } // Back wall translate([0, rows * pitch_y, 0]) cube([total_width, wall_thickness, (rows - 1) * step_height + hole_depth + base_thickness]); // Left side wall for (r = [0 : rows - 1]) { translate([0, r * pitch_y, 0]) cube([wall_thickness, pitch_y + wall_thickness, r * step_height + hole_depth + base_thickness]); } // Right side wall for (r = [0 : rows - 1]) { translate([total_width - wall_thickness, r * pitch_y, 0]) cube([wall_thickness, pitch_y + wall_thickness, r * step_height + hole_depth + base_thickness]); } } // Bottle cutouts for (r = [0 : rows - 1]) { for (c = [0 : columns - 1]) { translate([ wall_thickness + bottle_diameter / 2 + c * pitch_x, wall_thickness + bottle_diameter / 2 + r * pitch_y, r * step_height + base_thickness ]) cylinder(h = hole_depth + 1.0, d = bottle_diameter); } } }