Rendering these values. This takes a few seconds.
Download STL
Read this model as text

A modern wall mounted light bar for above a bathroom mirror. Three GU10 spots point down through the recessed bottom plate, hidden behind the front fascia so you see a clean bar and the light washes over the mirror. The fixture parameter picks how the spots are held: printed fixed cups, printed tilt cartridges on filament hinge pins, or store bought recessed GU10 fixtures that clamp into round cutouts in the plate with their own spring clips and their own tilt mechanism. The back is flat against the wall with rounded top corners that blend into the spherical front corners; one rounding radius for everything, sharp bottom edge, a service window behind each spot and a uniform bottom rim. The printed cups descend from mick/lamp-fittings. The bar splits into segments with dowel joints sized for a small printer bed.

The image shows the solid OpenSCAD renders at part all · segment_index 1 · cutaway false · show_fixtures true · fixture recessed · cutout_d 75 · bezel_d 93 · recess_depth 120 · total_width 500 · height 140 · depth 100 · rounding 14 · spots 3 · lip 15 · rim 2.5 · max_tilt 15 · tilt_angle 0 · segments 3 · wall 2.5 · plate_t 3 · gu10_hole_span 40 · smoothness 96 · color_body White.

MIT

Bathroom mirror light bar

mick/mirror-light@2.1.0

Remix this
Report

For a legal or policy problem: a license violation, personal data, somebody else’s work republished as their own. A model that prints badly is a comment, not a report.

Sign in to report

0reused0 remixes · 0 imports7downloads3.4.1latest

Parameters

from source
16, steps of 1
5090, steps of 1
60110, steps of 1
60150, steps of 5

Showing the render for these values.

Description

What is this

A modern wall mounted light bar for above a bathroom mirror. Three GU10 spots point down through the recessed bottom plate, hidden behind the front fascia so you see a clean bar and the light washes over the mirror. The fixture parameter picks how the spots are held: printed fixed cups, printed tilt cartridges on filament hinge pins, or store bought recessed GU10 fixtures that clamp into round cutouts in the plate with their own spring clips and their own tilt mechanism. The back is flat against the wall with rounded top corners that blend into the spherical front corners; one rounding radius for everything, sharp bottom edge, a service window behind each spot and a uniform bottom rim. The printed cups descend from mick/lamp-fittings. The bar splits into segments with dowel joints sized for a small printer bed.

What you use it for

For store bought recessed fixtures: measure the saw diameter, bezel diameter and required recess depth from the box and set cutout_d, bezel_d and recess_depth to match. The inside of the bar must be at least the recess depth: make height at least lip plus recess_depth plus wall, so 140 at the defaults of lip 15 and depth 120, or lower the lip to 10 and use 135. The preview draws a grey dummy of each fixture at full recess depth, so a bar that is too shallow shows the clash immediately in the cutaway; show_fixtures switches these dummies on and off and they are never part of a print. Print the segments, glue them on 4 mm dowels, push the fixtures into their cutouts from below until the clips grab the plate, wire them in parallel with Wago or terminal blocks through the service windows, feed the mains through the nearest window and hang the bar on the keyholes. For the printed variants: cups are fixed, cartridges tilt on 1.75 mm filament pins secured with glue or a melted head in their countersunk pockets. LED GU10 lamps only, PETG or ASA for a bathroom, out of the shower zones, and have the mains connection checked if you are not certain of it.

Design notes

The recessed fixtures clamp on the 3 mm plate exactly as they would on a ceiling panel, so no printed retention is needed; the bezel sits inside the open trough under the plate and the lip hides it from the front. The bezel must fit the trough: depth minus twice rim needs to exceed the bezel diameter, which holds at the defaults with a 93 mm bezel in a 100 mm deep bar. The shell is one convex hull with a flat back plate with rounded top corners blending into the front corner spheres, the cavity is the same hull inset by one wall and the bottom opening follows the outline at the rim offset. Keyholes sit in the columns between the service windows, offset from the segment cuts. part = segment exports one segment on its back for printing; part = cartridge exports the tilt cartridge for the printed tilting variant.

