# Kite Shield

> A knightly heater / kite shield (about 0.85 m tall) with a beveled wooden face, iron rim and a painted heraldic design — vertical stripe, chevron or cross. It stands upright on its point facing +Z. Perfect for medieval fantasy RPGs, castle armories, banners and loot tables.

![Kite Shield preview](https://codels.download/m/kite-shield.png)

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

## Facts

- Category: Items & Weapons › Weapons
- Size (W × H × D): 0.64 × 0.90 × 0.06 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 864 · Meshes: 5 · Materials: 4
- License: CC0-1.0 (Codels built-in)
- Tags: heater-shield, heraldry, kite-shield, knight, shield, low-poly, stylized, fantasy, medieval, castle, adventure, rpg, decoration, weapon, metal, wood, game-ready, mobile-friendly, parametric, color-blue, color-gray, size-small, poly-low
- Page: https://codels.download/models/kite-shield

## Files

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

## Parameters

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

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `field` | color | #rrggbb | #2b5791 | #2b5791 |
| `paint` | color | #rrggbb | #e9d9a6 | #e9d9a6 |
| `design` | select | stripe \| chevron \| cross | chevron | chevron |
| `boss` | boolean | true \| false | false | false |

## Parts

- board (extrude · field)
- rim (tube · iron)
- paint (extrude · paint)
- strap1 (box · leather)
- strap2 (box · leather)

## How to use

Save the code below as `kite-shield.js`, then:

```js
import { createKiteShield } from './kite-shield.js';
const model = createKiteShield();
scene.add(model);
```

## Code

```js
/**
 * Kite Shield — Codels 3D model library (https://codels.download/models/kite-shield)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 864 · Size (W × H × D): 0.64 × 0.90 × 0.06 m
 *
 * Usage:
 *   import { createKiteShield } from './kite-shield.js';
 *   
 *   const model = createKiteShield();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

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

// 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 createKiteShield() {
  const root = new THREE.Group();
  root.name = 'KiteShield';

  // Materials
  const fieldMat = new THREE.MeshStandardMaterial({ name: 'field', color: 0x2b5791, roughness: 0.75, flatShading: true });
  const paintMat = new THREE.MeshStandardMaterial({ name: 'paint', color: 0xe9d9a6, roughness: 0.75, flatShading: true });
  const ironMat = new THREE.MeshStandardMaterial({ name: 'iron', color: 0x8a929c, roughness: 0.4, metalness: 0.7, flatShading: true });
  const leatherMat = new THREE.MeshStandardMaterial({ name: 'leather', color: 0x5b3a22, roughness: 0.9, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(0.2, 0.04, 0.012);

  // Parts
  const board = new THREE.Mesh(extrude([[0.28, 0.8005], [0.1867, 0.8255], [0.0933, 0.8405], [0, 0.8455], [-0.0933, 0.8405], [-0.1867, 0.8255], [-0.28, 0.8005], [-0.28, 0.6005], [-0.2739, 0.5031], [-0.2558, 0.4071], [-0.2258, 0.3141], [-0.1845, 0.2256], [-0.1326, 0.1429], [-0.0708, 0.0673], [0, 0], [0.0708, 0.0673], [0.1326, 0.1429], [0.1845, 0.2256], [0.2258, 0.3141], [0.2558, 0.4071], [0.2739, 0.5031], [0.28, 0.6005]], 0.024, [], [0.01, 0.012, 1]), fieldMat);
  board.name = 'board';
  board.position.set(0, 0.017, 0);
  root.add(board);
  const rim = new THREE.Mesh(tube([[0.2866, 0.8237, 0], [0.1916, 0.8501, 0], [0.096, 0.8661, 0], [0, 0.8715, 0], [-0.096, 0.8661, 0], [-0.1916, 0.8501, 0], [-0.2866, 0.8237, 0], [-0.2888, 0.6194, 0], [-0.2828, 0.5188, 0], [-0.2637, 0.4199, 0], [-0.2322, 0.3248, 0], [-0.1891, 0.2349, 0], [-0.1354, 0.1514, 0], [-0.0721, 0.0754, 0], [0, 0.008, 0], [0.0721, 0.0754, 0], [0.1354, 0.1514, 0], [0.1891, 0.2349, 0], [0.2322, 0.3248, 0], [0.2637, 0.4199, 0], [0.2828, 0.5188, 0], [0.2888, 0.6194, 0]], 0.021, 64, 5, true), ironMat);
  rim.name = 'rim';
  root.add(rim);
  const paint = new THREE.Mesh(extrude([[-0.2671, 0.4668], [0, 0.7205], [0.2671, 0.4668], [0.2558, 0.4071], [0.2361, 0.3462], [0, 0.5705], [-0.2361, 0.3462], [-0.2558, 0.4071]], 0.004), paintMat);
  paint.name = 'paint';
  paint.position.set(0, 0.017, 0.023);
  root.add(paint);
  const strap1 = new THREE.Mesh(boxGeo, leatherMat);
  strap1.name = 'strap1';
  strap1.position.set(0, 0.4674, -0.026);
  root.add(strap1);
  const strap2 = new THREE.Mesh(boxGeo, leatherMat);
  strap2.name = 'strap2';
  strap2.position.set(0, 0.6975, -0.026);
  root.add(strap2);

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

export default createKiteShield;
```

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