# Desk Lamp

> An articulated balanced-arm desk lamp with a weighted round base, twin-rod lower and upper arms with chrome hinges and tension springs, and a conical shade with a glowing emissive bulb and pale inner reflector. Adjust the arm angle and head tilt to pose it, pick any enamel color, or switch it off. Great for offices, studies, workshops, bedrooms and detective desks.

![Desk Lamp preview](https://codels.download/m/desk-lamp.png)

Multi-view sheet (3/4, front, side, top): https://codels.download/m/desk-lamp.sheet.png

## Facts

- Category: Props › Lighting
- Size (W × H × D): 0.19 × 0.43 × 0.45 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 684 · Meshes: 19 · Materials: 6
- License: CC0-1.0 (Codels built-in)
- Tags: anglepoise, desk-lamp, house, lamp, low-poly, retro, stylized, modern, office, interior, decoration, interactable, light-source, prop, metal, emissive, mobile-friendly, parametric, color-gray, color-red, color-white, size-small, poly-low
- Page: https://codels.download/models/desk-lamp

## Files

| Format | URL |
|---|---|
| three.js ES module (`createDeskLamp()`) | https://codels.download/m/desk-lamp.js |
| React Three Fiber component (`<DeskLamp />`) | https://codels.download/m/desk-lamp.jsx |
| Instancing module (`createDeskLampInstances(count, place)`, one draw call per material) | https://codels.download/m/desk-lamp.instanced.js |
| Standalone HTML demo | https://codels.download/m/desk-lamp.html |
| glTF binary | https://codels.download/m/desk-lamp.glb |
| glTF binary, Meshopt-compressed (2–3× smaller; GLTFLoader needs `setMeshoptDecoder(MeshoptDecoder)`) | https://codels.download/m/desk-lamp.glb?compress=meshopt |
| glTF JSON | https://codels.download/m/desk-lamp.gltf |
| OBJ (vertex colors) + MTL | https://codels.download/m/desk-lamp.obj · https://codels.download/m/desk-lamp.mtl |
| STL | https://codels.download/m/desk-lamp.stl |
| CodelSpec JSON | https://codels.download/m/desk-lamp.json |

## Parameters

Append them as query parameters to any URL above to get a customized variant (e.g. `?angle=...`).

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `angle` | number | 10 – 60 | 28 | 28 |
| `head` | number | 0 – 80 | 35 | 35 |
| `color` | color | #rrggbb | #c8463a | #c8463a |
| `lit` | boolean | true \| false | true | true |

## Parts

- deskLamp (group)
  - base (cylinder · paint)
  - baseFoot (cylinder · rubber)
  - baseTrim (cylinder · chrome)
  - switch (box · rubber)
  - turret (cylinder · paint)
  - baseHinge (cylinder · chrome)
  - elbowHinge (cylinder · chrome)
  - headHinge (cylinder · chrome)
  - lowerRod (cylinder · paint)
  - upperRod (cylinder · paint)
  - lowerRod (cylinder · paint)
  - upperRod (cylinder · paint)
  - spring (cylinder · spring)
  - spring (cylinder · spring)
  - shade (group)
    - shadeOuter (lathe · paint)
    - shadeInner (lathe · reflector)
    - socket (cylinder · chrome)
    - bulb (sphere · bulb)
    - knuckle (cylinder · paint)

## How to use

Save the code below as `desk-lamp.js`, then:

```js
import { createDeskLamp } from './desk-lamp.js';
const model = createDeskLamp();
scene.add(model);
```

## Code

```js
/**
 * Desk Lamp — Codels 3D model library (https://codels.download/models/desk-lamp)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 684 · Size (W × H × D): 0.19 × 0.43 × 0.45 m
 *
 * Usage:
 *   import { createDeskLamp } from './desk-lamp.js';
 *   
 *   const model = createDeskLamp();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// Revolve a 2D profile [[radius, y], ...] around the Y axis.
function lathe(points, segments, phiStart = 0, phiLength = Math.PI * 2) {
  return new THREE.LatheGeometry(points.map(([x, y]) => new THREE.Vector2(x, y)), segments, phiStart, phiLength);
}

export function createDeskLamp() {
  const root = new THREE.Group();
  root.name = 'DeskLamp';

  // Materials
  const paintMat = new THREE.MeshStandardMaterial({ name: 'paint', color: 0xc8463a, roughness: 0.4, metalness: 0.2, flatShading: true });
  const chromeMat = new THREE.MeshStandardMaterial({ name: 'chrome', color: 0xc9ced4, roughness: 0.25, metalness: 0.8, flatShading: true });
  const springMat = new THREE.MeshStandardMaterial({ name: 'spring', color: 0x7d8188, roughness: 0.4, metalness: 0.7, flatShading: true });
  const reflectorMat = new THREE.MeshStandardMaterial({ name: 'reflector', color: 0xf2ede2, roughness: 0.6, flatShading: true });
  const bulbMat = new THREE.MeshStandardMaterial({ name: 'bulb', color: 0xfff4cf, roughness: 0.3, emissive: 0xffe08a, emissiveIntensity: 1.3, flatShading: true });
  const rubberMat = new THREE.MeshStandardMaterial({ name: 'rubber', color: 0x26262a, roughness: 0.8, flatShading: true });

  // Shared geometries
  const cylinderGeo = new THREE.CylinderGeometry(0.0065, 0.0065, 0.3, 6);
  const cylinderGeo2 = new THREE.CylinderGeometry(0.006, 0.006, 0.29, 6);
  const cylinderGeo3 = new THREE.CylinderGeometry(0.009, 0.009, 0.162, 6);

  // Parts
  const deskLamp = new THREE.Group();
  deskLamp.name = 'deskLamp';
  deskLamp.position.set(0, 0, -0.0181);
  root.add(deskLamp);
  const base = new THREE.Mesh(new THREE.CylinderGeometry(0.085, 0.095, 0.03, 12), paintMat);
  base.name = 'base';
  base.position.set(0, 0.015, 0);
  deskLamp.add(base);
  const baseFoot = new THREE.Mesh(new THREE.CylinderGeometry(0.096, 0.096, 0.006, 12), rubberMat);
  baseFoot.name = 'baseFoot';
  baseFoot.position.set(0, 0.003, 0);
  deskLamp.add(baseFoot);
  const baseTrim = new THREE.Mesh(new THREE.CylinderGeometry(0.06, 0.08, 0.012, 12), chromeMat);
  baseTrim.name = 'baseTrim';
  baseTrim.position.set(0, 0.036, 0);
  deskLamp.add(baseTrim);
  const switch2 = new THREE.Mesh(new THREE.BoxGeometry(0.024, 0.012, 0.016), rubberMat);
  switch2.name = 'switch';
  switch2.position.set(0.045, 0.036, 0.05);
  deskLamp.add(switch2);
  const turret = new THREE.Mesh(new THREE.CylinderGeometry(0.02, 0.026, 0.05, 8), paintMat);
  turret.name = 'turret';
  turret.position.set(0, 0.065, -0.01);
  deskLamp.add(turret);
  const baseHinge = new THREE.Mesh(new THREE.CylinderGeometry(0.016, 0.016, 0.05, 8), chromeMat);
  baseHinge.name = 'baseHinge';
  baseHinge.position.set(0, 0.09, -0.01);
  baseHinge.rotation.set(0, 0, deg(90));
  deskLamp.add(baseHinge);
  const elbowHinge = new THREE.Mesh(new THREE.CylinderGeometry(0.015, 0.015, 0.05, 8), chromeMat);
  elbowHinge.name = 'elbowHinge';
  elbowHinge.position.set(0, 0.3549, -0.1508);
  elbowHinge.rotation.set(0, 0, deg(90));
  deskLamp.add(elbowHinge);
  const headHinge = new THREE.Mesh(new THREE.CylinderGeometry(0.013, 0.013, 0.044, 8), chromeMat);
  headHinge.name = 'headHinge';
  headHinge.position.set(0, 0.4052, 0.1348);
  headHinge.rotation.set(0, 0, deg(90));
  deskLamp.add(headHinge);
  const lowerRod = new THREE.Mesh(cylinderGeo, paintMat);
  lowerRod.name = 'lowerRod';
  lowerRod.position.set(0.014, 0.2224, -0.0804);
  lowerRod.rotation.set(deg(-28), 0, 0);
  deskLamp.add(lowerRod);
  const upperRod = new THREE.Mesh(cylinderGeo2, paintMat);
  upperRod.name = 'upperRod';
  upperRod.position.set(0.014, 0.3801, -0.008);
  upperRod.rotation.set(deg(80), 0, 0);
  deskLamp.add(upperRod);
  const lowerRod2 = new THREE.Mesh(cylinderGeo, paintMat);
  lowerRod2.name = 'lowerRod';
  lowerRod2.position.set(-0.014, 0.2224, -0.0804);
  lowerRod2.rotation.set(deg(-28), 0, 0);
  deskLamp.add(lowerRod2);
  const upperRod2 = new THREE.Mesh(cylinderGeo2, paintMat);
  upperRod2.name = 'upperRod';
  upperRod2.position.set(-0.014, 0.3801, -0.008);
  upperRod2.rotation.set(deg(80), 0, 0);
  deskLamp.add(upperRod2);
  const spring = new THREE.Mesh(cylinderGeo3, springMat);
  spring.name = 'spring';
  spring.position.set(0.031, 0.1827, -0.0593);
  spring.rotation.set(deg(-28), 0, 0);
  deskLamp.add(spring);
  const spring2 = new THREE.Mesh(cylinderGeo3, springMat);
  spring2.name = 'spring';
  spring2.position.set(-0.031, 0.1827, -0.0593);
  spring2.rotation.set(deg(-28), 0, 0);
  deskLamp.add(spring2);
  const shade = new THREE.Group();
  shade.name = 'shade';
  shade.position.set(0, 0.3438, 0.1778);
  shade.rotation.set(deg(-35), 0, 0);
  deskLamp.add(shade);
  const shadeOuter = new THREE.Mesh(lathe([[0.083, -0.064], [0.09, -0.06], [0.028, 0.058], [0, 0.066]], 12), paintMat);
  shadeOuter.name = 'shadeOuter';
  shade.add(shadeOuter);
  const shadeInner = new THREE.Mesh(lathe([[0, 0.05], [0.022, 0.048], [0.083, -0.062]], 12), reflectorMat);
  shadeInner.name = 'shadeInner';
  shade.add(shadeInner);
  const socket = new THREE.Mesh(new THREE.CylinderGeometry(0.012, 0.016, 0.02, 8), chromeMat);
  socket.name = 'socket';
  socket.position.set(0, 0.035, 0);
  shade.add(socket);
  const bulb = new THREE.Mesh(new THREE.SphereGeometry(0.028, 8, 6), bulbMat);
  bulb.name = 'bulb';
  bulb.position.set(0, -0.005, 0);
  bulb.scale.set(1, 1.15, 1);
  shade.add(bulb);
  const knuckle = new THREE.Mesh(new THREE.CylinderGeometry(0.014, 0.014, 0.03, 6), paintMat);
  knuckle.name = 'knuckle';
  knuckle.position.set(0, 0.075, 0);
  shade.add(knuckle);

  root.traverse((o) => {
    if (o.isMesh) {
      o.castShadow = true;
      o.receiveShadow = true;
    }
  });
  return root;
}

export default createDeskLamp;
```

---
Codels — 3D models as code for three.js. Search more: https://codels.download/api/v1/models?q=<query> · Guide: https://codels.download/llms.txt