Parameters

fixture picks printed cups, printed tilt cartridges or store bought recessed fixtures, and show_fixtures toggles the grey preview dummies of the lamps and fixtures. cutout_d, bezel_d and recess_depth describe the recessed fixture; measure yours. total_width, height and depth size the bar, lip sets the fascia drop, rim the bottom rim thickness and rounding the single radius for all rounded edges. max_tilt and tilt_angle apply to the printed cartridges only. spots and segments set the count of lights and print sections, segment_index picks the section shown. wall and plate_t shape the shell, gu10_hole_span matches a bare socket for the printed variants, cutaway opens the display view and color_body sets the display colour.

Use with your agent
{
  "mcpServers": {
    "remixcad": {
      "type": "http",
      "url": "https://remix-cad.vercel.app/api/mcp"
    }
  }
}
get_model("mick/mirror-light@2.1.0")

Returns the manifest, the source, the import closure and the license obligations. Full MCP setup.

Parameter table

Parsed from the Customizer annotations in main.scad
Parameters of Bathroom mirror light bar, with the ranges the source declares
NameDefaultRangeUnitDescription
part"all"all, segment, cartridge
segment_index11 to 6 step 1
cutawayfalse
show_fixturestrue
fixture"recessed"cups, cartridges, recessed
cutout_d7550 to 90 step 1
bezel_d9360 to 110 step 1
recess_depth12060 to 150 step 5
total_width500300 to 800 step 10
height14070 to 160 step 5
depth10070 to 140 step 5
rounding142 to 40 step 1
spots32 to 5 step 1
lip158 to 30 step 1
rim2.52 to 12 step 0.5
max_tilt155 to 20 step 1
tilt_angle0-20 to 20 step 1
segments31 to 6 step 1
wall2.52 to 4 step 0.25
plate_t32 to 5 step 0.5
gu10_hole_span4024 to 50 step 1
smoothness9624 to 160 step 8
color_body"White"White, Silver, Gainsboro, DimGray, Black, SlateGray, FireBrick, SteelBlue, ForestGreen, Goldenrod

Lineage

0 models depend on this one

Only what this model came from and what came from it.

Remix, the code changed Import, used unchanged and pinned The version you are on Withdrawn, still recorded

License

Whoever downloads this takes these obligations along
  • mick/mirror-light@2.1.0 is MIT

Source

main.scad is the entrypoint
main.scad
// Bathroom mirror light bar. Remix of mick/lamp-fittings. Spots point down
// behind a front lip. Three fixture options: printed fixed cups, printed tilt
// cartridges on filament hinge pins, or store bought recessed GU10 fixtures
// clamping into round cutouts in the bottom plate. Flat back with rounded top
// corners blending into spherical front corners, sharp bottom edge, service
// windows behind the spots. Split into printer bed sized segments on dowels.

/* [Model] */
// The whole bar, one print segment laid flat, or one tilt cartridge print ready.
part = "all"; // [all, segment, cartridge]
// Which segment when part = segment.
segment_index = 1; // [1:1:6]
// Slice the display view open through the spots.
cutaway = false;
// Show the grey lamp and fixture dummies in the preview. Display only, never part of a print.
show_fixtures = true;

/* [Fixture] */
// How the spots are held: printed fixed cups, printed tilting cartridges, or store bought recessed GU10 fixtures in round cutouts.
fixture = "recessed"; // [cups, cartridges, recessed]

/* [Recessed fixtures, measure yours] */
// Saw diameter of the recessed fixture, the cutout in the plate.
cutout_d = 75; // [50:1:90]
// Outer bezel diameter of the recessed fixture. Display only, must fit inside depth minus twice rim.
bezel_d = 93; // [60:1:110]
// Required recess depth behind the plate. Make height at least lip + recess_depth + wall.
recess_depth = 120; // [60:5:150]

/* [Size] */
// Width of the bar in mm.
total_width = 500; // [300:10:800]
// Height of the front fascia in mm. Recessed fixtures need lip + recess_depth + wall.
height = 140; // [70:5:160]
// Depth from the wall in mm.
depth = 100; // [70:5:140]

