# Pirate

> A swashbuckling, chibi-proportioned low-poly pirate captain with a gold-trimmed tricorn hat and skull badge, eye patch, bushy beard, gold earring, a long red coat with brass buttons and wide cuffs, a big-buckled belt and a curved cutlass raised in the right hand. Toggle the wooden peg leg and the cutlass. Head, arms and legs (legR becomes the peg) are pivoted groups for walk and attack animations in pirate, island and treasure-hunt games.

![Pirate preview](https://codels.download/m/pirate.png)

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

## Facts

- Category: Characters › Humanoids
- Size (W × H × D): 0.92 × 1.79 × 1.17 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 1,028 · Meshes: 71 · Materials: 10
- License: CC0-1.0 (Codels built-in)
- Tags: captain, sword, blocky, cartoon, low-poly, nautical, pirate, tropical, beach, ocean, adventure, rpg, character, enemy, npc, game-ready, mobile-friendly, parametric, color-gray, multicolor, color-orange, color-red, size-medium, poly-low
- Page: https://codels.download/models/pirate

## Files

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

## Parameters

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

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `coat` | color | #rrggbb | #b2272f | #b2272f |
| `beard` | color | #rrggbb | #2b1d17 | #2b1d17 |
| `pegLeg` | boolean | true \| false | true | true |
| `cutlass` | boolean | true \| false | true | true |

## Parts

- legL (group)
  - trouserL (box · coatDark)
  - bootL (box · black)
  - bootCuffL (box · black)
  - bootToeL (box · black)
- legR (group)
  - pegThigh (box · coatDark)
  - pegCuff (cylinder · wood)
  - peg (cylinder · wood)
  - pegTip (cylinder · black)
- body (group)
  - coat (box · coat)
  - shirtV (extrude · shirt)
  - ruffle (box · shirt)
  - lapelL (box · coatDark)
  - button (box · gold)
  - button (box · gold)
  - lapelR (box · coatDark)
  - button (box · gold)
  - button (box · gold)
  - belt (box · black)
  - buckle (box · gold)
  - buckleHole (box · black)
  - coatTailBack (box · coat)
  - coatTailL (box · coat)
  - coatFrontL (box · coat)
  - coatEdgeL (box · gold)
  - coatTailR (box · coat)
  - coatFrontR (box · coat)
  - coatEdgeR (box · gold)
- armL (group)
  - sleeveL (box · coat)
  - cuffL (box · coatDark)
  - cuffTrimL (box · gold)
  - handL (box · skin)
- armR (group)
  - sleeveR (box · coat)
  - cuffR (box · coatDark)
  - cuffTrimR (box · gold)
  - handR (box · skin)

## How to use

Save the code below as `pirate.js`, then:

```js
import { createPirate } from './pirate.js';
const model = createPirate();
scene.add(model);
```

## Code

```js
/**
 * Pirate — Codels 3D model library (https://codels.download/models/pirate)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,028 · Size (W × H × D): 0.92 × 1.79 × 1.17 m
 *
 * Usage:
 *   import { createPirate } from './pirate.js';
 *   
 *   const model = createPirate();
 *   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 createPirate() {
  const root = new THREE.Group();
  root.name = 'Pirate';

  // Materials
  const skinMat = new THREE.MeshStandardMaterial({ name: 'skin', color: 0xeebc93, roughness: 0.8, flatShading: true });
  const coatMat = new THREE.MeshStandardMaterial({ name: 'coat', color: 0xb2272f, roughness: 0.85, flatShading: true });
  const coatDarkMat = new THREE.MeshStandardMaterial({ name: 'coatDark', color: 0x62151a, roughness: 0.85, flatShading: true });
  const shirtMat = new THREE.MeshStandardMaterial({ name: 'shirt', color: 0xf1ead9, roughness: 0.9, flatShading: true });
  const hatMat = new THREE.MeshStandardMaterial({ name: 'hat', color: 0x2c2830, roughness: 0.75, flatShading: true });
  const blackMat = new THREE.MeshStandardMaterial({ name: 'black', color: 0x1e1b1f, roughness: 0.6, flatShading: true });
  const goldMat = new THREE.MeshStandardMaterial({ name: 'gold', color: 0xf0c04a, roughness: 0.3, metalness: 0.65, flatShading: true });
  const beardMat = new THREE.MeshStandardMaterial({ name: 'beard', color: 0x2b1d17, roughness: 0.95, flatShading: true });
  const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0x8a5c37, roughness: 0.85, flatShading: true });
  const bladeMat = new THREE.MeshStandardMaterial({ name: 'blade', color: 0xdfe5ec, roughness: 0.2, metalness: 0.8, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(0.05, 0.33, 0.012);
  const boxGeo2 = new THREE.BoxGeometry(0.035, 0.035, 0.02);
  const boxGeo3 = new THREE.BoxGeometry(0.04, 0.32, 0.3);
  const boxGeo4 = new THREE.BoxGeometry(0.13, 0.32, 0.04);
  const boxGeo5 = new THREE.BoxGeometry(0.02, 0.32, 0.045);
  const boxGeo6 = new THREE.BoxGeometry(0.16, 0.36, 0.18);
  const boxGeo7 = new THREE.BoxGeometry(0.2, 0.12, 0.21);
  const boxGeo8 = new THREE.BoxGeometry(0.205, 0.025, 0.215);
  const boxGeo9 = new THREE.BoxGeometry(0.11, 0.11, 0.11);
  const boxGeo10 = new THREE.BoxGeometry(0.13, 0.045, 0.05);
  const boxGeo11 = new THREE.BoxGeometry(0.04, 0.06, 0.045);
  const boxGeo12 = new THREE.BoxGeometry(0.6942, 0.2, 0.035);
  const boxGeo13 = new THREE.BoxGeometry(0.6942, 0.025, 0.04);
  const boxGeo14 = new THREE.BoxGeometry(0.12, 0.022, 0.01);
  const boxGeo15 = new THREE.BoxGeometry(0.014, 0.014, 0.01);

  // Parts
  const legL = new THREE.Group();
  legL.name = 'legL';
  legL.position.set(0.105, 0.58, 0);
  root.add(legL);
  const trouserL = new THREE.Mesh(new THREE.BoxGeometry(0.19, 0.32, 0.21), coatDarkMat);
  trouserL.name = 'trouserL';
  trouserL.position.set(0, -0.16, 0);
  legL.add(trouserL);
  const bootL = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.26, 0.22), blackMat);
  bootL.name = 'bootL';
  bootL.position.set(0, -0.45, 0.005);
  legL.add(bootL);
  const bootCuffL = new THREE.Mesh(new THREE.BoxGeometry(0.24, 0.07, 0.25), blackMat);
  bootCuffL.name = 'bootCuffL';
  bootCuffL.position.set(0, -0.31, 0.005);
  bootCuffL.rotation.set(deg(-6), 0, 0);
  legL.add(bootCuffL);
  const bootToeL = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.06, 0.08), blackMat);
  bootToeL.name = 'bootToeL';
  bootToeL.position.set(0, -0.55, 0.14);
  legL.add(bootToeL);
  const legR = new THREE.Group();
  legR.name = 'legR';
  legR.position.set(-0.105, 0.58, 0);
  root.add(legR);
  const pegThigh = new THREE.Mesh(new THREE.BoxGeometry(0.19, 0.24, 0.21), coatDarkMat);
  pegThigh.name = 'pegThigh';
  pegThigh.position.set(0, -0.12, 0);
  legR.add(pegThigh);
  const pegCuff = new THREE.Mesh(new THREE.CylinderGeometry(0.075, 0.08, 0.07, 8), woodMat);
  pegCuff.name = 'pegCuff';
  pegCuff.position.set(0, -0.27, 0);
  legR.add(pegCuff);
  const peg = new THREE.Mesh(new THREE.CylinderGeometry(0.055, 0.032, 0.28, 7), woodMat);
  peg.name = 'peg';
  peg.position.set(0, -0.44, 0);
  legR.add(peg);
  const pegTip = new THREE.Mesh(new THREE.CylinderGeometry(0.04, 0.04, 0.03, 7), blackMat);
  pegTip.name = 'pegTip';
  pegTip.position.set(0, -0.565, 0);
  legR.add(pegTip);
  const body = new THREE.Group();
  body.name = 'body';
  root.add(body);
  const coat = new THREE.Mesh(new THREE.BoxGeometry(0.47, 0.56, 0.28), coatMat);
  coat.name = 'coat';
  coat.position.set(0, 0.82, 0);
  body.add(coat);
  const shirtV = new THREE.Mesh(extrude([[-0.12, 0], [0.12, 0], [0, -0.3]], 0.01), shirtMat);
  shirtV.name = 'shirtV';
  shirtV.position.set(0, 1.1, 0.142);
  body.add(shirtV);
  const ruffle = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.1, 0.03), shirtMat);
  ruffle.name = 'ruffle';
  ruffle.position.set(0, 1, 0.152);
  ruffle.rotation.set(0, 0, deg(45));
  body.add(ruffle);
  const lapelL = new THREE.Mesh(boxGeo, coatDarkMat);
  lapelL.name = 'lapelL';
  lapelL.position.set(0.065, 0.97, 0.146);
  lapelL.rotation.set(0, 0, deg(21));
  body.add(lapelL);
  const button = new THREE.Mesh(boxGeo2, goldMat);
  button.name = 'button';
  button.position.set(0.155, 0.89, 0.148);
  body.add(button);
  const button2 = new THREE.Mesh(boxGeo2, goldMat);
  button2.name = 'button';
  button2.position.set(0.155, 0.77, 0.148);
  body.add(button2);
  const lapelR = new THREE.Mesh(boxGeo, coatDarkMat);
  lapelR.name = 'lapelR';
  lapelR.position.set(-0.065, 0.97, 0.146);
  lapelR.rotation.set(0, 0, deg(-21));
  body.add(lapelR);
  const button3 = new THREE.Mesh(boxGeo2, goldMat);
  button3.name = 'button';
  button3.position.set(-0.155, 0.89, 0.148);
  body.add(button3);
  const button4 = new THREE.Mesh(boxGeo2, goldMat);
  button4.name = 'button';
  button4.position.set(-0.155, 0.77, 0.148);
  body.add(button4);
  const belt = new THREE.Mesh(new THREE.BoxGeometry(0.482, 0.08, 0.292), blackMat);
  belt.name = 'belt';
  belt.position.set(0, 0.63, 0);
  body.add(belt);
  const buckle = new THREE.Mesh(new THREE.BoxGeometry(0.12, 0.1, 0.02), goldMat);
  buckle.name = 'buckle';
  buckle.position.set(0, 0.63, 0.154);
  body.add(buckle);
  const buckleHole = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.05, 0.022), blackMat);
  buckleHole.name = 'buckleHole';
  buckleHole.position.set(0, 0.63, 0.156);
  body.add(buckleHole);
  const coatTailBack = new THREE.Mesh(new THREE.BoxGeometry(0.51, 0.32, 0.04), coatMat);
  coatTailBack.name = 'coatTailBack';
  coatTailBack.position.set(0, 0.44, -0.14);
  coatTailBack.rotation.set(deg(-8), 0, 0);
  body.add(coatTailBack);
  const coatTailL = new THREE.Mesh(boxGeo3, coatMat);
  coatTailL.name = 'coatTailL';
  coatTailL.position.set(0.245, 0.44, -0.005);
  coatTailL.rotation.set(0, 0, deg(7));
  body.add(coatTailL);
  const coatFrontL = new THREE.Mesh(boxGeo4, coatMat);
  coatFrontL.name = 'coatFrontL';
  coatFrontL.position.set(0.18, 0.44, 0.14);
  coatFrontL.rotation.set(deg(8), 0, deg(4));
  body.add(coatFrontL);
  const coatEdgeL = new THREE.Mesh(boxGeo5, goldMat);
  coatEdgeL.name = 'coatEdgeL';
  coatEdgeL.position.set(0.11, 0.44, 0.142);
  coatEdgeL.rotation.set(deg(8), 0, deg(4));
  body.add(coatEdgeL);
  const coatTailR = new THREE.Mesh(boxGeo3, coatMat);
  coatTailR.name = 'coatTailR';
  coatTailR.position.set(-0.245, 0.44, -0.005);
  coatTailR.rotation.set(0, 0, deg(-7));
  body.add(coatTailR);
  const coatFrontR = new THREE.Mesh(boxGeo4, coatMat);
  coatFrontR.name = 'coatFrontR';
  coatFrontR.position.set(-0.18, 0.44, 0.14);
  coatFrontR.rotation.set(deg(8), 0, deg(-4));
  body.add(coatFrontR);
  const coatEdgeR = new THREE.Mesh(boxGeo5, goldMat);
  coatEdgeR.name = 'coatEdgeR';
  coatEdgeR.position.set(-0.11, 0.44, 0.142);
  coatEdgeR.rotation.set(deg(8), 0, deg(-4));
  body.add(coatEdgeR);
  const armL = new THREE.Group();
  armL.name = 'armL';
  armL.position.set(0.315, 1.04, 0);
  armL.rotation.set(0, 0, deg(7));
  root.add(armL);
  const sleeveL = new THREE.Mesh(boxGeo6, coatMat);
  sleeveL.name = 'sleeveL';
  sleeveL.position.set(0, -0.16, 0);
  armL.add(sleeveL);
  const cuffL = new THREE.Mesh(boxGeo7, coatDarkMat);
  cuffL.name = 'cuffL';
  cuffL.position.set(0, -0.36, 0);
  armL.add(cuffL);
  const cuffTrimL = new THREE.Mesh(boxGeo8, goldMat);
  cuffTrimL.name = 'cuffTrimL';
  cuffTrimL.position.set(0, -0.31, 0);
  armL.add(cuffTrimL);
  const handL = new THREE.Mesh(boxGeo9, skinMat);
  handL.name = 'handL';
  handL.position.set(0, -0.47, 0);
  armL.add(handL);
  const armR = new THREE.Group();
  armR.name = 'armR';
  armR.position.set(-0.315, 1.04, 0);
  armR.rotation.set(deg(-58), 0, deg(-6));
  root.add(armR);
  const sleeveR = new THREE.Mesh(boxGeo6, coatMat);
  sleeveR.name = 'sleeveR';
  sleeveR.position.set(0, -0.16, 0);
  armR.add(sleeveR);
  const cuffR = new THREE.Mesh(boxGeo7, coatDarkMat);
  cuffR.name = 'cuffR';
  cuffR.position.set(0, -0.36, 0);
  armR.add(cuffR);
  const cuffTrimR = new THREE.Mesh(boxGeo8, goldMat);
  cuffTrimR.name = 'cuffTrimR';
  cuffTrimR.position.set(0, -0.31, 0);
  armR.add(cuffTrimR);
  const handR = new THREE.Mesh(boxGeo9, skinMat);
  handR.name = 'handR';
  handR.position.set(0, -0.47, 0);
  armR.add(handR);
  const cutlass = new THREE.Group();
  cutlass.name = 'cutlass';
  cutlass.position.set(0, -0.47, 0);
  cutlass.rotation.set(deg(95), 0, 0);
  armR.add(cutlass);
  const grip = new THREE.Mesh(new THREE.BoxGeometry(0.04, 0.13, 0.04), blackMat);
  grip.name = 'grip';
  cutlass.add(grip);
  const pommel = new THREE.Mesh(new THREE.BoxGeometry(0.055, 0.04, 0.055), goldMat);
  pommel.name = 'pommel';
  pommel.position.set(0, -0.08, 0);
  cutlass.add(pommel);
  const crossguard = new THREE.Mesh(new THREE.BoxGeometry(0.16, 0.035, 0.06), goldMat);
  crossguard.name = 'crossguard';
  crossguard.position.set(0, 0.075, 0);
  cutlass.add(crossguard);
  const knuckleBow = new THREE.Mesh(new THREE.BoxGeometry(0.025, 0.14, 0.025), goldMat);
  knuckleBow.name = 'knuckleBow';
  knuckleBow.position.set(0.075, 0, 0);
  cutlass.add(knuckleBow);
  const blade = new THREE.Mesh(extrude([[-0.028, 0], [0.032, 0], [0.046, 0.2], [0.05, 0.38], [0.035, 0.52], [0, 0.62], [-0.045, 0.68], [-0.032, 0.58], [-0.018, 0.47], [-0.016, 0.32], [-0.022, 0.16]], 0.018), bladeMat);
  blade.name = 'blade';
  blade.position.set(0, 0.09, 0);
  cutlass.add(blade);
  const head = new THREE.Group();
  head.name = 'head';
  head.position.set(0, 1.08, 0);
  root.add(head);
  const skull = new THREE.Mesh(new THREE.BoxGeometry(0.46, 0.46, 0.46), skinMat);
  skull.name = 'skull';
  skull.position.set(0, 0.25, 0);
  head.add(skull);
  const eyeL = new THREE.Mesh(new THREE.BoxGeometry(0.055, 0.075, 0.01), blackMat);
  eyeL.name = 'eyeL';
  eyeL.position.set(0.095, 0.27, 0.233);
  head.add(eyeL);
  const eyeShineL = new THREE.Mesh(new THREE.BoxGeometry(0.0209, 0.0209, 0.006), shirtMat);
  eyeShineL.name = 'eyeShineL';
  eyeShineL.position.set(0.1027, 0.2865, 0.239);
  head.add(eyeShineL);
  const eyePatch = new THREE.Mesh(new THREE.BoxGeometry(0.1, 0.09, 0.016), blackMat);
  eyePatch.name = 'eyePatch';
  eyePatch.position.set(-0.095, 0.27, 0.238);
  head.add(eyePatch);
  const patchStrap = new THREE.Mesh(new THREE.BoxGeometry(0.36, 0.022, 0.01), blackMat);
  patchStrap.name = 'patchStrap';
  patchStrap.position.set(0.02, 0.36, 0.235);
  patchStrap.rotation.set(0, 0, deg(-27));
  head.add(patchStrap);
  const patchStrapSide = new THREE.Mesh(new THREE.BoxGeometry(0.01, 0.022, 0.345), blackMat);
  patchStrapSide.name = 'patchStrapSide';
  patchStrapSide.position.set(-0.233, 0.29, -0.05);
  patchStrapSide.rotation.set(deg(-12), 0, 0);
  head.add(patchStrapSide);
  const nose = new THREE.Mesh(new THREE.BoxGeometry(0.08, 0.09, 0.07), skinMat);
  nose.name = 'nose';
  nose.position.set(0, 0.21, 0.26);
  head.add(nose);
  const beardJaw = new THREE.Mesh(new THREE.BoxGeometry(0.472, 0.16, 0.32), beardMat);
  beardJaw.name = 'beardJaw';
  beardJaw.position.set(0, 0.094, 0.076);
  head.add(beardJaw);
  const beardChin = new THREE.Mesh(extrude([[-0.2, 0], [0.2, 0], [0.12, -0.1], [0, -0.15], [-0.12, -0.1]], 0.14), beardMat);
  beardChin.name = 'beardChin';
  beardChin.position.set(0, 0.04, 0.18);
  head.add(beardChin);
  const mouth = new THREE.Mesh(new THREE.BoxGeometry(0.07, 0.03, 0.012), coatDarkMat);
  mouth.name = 'mouth';
  mouth.position.set(0, 0.13, 0.24);
  head.add(mouth);
  const mustacheL = new THREE.Mesh(boxGeo10, beardMat);
  mustacheL.name = 'mustacheL';
  mustacheL.position.set(0.07, 0.16, 0.255);
  mustacheL.rotation.set(0, 0, deg(12));
  head.add(mustacheL);
  const mustacheCurlL = new THREE.Mesh(boxGeo11, beardMat);
  mustacheCurlL.name = 'mustacheCurlL';
  mustacheCurlL.position.set(0.14, 0.185, 0.255);
  mustacheCurlL.rotation.set(0, 0, deg(-20));
  head.add(mustacheCurlL);
  const mustacheR = new THREE.Mesh(boxGeo10, beardMat);
  mustacheR.name = 'mustacheR';
  mustacheR.position.set(-0.07, 0.16, 0.255);
  mustacheR.rotation.set(0, 0, deg(-12));
  head.add(mustacheR);
  const mustacheCurlR = new THREE.Mesh(boxGeo11, beardMat);
  mustacheCurlR.name = 'mustacheCurlR';
  mustacheCurlR.position.set(-0.14, 0.185, 0.255);
  mustacheCurlR.rotation.set(0, 0, deg(20));
  head.add(mustacheCurlR);
  const hairBack = new THREE.Mesh(new THREE.BoxGeometry(0.472, 0.3, 0.14), beardMat);
  hairBack.name = 'hairBack';
  hairBack.position.set(0, 0.27, -0.166);
  head.add(hairBack);
  const ponytail = new THREE.Mesh(new THREE.BoxGeometry(0.07, 0.16, 0.07), beardMat);
  ponytail.name = 'ponytail';
  ponytail.position.set(0, 0.13, -0.255);
  ponytail.rotation.set(deg(15), 0, 0);
  head.add(ponytail);
  const earring = new THREE.Mesh(new THREE.TorusGeometry(0.035, 0.009, 4, 10), goldMat);
  earring.name = 'earring';
  earring.position.set(0.242, 0.13, -0.02);
  earring.rotation.set(0, deg(90), 0);
  head.add(earring);
  const tricorn = new THREE.Group();
  tricorn.name = 'tricorn';
  tricorn.position.set(0, 0.44, -0.01);
  tricorn.rotation.set(deg(-6), 0, 0);
  head.add(tricorn);
  const hatBrim = new THREE.Mesh(extrude([[0, 0.4], [0.43, -0.22], [-0.43, -0.22]], 0.03), hatMat);
  hatBrim.name = 'hatBrim';
  hatBrim.position.set(0, 0.015, 0);
  hatBrim.rotation.set(deg(90), 0, 0);
  tricorn.add(hatBrim);
  const hatCrown = new THREE.Mesh(new THREE.CylinderGeometry(0.2121, 0.297, 0.15, 4, 1, false, Math.PI / 4), hatMat);
  hatCrown.name = 'hatCrown';
  hatCrown.position.set(0, 0.075, -0.01);
  tricorn.add(hatCrown);
  const hatDome = new THREE.Mesh(new THREE.SphereGeometry(0.2, 8, 3, 0, Math.PI * 2, 0, Math.PI / 2), hatMat);
  hatDome.name = 'hatDome';
  hatDome.position.set(0, 0.14, -0.01);
  hatDome.scale.set(1, 0.55, 1);
  tricorn.add(hatDome);
  const hatFlap1 = new THREE.Mesh(boxGeo12, hatMat);
  hatFlap1.name = 'hatFlap1';
  hatFlap1.position.set(0.2064, 0.12, 0.0864);
  hatFlap1.rotation.set(deg(20.4541), deg(53.4905), deg(-16.6877));
  tricorn.add(hatFlap1);
  const hatTrim1 = new THREE.Mesh(boxGeo13, goldMat);
  hatTrim1.name = 'hatTrim1';
  hatTrim1.position.set(0.2235, 0.2178, 0.0982);
  hatTrim1.rotation.set(deg(20.4541), deg(53.4905), deg(-16.6877));
  tricorn.add(hatTrim1);
  const hatFlap2 = new THREE.Mesh(new THREE.BoxGeometry(0.7912, 0.2, 0.035), hatMat);
  hatFlap2.name = 'hatFlap2';
  hatFlap2.position.set(0, 0.12, -0.2112);
  hatFlap2.rotation.set(deg(168), 0, deg(180));
  tricorn.add(hatFlap2);
  const hatTrim2 = new THREE.Mesh(new THREE.BoxGeometry(0.7912, 0.025, 0.04), goldMat);
  hatTrim2.name = 'hatTrim2';
  hatTrim2.position.set(0, 0.2178, -0.232);
  hatTrim2.rotation.set(deg(168), 0, deg(180));
  tricorn.add(hatTrim2);
  const hatFlap3 = new THREE.Mesh(boxGeo12, hatMat);
  hatFlap3.name = 'hatFlap3';
  hatFlap3.position.set(-0.2064, 0.12, 0.0864);
  hatFlap3.rotation.set(deg(20.4541), deg(-53.4905), deg(16.6877));
  tricorn.add(hatFlap3);
  const hatTrim3 = new THREE.Mesh(boxGeo13, goldMat);
  hatTrim3.name = 'hatTrim3';
  hatTrim3.position.set(-0.2235, 0.2178, 0.0982);
  hatTrim3.rotation.set(deg(20.4541), deg(-53.4905), deg(16.6877));
  tricorn.add(hatTrim3);
  const hatBadge = new THREE.Group();
  hatBadge.name = 'hatBadge';
  hatBadge.position.set(0, 0.13, 0.385);
  hatBadge.rotation.set(deg(-12), 0, 0);
  tricorn.add(hatBadge);
  const boneA = new THREE.Mesh(boxGeo14, shirtMat);
  boneA.name = 'boneA';
  boneA.rotation.set(0, 0, deg(35));
  hatBadge.add(boneA);
  const boneB = new THREE.Mesh(boxGeo14, shirtMat);
  boneB.name = 'boneB';
  boneB.rotation.set(0, 0, deg(-35));
  hatBadge.add(boneB);
  const skullBadge = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.055, 0.02), shirtMat);
  skullBadge.name = 'skullBadge';
  skullBadge.position.set(0, 0.008, 0.008);
  hatBadge.add(skullBadge);
  const skullEye = new THREE.Mesh(boxGeo15, blackMat);
  skullEye.name = 'skullEye';
  skullEye.position.set(0.013, 0.013, 0.02);
  hatBadge.add(skullEye);
  const skullEye2 = new THREE.Mesh(boxGeo15, blackMat);
  skullEye2.name = 'skullEye';
  skullEye2.position.set(-0.013, 0.013, 0.02);
  hatBadge.add(skullEye2);

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

export default createPirate;
```

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