# Park Bench

> A classic park bench with warm wooden seat and backrest slats bolted onto ornamental cast-iron side frames with curled armrests. Realistic 0.45 m seat height; set the length, wood and iron colors. Great street furniture for parks, city sidewalks, plazas, gardens and train platforms.

![Park Bench preview](https://codels.download/m/park-bench.png)

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

## Facts

- Category: Urban & Street › Street Furniture
- Size (W × H × D): 1.71 × 0.88 × 0.66 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 304 · Meshes: 16 · Materials: 2
- License: CC0-1.0 (Codels built-in)
- Tags: bench, park-bench, low-poly, stylized, modern, city, garden, decoration, furniture, interactable, prop, street-furniture, metal, wood, game-ready, instancing-friendly, mobile-friendly, parametric, color-gray, color-orange, size-medium, poly-low
- Page: https://codels.download/models/park-bench

## Files

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

## Parameters

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

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `length` | number | 1.2 – 2.6 | 1.7 | 1.7 |
| `wood` | color | #rrggbb | #b3773f | #b3773f |
| `iron` | color | #rrggbb | #2e3a34 | #2e3a34 |

## Parts

- sideFrame (extrude · iron)
- foot (box · iron)
- foot (box · iron)
- sideFrame (extrude · iron)
- foot (box · iron)
- foot (box · iron)
- seatSlat (box · wood)
- seatSlat (box · wood)
- seatSlat (box · wood)
- seatSlat (box · wood)
- seatSlat (box · wood)
- backSlat (box · wood)
- backSlat (box · wood)
- backSlat (box · wood)
- armrest (box · wood)
- armrest (box · wood)

## How to use

Save the code below as `park-bench.js`, then:

```js
import { createParkBench } from './park-bench.js';
const model = createParkBench();
scene.add(model);
```

## Code

```js
/**
 * Park Bench — Codels 3D model library (https://codels.download/models/park-bench)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 304 · Size (W × H × D): 1.71 × 0.88 × 0.66 m
 *
 * Usage:
 *   import { createParkBench } from './park-bench.js';
 *   
 *   const model = createParkBench();
 *   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 createParkBench() {
  const root = new THREE.Group();
  root.name = 'ParkBench';

  // Materials
  const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0xb3773f, roughness: 0.85, flatShading: true });
  const ironMat = new THREE.MeshStandardMaterial({ name: 'iron', color: 0x2e3a34, roughness: 0.55, metalness: 0.5, flatShading: true });

  // Shared geometries
  const extrudeGeo = extrude([[0.27, 0], [0.17, 0], [0.15, 0.33], [-0.12, 0.33], [-0.18, 0], [-0.29, 0], [-0.25, 0.4], [-0.37, 0.86], [-0.29, 0.88], [-0.19, 0.43], [0.16, 0.455], [0.18, 0.58], [-0.1, 0.61], [-0.09, 0.67], [0.25, 0.66], [0.29, 0.6], [0.23, 0.43], [0.25, 0.3]], 0.05);
  const boxGeo = new THREE.BoxGeometry(0.08, 0.025, 0.14);
  const boxGeo2 = new THREE.BoxGeometry(0.07, 0.035, 0.38);

  // Parts
  const sideFrame = new THREE.Mesh(extrudeGeo, ironMat);
  sideFrame.name = 'sideFrame';
  sideFrame.position.set(-0.73, 0, 0);
  sideFrame.rotation.set(0, deg(-90), 0);
  root.add(sideFrame);
  const foot = new THREE.Mesh(boxGeo, ironMat);
  foot.name = 'foot';
  foot.position.set(-0.73, 0.0125, 0.22);
  root.add(foot);
  const foot2 = new THREE.Mesh(boxGeo, ironMat);
  foot2.name = 'foot';
  foot2.position.set(-0.73, 0.0125, -0.235);
  root.add(foot2);
  const sideFrame2 = new THREE.Mesh(extrudeGeo, ironMat);
  sideFrame2.name = 'sideFrame';
  sideFrame2.position.set(0.73, 0, 0);
  sideFrame2.rotation.set(0, deg(-90), 0);
  root.add(sideFrame2);
  const foot3 = new THREE.Mesh(boxGeo, ironMat);
  foot3.name = 'foot';
  foot3.position.set(0.73, 0.0125, 0.22);
  root.add(foot3);
  const foot4 = new THREE.Mesh(boxGeo, ironMat);
  foot4.name = 'foot';
  foot4.position.set(0.73, 0.0125, -0.235);
  root.add(foot4);
  const seatSlat = new THREE.Mesh(new THREE.BoxGeometry(1.6931, 0.04, 0.062), woodMat);
  seatSlat.name = 'seatSlat';
  seatSlat.position.set(0, 0.4545, -0.149);
  seatSlat.rotation.set(deg(-3.9725), 0, 0);
  root.add(seatSlat);
  const seatSlat2 = new THREE.Mesh(new THREE.BoxGeometry(1.7025, 0.04, 0.062), woodMat);
  seatSlat2.name = 'seatSlat';
  seatSlat2.position.set(0, 0.4595, -0.077);
  seatSlat2.rotation.set(deg(-3.9725), 0, 0);
  root.add(seatSlat2);
  const seatSlat3 = new THREE.Mesh(new THREE.BoxGeometry(1.696, 0.04, 0.062), woodMat);
  seatSlat3.name = 'seatSlat';
  seatSlat3.position.set(0, 0.4645, -0.005);
  seatSlat3.rotation.set(deg(-3.9725), 0, 0);
  root.add(seatSlat3);
  const seatSlat4 = new THREE.Mesh(new THREE.BoxGeometry(1.7039, 0.04, 0.062), woodMat);
  seatSlat4.name = 'seatSlat';
  seatSlat4.position.set(0, 0.4695, 0.067);
  seatSlat4.rotation.set(deg(-3.9725), 0, 0);
  root.add(seatSlat4);
  const seatSlat5 = new THREE.Mesh(new THREE.BoxGeometry(1.7017, 0.04, 0.062), woodMat);
  seatSlat5.name = 'seatSlat';
  seatSlat5.position.set(0, 0.4745, 0.139);
  seatSlat5.rotation.set(deg(-3.9725), 0, 0);
  root.add(seatSlat5);
  const backSlat = new THREE.Mesh(new THREE.BoxGeometry(1.699, 0.1, 0.035), woodMat);
  backSlat.name = 'backSlat';
  backSlat.position.set(0, 0.56, -0.1867);
  backSlat.rotation.set(deg(-15.5241), 0, 0);
  root.add(backSlat);
  const backSlat2 = new THREE.Mesh(new THREE.BoxGeometry(1.7064, 0.1, 0.035), woodMat);
  backSlat2.name = 'backSlat';
  backSlat2.position.set(0, 0.68, -0.22);
  backSlat2.rotation.set(deg(-15.5241), 0, 0);
  root.add(backSlat2);
  const backSlat3 = new THREE.Mesh(new THREE.BoxGeometry(1.6948, 0.1, 0.035), woodMat);
  backSlat3.name = 'backSlat';
  backSlat3.position.set(0, 0.8, -0.2533);
  backSlat3.rotation.set(deg(-15.5241), 0, 0);
  root.add(backSlat3);
  const armrest = new THREE.Mesh(boxGeo2, woodMat);
  armrest.name = 'armrest';
  armrest.position.set(-0.73, 0.685, 0.08);
  root.add(armrest);
  const armrest2 = new THREE.Mesh(boxGeo2, woodMat);
  armrest2.name = 'armrest';
  armrest2.position.set(0.73, 0.685, 0.08);
  root.add(armrest2);

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

export default createParkBench;
```

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