/* [Rounding] */
// One radius for all rounded edges: the top front edge, the vertical front edges, the corner blends and the top corners of the back outline. The back plane always stays flat against the wall and the bottom edge always stays sharp.
rounding = 14; // [2:1:40]

/* [Light] */
// Number of GU10 spots.
spots = 3; // [2:1:5]
// How far the front fascia drops past the lamp faces, hiding them from view.
lip = 15; // [8:1:30]
// Thickness of the visible rim around the bottom opening.
rim = 2.5; // [2:0.5:12]

/* [Printed tilting cartridges] */
// Designed tilt range in degrees to either side, for fixture = cartridges.
max_tilt = 15; // [5:1:20]
// Tilt of the cartridges in the preview only, degrees. Positive tilts forward.
tilt_angle = 0; // [-20:1:20]

/* [Build] */
// Number of print segments. Keep total_width / segments under your printer bed size.
segments = 3; // [1:1:6]
// Wall thickness of the shell.
wall = 2.5; // [2:0.25:4]
// Thickness of the bottom plate that carries the spots.
plate_t = 3; // [2:0.5:5]

/* [GU10 socket, for printed variants] */
// Centre distance of the two fixing holes of a bare GU10 socket.
gu10_hole_span = 40; // [24:1:50]

/* [Quality] */
// Facets on round surfaces.
smoothness = 96; // [24:8:160]

/* [Colour] */
// Display colour of the body.
color_body = "White"; // [White, Silver, Gainsboro, DimGray, Black, SlateGray, FireBrick, SteelBlue, ForestGreen, Goldenrod]

/* [Hidden] */
$fn = smoothness;
eps = 0.01;
clearance = 0.3;
spot_len = 46;                 // GU10 lamp length without pins
cup_id = 50 + 2 * clearance;   // bore for the 50 mm lamp face
cup_od = cup_id + 2 * wall;
plate_bot = lip;
plate_top = lip + plate_t;
cap_bot = lip + spot_len;
seg_w = total_width / segments;
r_ = min(rounding, height / 2 - 2, depth / 2 - 2, total_width / 4);
r_i = max(r_ - wall, 1);
r_rim = max(r_ - rim, 1);
spacing = total_width / spots;
win_w = max(spacing - 56, 40);
win_z0 = plate_top + 4;
win_z1 = height - 14;
function sx(i) = (i + 0.5) * spacing;
kx1 = (sx(0) + sx(1)) / 2 - 12;
kx2 = (sx(spots - 2) + sx(spots - 1)) / 2 + 12;
// Printed tilting geometry
cart_od = cup_id + 2 * wall;
cart_h = spot_len + plate_t;
pivot_rel = 15;
pivot_z = lip + pivot_rel;
gap_t = 1.5;
ring_wall = 2.5;
ring_od = cart_od + 2 * gap_t + 2 * ring_wall;
ring_top = pivot_z + 8;
tilt_show = max(-max_tilt, min(max_tilt, tilt_angle));

// ---- Shell: flat back with rounded top corners, rounded front, sharp bottom ----

module back_face_2d(x0, x1, z0, z1, r)
  hull() {
    translate([x0, z0]) square([x1 - x0, max(z1 - z0 - r, 0.1)]);
    translate([x0 + r, z1 - r]) circle(r);
    translate([x1 - r, z1 - r]) circle(r);
  }

module bar_solid()
  hull() {
    translate([0, 1, 0]) rotate([90, 0, 0])
      linear_extrude(1) back_face_2d(0, total_width, 0, height, r_);
    for (px = [r_, total_width - r_]) {
      translate([px, depth - r_, 0]) cylinder(r = r_, h = 1);
      translate([px, depth - r_, height - r_]) sphere(r = r_);
    }
    translate([r_, depth - r_, height - r_])
      rotate([0, 90, 0]) cylinder(r = r_, h = total_width - 2 * r_);
  }

