# Aviator Goggles

> Stylized aviator / steampunk goggles resting on the ground as if worn: two round metal-rimmed eye cups with tinted, softly glowing lenses, a bridge, padded leather and a looped strap with a buckle. The steampunk style adds rivets, side vents and a flip-down magnifier loupe. Real-world size (about 0.2 m across). Great as an equipment pickup, inventory icon or prop for pilots, inventors and explorers.

![Aviator Goggles preview](https://codels.download/m/goggles.png)

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

## Facts

- Category: Items & Weapons › Equipment
- Size (W × H × D): 0.19 × 0.09 × 0.23 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 1,476 · Meshes: 38 · Materials: 6
- License: CC0-1.0 (Codels built-in)
- Tags: goggles, cartoon, low-poly, stylized, fantasy, steampunk, adventure, rpg, equipment, pickup, prop, glass, leather, metal, emissive, game-ready, mobile-friendly, parametric, color-brown, color-orange, size-tiny, poly-low
- Page: https://codels.download/models/goggles

## Files

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

## Parameters

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

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `style` | select | steampunk \| aviator | steampunk | steampunk |
| `lens` | color | #rrggbb | #e8762c | #e8762c |
| `frame` | color | #rrggbb | #c99a3c | #c99a3c |
| `strap` | color | #rrggbb | #6b4527 | #6b4527 |

## Parts

- goggles (group)
  - cupR (cylinder · pad)
  - paddingR (torus · pad)
  - bezelR (cylinder · frame)
  - rimR (torus · frame)
  - lensR (sphere · lens)
  - glintR (box · glint)
  - rivetR1 (octahedron · frame)
  - rivetR2 (octahedron · frame)
  - rivetR3 (octahedron · frame)
  - rivetR4 (octahedron · frame)
  - rivetR5 (octahedron · frame)
  - rivetR6 (octahedron · frame)
  - ventR (cylinder · frame)
  - ventGrilleR (cylinder · dark)
  - cupL (cylinder · pad)
  - paddingL (torus · pad)
  - bezelL (cylinder · frame)
  - rimL (torus · frame)
  - lensL (sphere · lens)
  - glintL (box · glint)
  - rivetL1 (octahedron · frame)
  - rivetL2 (octahedron · frame)
  - rivetL3 (octahedron · frame)
  - rivetL4 (octahedron · frame)
  - rivetL5 (octahedron · frame)
  - rivetL6 (octahedron · frame)
  - ventL (cylinder · frame)
  - ventGrilleL (cylinder · dark)
  - bridge (tube · frame)
  - loupeHinge (sphere · frame)
  - loupe (group)
    - loupeArm (box · frame)
    - loupeRim (torus · frame)
    - loupeLens (cylinder · lens)
  - strapPivot (group)
    - strap (lathe · strap)
    - buckle (box · frame)
    - buckleTongue (box · strap)
  - bracketR (box · frame)

## How to use

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

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

## Code

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

  // Materials
  const frameMat = new THREE.MeshStandardMaterial({ name: 'frame', color: 0xc99a3c, roughness: 0.32, metalness: 0.8, flatShading: true });
  const strapMat = new THREE.MeshStandardMaterial({ name: 'strap', color: 0x6b4527, roughness: 0.85, flatShading: true });
  const padMat = new THREE.MeshStandardMaterial({ name: 'pad', color: 0x3b2615, roughness: 0.9, flatShading: true });
  const lensMat = new THREE.MeshStandardMaterial({ name: 'lens', color: 0xe8762c, roughness: 0.08, metalness: 0.3, emissive: 0xe8762c, emissiveIntensity: 0.22 });
  const glintMat = new THREE.MeshStandardMaterial({ name: 'glint', color: 0xffffff, roughness: 0.2, emissive: 0xffffff, emissiveIntensity: 0.6, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x1d1a17, roughness: 0.9, flatShading: true });

  // Shared geometries
  const cylinderGeo = new THREE.CylinderGeometry(0.032, 0.036, 0.03, 12);
  const torusGeo = new THREE.TorusGeometry(0.032, 0.007, 4, 12);
  const cylinderGeo2 = new THREE.CylinderGeometry(0.037, 0.037, 0.014, 14);
  const torusGeo2 = new THREE.TorusGeometry(0.03, 0.0055, 4, 14);
  const sphereGeo = new THREE.SphereGeometry(0.028, 14, 3, 0, Math.PI * 2, 0, Math.PI / 2);
  const boxGeo = new THREE.BoxGeometry(0.016, 0.004, 0.002);
  const octahedronGeo = new THREE.OctahedronGeometry(0.0035, 0);
  const cylinderGeo3 = new THREE.CylinderGeometry(0.012, 0.012, 0.008, 8);
  const cylinderGeo4 = new THREE.CylinderGeometry(0.007, 0.007, 0.004, 8);
  const boxGeo2 = new THREE.BoxGeometry(0.008, 0.026, 0.016);

  // Parts
  const goggles = new THREE.Group();
  goggles.name = 'goggles';
  goggles.position.set(0, 0.0443, 0);
  root.add(goggles);
  const cupR = new THREE.Mesh(cylinderGeo, padMat);
  cupR.name = 'cupR';
  cupR.position.set(0.043, 0, 0.052);
  cupR.rotation.set(deg(90), 0, 0);
  goggles.add(cupR);
  const paddingR = new THREE.Mesh(torusGeo, padMat);
  paddingR.name = 'paddingR';
  paddingR.position.set(0.043, 0, 0.038);
  goggles.add(paddingR);
  const bezelR = new THREE.Mesh(cylinderGeo2, frameMat);
  bezelR.name = 'bezelR';
  bezelR.position.set(0.043, 0, 0.07);
  bezelR.rotation.set(deg(90), 0, 0);
  goggles.add(bezelR);
  const rimR = new THREE.Mesh(torusGeo2, frameMat);
  rimR.name = 'rimR';
  rimR.position.set(0.043, 0, 0.077);
  goggles.add(rimR);
  const lensR = new THREE.Mesh(sphereGeo, lensMat);
  lensR.name = 'lensR';
  lensR.position.set(0.043, 0, 0.075);
  lensR.rotation.set(deg(90), 0, 0);
  lensR.scale.set(1, 0.32, 1);
  goggles.add(lensR);
  const glintR = new THREE.Mesh(boxGeo, glintMat);
  glintR.name = 'glintR';
  glintR.position.set(0.033, 0.012, 0.0835);
  glintR.rotation.set(deg(-18), deg(16), deg(40));
  goggles.add(glintR);
  const rivetR1 = new THREE.Mesh(octahedronGeo, frameMat);
  rivetR1.name = 'rivetR1';
  rivetR1.position.set(0.0759, 0.019, 0.07);
  goggles.add(rivetR1);
  const rivetR2 = new THREE.Mesh(octahedronGeo, frameMat);
  rivetR2.name = 'rivetR2';
  rivetR2.position.set(0.043, 0.038, 0.07);
  goggles.add(rivetR2);
  const rivetR3 = new THREE.Mesh(octahedronGeo, frameMat);
  rivetR3.name = 'rivetR3';
  rivetR3.position.set(0.0101, 0.019, 0.07);
  goggles.add(rivetR3);
  const rivetR4 = new THREE.Mesh(octahedronGeo, frameMat);
  rivetR4.name = 'rivetR4';
  rivetR4.position.set(0.0101, -0.019, 0.07);
  goggles.add(rivetR4);
  const rivetR5 = new THREE.Mesh(octahedronGeo, frameMat);
  rivetR5.name = 'rivetR5';
  rivetR5.position.set(0.043, -0.038, 0.07);
  goggles.add(rivetR5);
  const rivetR6 = new THREE.Mesh(octahedronGeo, frameMat);
  rivetR6.name = 'rivetR6';
  rivetR6.position.set(0.0759, -0.019, 0.07);
  goggles.add(rivetR6);
  const ventR = new THREE.Mesh(cylinderGeo3, frameMat);
  ventR.name = 'ventR';
  ventR.position.set(0.08, 0, 0.054);
  ventR.rotation.set(0, 0, deg(90));
  goggles.add(ventR);
  const ventGrilleR = new THREE.Mesh(cylinderGeo4, darkMat);
  ventGrilleR.name = 'ventGrilleR';
  ventGrilleR.position.set(0.084, 0, 0.054);
  ventGrilleR.rotation.set(0, 0, deg(90));
  goggles.add(ventGrilleR);
  const cupL = new THREE.Mesh(cylinderGeo, padMat);
  cupL.name = 'cupL';
  cupL.position.set(-0.043, 0, 0.052);
  cupL.rotation.set(deg(90), 0, 0);
  goggles.add(cupL);
  const paddingL = new THREE.Mesh(torusGeo, padMat);
  paddingL.name = 'paddingL';
  paddingL.position.set(-0.043, 0, 0.038);
  goggles.add(paddingL);
  const bezelL = new THREE.Mesh(cylinderGeo2, frameMat);
  bezelL.name = 'bezelL';
  bezelL.position.set(-0.043, 0, 0.07);
  bezelL.rotation.set(deg(90), 0, 0);
  goggles.add(bezelL);
  const rimL = new THREE.Mesh(torusGeo2, frameMat);
  rimL.name = 'rimL';
  rimL.position.set(-0.043, 0, 0.077);
  goggles.add(rimL);
  const lensL = new THREE.Mesh(sphereGeo, lensMat);
  lensL.name = 'lensL';
  lensL.position.set(-0.043, 0, 0.075);
  lensL.rotation.set(deg(90), 0, 0);
  lensL.scale.set(1, 0.32, 1);
  goggles.add(lensL);
  const glintL = new THREE.Mesh(boxGeo, glintMat);
  glintL.name = 'glintL';
  glintL.position.set(-0.053, 0.012, 0.0835);
  glintL.rotation.set(deg(-18), deg(16), deg(40));
  goggles.add(glintL);
  const rivetL1 = new THREE.Mesh(octahedronGeo, frameMat);
  rivetL1.name = 'rivetL1';
  rivetL1.position.set(-0.0101, 0.019, 0.07);
  goggles.add(rivetL1);
  const rivetL2 = new THREE.Mesh(octahedronGeo, frameMat);
  rivetL2.name = 'rivetL2';
  rivetL2.position.set(-0.043, 0.038, 0.07);
  goggles.add(rivetL2);
  const rivetL3 = new THREE.Mesh(octahedronGeo, frameMat);
  rivetL3.name = 'rivetL3';
  rivetL3.position.set(-0.0759, 0.019, 0.07);
  goggles.add(rivetL3);
  const rivetL4 = new THREE.Mesh(octahedronGeo, frameMat);
  rivetL4.name = 'rivetL4';
  rivetL4.position.set(-0.0759, -0.019, 0.07);
  goggles.add(rivetL4);
  const rivetL5 = new THREE.Mesh(octahedronGeo, frameMat);
  rivetL5.name = 'rivetL5';
  rivetL5.position.set(-0.043, -0.038, 0.07);
  goggles.add(rivetL5);
  const rivetL6 = new THREE.Mesh(octahedronGeo, frameMat);
  rivetL6.name = 'rivetL6';
  rivetL6.position.set(-0.0101, -0.019, 0.07);
  goggles.add(rivetL6);
  const ventL = new THREE.Mesh(cylinderGeo3, frameMat);
  ventL.name = 'ventL';
  ventL.position.set(-0.08, 0, 0.054);
  ventL.rotation.set(0, 0, deg(90));
  goggles.add(ventL);
  const ventGrilleL = new THREE.Mesh(cylinderGeo4, darkMat);
  ventGrilleL.name = 'ventGrilleL';
  ventGrilleL.position.set(-0.084, 0, 0.054);
  ventGrilleL.rotation.set(0, 0, deg(90));
  goggles.add(ventGrilleL);
  const bridge = new THREE.Mesh(tube([[-0.015, 0.006, 0.07], [-0.012, 0.014, 0.074], [0.012, 0.014, 0.074], [0.015, 0.006, 0.07]], 0.0045, 8, 5), frameMat);
  bridge.name = 'bridge';
  goggles.add(bridge);
  const loupeHinge = new THREE.Mesh(new THREE.SphereGeometry(0.006, 6, 4), frameMat);
  loupeHinge.name = 'loupeHinge';
  loupeHinge.position.set(0.0675, 0.0245, 0.074);
  goggles.add(loupeHinge);
  const loupe = new THREE.Group();
  loupe.name = 'loupe';
  loupe.position.set(0.0675, 0.0245, 0.076);
  loupe.rotation.set(deg(-22), 0, deg(28));
  goggles.add(loupe);
  const loupeArm = new THREE.Mesh(new THREE.BoxGeometry(0.005, 0.034, 0.004), frameMat);
  loupeArm.name = 'loupeArm';
  loupeArm.position.set(0, -0.017, 0.006);
  loupe.add(loupeArm);
  const loupeRim = new THREE.Mesh(new THREE.TorusGeometry(0.015, 0.003, 4, 12), frameMat);
  loupeRim.name = 'loupeRim';
  loupeRim.position.set(-0.004, -0.036, 0.008);
  loupe.add(loupeRim);
  const loupeLens = new THREE.Mesh(new THREE.CylinderGeometry(0.0125, 0.0125, 0.002, 12), lensMat);
  loupeLens.name = 'loupeLens';
  loupeLens.position.set(-0.004, -0.036, 0.008);
  loupeLens.rotation.set(deg(90), 0, 0);
  loupe.add(loupeLens);
  const strapPivot = new THREE.Group();
  strapPivot.name = 'strapPivot';
  strapPivot.position.set(0, 0, 0.052);
  strapPivot.rotation.set(deg(-8), 0, 0);
  goggles.add(strapPivot);
  const strap = new THREE.Mesh(lathe([[0.088, -0.016], [0.092, -0.016], [0.092, 0.016], [0.088, 0.016], [0.088, -0.016]], 18, 0.9076, 4.468), strapMat);
  strap.name = 'strap';
  strap.position.set(0, 0, -0.065);
  strap.scale.set(1, 1, 1.15);
  strapPivot.add(strap);
  const buckle = new THREE.Mesh(new THREE.BoxGeometry(0.03, 0.04, 0.006), frameMat);
  buckle.name = 'buckle';
  buckle.position.set(0, 0, -0.1728);
  strapPivot.add(buckle);
  const buckleTongue = new THREE.Mesh(new THREE.BoxGeometry(0.018, 0.026, 0.008), strapMat);
  buckleTongue.name = 'buckleTongue';
  buckleTongue.position.set(0, 0, -0.1738);
  strapPivot.add(buckleTongue);
  const bracketR = new THREE.Mesh(boxGeo2, frameMat);
  bracketR.name = 'bracketR';
  bracketR.position.set(0.075, 0, 0.048);
  goggles.add(bracketR);
  const bracketL = new THREE.Mesh(boxGeo2, frameMat);
  bracketL.name = 'bracketL';
  bracketL.position.set(-0.075, 0, 0.048);
  goggles.add(bracketL);

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

export default createGoggles;
```

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