# Gem Ring

> A precious gold ring standing upright and facing +Z, centered on the origin for spinning pickups: a rounded band with a cup setting, four claw prongs holding a faceted, softly glowing gemstone and two small diamond accents on the shoulders. Defaults to a readable game-pickup size (0.15 m across); scale it down to a real 2 cm ring. Set metal and gem colors for magic rings, wedding rings and treasure loot.

![Gem Ring preview](https://codels.download/m/ring.png)

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

## Facts

- Category: Items & Weapons › Collectibles
- Size (W × H × D): 0.15 × 0.19 × 0.06 m — units are meters, +Y up, front faces +Z
- Origin: center of the model (it floats — pickups, planets)
- Triangles: 696 · Meshes: 14 · Materials: 3
- License: CC0-1.0 (Codels built-in)
- Tags: gem, reward, ring, treasure, cartoon, low-poly, stylized, fantasy, medieval, adventure, rpg, collectible, pickup, crystal, gold, metal, emissive, game-ready, instancing-friendly, mobile-friendly, parametric, color-orange, size-tiny, poly-low
- Page: https://codels.download/models/ring

## Files

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

## Parameters

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

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `metal` | color | #rrggbb | #f2c14e | #f2c14e |
| `gem` | color | #rrggbb | #d81e47 | #d81e47 |
| `size` | number | 0.02 – 0.4 | 0.15 | 0.15 |

## Parts

- ring (group)
  - band (torus · metal)
  - setting (cylinder · metal)
  - bezel (cylinder · metal)
  - gem (lathe · gem)
  - prong1 (cylinder · metal)
  - prongTip1 (sphere · metal)
  - prong2 (cylinder · metal)
  - prongTip2 (sphere · metal)
  - prong3 (cylinder · metal)
  - prongTip3 (sphere · metal)
  - prong4 (cylinder · metal)
  - prongTip4 (sphere · metal)
  - accentR (octahedron · diamond)
  - accentL (octahedron · diamond)

## How to use

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

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

## Code

```js
/**
 * Gem Ring — Codels 3D model library (https://codels.download/models/ring)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the model (it floats — pickups, planets)
 * Triangles: 696 · Size (W × H × D): 0.15 × 0.19 × 0.06 m
 *
 * Usage:
 *   import { createRing } from './ring.js';
 *   
 *   const model = createRing();
 *   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);
}

export function createRing() {
  const root = new THREE.Group();
  root.name = 'Ring';

  // Materials
  const metalMat = new THREE.MeshStandardMaterial({ name: 'metal', color: 0xf2c14e, roughness: 0.25, metalness: 0.9, flatShading: true });
  const gemMat = new THREE.MeshStandardMaterial({ name: 'gem', color: 0xd81e47, roughness: 0.1, metalness: 0.1, emissive: 0xd81e47, emissiveIntensity: 0.25, flatShading: true });
  const diamondMat = new THREE.MeshStandardMaterial({ name: 'diamond', color: 0xeef8ff, roughness: 0.05, metalness: 0.1, emissive: 0xcfe8ff, emissiveIntensity: 0.25, flatShading: true });

  // Shared geometries
  const cylinderGeo = new THREE.CylinderGeometry(0.0032, 0.004, 0.026, 5);
  const sphereGeo = new THREE.SphereGeometry(0.0042, 5, 4);
  const octahedronGeo = new THREE.OctahedronGeometry(0.009, 0);

  // Parts
  const ring = new THREE.Group();
  ring.name = 'ring';
  ring.position.set(0, -0.0183, 0);
  ring.scale.setScalar(0.9868);
  root.add(ring);
  const band = new THREE.Mesh(new THREE.TorusGeometry(0.065, 0.011, 6, 28), metalMat);
  band.name = 'band';
  band.scale.set(1, 1, 1.45);
  ring.add(band);
  const setting = new THREE.Mesh(new THREE.CylinderGeometry(0.024, 0.012, 0.022, 8), metalMat);
  setting.name = 'setting';
  setting.position.set(0, 0.082, 0);
  setting.rotation.set(0, deg(22.5), 0);
  ring.add(setting);
  const bezel = new THREE.Mesh(new THREE.CylinderGeometry(0.026, 0.026, 0.004, 8), metalMat);
  bezel.name = 'bezel';
  bezel.position.set(0, 0.093, 0);
  bezel.rotation.set(0, deg(22.5), 0);
  ring.add(bezel);
  const gem = new THREE.Mesh(lathe([[0, -0.024], [0.03, -0.002], [0.03, 0.002], [0.026, 0.009], [0.018, 0.0135], [0, 0.0135]], 8), gemMat);
  gem.name = 'gem';
  gem.position.set(0, 0.099, 0);
  gem.rotation.set(0, deg(22.5), 0);
  ring.add(gem);
  const prong1 = new THREE.Mesh(cylinderGeo, metalMat);
  prong1.name = 'prong1';
  prong1.position.set(0.0191, 0.095, 0.0191);
  prong1.rotation.set(deg(-4.8328), deg(-0.2041), deg(4.8328));
  ring.add(prong1);
  const prongTip1 = new THREE.Mesh(sphereGeo, metalMat);
  prongTip1.name = 'prongTip1';
  prongTip1.position.set(0.018, 0.107, 0.018);
  ring.add(prongTip1);
  const prong2 = new THREE.Mesh(cylinderGeo, metalMat);
  prong2.name = 'prong2';
  prong2.position.set(0.0191, 0.095, -0.0191);
  prong2.rotation.set(deg(4.8328), deg(0.2041), deg(4.8328));
  ring.add(prong2);
  const prongTip2 = new THREE.Mesh(sphereGeo, metalMat);
  prongTip2.name = 'prongTip2';
  prongTip2.position.set(0.018, 0.107, -0.018);
  ring.add(prongTip2);
  const prong3 = new THREE.Mesh(cylinderGeo, metalMat);
  prong3.name = 'prong3';
  prong3.position.set(-0.0191, 0.095, -0.0191);
  prong3.rotation.set(deg(4.8328), deg(-0.2041), deg(-4.8328));
  ring.add(prong3);
  const prongTip3 = new THREE.Mesh(sphereGeo, metalMat);
  prongTip3.name = 'prongTip3';
  prongTip3.position.set(-0.018, 0.107, -0.018);
  ring.add(prongTip3);
  const prong4 = new THREE.Mesh(cylinderGeo, metalMat);
  prong4.name = 'prong4';
  prong4.position.set(-0.0191, 0.095, 0.0191);
  prong4.rotation.set(deg(-4.8328), deg(0.2041), deg(-4.8328));
  ring.add(prong4);
  const prongTip4 = new THREE.Mesh(sphereGeo, metalMat);
  prongTip4.name = 'prongTip4';
  prongTip4.position.set(-0.018, 0.107, 0.018);
  ring.add(prongTip4);
  const accentR = new THREE.Mesh(octahedronGeo, diamondMat);
  accentR.name = 'accentR';
  accentR.position.set(0.0377, 0.0603, 0.0104);
  accentR.rotation.set(0, 0, deg(-32));
  accentR.scale.set(1, 1, 0.6);
  ring.add(accentR);
  const accentL = new THREE.Mesh(octahedronGeo, diamondMat);
  accentL.name = 'accentL';
  accentL.position.set(-0.0377, 0.0603, 0.0104);
  accentL.rotation.set(0, 0, deg(32));
  accentL.scale.set(1, 1, 0.6);
  ring.add(accentL);

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

export default createRing;
```

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