# Oak Tree

> A broad, round-crowned low-poly oak with a thick flared trunk, sturdy branches and a canopy of jittered foliage clusters in three leaf tones. Tune height, canopy size, cluster density, leaf color and a variation seed to fill forests, parks and village greens.

![Oak Tree preview](https://codels.download/m/oak-tree.png)

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

## Facts

- Category: Nature › Trees
- Size (W × H × D): 4.48 × 4.55 × 4.10 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 1,024 · Meshes: 18 · Materials: 4
- License: CC0-1.0 (Codels built-in)
- Tags: deciduous, oak, tree, low-poly, stylized, forest, garden, grassland, village, adventure, rpg, survival, background, vegetation, foliage-material, wood, round, game-ready, mobile-friendly, parametric, color-green, size-large, poly-low
- Page: https://codels.download/models/oak-tree

## Files

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

## Parameters

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

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `height` | number | 3 – 10 | 5.5 | 5.5 |
| `canopy` | number | 0.7 – 1.4 | 1 | 1 |
| `density` | int | 5 – 14 | 9 | 9 |
| `leaves` | color | #rrggbb | #4f8a3c | #4f8a3c |
| `seed` | int | 1 – 20 | 3 | 3 |

## Parts

- trunk (lathe · bark)
- root1 (cylinder · bark)
- root2 (cylinder · bark)
- root3 (cylinder · bark)
- root4 (cylinder · bark)
- branch1 (cylinder · bark)
- branch2 (cylinder · bark)
- branch3 (cylinder · bark)
- canopyCore (icosahedron · leaf)
- leaves1 (icosahedron · leafDark)
- leaves2 (icosahedron · leafDark)
- leaves3 (icosahedron · leafDark)
- leaves4 (icosahedron · leaf)
- leaves5 (icosahedron · leaf)
- leaves6 (icosahedron · leafLight)
- leaves7 (icosahedron · leafLight)
- leaves8 (icosahedron · leafLight)
- leaves9 (icosahedron · leafLight)

## How to use

Save the code below as `oak-tree.js`, then:

```js
import { createOakTree } from './oak-tree.js';
const model = createOakTree();
scene.add(model);
```

## Code

```js
/**
 * Oak Tree — Codels 3D model library (https://codels.download/models/oak-tree)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,024 · Size (W × H × D): 4.48 × 4.55 × 4.10 m
 *
 * Usage:
 *   import { createOakTree } from './oak-tree.js';
 *   
 *   const model = createOakTree();
 *   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;
}

// 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);
}

export function createOakTree() {
  const root = new THREE.Group();
  root.name = 'OakTree';

  // Materials
  const barkMat = new THREE.MeshStandardMaterial({ name: 'bark', color: 0x6a4a30, roughness: 0.95, flatShading: true });
  const leafMat = new THREE.MeshStandardMaterial({ name: 'leaf', color: 0x4f8a3c, roughness: 0.85, flatShading: true });
  const leafLightMat = new THREE.MeshStandardMaterial({ name: 'leafLight', color: 0x579b4b, roughness: 0.85, flatShading: true });
  const leafDarkMat = new THREE.MeshStandardMaterial({ name: 'leafDark', color: 0x446c2f, roughness: 0.9, flatShading: true });

  // Parts
  const trunk = new THREE.Mesh(lathe([[0, 0], [0.484, 0], [0.3691, 0.22], [0.3086, 0.66], [0.2602, 1.386], [0.2178, 2.5245], [0, 2.5245]], 7), barkMat);
  trunk.name = 'trunk';
  root.add(trunk);
  const root1 = new THREE.Mesh(new THREE.CylinderGeometry(0.0484, 0.1664, 0.5334, 5), barkMat);
  root1.name = 'root1';
  root1.position.set(0.2672, 0.1376, 0.2593);
  root1.rotation.set(deg(61.756), deg(-41.8357), deg(-65.1734));
  root.add(root1);
  const root2 = new THREE.Mesh(new THREE.CylinderGeometry(0.0484, 0.1664, 0.506, 5), barkMat);
  root2.name = 'root2';
  root2.position.set(-0.2242, 0.1376, 0.2788);
  root2.rotation.set(deg(76.239), deg(41.3475), deg(51.3666));
  root.add(root2);
  const root3 = new THREE.Mesh(new THREE.CylinderGeometry(0.0484, 0.1664, 0.5461, 5), barkMat);
  root3.name = 'root3';
  root3.position.set(-0.3168, 0.1376, -0.2081);
  root3.rotation.set(deg(-40.8562), deg(-37.5094), deg(84.7073));
  root.add(root3);
  const root4 = new THREE.Mesh(new THREE.CylinderGeometry(0.0484, 0.1664, 0.5178, 5), barkMat);
  root4.name = 'root4';
  root4.position.set(0.2847, 0.1376, -0.2268);
  root4.rotation.set(deg(-50.7354), deg(40.943), deg(-76.4303));
  root.add(root4);
  const branch1 = new THREE.Mesh(new THREE.CylinderGeometry(0.0545, 0.1513, 1.839, 5), barkMat);
  branch1.name = 'branch1';
  branch1.position.set(0.5375, 2.3984, -0.1326);
  branch1.rotation.set(deg(-8.2997), deg(2.686), deg(-35.8133));
  root.add(branch1);
  const branch2 = new THREE.Mesh(new THREE.CylinderGeometry(0.0545, 0.1513, 1.8104, 5), barkMat);
  branch2.name = 'branch2';
  branch2.position.set(-0.441, 2.3781, 0.3346);
  branch2.rotation.set(deg(21.8085), deg(5.7699), deg(29.319));
  root.add(branch2);
  const branch3 = new THREE.Mesh(new THREE.CylinderGeometry(0.0545, 0.1513, 1.67, 5), barkMat);
  branch3.name = 'branch3';
  branch3.position.set(-0.3419, 2.2665, -0.4354);
  branch3.rotation.set(deg(-31.6931), deg(-7.0126), deg(24.3624));
  root.add(branch3);
  const canopyCore = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(1.2705, 1), 0.1089, 3), leafMat);
  canopyCore.name = 'canopyCore';
  canopyCore.position.set(0, 3.2505, 0);
  canopyCore.scale.set(1.22, 0.8, 1.22);
  root.add(canopyCore);
  const leaves1 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.8709, 1), 0.0871, 93), leafDarkMat);
  leaves1.name = 'leaves1';
  leaves1.position.set(1.4456, 2.8664, -0.1705);
  leaves1.rotation.set(deg(17.3941), deg(42.9491), 0);
  leaves1.scale.set(1, 0.85, 1);
  root.add(leaves1);
  const leaves2 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.8034, 1), 0.0803, 94), leafDarkMat);
  leaves2.name = 'leaves2';
  leaves2.position.set(-1.0134, 2.9916, 0.6871);
  leaves2.rotation.set(deg(56.4261), deg(217.7235), 0);
  leaves2.scale.set(1, 0.85, 1);
  root.add(leaves2);
  const leaves3 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.7707, 1), 0.0771, 95), leafDarkMat);
  leaves3.name = 'leaves3';
  leaves3.position.set(-0.2478, 3.0586, -1.4004);
  leaves3.rotation.set(deg(45.2744), deg(63.4196), 0);
  leaves3.scale.set(1, 0.85, 1);
  root.add(leaves3);
  const leaves4 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.6626, 1), 0.0663, 96), leafMat);
  leaves4.name = 'leaves4';
  leaves4.position.set(0.8877, 3.2109, 1.025);
  leaves4.rotation.set(deg(0.3043), deg(46.7638), 0);
  leaves4.scale.set(1, 0.85, 1);
  root.add(leaves4);
  const leaves5 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.7747, 1), 0.0775, 97), leafMat);
  leaves5.name = 'leaves5';
  leaves5.position.set(-1.4184, 3.2607, -0.3301);
  leaves5.rotation.set(deg(30.9687), deg(172.3031), 0);
  leaves5.scale.set(1, 0.85, 1);
  root.add(leaves5);
  const leaves6 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.7791, 1), 0.0779, 98), leafLightMat);
  leaves6.name = 'leaves6';
  leaves6.position.set(1.0184, 3.3453, -0.586);
  leaves6.rotation.set(deg(44.6369), deg(153.1454), 0);
  leaves6.scale.set(1, 0.85, 1);
  root.add(leaves6);
  const leaves7 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.7113, 1), 0.0711, 99), leafLightMat);
  leaves7.name = 'leaves7';
  leaves7.position.set(-0.1581, 3.5786, 1.297);
  leaves7.rotation.set(deg(16.0568), deg(101.0846), 0);
  leaves7.scale.set(1, 0.85, 1);
  root.add(leaves7);
  const leaves8 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.6814, 1), 0.0681, 100), leafLightMat);
  leaves8.name = 'leaves8';
  leaves8.position.set(-0.3694, 3.5426, -0.9875);
  leaves8.rotation.set(deg(20.2814), deg(90.0089), 0);
  leaves8.scale.set(1, 0.85, 1);
  root.add(leaves8);
  const leaves9 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.8242, 1), 0.0824, 101), leafLightMat);
  leaves9.name = 'leaves9';
  leaves9.position.set(0.9016, 3.7622, 0.2995);
  leaves9.rotation.set(deg(33.7375), deg(214.1656), 0);
  leaves9.scale.set(1, 0.85, 1);
  root.add(leaves9);

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

export default createOakTree;
```

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