# Watermelon

> A summery watermelon in two forms: a whole oblong melon with alternating light and dark green stripes, or a classic triangular slice with red flesh, a pale rind band, dark green skin and black seeds on both faces. Real-world size by default; great for picnics, beach scenes, farm games and food pickups.

![Watermelon preview](https://codels.download/m/watermelon.png)

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

## Facts

- Category: Food & Drink › Fruits & Vegetables
- Size (W × H × D): 0.15 × 0.14 × 0.04 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 632 · Meshes: 17 · Materials: 4
- License: CC0-1.0 (Codels built-in)
- Tags: fruit, slice, watermelon, cartoon, low-poly, stylized, farm, kitchen, tropical, beach, farming-sim, collectible, food, pickup, prop, organic, game-ready, mobile-friendly, parametric, color-green, color-red, size-tiny, poly-low
- Page: https://codels.download/models/watermelon

## Files

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

## Parameters

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

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `variant` | select | whole \| slice | slice | slice |
| `size` | number | 0.2 – 1 | 0.35 | 0.35 |
| `seeds` | boolean | true \| false | true | true |

## Parts

- slice (group)
  - flesh (extrude · flesh)
  - rind (extrude · rind)
  - skin (extrude · skin)
  - seedFront1 (sphere · seed)
  - seedFront2 (sphere · seed)
  - seedFront3 (sphere · seed)
  - seedFront4 (sphere · seed)
  - seedFront5 (sphere · seed)
  - seedFront6 (sphere · seed)
  - seedFront7 (sphere · seed)
  - seedBack1 (sphere · seed)
  - seedBack2 (sphere · seed)
  - seedBack3 (sphere · seed)
  - seedBack4 (sphere · seed)
  - seedBack5 (sphere · seed)
  - seedBack6 (sphere · seed)
  - seedBack7 (sphere · seed)

## How to use

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

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

## Code

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

  // Materials
  const skinMat = new THREE.MeshStandardMaterial({ name: 'skin', color: 0x2a7a30, roughness: 0.55, flatShading: true });
  const rindMat = new THREE.MeshStandardMaterial({ name: 'rind', color: 0xe8f2c4, roughness: 0.7, flatShading: true });
  const fleshMat = new THREE.MeshStandardMaterial({ name: 'flesh', color: 0xf2414f, roughness: 0.6, flatShading: true });
  const seedMat = new THREE.MeshStandardMaterial({ name: 'seed', color: 0x241a14, roughness: 0.4, flatShading: true });

  // Shared geometries
  const sphereGeo = new THREE.SphereGeometry(0.0049, 5, 4);

  // Parts
  const slice = new THREE.Group();
  slice.name = 'slice';
  slice.position.set(0, 0.14, 0);
  root.add(slice);
  const flesh = new THREE.Mesh(extrude([[-0.0594, -0.095], [-0.0484, -0.101], [-0.0368, -0.1058], [-0.0248, -0.1092], [-0.0125, -0.1113], [0, -0.112], [0.0125, -0.1113], [0.0248, -0.1092], [0.0368, -0.1058], [0.0484, -0.101], [0.0594, -0.095], [0, 0]], 0.0392), fleshMat);
  flesh.name = 'flesh';
  slice.add(flesh);
  const rind = new THREE.Mesh(extrude([[-0.0683, -0.1092], [-0.0557, -0.1162], [-0.0424, -0.1216], [-0.0285, -0.1256], [-0.0144, -0.128], [0, -0.1288], [0.0144, -0.128], [0.0285, -0.1256], [0.0424, -0.1216], [0.0557, -0.1162], [0.0683, -0.1092], [0.0594, -0.095], [0.0484, -0.101], [0.0368, -0.1058], [0.0248, -0.1092], [0.0125, -0.1113], [0, -0.112], [-0.0125, -0.1113], [-0.0248, -0.1092], [-0.0368, -0.1058], [-0.0484, -0.101], [-0.0594, -0.095]], 0.0392), rindMat);
  rind.name = 'rind';
  slice.add(rind);
  const skin = new THREE.Mesh(extrude([[-0.0742, -0.1187], [-0.0605, -0.1263], [-0.046, -0.1322], [-0.031, -0.1365], [-0.0156, -0.1391], [0, -0.14], [0.0156, -0.1391], [0.031, -0.1365], [0.046, -0.1322], [0.0605, -0.1263], [0.0742, -0.1187], [0.0683, -0.1092], [0.0557, -0.1162], [0.0424, -0.1216], [0.0285, -0.1256], [0.0144, -0.128], [0, -0.1288], [-0.0144, -0.128], [-0.0285, -0.1256], [-0.0424, -0.1216], [-0.0557, -0.1162], [-0.0683, -0.1092]], 0.0392), skinMat);
  skin.name = 'skin';
  slice.add(skin);
  const seedFront1 = new THREE.Mesh(sphereGeo, seedMat);
  seedFront1.name = 'seedFront1';
  seedFront1.position.set(-0.0127, -0.0848, 0.0196);
  seedFront1.rotation.set(0, 0, deg(-8.4986));
  seedFront1.scale.set(0.6, 1, 0.45);
  slice.add(seedFront1);
  const seedFront2 = new THREE.Mesh(sphereGeo, seedMat);
  seedFront2.name = 'seedFront2';
  seedFront2.position.set(-0.0151, -0.0481, 0.0196);
  seedFront2.rotation.set(0, 0, deg(-17.4397));
  seedFront2.scale.set(0.6, 1, 0.45);
  slice.add(seedFront2);
  const seedFront3 = new THREE.Mesh(sphereGeo, seedMat);
  seedFront3.name = 'seedFront3';
  seedFront3.position.set(0.0003, -0.051, 0.0196);
  seedFront3.rotation.set(0, 0, deg(0.3567));
  seedFront3.scale.set(0.6, 1, 0.45);
  slice.add(seedFront3);
  const seedFront4 = new THREE.Mesh(sphereGeo, seedMat);
  seedFront4.name = 'seedFront4';
  seedFront4.position.set(0.0133, -0.041, 0.0196);
  seedFront4.rotation.set(0, 0, deg(17.9805));
  seedFront4.scale.set(0.6, 1, 0.45);
  slice.add(seedFront4);
  const seedFront5 = new THREE.Mesh(sphereGeo, seedMat);
  seedFront5.name = 'seedFront5';
  seedFront5.position.set(0.0112, -0.0696, 0.0196);
  seedFront5.rotation.set(0, 0, deg(9.1749));
  seedFront5.scale.set(0.6, 1, 0.45);
  slice.add(seedFront5);
  const seedFront6 = new THREE.Mesh(sphereGeo, seedMat);
  seedFront6.name = 'seedFront6';
  seedFront6.position.set(-0.0088, -0.0774, 0.0196);
  seedFront6.rotation.set(0, 0, deg(-6.4885));
  seedFront6.scale.set(0.6, 1, 0.45);
  slice.add(seedFront6);
  const seedFront7 = new THREE.Mesh(sphereGeo, seedMat);
  seedFront7.name = 'seedFront7';
  seedFront7.position.set(0.0242, -0.0722, 0.0196);
  seedFront7.rotation.set(0, 0, deg(18.5106));
  seedFront7.scale.set(0.6, 1, 0.45);
  slice.add(seedFront7);
  const seedBack1 = new THREE.Mesh(sphereGeo, seedMat);
  seedBack1.name = 'seedBack1';
  seedBack1.position.set(-0.0127, -0.0848, -0.0196);
  seedBack1.rotation.set(0, 0, deg(-8.4986));
  seedBack1.scale.set(0.6, 1, 0.45);
  slice.add(seedBack1);
  const seedBack2 = new THREE.Mesh(sphereGeo, seedMat);
  seedBack2.name = 'seedBack2';
  seedBack2.position.set(-0.0151, -0.0481, -0.0196);
  seedBack2.rotation.set(0, 0, deg(-17.4397));
  seedBack2.scale.set(0.6, 1, 0.45);
  slice.add(seedBack2);
  const seedBack3 = new THREE.Mesh(sphereGeo, seedMat);
  seedBack3.name = 'seedBack3';
  seedBack3.position.set(0.0003, -0.051, -0.0196);
  seedBack3.rotation.set(0, 0, deg(0.3567));
  seedBack3.scale.set(0.6, 1, 0.45);
  slice.add(seedBack3);
  const seedBack4 = new THREE.Mesh(sphereGeo, seedMat);
  seedBack4.name = 'seedBack4';
  seedBack4.position.set(0.0133, -0.041, -0.0196);
  seedBack4.rotation.set(0, 0, deg(17.9805));
  seedBack4.scale.set(0.6, 1, 0.45);
  slice.add(seedBack4);
  const seedBack5 = new THREE.Mesh(sphereGeo, seedMat);
  seedBack5.name = 'seedBack5';
  seedBack5.position.set(0.0112, -0.0696, -0.0196);
  seedBack5.rotation.set(0, 0, deg(9.1749));
  seedBack5.scale.set(0.6, 1, 0.45);
  slice.add(seedBack5);
  const seedBack6 = new THREE.Mesh(sphereGeo, seedMat);
  seedBack6.name = 'seedBack6';
  seedBack6.position.set(-0.0088, -0.0774, -0.0196);
  seedBack6.rotation.set(0, 0, deg(-6.4885));
  seedBack6.scale.set(0.6, 1, 0.45);
  slice.add(seedBack6);
  const seedBack7 = new THREE.Mesh(sphereGeo, seedMat);
  seedBack7.name = 'seedBack7';
  seedBack7.position.set(0.0242, -0.0722, -0.0196);
  seedBack7.rotation.set(0, 0, deg(18.5106));
  seedBack7.scale.set(0.6, 1, 0.45);
  slice.add(seedBack7);

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

export default createWatermelon;
```

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