module cavity()
  hull() {
    translate([0, wall + 1, 0]) rotate([90, 0, 0])
      linear_extrude(1)
        back_face_2d(wall, total_width - wall, plate_top, height - wall, r_i);
    for (px = [wall + r_i, total_width - wall - r_i]) {
      translate([px, depth - wall - r_i, plate_top]) cylinder(r = r_i, h = 1);
      translate([px, depth - wall - r_i, height - wall - r_i]) sphere(r = r_i);
    }
    translate([wall + r_i, depth - wall - r_i, height - wall - r_i])
      rotate([0, 90, 0]) cylinder(r = r_i, h = total_width - 2 * (wall + r_i));
  }

module plan_in()
  hull() {
    translate([rim, rim]) square([total_width - 2 * rim, 1]);
    for (px = [rim + r_rim, total_width - rim - r_rim])
      translate([px, depth - rim - r_rim]) circle(r = r_rim);
  }

module trough()
  translate([0, 0, -1]) linear_extrude(lip + 1) plan_in();

// ---- Service windows: one behind each spot, hidden by the wall ----

module rrect2(w, h, r)
  hull()
    for (dx = [r, w - r], dz = [r, h - r])
      translate([dx, dz]) circle(r);

module service_windows()
  for (i = [0:spots - 1])
    translate([sx(i) - win_w / 2, wall + 1, win_z0])
      rotate([90, 0, 0])
        linear_extrude(wall + 2)
          rrect2(win_w, win_z1 - win_z0, 6);

// ---- Fixed printed cups (construction from mick/lamp-fittings) ----

module cups()
  for (i = [0:spots - 1])
    translate([sx(i), depth / 2, plate_bot])
      cylinder(d = cup_od, h = spot_len + plate_t);

module cup_bores()
  for (i = [0:spots - 1])
    translate([sx(i), depth / 2, -1])
      cylinder(d = cup_id, h = cap_bot + 1);

module cap_holes()
  for (i = [0:spots - 1])
    translate([sx(i), depth / 2, cap_bot - 1]) {
      cylinder(d = 30, h = plate_t + 2);
      for (s = [-1, 1])
        translate([s * gu10_hole_span / 2, 0, 0])
          cylinder(d = 2.8, h = plate_t + 2);
    }

// ---- Printed tilting: pivot rings, swept clearance and the cartridge ----

module cart_sweep()
  hull()
    for (a = [-max_tilt, 0, max_tilt])
      translate([0, 0, pivot_rel])
        rotate([a, 0, 0])
          translate([0, 0, -pivot_rel - 1])
            cylinder(d = cart_od + 2.4, h = cart_h + 2);

module rings()
  for (i = [0:spots - 1])
    translate([sx(i), depth / 2, plate_bot])
      cylinder(d = ring_od, h = ring_top - plate_bot);

module ring_carve()
  for (i = [0:spots - 1])
    translate([sx(i), depth / 2, plate_bot])
      cart_sweep();

module pivot_holes()
  for (i = [0:spots - 1])
    translate([sx(i), depth / 2, pivot_z]) {
      rotate([0, 90, 0])
        cylinder(d = 2.0, h = ring_od + 8, center = true);
      for (s = [-1, 1])
        translate([s * (ring_od / 2 - 0.6), 0, 0])
          rotate([0, 90, 0])
            cylinder(d = 4.5, h = 1.4, center = true);
    }

module cartridge_part()
  difference() {
    cylinder(d = cart_od, h = cart_h);
    translate([0, 0, -1]) cylinder(d = cup_id, h = spot_len + 1);
    translate([0, 0, spot_len - 1]) cylinder(d = 30, h = plate_t + 2);
    for (s = [-1, 1])
      translate([s * gu10_hole_span / 2, 0, spot_len - 1])
        cylinder(d = 2.8, h = plate_t + 2);
    translate([0, 0, pivot_rel])
      rotate([0, 90, 0])
        cylinder(d = 1.7, h = cart_od + 2, center = true);
  }

// ---- Store bought recessed fixtures: round cutouts, clip mounted ----

module recessed_openings()
  for (i = [0:spots - 1])
    translate([sx(i), depth / 2, plate_bot - 1])
      cylinder(d = cutout_d, h = plate_t + 2);

