# Traffic Light

> A street traffic signal on a sturdy pole: a three-lamp housing with sun visors and a backplate, a base plate and a pedestrian push button. Choose which lamp is lit (red, yellow or green glow emissive while the others stay dim), the pole height and the housing color. Ready for city intersections, driving games and traffic simulations.

![Traffic Light preview](https://codels.download/m/traffic-light.png)

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

## Facts

- Category: Urban & Street › Traffic
- Size (W × H × D): 0.66 × 4.19 × 0.56 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 1,116 · Meshes: 25 · Materials: 7
- License: CC0-1.0 (Codels built-in)
- Tags: stoplight, traffic-light, traffic-signal, cartoon, low-poly, stylized, modern, city, road, city-builder, racing-game, decoration, interactable, light-source, prop, street-furniture, metal, emissive, mobile-friendly, parametric, color-black, color-gray, color-yellow, size-large, poly-low
- Page: https://codels.download/models/traffic-light

## Files

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

## Parameters

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

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `active` | select | red \| yellow \| green | red | red |
| `height` | number | 2.4 – 4.5 | 3 | 3 |
| `housing` | color | #rrggbb | #353b40 | #353b40 |

## Parts

- basePlate (cylinder · pole)
- anchorBolt (cylinder · plate)
- anchorBolt (cylinder · plate)
- anchorBolt (cylinder · plate)
- anchorBolt (cylinder · plate)
- poleBase (cylinder · pole)
- pole (cylinder · pole)
- poleCollar (cylinder · pole)
- buttonBox (box · housing)
- pushButton (cylinder · accent)
- buttonSign (box · plate)
- mount (box · housing)
- signalHousing (box · housing)
- backplate (box · plate)
- backplateBorder (box · accent)
- housingCap (box · housing)
- lampRing (cylinder · plate)
- lens (sphere · red)
- visor (extrude · housing)
- lampRing (cylinder · plate)
- lens (sphere · yellow)
- visor (extrude · housing)
- lampRing (cylinder · plate)
- lens (sphere · green)
- visor (extrude · housing)

## How to use

Save the code below as `traffic-light.js`, then:

```js
import { createTrafficLight } from './traffic-light.js';
const model = createTrafficLight();
scene.add(model);
```

## Code

```js
/**
 * Traffic Light — Codels 3D model library (https://codels.download/models/traffic-light)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,116 · Size (W × H × D): 0.66 × 4.19 × 0.56 m
 *
 * Usage:
 *   import { createTrafficLight } from './traffic-light.js';
 *   
 *   const model = createTrafficLight();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// Extrude a 2D outline along Z (centered). bevel = [thickness, size, segments].
function extrude(outline, depth, holes = [], bevel = null) {
  const shape = new THREE.Shape(outline.map(([x, y]) => new THREE.Vector2(x, y)));
  for (const hole of holes) shape.holes.push(new THREE.Path(hole.map(([x, y]) => new THREE.Vector2(x, y))));
  const options = bevel
    ? { depth, bevelEnabled: true, bevelThickness: bevel[0], bevelSize: bevel[1], bevelSegments: bevel[2] }
    : { depth, bevelEnabled: false };
  return new THREE.ExtrudeGeometry(shape, options).translate(0, 0, -depth / 2);
}

export function createTrafficLight() {
  const root = new THREE.Group();
  root.name = 'TrafficLight';

  // Materials
  const poleMat = new THREE.MeshStandardMaterial({ name: 'pole', color: 0x7d848b, roughness: 0.45, metalness: 0.6, flatShading: true });
  const housingMat = new THREE.MeshStandardMaterial({ name: 'housing', color: 0x353b40, roughness: 0.6, metalness: 0.2, flatShading: true });
  const plateMat = new THREE.MeshStandardMaterial({ name: 'plate', color: 0x1b1d1f, roughness: 0.7, flatShading: true });
  const accentMat = new THREE.MeshStandardMaterial({ name: 'accent', color: 0xe3bd2c, roughness: 0.4, flatShading: true });
  const redMat = new THREE.MeshStandardMaterial({ name: 'red', color: 0xff5a4a, roughness: 0.25, emissive: 0xff2a1a, emissiveIntensity: 1.3, flatShading: true });
  const yellowMat = new THREE.MeshStandardMaterial({ name: 'yellow', color: 0x665219, roughness: 0.3, metalness: 0.1, flatShading: true });
  const greenMat = new THREE.MeshStandardMaterial({ name: 'green', color: 0x1a5236, roughness: 0.3, metalness: 0.1, flatShading: true });

  // Shared geometries
  const cylinderGeo = new THREE.CylinderGeometry(0.018, 0.018, 0.035, 6);
  const cylinderGeo2 = new THREE.CylinderGeometry(0.135, 0.135, 0.02, 12);
  const sphereGeo = new THREE.SphereGeometry(0.115, 12, 6, 0, Math.PI * 2, 0, Math.PI / 2);
  const extrudeGeo = extrude([[0.15, 0], [0.1386, 0.0574], [0.1061, 0.1061], [0.0574, 0.1386], [0, 0.15], [-0.0574, 0.1386], [-0.1061, 0.1061], [-0.1386, 0.0574], [-0.15, 0], [-0.128, 0], [-0.1183, 0.049], [-0.0905, 0.0905], [-0.049, 0.1183], [0, 0.128], [0.049, 0.1183], [0.0905, 0.0905], [0.1183, 0.049], [0.128, 0]], 0.2);

  // Parts
  const basePlate = new THREE.Mesh(new THREE.CylinderGeometry(0.2, 0.22, 0.04, 10), poleMat);
  basePlate.name = 'basePlate';
  basePlate.position.set(0, 0.02, 0);
  root.add(basePlate);
  const anchorBolt = new THREE.Mesh(cylinderGeo, plateMat);
  anchorBolt.name = 'anchorBolt';
  anchorBolt.position.set(0.1061, 0.0575, 0.1061);
  root.add(anchorBolt);
  const anchorBolt2 = new THREE.Mesh(cylinderGeo, plateMat);
  anchorBolt2.name = 'anchorBolt';
  anchorBolt2.position.set(0.1061, 0.0575, -0.1061);
  root.add(anchorBolt2);
  const anchorBolt3 = new THREE.Mesh(cylinderGeo, plateMat);
  anchorBolt3.name = 'anchorBolt';
  anchorBolt3.position.set(-0.1061, 0.0575, -0.1061);
  root.add(anchorBolt3);
  const anchorBolt4 = new THREE.Mesh(cylinderGeo, plateMat);
  anchorBolt4.name = 'anchorBolt';
  anchorBolt4.position.set(-0.1061, 0.0575, 0.1061);
  root.add(anchorBolt4);
  const poleBase = new THREE.Mesh(new THREE.CylinderGeometry(0.09, 0.1, 0.35, 10), poleMat);
  poleBase.name = 'poleBase';
  poleBase.position.set(0, 0.215, 0);
  root.add(poleBase);
  const pole = new THREE.Mesh(new THREE.CylinderGeometry(0.065, 0.08, 2.61, 10), poleMat);
  pole.name = 'pole';
  pole.position.set(0, 1.695, 0);
  root.add(pole);
  const poleCollar = new THREE.Mesh(new THREE.CylinderGeometry(0.085, 0.085, 0.06, 10), poleMat);
  poleCollar.name = 'poleCollar';
  poleCollar.position.set(0, 2.97, 0);
  root.add(poleCollar);
  const buttonBox = new THREE.Mesh(new THREE.BoxGeometry(0.12, 0.18, 0.08), housingMat);
  buttonBox.name = 'buttonBox';
  buttonBox.position.set(0, 1.1, 0.1);
  root.add(buttonBox);
  const pushButton = new THREE.Mesh(new THREE.CylinderGeometry(0.03, 0.03, 0.02, 8), accentMat);
  pushButton.name = 'pushButton';
  pushButton.position.set(0, 1.08, 0.145);
  pushButton.rotation.set(deg(90), 0, 0);
  root.add(pushButton);
  const buttonSign = new THREE.Mesh(new THREE.BoxGeometry(0.08, 0.05, 0.012), plateMat);
  buttonSign.name = 'buttonSign';
  buttonSign.position.set(0, 1.15, 0.143);
  root.add(buttonSign);
  const mount = new THREE.Mesh(new THREE.BoxGeometry(0.14, 0.1, 0.14), housingMat);
  mount.name = 'mount';
  mount.position.set(0, 3.05, 0);
  root.add(mount);
  const signalHousing = new THREE.Mesh(new THREE.BoxGeometry(0.36, 1, 0.26), housingMat);
  signalHousing.name = 'signalHousing';
  signalHousing.position.set(0, 3.54, 0);
  root.add(signalHousing);
  const backplate = new THREE.Mesh(new THREE.BoxGeometry(0.62, 1.26, 0.025), plateMat);
  backplate.name = 'backplate';
  backplate.position.set(0, 3.54, -0.145);
  root.add(backplate);
  const backplateBorder = new THREE.Mesh(new THREE.BoxGeometry(0.66, 1.3, 0.012), accentMat);
  backplateBorder.name = 'backplateBorder';
  backplateBorder.position.set(0, 3.54, -0.161);
  root.add(backplateBorder);
  const housingCap = new THREE.Mesh(new THREE.BoxGeometry(0.4, 0.05, 0.3), housingMat);
  housingCap.name = 'housingCap';
  housingCap.position.set(0, 4.065, 0);
  root.add(housingCap);
  const lampRing = new THREE.Mesh(cylinderGeo2, plateMat);
  lampRing.name = 'lampRing';
  lampRing.position.set(0, 3.85, 0.138);
  lampRing.rotation.set(deg(90), 0, 0);
  root.add(lampRing);
  const lens = new THREE.Mesh(sphereGeo, redMat);
  lens.name = 'lens';
  lens.position.set(0, 3.85, 0.142);
  lens.rotation.set(deg(90), 0, 0);
  lens.scale.set(1, 0.35, 1);
  root.add(lens);
  const visor = new THREE.Mesh(extrudeGeo, housingMat);
  visor.name = 'visor';
  visor.position.set(0, 3.85, 0.24);
  root.add(visor);
  const lampRing2 = new THREE.Mesh(cylinderGeo2, plateMat);
  lampRing2.name = 'lampRing';
  lampRing2.position.set(0, 3.54, 0.138);
  lampRing2.rotation.set(deg(90), 0, 0);
  root.add(lampRing2);
  const lens2 = new THREE.Mesh(sphereGeo, yellowMat);
  lens2.name = 'lens';
  lens2.position.set(0, 3.54, 0.142);
  lens2.rotation.set(deg(90), 0, 0);
  lens2.scale.set(1, 0.35, 1);
  root.add(lens2);
  const visor2 = new THREE.Mesh(extrudeGeo, housingMat);
  visor2.name = 'visor';
  visor2.position.set(0, 3.54, 0.24);
  root.add(visor2);
  const lampRing3 = new THREE.Mesh(cylinderGeo2, plateMat);
  lampRing3.name = 'lampRing';
  lampRing3.position.set(0, 3.23, 0.138);
  lampRing3.rotation.set(deg(90), 0, 0);
  root.add(lampRing3);
  const lens3 = new THREE.Mesh(sphereGeo, greenMat);
  lens3.name = 'lens';
  lens3.position.set(0, 3.23, 0.142);
  lens3.rotation.set(deg(90), 0, 0);
  lens3.scale.set(1, 0.35, 1);
  root.add(lens3);
  const visor3 = new THREE.Mesh(extrudeGeo, housingMat);
  visor3.name = 'visor';
  visor3.position.set(0, 3.23, 0.24);
  root.add(visor3);

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

export default createTrafficLight;
```

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