# Wooden Chair

> A rustic low-poly wooden chair with a plank seat, tapered legs, side stretchers and an arched crest rail. Choose vertical back slats or a ladder back and add a soft seat cushion. Designed to match the Wooden Table for taverns, kitchens, cabins and dining rooms.

![Wooden Chair preview](https://codels.download/m/wooden-chair.png)

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

## Facts

- Category: Props › Furniture
- Size (W × H × D): 0.44 × 0.95 × 0.41 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 300 · Meshes: 22 · Materials: 5
- License: CC0-1.0 (Codels built-in)
- Tags: chair, rustic, tavern, low-poly, stylized, kitchen, medieval, interior, village, city-builder, rpg, furniture, interactable, prop, wood, game-ready, mobile-friendly, parametric, color-brown, size-small, poly-low
- Page: https://codels.download/models/wooden-chair

## Files

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

## Parameters

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

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `back` | select | slats \| ladder | slats | slats |
| `wood` | color | #rrggbb | #a5693a | #a5693a |
| `cushion` | boolean | true \| false | false | false |
| `fabric` | color | #rrggbb | #b5443a | #b5443a |

## Parts

- seatPlank (box · plank)
- seatPlank (box · plankAlt)
- seatPlank (box · plank)
- seatBoard (box · under)
- legFront (cylinder · frame)
- legBack (box · frame)
- finial (cylinder · frame)
- legFront (cylinder · frame)
- legBack (box · frame)
- finial (cylinder · frame)
- apronFront (box · trim)
- apronBack (box · trim)
- apronSide (box · trim)
- stretcherSide (box · frame)
- apronSide (box · trim)
- stretcherSide (box · frame)
- stretcherFront (box · frame)
- crestRail (extrude · plank)
- lowerRail (box · trim)
- slat (box · plank)
- slat (box · plankAlt)
- slat (box · plank)

## How to use

Save the code below as `wooden-chair.js`, then:

```js
import { createWoodenChair } from './wooden-chair.js';
const model = createWoodenChair();
scene.add(model);
```

## Code

```js
/**
 * Wooden Chair — Codels 3D model library (https://codels.download/models/wooden-chair)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 300 · Size (W × H × D): 0.44 × 0.95 × 0.41 m
 *
 * Usage:
 *   import { createWoodenChair } from './wooden-chair.js';
 *   
 *   const model = createWoodenChair();
 *   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 createWoodenChair() {
  const root = new THREE.Group();
  root.name = 'WoodenChair';

  // Materials
  const plankMat = new THREE.MeshStandardMaterial({ name: 'plank', color: 0xa5693a, roughness: 0.85, flatShading: true });
  const plankAltMat = new THREE.MeshStandardMaterial({ name: 'plankAlt', color: 0xb97641, roughness: 0.85, flatShading: true });
  const frameMat = new THREE.MeshStandardMaterial({ name: 'frame', color: 0x774c2a, roughness: 0.9, flatShading: true });
  const trimMat = new THREE.MeshStandardMaterial({ name: 'trim', color: 0x915c33, roughness: 0.85, flatShading: true });
  const underMat = new THREE.MeshStandardMaterial({ name: 'under', color: 0x422a17, roughness: 1, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(0.44, 0.04, 0.133);
  const cylinderGeo = new THREE.CylinderGeometry(0.0318, 0.0255, 0.394, 4);
  const boxGeo2 = new THREE.BoxGeometry(0.045, 0.92, 0.045);
  const cylinderGeo2 = new THREE.CylinderGeometry(0.012, 0.0225, 0.035, 4);
  const boxGeo3 = new THREE.BoxGeometry(0.371, 0.06, 0.02);
  const boxGeo4 = new THREE.BoxGeometry(0.02, 0.06, 0.35);
  const boxGeo5 = new THREE.BoxGeometry(0.024, 0.024, 0.35);
  const boxGeo6 = new THREE.BoxGeometry(0.055, 0.235, 0.016);

  // Parts
  const seatPlank = new THREE.Mesh(boxGeo, plankMat);
  seatPlank.name = 'seatPlank';
  seatPlank.position.set(0, 0.43, -0.14);
  root.add(seatPlank);
  const seatPlank2 = new THREE.Mesh(boxGeo, plankAltMat);
  seatPlank2.name = 'seatPlank';
  seatPlank2.position.set(0, 0.43, 0);
  root.add(seatPlank2);
  const seatPlank3 = new THREE.Mesh(boxGeo, plankMat);
  seatPlank3.name = 'seatPlank';
  seatPlank3.position.set(0, 0.43, 0.14);
  root.add(seatPlank3);
  const seatBoard = new THREE.Mesh(new THREE.BoxGeometry(0.41, 0.016, 0.39), underMat);
  seatBoard.name = 'seatBoard';
  seatBoard.position.set(0, 0.402, 0);
  root.add(seatBoard);
  const legFront = new THREE.Mesh(cylinderGeo, frameMat);
  legFront.name = 'legFront';
  legFront.position.set(-0.1855, 0.197, 0.1675);
  legFront.rotation.set(0, deg(45), 0);
  root.add(legFront);
  const legBack = new THREE.Mesh(boxGeo2, frameMat);
  legBack.name = 'legBack';
  legBack.position.set(-0.1855, 0.46, -0.1825);
  root.add(legBack);
  const finial = new THREE.Mesh(cylinderGeo2, frameMat);
  finial.name = 'finial';
  finial.position.set(-0.1855, 0.9375, -0.1825);
  finial.rotation.set(0, deg(45), 0);
  root.add(finial);
  const legFront2 = new THREE.Mesh(cylinderGeo, frameMat);
  legFront2.name = 'legFront';
  legFront2.position.set(0.1855, 0.197, 0.1675);
  legFront2.rotation.set(0, deg(45), 0);
  root.add(legFront2);
  const legBack2 = new THREE.Mesh(boxGeo2, frameMat);
  legBack2.name = 'legBack';
  legBack2.position.set(0.1855, 0.46, -0.1825);
  root.add(legBack2);
  const finial2 = new THREE.Mesh(cylinderGeo2, frameMat);
  finial2.name = 'finial';
  finial2.position.set(0.1855, 0.9375, -0.1825);
  finial2.rotation.set(0, deg(45), 0);
  root.add(finial2);
  const apronFront = new THREE.Mesh(boxGeo3, trimMat);
  apronFront.name = 'apronFront';
  apronFront.position.set(0, 0.364, 0.174);
  root.add(apronFront);
  const apronBack = new THREE.Mesh(boxGeo3, trimMat);
  apronBack.name = 'apronBack';
  apronBack.position.set(0, 0.364, -0.1825);
  root.add(apronBack);
  const apronSide = new THREE.Mesh(boxGeo4, trimMat);
  apronSide.name = 'apronSide';
  apronSide.position.set(-0.192, 0.364, -0.0075);
  root.add(apronSide);
  const stretcherSide = new THREE.Mesh(boxGeo5, frameMat);
  stretcherSide.name = 'stretcherSide';
  stretcherSide.position.set(-0.1855, 0.13, -0.0075);
  root.add(stretcherSide);
  const apronSide2 = new THREE.Mesh(boxGeo4, trimMat);
  apronSide2.name = 'apronSide';
  apronSide2.position.set(0.192, 0.364, -0.0075);
  root.add(apronSide2);
  const stretcherSide2 = new THREE.Mesh(boxGeo5, frameMat);
  stretcherSide2.name = 'stretcherSide';
  stretcherSide2.position.set(0.1855, 0.13, -0.0075);
  root.add(stretcherSide2);
  const stretcherFront = new THREE.Mesh(new THREE.BoxGeometry(0.371, 0.024, 0.024), frameMat);
  stretcherFront.name = 'stretcherFront';
  stretcherFront.position.set(0, 0.19, 0.1675);
  root.add(stretcherFront);
  const crestRail = new THREE.Mesh(extrude([[-0.1855, 0], [-0.1855, 0.075], [-0.1237, 0.09], [-0.0618, 0.101], [0, 0.105], [0.0618, 0.101], [0.1237, 0.09], [0.1855, 0.075], [0.1855, 0]], 0.028), plankMat);
  crestRail.name = 'crestRail';
  crestRail.position.set(0, 0.81, -0.1825);
  root.add(crestRail);
  const lowerRail = new THREE.Mesh(new THREE.BoxGeometry(0.371, 0.045, 0.024), trimMat);
  lowerRail.name = 'lowerRail';
  lowerRail.position.set(0, 0.5725, -0.1825);
  root.add(lowerRail);
  const slat = new THREE.Mesh(boxGeo6, plankMat);
  slat.name = 'slat';
  slat.position.set(-0.11, 0.7025, -0.1825);
  root.add(slat);
  const slat2 = new THREE.Mesh(boxGeo6, plankAltMat);
  slat2.name = 'slat';
  slat2.position.set(0, 0.7025, -0.1825);
  root.add(slat2);
  const slat3 = new THREE.Mesh(boxGeo6, plankMat);
  slat3.name = 'slat';
  slat3.position.set(0.11, 0.7025, -0.1825);
  root.add(slat3);

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

export default createWoodenChair;
```

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