// Display dummy at full recess depth, so a too shallow bar shows the clash.
module recessed_mock() {
  color("Gainsboro") {
    translate([0, 0, -4]) cylinder(d = bezel_d, h = 4);
    cylinder(d = cutout_d - 3, h = recess_depth - 6);
    translate([0, 0, recess_depth - 6]) cylinder(d = 24, h = 5);
  }
  color("WhiteSmoke") translate([0, 0, -3.5]) cylinder(d = 50, h = 3);
}

// ---- Segment joints ----

module join_blocks()
  if (segments > 1)
    for (j = [1:segments - 1]) {
      xi = j * seg_w;
      translate([xi - 12, wall, plate_top]) cube([24, 12, 12]);
      translate([xi - 12, depth - wall - 12, plate_top]) cube([24, 12, 12]);
      translate([xi - 12, depth / 2 - 6, height - wall - 12]) cube([24, 12, 12]);
    }

module dowel_holes()
  if (segments > 1)
    for (j = [1:segments - 1]) {
      xi = j * seg_w;
      for (p = [[wall + 6, plate_top + 6],
                [depth - wall - 6, plate_top + 6],
                [depth / 2, height - wall - 6]])
        translate([xi, p[0], p[1]])
          rotate([0, 90, 0])
            cylinder(d = 4.2, h = 24, center = true);
    }

// ---- Wall mount ----

module keyholes()
  for (kx = [kx1, kx2])
    translate([kx, -1, 0]) rotate([-90, 0, 0]) {
      translate([0, -(height - 35), 0]) cylinder(d = 9, h = wall + 2);
      hull()
        for (dz = [0, 12])
          translate([0, -(height - 35) - dz, 0])
            cylinder(d = 4.5, h = wall + 2);
    }

// ---- Body ----

module body()
  difference() {
    union() {
      difference() {
        bar_solid();
        cavity();
        trough();
      }
      intersection() {
        union() {
          if (fixture == "cups") cups();
          if (fixture == "cartridges") rings();
          join_blocks();
        }
        bar_solid();
      }
    }
    if (fixture == "cups") {
      cup_bores();
      cap_holes();
    }
    if (fixture == "cartridges") {
      ring_carve();
      pivot_holes();
    }
    if (fixture == "recessed") recessed_openings();
    dowel_holes();
    keyholes();
    service_windows();
  }

module spot_mock()
  color("Gainsboro") {
    cylinder(d = 50, h = 6);
    translate([0, 0, 6]) cylinder(d1 = 50, d2 = 24, h = 32);
    translate([0, 0, 38]) cylinder(d = 24, h = 8);
  }

module display() {
  color(color_body) body();
  for (i = [0:spots - 1])
    translate([sx(i), depth / 2, plate_bot])
      if (fixture == "cartridges") {
        translate([0, 0, pivot_rel])
          rotate([tilt_show, 0, 0])
            translate([0, 0, -pivot_rel]) {
              color(color_body) cartridge_part();
              if (show_fixtures) spot_mock();
            }
      } else if (fixture == "recessed") {
        if (show_fixtures) recessed_mock();
      } else {
        if (show_fixtures) spot_mock();
      }
}

// ---- Layout ----

if (part == "cartridge") {
  translate([0, 0, cart_h]) rotate([180, 0, 0])
    color(color_body) cartridge_part();
} else if (part == "segment") {
  si = min(segment_index, segments);
  rotate([90, 0, 0])
    translate([-(si - 1) * seg_w, 0, 0])
      intersection() {
        color(color_body) body();
        translate([(si - 1) * seg_w, -10, -10])
          cube([seg_w, depth + 20, height + 20]);
      }
} else {
  if (cutaway)
    difference() {
      display();
      translate([-10, -10, -10])
        cube([total_width + 20, depth / 2 + 10, height + 20]);
    }
  else
    display();
}

Comments

Context, not a score. Comments never move a model up or down the results.

No comments yet

Printed it? A note about your material and the clearance you landed on saves the next person a failed print.

Sign in to comment