min_size = 40; thickness = 1.5; levels = 4; $fn = 50; cutoff_scale = 1.0 - 0.1 * (thickness + 1); level_dist = 10; module hollow_cube(size_, innermost=false, outermost = false) { outer_radius = size_/2; inner_radius = outer_radius - thickness; spike_offset = (outer_radius + inner_radius) / 2; joint_dist = level_dist/2; spike_height = joint_dist * 0.66; module spike(){ translate([0, 0, spike_offset]) cylinder(spike_height, spike_height*0.8, 0); } module joint(){ translate([0, 0, -spike_offset]) difference(){ cylinder(spike_height, spike_height*0.8, 0); rotate([180, 0, 0]) translate([0, 0, -joint_dist*0.95]) cylinder(spike_height, spike_height*0.8, 0); }; } difference(){ intersection(){ sphere(outer_radius); cube(size_ * cutoff_scale, center=true); }; sphere(inner_radius); }; if(!outermost){ rotate([90, 0, 45]) spike(); rotate([-90, 0, 45]) spike(); } if(!innermost){ rotate([-90, 0, -45]) joint(); rotate([90, 0, -45]) joint(); } } for(i = [1:levels]){ s = min_size + level_dist * i; translate([0, 0, s/2 * cutoff_scale]) hollow_cube(s, i==1, i==levels); }