# Parking Meter

> A classic coin-operated parking meter on a steel post: a cast housing with a domed glass window over the dial and time flag, a coin slot, a turn handle and a little receipt plate. Choose a single head or a double head on a yoke serving two parking spaces, set the housing color and show the red expired flag. Street furniture for curbside parking in city scenes.

![Parking Meter preview](https://codels.download/m/parking-meter.png)

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

## Facts

- Category: Urban & Street › Traffic
- Size (W × H × D): 0.17 × 1.54 × 0.18 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 456 · Meshes: 15 · Materials: 7
- License: CC0-1.0 (Codels built-in)
- Tags: parking, low-poly, retro, stylized, modern, city, road, city-builder, interactable, prop, street-furniture, glass, metal, tall, game-ready, instancing-friendly, mobile-friendly, parametric, color-blue, color-gray, color-white, size-medium, poly-low
- Page: https://codels.download/models/parking-meter

## Files

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

## Parameters

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

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `heads` | select | single \| double | single | single |
| `color` | color | #rrggbb | #5f7f96 | #5f7f96 |
| `expired` | boolean | true \| false | false | false |

## Parts

- baseFlange (cylinder · post)
- post (cylinder · post)
- head (group)
  - body (box · housing)
  - collar (box · trim)
  - neck (box · housing)
  - dial (cylinder · dial)
  - timeFlag (box · flag)
  - dome (cylinder · glass)
  - domeRim (torus · trim)
  - domeBack (cylinder · housing)
  - coinPlate (box · trim)
  - coinSlot (box · dark)
  - handleHub (cylinder · trim)
  - handle (box · trim)
  - infoPlate (box · dial)

## How to use

Save the code below as `parking-meter.js`, then:

```js
import { createParkingMeter } from './parking-meter.js';
const model = createParkingMeter();
scene.add(model);
```

## Code

```js
/**
 * Parking Meter — Codels 3D model library (https://codels.download/models/parking-meter)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 456 · Size (W × H × D): 0.17 × 1.54 × 0.18 m
 *
 * Usage:
 *   import { createParkingMeter } from './parking-meter.js';
 *   
 *   const model = createParkingMeter();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

export function createParkingMeter() {
  const root = new THREE.Group();
  root.name = 'ParkingMeter';

  // Materials
  const housingMat = new THREE.MeshStandardMaterial({ name: 'housing', color: 0x5f7f96, roughness: 0.45, metalness: 0.45, flatShading: true });
  const trimMat = new THREE.MeshStandardMaterial({ name: 'trim', color: 0xc4c8cc, roughness: 0.3, metalness: 0.8, flatShading: true });
  const postMat = new THREE.MeshStandardMaterial({ name: 'post', color: 0x4a5056, roughness: 0.5, metalness: 0.5, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x1d1f22, roughness: 0.6, flatShading: true });
  const dialMat = new THREE.MeshStandardMaterial({ name: 'dial', color: 0xefe9d6, roughness: 0.5, flatShading: true });
  const flagMat = new THREE.MeshStandardMaterial({ name: 'flag', color: 0x6f7a80, roughness: 0.5, flatShading: true });
  const glassMat = new THREE.MeshStandardMaterial({ name: 'glass', color: 0xd8ecf4, roughness: 0.25, transparent: true, opacity: 0.22 });

  // Parts
  const baseFlange = new THREE.Mesh(new THREE.CylinderGeometry(0.08, 0.09, 0.02, 10), postMat);
  baseFlange.name = 'baseFlange';
  baseFlange.position.set(0, 0.01, 0);
  root.add(baseFlange);
  const post = new THREE.Mesh(new THREE.CylinderGeometry(0.032, 0.036, 1.12, 10), postMat);
  post.name = 'post';
  post.position.set(0, 0.58, 0);
  root.add(post);
  const head = new THREE.Group();
  head.name = 'head';
  head.position.set(0, 1.19, 0);
  root.add(head);
  const body = new THREE.Mesh(new THREE.BoxGeometry(0.16, 0.24, 0.13), housingMat);
  body.name = 'body';
  body.position.set(0, 0.12, 0);
  head.add(body);
  const collar = new THREE.Mesh(new THREE.BoxGeometry(0.172, 0.03, 0.142), trimMat);
  collar.name = 'collar';
  collar.position.set(0, 0.25, 0);
  head.add(collar);
  const neck = new THREE.Mesh(new THREE.BoxGeometry(0.12, 0.05, 0.11), housingMat);
  neck.name = 'neck';
  neck.position.set(0, -0.025, 0);
  head.add(neck);
  const dial = new THREE.Mesh(new THREE.CylinderGeometry(0.066, 0.066, 0.008, 12, 1, false, Math.PI / 2, Math.PI), dialMat);
  dial.name = 'dial';
  dial.position.set(0, 0.266, -0.012);
  dial.rotation.set(deg(90), 0, 0);
  head.add(dial);
  const timeFlag = new THREE.Mesh(new THREE.BoxGeometry(0.024, 0.05, 0.006), flagMat);
  timeFlag.name = 'timeFlag';
  timeFlag.position.set(0.015, 0.3, 0.004);
  timeFlag.rotation.set(0, 0, deg(-60));
  head.add(timeFlag);
  const dome = new THREE.Mesh(new THREE.CylinderGeometry(0.075, 0.075, 0.12, 12, 1, false, Math.PI / 2, Math.PI), glassMat);
  dome.name = 'dome';
  dome.position.set(0, 0.265, 0);
  dome.rotation.set(deg(90), 0, 0);
  head.add(dome);
  const domeRim = new THREE.Mesh(new THREE.TorusGeometry(0.076, 0.007, 4, 12, Math.PI), trimMat);
  domeRim.name = 'domeRim';
  domeRim.position.set(0, 0.265, 0.062);
  head.add(domeRim);
  const domeBack = new THREE.Mesh(new THREE.CylinderGeometry(0.08, 0.08, 0.012, 12, 1, false, Math.PI / 2, Math.PI), housingMat);
  domeBack.name = 'domeBack';
  domeBack.position.set(0, 0.265, -0.066);
  domeBack.rotation.set(deg(90), 0, 0);
  head.add(domeBack);
  const coinPlate = new THREE.Mesh(new THREE.BoxGeometry(0.07, 0.05, 0.012), trimMat);
  coinPlate.name = 'coinPlate';
  coinPlate.position.set(0, 0.19, 0.068);
  head.add(coinPlate);
  const coinSlot = new THREE.Mesh(new THREE.BoxGeometry(0.04, 0.007, 0.004), darkMat);
  coinSlot.name = 'coinSlot';
  coinSlot.position.set(0, 0.195, 0.075);
  head.add(coinSlot);
  const handleHub = new THREE.Mesh(new THREE.CylinderGeometry(0.022, 0.022, 0.02, 10), trimMat);
  handleHub.name = 'handleHub';
  handleHub.position.set(0, 0.11, 0.072);
  handleHub.rotation.set(deg(90), 0, 0);
  head.add(handleHub);
  const handle = new THREE.Mesh(new THREE.BoxGeometry(0.09, 0.016, 0.014), trimMat);
  handle.name = 'handle';
  handle.position.set(0, 0.11, 0.084);
  handle.rotation.set(0, 0, deg(20));
  head.add(handle);
  const infoPlate = new THREE.Mesh(new THREE.BoxGeometry(0.1, 0.05, 0.006), dialMat);
  infoPlate.name = 'infoPlate';
  infoPlate.position.set(0, 0.04, 0.067);
  head.add(infoPlate);

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

export default createParkingMeter;
```

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