# Fallen Log

> A low-poly fallen tree trunk lying on its side, with sawn ends showing growth rings, broken branch stubs, a mossy back and optional little orange mushrooms. Great as a forest-floor obstacle, natural bench or decoration for camps, swamps and woodland paths.

![Fallen Log preview](https://codels.download/m/fallen-log.png)

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

## Facts

- Category: Nature › Trees
- Size (W × H × D): 2.23 × 0.72 × 0.87 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 1,036 · Meshes: 22 · Materials: 6
- License: CC0-1.0 (Codels built-in)
- Tags: fallen-log, log, moss, mushroom, trunk, low-poly, stylized, camping, forest, river, swamp, adventure, rpg, survival, decoration, obstacle, prop, wood, mobile-friendly, parametric, color-brown, color-green, size-medium, poly-low
- Page: https://codels.download/models/fallen-log

## Files

| Format | URL |
|---|---|
| three.js ES module (`createFallenLog()`) | https://codels.download/m/fallen-log.js |
| React Three Fiber component (`<FallenLog />`) | https://codels.download/m/fallen-log.jsx |
| Instancing module (`createFallenLogInstances(count, place)`, one draw call per material) | https://codels.download/m/fallen-log.instanced.js |
| Standalone HTML demo | https://codels.download/m/fallen-log.html |
| glTF binary | https://codels.download/m/fallen-log.glb |
| glTF binary, Meshopt-compressed (2–3× smaller; GLTFLoader needs `setMeshoptDecoder(MeshoptDecoder)`) | https://codels.download/m/fallen-log.glb?compress=meshopt |
| glTF JSON | https://codels.download/m/fallen-log.gltf |
| OBJ (vertex colors) + MTL | https://codels.download/m/fallen-log.obj · https://codels.download/m/fallen-log.mtl |
| STL | https://codels.download/m/fallen-log.stl |
| CodelSpec JSON | https://codels.download/m/fallen-log.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 – 4 | 2.2 | 2.2 |
| `radius` | number | 0.15 – 0.5 | 0.28 | 0.28 |
| `moss` | boolean | true \| false | true | true |
| `mushrooms` | boolean | true \| false | true | true |

## Parts

- log (group)
  - trunk (cylinder · bark)
  - cutLeft (cylinder · cut)
  - ringL1 (ring · ring)
  - ringL2 (ring · ring)
  - ringL3 (ring · ring)
  - cutRight (cylinder · cut)
  - ringR1 (ring · ring)
  - ringR2 (ring · ring)
  - ringR3 (ring · ring)
  - stub1 (cylinder · bark)
  - stub2 (cylinder · bark)
  - moss1 (dodecahedron · moss)
  - moss2 (dodecahedron · moss)
  - moss3 (dodecahedron · moss)
  - mushroom1 (group)
    - stem (cylinder · stem)
    - cap (sphere · cap)
  - mushroom2 (group)
    - stem (cylinder · stem)
    - cap (sphere · cap)
  - mushroom3 (group)
    - stem (cylinder · stem)
    - cap (sphere · cap)
  - mushroom4 (group)
    - stem (cylinder · stem)
    - cap (sphere · cap)

## How to use

Save the code below as `fallen-log.js`, then:

```js
import { createFallenLog } from './fallen-log.js';
const model = createFallenLog();
scene.add(model);
```

## Code

```js
/**
 * Fallen Log — Codels 3D model library (https://codels.download/models/fallen-log)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,036 · Size (W × H × D): 2.23 × 0.72 × 0.87 m
 *
 * Usage:
 *   import { createFallenLog } from './fallen-log.js';
 *   
 *   const model = createFallenLog();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// Deterministic vertex displacement (organic low-poly look).
function jitter(geometry, amount, seed) {
  const pos = geometry.attributes.position;
  const h = (a, b, c, s) => {
    let x = Math.imul(a, 73856093) ^ Math.imul(b, 19349663) ^ Math.imul(c, 83492791) ^ Math.imul(s, 2654435761);
    x = Math.imul(x ^ (x >>> 16), 2246822507);
    x = Math.imul(x ^ (x >>> 13), 3266489909);
    return ((x ^ (x >>> 16)) >>> 0) / 4294967295 - 0.5;
  };
  for (let i = 0; i < pos.count; i++) {
    const x = pos.getX(i), y = pos.getY(i), z = pos.getZ(i);
    const qx = Math.round(x * 1000), qy = Math.round(y * 1000), qz = Math.round(z * 1000);
    pos.setXYZ(i, x + h(qx, qy, qz, seed) * 2 * amount, y + h(qx, qy, qz, seed + 1) * 2 * amount, z + h(qx, qy, qz, seed + 2) * 2 * amount);
  }
  pos.needsUpdate = true;
  geometry.computeVertexNormals();
  return geometry;
}

export function createFallenLog() {
  const root = new THREE.Group();
  root.name = 'FallenLog';

  // Materials
  const barkMat = new THREE.MeshStandardMaterial({ name: 'bark', color: 0x5f4631, roughness: 0.95, flatShading: true });
  const cutMat = new THREE.MeshStandardMaterial({ name: 'cut', color: 0xd3a262, roughness: 0.85, flatShading: true });
  const ringMat = new THREE.MeshStandardMaterial({ name: 'ring', color: 0x9c6a3a, roughness: 0.9, flatShading: true });
  const mossMat = new THREE.MeshStandardMaterial({ name: 'moss', color: 0x5b8a35, roughness: 1, flatShading: true });
  const capMat = new THREE.MeshStandardMaterial({ name: 'cap', color: 0xd8662f, roughness: 0.7, flatShading: true });
  const stemMat = new THREE.MeshStandardMaterial({ name: 'stem', color: 0xefe2c4, roughness: 0.8, flatShading: true });

  // Parts
  const log = new THREE.Group();
  log.name = 'log';
  log.position.set(0, 0.2757, 0);
  root.add(log);
  const trunk = new THREE.Mesh(new THREE.CylinderGeometry(0.2576, 0.28, 2.2, 9), barkMat);
  trunk.name = 'trunk';
  trunk.rotation.set(0, 0, deg(90));
  log.add(trunk);
  const cutLeft = new THREE.Mesh(new THREE.CylinderGeometry(0.2215, 0.2215, 0.02, 9), cutMat);
  cutLeft.name = 'cutLeft';
  cutLeft.position.set(-1.103, 0, 0);
  cutLeft.rotation.set(0, 0, deg(90));
  log.add(cutLeft);
  const ringL1 = new THREE.Mesh(new THREE.RingGeometry(0.038, 0.0492, 16), ringMat);
  ringL1.name = 'ringL1';
  ringL1.position.set(-1.1145, 0, 0);
  ringL1.rotation.set(0, deg(-90), 0);
  log.add(ringL1);
  const ringL2 = new THREE.Mesh(new THREE.RingGeometry(0.0996, 0.1108, 16), ringMat);
  ringL2.name = 'ringL2';
  ringL2.position.set(-1.1145, 0, 0);
  ringL2.rotation.set(0, deg(-90), 0);
  log.add(ringL2);
  const ringL3 = new THREE.Mesh(new THREE.RingGeometry(0.1611, 0.1723, 16), ringMat);
  ringL3.name = 'ringL3';
  ringL3.position.set(-1.1145, 0, 0);
  ringL3.rotation.set(0, deg(-90), 0);
  log.add(ringL3);
  const cutRight = new THREE.Mesh(new THREE.CylinderGeometry(0.2408, 0.2408, 0.02, 9), cutMat);
  cutRight.name = 'cutRight';
  cutRight.position.set(1.103, 0, 0);
  cutRight.rotation.set(0, 0, deg(90));
  log.add(cutRight);
  const ringR1 = new THREE.Mesh(new THREE.RingGeometry(0.0423, 0.0535, 16), ringMat);
  ringR1.name = 'ringR1';
  ringR1.position.set(1.1145, 0, 0);
  ringR1.rotation.set(0, deg(90), 0);
  log.add(ringR1);
  const ringR2 = new THREE.Mesh(new THREE.RingGeometry(0.1092, 0.1204, 16), ringMat);
  ringR2.name = 'ringR2';
  ringR2.position.set(1.1145, 0, 0);
  ringR2.rotation.set(0, deg(90), 0);
  log.add(ringR2);
  const ringR3 = new THREE.Mesh(new THREE.RingGeometry(0.1761, 0.1873, 16), ringMat);
  ringR3.name = 'ringR3';
  ringR3.position.set(1.1145, 0, 0);
  ringR3.rotation.set(0, deg(90), 0);
  log.add(ringR3);
  const stub1 = new THREE.Mesh(new THREE.CylinderGeometry(0.056, 0.084, 0.3676, 6), barkMat);
  stub1.name = 'stub1';
  stub1.position.set(-0.4215, 0.175, 0.3031);
  stub1.rotation.set(deg(59.3595), deg(4.5633), deg(7.9981));
  log.add(stub1);
  const stub2 = new THREE.Mesh(new THREE.CylinderGeometry(0.056, 0.084, 0.3674, 6), barkMat);
  stub2.name = 'stub2';
  stub2.position.set(0.6189, 0.2681, -0.225);
  stub2.rotation.set(deg(-39.6136), deg(2.8174), deg(-7.812));
  log.add(stub2);
  const moss1 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(1, 1), 0.12, 40), mossMat);
  moss1.name = 'moss1';
  moss1.position.set(-0.484, 0.224, 0.0243);
  moss1.rotation.set(deg(10), 0, 0);
  moss1.scale.set(0.374, 0.0896, 0.2016);
  log.add(moss1);
  const moss2 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(1, 1), 0.12, 41), mossMat);
  moss2.name = 'moss2';
  moss2.position.set(0.132, 0.224, -0.0362);
  moss2.rotation.set(deg(-15), 0, 0);
  moss2.scale.set(0.242, 0.0896, 0.2016);
  log.add(moss2);
  const moss3 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(1, 1), 0.12, 42), mossMat);
  moss3.name = 'moss3';
  moss3.position.set(-0.924, 0.224, 0.0592);
  moss3.rotation.set(deg(25), 0, 0);
  moss3.scale.set(0.132, 0.0896, 0.2016);
  log.add(moss3);
  const mushroom1 = new THREE.Group();
  mushroom1.name = 'mushroom1';
  mushroom1.position.set(0.66, 0.1674, 0.1995);
  mushroom1.rotation.set(deg(16.1649), 0, 0);
  log.add(mushroom1);
  const stem = new THREE.Mesh(new THREE.CylinderGeometry(0.0304, 0.038, 0.133, 6), stemMat);
  stem.name = 'stem';
  stem.position.set(0, 0.0665, 0);
  mushroom1.add(stem);
  const cap = new THREE.Mesh(new THREE.SphereGeometry(0.0855, 8, 3, 0, Math.PI * 2, 0, Math.PI / 2), capMat);
  cap.name = 'cap';
  cap.position.set(0, 0.1178, 0);
  cap.scale.set(1, 0.75, 1);
  mushroom1.add(cap);
  const mushroom2 = new THREE.Group();
  mushroom2.name = 'mushroom2';
  mushroom2.position.set(0.814, 0.11, 0.236);
  mushroom2.rotation.set(deg(20.511), 0, 0);
  log.add(mushroom2);
  const stem2 = new THREE.Mesh(new THREE.CylinderGeometry(0.0228, 0.0285, 0.0998, 6), stemMat);
  stem2.name = 'stem';
  stem2.position.set(0, 0.0499, 0);
  mushroom2.add(stem2);
  const cap2 = new THREE.Mesh(new THREE.SphereGeometry(0.0641, 8, 3, 0, Math.PI * 2, 0, Math.PI / 2), capMat);
  cap2.name = 'cap';
  cap2.position.set(0, 0.0884, 0);
  cap2.scale.set(1, 0.75, 1);
  mushroom2.add(cap2);
  const mushroom3 = new THREE.Group();
  mushroom3.name = 'mushroom3';
  mushroom3.position.set(0.528, 0.0891, 0.2447);
  mushroom3.rotation.set(deg(21.8622), 0, 0);
  log.add(mushroom3);
  const stem3 = new THREE.Mesh(new THREE.CylinderGeometry(0.0182, 0.0228, 0.0798, 6), stemMat);
  stem3.name = 'stem';
  stem3.position.set(0, 0.0399, 0);
  mushroom3.add(stem3);
  const cap3 = new THREE.Mesh(new THREE.SphereGeometry(0.0513, 8, 3, 0, Math.PI * 2, 0, Math.PI / 2), capMat);
  cap3.name = 'cap';
  cap3.position.set(0, 0.0707, 0);
  cap3.scale.set(1, 0.75, 1);
  mushroom3.add(cap3);
  const mushroom4 = new THREE.Group();
  mushroom4.name = 'mushroom4';
  mushroom4.position.set(-0.66, 0.1995, 0.1674);
  mushroom4.rotation.set(deg(13.0825), 0, 0);
  log.add(mushroom4);
  const stem4 = new THREE.Mesh(new THREE.CylinderGeometry(0.0213, 0.0266, 0.0931, 6), stemMat);
  stem4.name = 'stem';
  stem4.position.set(0, 0.0466, 0);
  mushroom4.add(stem4);
  const cap4 = new THREE.Mesh(new THREE.SphereGeometry(0.0598, 8, 3, 0, Math.PI * 2, 0, Math.PI / 2), capMat);
  cap4.name = 'cap';
  cap4.position.set(0, 0.0825, 0);
  cap4.scale.set(1, 0.75, 1);
  mushroom4.add(cap4);

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

export default createFallenLog;
```

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