# Wicker Basket

> A woven low-poly wicker basket with ribbed rows, vertical stakes, a rolled rim and an optional arched handle. Fill it with a heap of shiny apples or fresh bread loaves, or leave it empty. Lovely set dressing for markets, kitchens, picnics, farms and cozy village scenes.

![Wicker Basket preview](https://codels.download/m/wicker-basket.png)

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

## Facts

- Category: Props › Containers
- Size (W × H × D): 0.48 × 0.51 × 0.48 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 1,420 · Meshes: 37 · Materials: 7
- License: CC0-1.0 (Codels built-in)
- Tags: apple, basket, bread, picnic, cartoon, low-poly, stylized, farm, kitchen, medieval, village, farming-sim, rpg, container, decoration, food, prop, organic, wood, mobile-friendly, parametric, color-brown, color-orange, size-small, poly-low
- Page: https://codels.download/models/wicker-basket

## Files

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

## Parameters

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

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `contents` | select | empty \| apples \| bread | apples | apples |
| `handle` | boolean | true \| false | true | true |
| `wicker` | color | #rrggbb | #c2914f | #c2914f |
| `fruit` | color | #rrggbb | #d1352b | #d1352b |

## Parts

- body (lathe · wicker)
- interior (lathe · inner)
- stake1 (group)
  - stake (box · stake)
- stake2 (group)
  - stake (box · stake)
- stake3 (group)
  - stake (box · stake)
- stake4 (group)
  - stake (box · stake)
- stake5 (group)
  - stake (box · stake)
- stake6 (group)
  - stake (box · stake)
- stake7 (group)
  - stake (box · stake)
- stake8 (group)
  - stake (box · stake)
- stake9 (group)
  - stake (box · stake)
- stake10 (group)
  - stake (box · stake)
- stake11 (group)
  - stake (box · stake)
- stake12 (group)
  - stake (box · stake)
- rim (torus · stake)
- handle (tube · wicker)
- handleWrap (cylinder · stake)
- handleWrap (cylinder · stake)
- apple1 (group)
  - fruit (sphere · apple)
  - stem (cylinder · stem)
  - leaf (box · leaf)
- apple2 (group)
  - fruit (sphere · apple)
  - stem (cylinder · stem)
- apple3 (group)
  - fruit (sphere · apple)
  - stem (cylinder · stem)

## How to use

Save the code below as `wicker-basket.js`, then:

```js
import { createWickerBasket } from './wicker-basket.js';
const model = createWickerBasket();
scene.add(model);
```

## Code

```js
/**
 * Wicker Basket — Codels 3D model library (https://codels.download/models/wicker-basket)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,420 · Size (W × H × D): 0.48 × 0.51 × 0.48 m
 *
 * Usage:
 *   import { createWickerBasket } from './wicker-basket.js';
 *   
 *   const model = createWickerBasket();
 *   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);
}

// Tube along a smooth curve through the given points.
function tube(path, radius, tubularSegments, radialSegments, closed = false) {
  const curve = new THREE.CatmullRomCurve3(path.map(([x, y, z]) => new THREE.Vector3(x, y, z)), closed);
  return new THREE.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
}

export function createWickerBasket() {
  const root = new THREE.Group();
  root.name = 'WickerBasket';

  // Materials
  const wickerMat = new THREE.MeshStandardMaterial({ name: 'wicker', color: 0xc2914f, roughness: 0.95, flatShading: true });
  const stakeMat = new THREE.MeshStandardMaterial({ name: 'stake', color: 0x8c6839, roughness: 0.95, flatShading: true });
  const innerMat = new THREE.MeshStandardMaterial({ name: 'inner', color: 0x513d21, roughness: 1, flatShading: true });
  const appleMat = new THREE.MeshStandardMaterial({ name: 'apple', color: 0xd1352b, roughness: 0.45, flatShading: true });
  const appleAltMat = new THREE.MeshStandardMaterial({ name: 'appleAlt', color: 0x9cbf3a, roughness: 0.5, flatShading: true });
  const stemMat = new THREE.MeshStandardMaterial({ name: 'stem', color: 0x4a3220, roughness: 0.9, flatShading: true });
  const leafMat = new THREE.MeshStandardMaterial({ name: 'leaf', color: 0x3f8f3a, roughness: 0.8, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(0.016, 0.2109, 0.012);
  const cylinderGeo = new THREE.CylinderGeometry(0.022, 0.022, 0.05, 6);
  const sphereGeo = new THREE.SphereGeometry(0.05, 7, 5);
  const cylinderGeo2 = new THREE.CylinderGeometry(0.004, 0.005, 0.03, 4);
  const boxGeo2 = new THREE.BoxGeometry(0.03, 0.004, 0.016);

  // Parts
  const body = new THREE.Mesh(lathe([[0, 0.004], [0.148, 0], [0.16, 0.012], [0.1824, 0.0328], [0.1771, 0.0536], [0.1957, 0.0744], [0.1903, 0.0952], [0.2089, 0.116], [0.2035, 0.1368], [0.2221, 0.1576], [0.2168, 0.1784], [0.2354, 0.1992], [0.23, 0.22], [0.21, 0.22]], 12), wickerMat);
  body.name = 'body';
  root.add(body);
  const interior = new THREE.Mesh(lathe([[0.21, 0.22], [0.1877, 0.15], [0, 0.15]], 12), innerMat);
  interior.name = 'interior';
  root.add(interior);
  const stake1 = new THREE.Group();
  stake1.name = 'stake1';
  stake1.rotation.set(0, deg(15), 0);
  root.add(stake1);
  const stake = new THREE.Mesh(boxGeo, stakeMat);
  stake.name = 'stake';
  stake.position.set(0, 0.11, 0.2016);
  stake.rotation.set(deg(17.6501), 0, 0);
  stake1.add(stake);
  const stake2 = new THREE.Group();
  stake2.name = 'stake2';
  stake2.rotation.set(0, deg(45), 0);
  root.add(stake2);
  const stake3 = new THREE.Mesh(boxGeo, stakeMat);
  stake3.name = 'stake';
  stake3.position.set(0, 0.11, 0.2016);
  stake3.rotation.set(deg(17.6501), 0, 0);
  stake2.add(stake3);
  const stake32 = new THREE.Group();
  stake32.name = 'stake3';
  stake32.rotation.set(0, deg(75), 0);
  root.add(stake32);
  const stake4 = new THREE.Mesh(boxGeo, stakeMat);
  stake4.name = 'stake';
  stake4.position.set(0, 0.11, 0.2016);
  stake4.rotation.set(deg(17.6501), 0, 0);
  stake32.add(stake4);
  const stake42 = new THREE.Group();
  stake42.name = 'stake4';
  stake42.rotation.set(0, deg(105), 0);
  root.add(stake42);
  const stake5 = new THREE.Mesh(boxGeo, stakeMat);
  stake5.name = 'stake';
  stake5.position.set(0, 0.11, 0.2016);
  stake5.rotation.set(deg(17.6501), 0, 0);
  stake42.add(stake5);
  const stake52 = new THREE.Group();
  stake52.name = 'stake5';
  stake52.rotation.set(0, deg(135), 0);
  root.add(stake52);
  const stake6 = new THREE.Mesh(boxGeo, stakeMat);
  stake6.name = 'stake';
  stake6.position.set(0, 0.11, 0.2016);
  stake6.rotation.set(deg(17.6501), 0, 0);
  stake52.add(stake6);
  const stake62 = new THREE.Group();
  stake62.name = 'stake6';
  stake62.rotation.set(0, deg(165), 0);
  root.add(stake62);
  const stake7 = new THREE.Mesh(boxGeo, stakeMat);
  stake7.name = 'stake';
  stake7.position.set(0, 0.11, 0.2016);
  stake7.rotation.set(deg(17.6501), 0, 0);
  stake62.add(stake7);
  const stake72 = new THREE.Group();
  stake72.name = 'stake7';
  stake72.rotation.set(0, deg(195), 0);
  root.add(stake72);
  const stake8 = new THREE.Mesh(boxGeo, stakeMat);
  stake8.name = 'stake';
  stake8.position.set(0, 0.11, 0.2016);
  stake8.rotation.set(deg(17.6501), 0, 0);
  stake72.add(stake8);
  const stake82 = new THREE.Group();
  stake82.name = 'stake8';
  stake82.rotation.set(0, deg(225), 0);
  root.add(stake82);
  const stake9 = new THREE.Mesh(boxGeo, stakeMat);
  stake9.name = 'stake';
  stake9.position.set(0, 0.11, 0.2016);
  stake9.rotation.set(deg(17.6501), 0, 0);
  stake82.add(stake9);
  const stake92 = new THREE.Group();
  stake92.name = 'stake9';
  stake92.rotation.set(0, deg(255), 0);
  root.add(stake92);
  const stake10 = new THREE.Mesh(boxGeo, stakeMat);
  stake10.name = 'stake';
  stake10.position.set(0, 0.11, 0.2016);
  stake10.rotation.set(deg(17.6501), 0, 0);
  stake92.add(stake10);
  const stake102 = new THREE.Group();
  stake102.name = 'stake10';
  stake102.rotation.set(0, deg(285), 0);
  root.add(stake102);
  const stake11 = new THREE.Mesh(boxGeo, stakeMat);
  stake11.name = 'stake';
  stake11.position.set(0, 0.11, 0.2016);
  stake11.rotation.set(deg(17.6501), 0, 0);
  stake102.add(stake11);
  const stake112 = new THREE.Group();
  stake112.name = 'stake11';
  stake112.rotation.set(0, deg(315), 0);
  root.add(stake112);
  const stake12 = new THREE.Mesh(boxGeo, stakeMat);
  stake12.name = 'stake';
  stake12.position.set(0, 0.11, 0.2016);
  stake12.rotation.set(deg(17.6501), 0, 0);
  stake112.add(stake12);
  const stake122 = new THREE.Group();
  stake122.name = 'stake12';
  stake122.rotation.set(0, deg(345), 0);
  root.add(stake122);
  const stake13 = new THREE.Mesh(boxGeo, stakeMat);
  stake13.name = 'stake';
  stake13.position.set(0, 0.11, 0.2016);
  stake13.rotation.set(deg(17.6501), 0, 0);
  stake122.add(stake13);
  const rim = new THREE.Mesh(new THREE.TorusGeometry(0.224, 0.018, 4, 12), stakeMat);
  rim.name = 'rim';
  rim.position.set(0, 0.22, 0);
  rim.rotation.set(deg(90), 0, 0);
  root.add(rim);
  const handle = new THREE.Mesh(tube([[-0.22, 0.21, 0], [-0.2024, 0.35, 0], [-0.121, 0.46, 0], [0, 0.495, 0], [0.121, 0.46, 0], [0.2024, 0.35, 0], [0.22, 0.21, 0]], 0.015, 16, 5), wickerMat);
  handle.name = 'handle';
  root.add(handle);
  const handleWrap = new THREE.Mesh(cylinderGeo, stakeMat);
  handleWrap.name = 'handleWrap';
  handleWrap.position.set(-0.216, 0.245, 0);
  handleWrap.rotation.set(0, 0, deg(-6));
  root.add(handleWrap);
  const handleWrap2 = new THREE.Mesh(cylinderGeo, stakeMat);
  handleWrap2.name = 'handleWrap';
  handleWrap2.position.set(0.216, 0.245, 0);
  handleWrap2.rotation.set(0, 0, deg(6));
  root.add(handleWrap2);
  const apple1 = new THREE.Group();
  apple1.name = 'apple1';
  apple1.position.set(0, 0.2225, 0);
  apple1.rotation.set(deg(4.5079), deg(306.2796), deg(1.9011));
  root.add(apple1);
  const fruit = new THREE.Mesh(sphereGeo, appleMat);
  fruit.name = 'fruit';
  fruit.scale.set(1, 0.9, 1);
  apple1.add(fruit);
  const stem = new THREE.Mesh(cylinderGeo2, stemMat);
  stem.name = 'stem';
  stem.position.set(0, 0.0475, 0);
  stem.rotation.set(deg(0.3476), 0, deg(0.8984));
  apple1.add(stem);
  const leaf = new THREE.Mesh(boxGeo2, leafMat);
  leaf.name = 'leaf';
  leaf.position.set(0.016, 0.0475, 0);
  leaf.rotation.set(0, deg(109.4613), deg(20));
  apple1.add(leaf);
  const apple2 = new THREE.Group();
  apple2.name = 'apple2';
  apple2.position.set(0.1194, 0.1925, 0.0369);
  apple2.rotation.set(deg(5.3868), deg(162.117), deg(-0.9979));
  root.add(apple2);
  const fruit2 = new THREE.Mesh(sphereGeo, appleMat);
  fruit2.name = 'fruit';
  fruit2.scale.set(1, 0.9, 1);
  apple2.add(fruit2);
  const stem2 = new THREE.Mesh(cylinderGeo2, stemMat);
  stem2.name = 'stem';
  stem2.position.set(0, 0.0475, 0);
  stem2.rotation.set(deg(-12.5992), 0, deg(0.9152));
  apple2.add(stem2);
  const apple3 = new THREE.Group();
  apple3.name = 'apple3';
  apple3.position.set(0.0018, 0.1925, 0.125);
  apple3.rotation.set(deg(8.5104), deg(245.3503), deg(-16.9593));
  root.add(apple3);
  const fruit3 = new THREE.Mesh(sphereGeo, appleMat);
  fruit3.name = 'fruit';
  fruit3.scale.set(1, 0.9, 1);
  apple3.add(fruit3);
  const stem3 = new THREE.Mesh(cylinderGeo2, stemMat);
  stem3.name = 'stem';
  stem3.position.set(0, 0.0475, 0);
  stem3.rotation.set(deg(10.3056), 0, deg(-2.4007));
  apple3.add(stem3);
  const apple4 = new THREE.Group();
  apple4.name = 'apple4';
  apple4.position.set(-0.1183, 0.1925, 0.0403);
  apple4.rotation.set(deg(-6.1518), deg(209.7033), deg(-18.6259));
  root.add(apple4);
  const fruit4 = new THREE.Mesh(sphereGeo, appleAltMat);
  fruit4.name = 'fruit';
  fruit4.scale.set(1, 0.9, 1);
  apple4.add(fruit4);
  const stem4 = new THREE.Mesh(cylinderGeo2, stemMat);
  stem4.name = 'stem';
  stem4.position.set(0, 0.0475, 0);
  stem4.rotation.set(deg(-9.6446), 0, deg(-6.7168));
  apple4.add(stem4);
  const leaf2 = new THREE.Mesh(boxGeo2, leafMat);
  leaf2.name = 'leaf';
  leaf2.position.set(0.016, 0.0475, 0);
  leaf2.rotation.set(0, deg(71.2652), deg(20));
  apple4.add(leaf2);
  const apple5 = new THREE.Group();
  apple5.name = 'apple5';
  apple5.position.set(-0.0749, 0.1925, -0.1001);
  apple5.rotation.set(deg(-4.0791), deg(303.9301), deg(15.2692));
  root.add(apple5);
  const fruit5 = new THREE.Mesh(sphereGeo, appleMat);
  fruit5.name = 'fruit';
  fruit5.scale.set(1, 0.9, 1);
  apple5.add(fruit5);
  const stem5 = new THREE.Mesh(cylinderGeo2, stemMat);
  stem5.name = 'stem';
  stem5.position.set(0, 0.0475, 0);
  stem5.rotation.set(deg(2.9125), 0, deg(2.2962));
  apple5.add(stem5);
  const apple6 = new THREE.Group();
  apple6.name = 'apple6';
  apple6.position.set(0.072, 0.1925, -0.1022);
  apple6.rotation.set(deg(6.1554), deg(90.6045), deg(-22.1883));
  root.add(apple6);
  const fruit6 = new THREE.Mesh(sphereGeo, appleMat);
  fruit6.name = 'fruit';
  fruit6.scale.set(1, 0.9, 1);
  apple6.add(fruit6);
  const stem6 = new THREE.Mesh(cylinderGeo2, stemMat);
  stem6.name = 'stem';
  stem6.position.set(0, 0.0475, 0);
  stem6.rotation.set(deg(8.0641), 0, deg(-5.4717));
  apple6.add(stem6);
  const apple7 = new THREE.Group();
  apple7.name = 'apple7';
  apple7.position.set(0.0272, 0.2575, 0.0535);
  apple7.rotation.set(deg(-17.6733), deg(267.6785), deg(-7.6393));
  root.add(apple7);
  const fruit7 = new THREE.Mesh(sphereGeo, appleMat);
  fruit7.name = 'fruit';
  fruit7.scale.set(1, 0.9, 1);
  apple7.add(fruit7);
  const stem7 = new THREE.Mesh(cylinderGeo2, stemMat);
  stem7.name = 'stem';
  stem7.position.set(0, 0.0475, 0);
  stem7.rotation.set(deg(7.2273), 0, deg(14.3301));
  apple7.add(stem7);
  const leaf3 = new THREE.Mesh(boxGeo2, leafMat);
  leaf3.name = 'leaf';
  leaf3.position.set(0.016, 0.0475, 0);
  leaf3.rotation.set(0, deg(53.4306), deg(20));
  apple7.add(leaf3);
  const apple8 = new THREE.Group();
  apple8.name = 'apple8';
  apple8.position.set(-0.0272, 0.2575, -0.0535);
  apple8.rotation.set(deg(17.2753), deg(51.5586), deg(17.4854));
  root.add(apple8);
  const fruit8 = new THREE.Mesh(sphereGeo, appleMat);
  fruit8.name = 'fruit';
  fruit8.scale.set(1, 0.9, 1);
  apple8.add(fruit8);
  const stem8 = new THREE.Mesh(cylinderGeo2, stemMat);
  stem8.name = 'stem';
  stem8.position.set(0, 0.0475, 0);
  stem8.rotation.set(deg(1.6034), 0, deg(2.3002));
  apple8.add(stem8);

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

export default createWickerBasket;
```

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