1.5K tris0.27 × 0.16 × 0.16 m
Use it in code
Remix in the editortea-pot.js · 171 lines
Self-contained ES module — only depends on three. Call the factory and add the group to your scene.
/**
* Teapot — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 1,520 · Size (W × H × D): 0.27 × 0.16 × 0.16 m
*
* Usage:
* import { createTeaPot } from './tea-pot.js';
*
* const model = createTeaPot();
* 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 createTeaPot() {
const root = new THREE.Group();
root.name = 'TeaPot';
// Materials
const glazeMat = new THREE.MeshStandardMaterial({ name: 'glaze', color: 0x5aa39a, roughness: 0.25 });
const accentMat = new THREE.MeshStandardMaterial({ name: 'accent', color: 0xf4ead6, roughness: 0.3 });
const footMat = new THREE.MeshStandardMaterial({ name: 'foot', color: 0x447a74, roughness: 0.4, flatShading: true });
// Shared geometries
const circleGeo = new THREE.CircleGeometry(0.0075, 8);
// Parts
const body = new THREE.Mesh(lathe([[0, 0.004], [0.04, 0.004], [0.044, 0], [0.05, 0.002], [0.054, 0.008], [0.068, 0.024], [0.077, 0.045], [0.079, 0.064], [0.074, 0.084], [0.062, 0.101], [0.046, 0.112], [0.041, 0.116], [0.04, 0.12]], 16), glazeMat);
body.name = 'body';
root.add(body);
const footRing = new THREE.Mesh(lathe([[0.04, 0], [0.051, 0], [0.054, 0.008], [0.05, 0.009], [0.04, 0.006]], 16), footMat);
footRing.name = 'footRing';
root.add(footRing);
const bellyBand = new THREE.Mesh(lathe([[0.0755, 0.059], [0.08, 0.059], [0.0793, 0.069], [0.0748, 0.069]], 16), accentMat);
bellyBand.name = 'bellyBand';
root.add(bellyBand);
const shoulderBand = new THREE.Mesh(lathe([[0.0625, 0.096], [0.067, 0.096], [0.0642, 0.1], [0.0597, 0.1]], 16), accentMat);
shoulderBand.name = 'shoulderBand';
root.add(shoulderBand);
const dot11 = new THREE.Mesh(circleGeo, accentMat);
dot11.name = 'dot1_1';
dot11.position.set(0.0153, 0.0415, 0.0753);
dot11.rotation.set(deg(23.6192), deg(10.5216), deg(-2.2058));
root.add(dot11);
const dot12 = new THREE.Mesh(circleGeo, accentMat);
dot12.name = 'dot1_2';
dot12.position.set(0.0601, 0.0415, 0.0479);
dot12.rotation.set(deg(34.5216), deg(45.9656), deg(-15.0144));
root.add(dot12);
const dot14 = new THREE.Mesh(circleGeo, accentMat);
dot14.name = 'dot1_4';
dot14.position.set(0.0576, 0.0415, -0.0509);
dot14.rotation.set(deg(147.0848), deg(43.5378), deg(-107.0165));
root.add(dot14);
const dot15 = new THREE.Mesh(circleGeo, accentMat);
dot15.name = 'dot1_5';
dot15.position.set(0.0114, 0.0415, -0.076);
dot15.rotation.set(deg(156.5692), deg(7.8457), deg(-36.5964));
root.add(dot15);
const dot16 = new THREE.Mesh(circleGeo, accentMat);
dot16.name = 'dot1_6';
dot16.position.set(-0.0401, 0.0415, -0.0655);
dot16.rotation.set(deg(153.3241), deg(-28.6654), deg(94.2818));
root.add(dot16);
const dot19 = new THREE.Mesh(circleGeo, accentMat);
dot19.name = 'dot1_9';
dot19.position.set(-0.0367, 0.0415, 0.0675);
dot19.rotation.set(deg(26.0058), deg(-26.0499), deg(6.1155));
root.add(dot19);
const dot21 = new THREE.Mesh(circleGeo, accentMat);
dot21.name = 'dot2_1';
dot21.position.set(0.0395, 0.0823, 0.0645);
dot21.rotation.set(deg(-16.3348), deg(30.4182), deg(4.4689));
root.add(dot21);
const dot24 = new THREE.Mesh(circleGeo, accentMat);
dot24.name = 'dot2_4';
dot24.position.set(0.0362, 0.0823, -0.0665);
dot24.rotation.set(deg(-164.1145), deg(27.6145), deg(120.8309));
root.add(dot24);
const dot25 = new THREE.Mesh(circleGeo, accentMat);
dot25.name = 'dot2_5';
dot25.position.set(-0.015, 0.0823, -0.0742);
dot25.rotation.set(deg(-165.6899), deg(-11.1126), deg(-75.5474));
root.add(dot25);
const dot26 = new THREE.Mesh(circleGeo, accentMat);
dot26.name = 'dot2_6';
dot26.position.set(-0.0592, 0.0823, -0.0471);
dot26.rotation.set(deg(-158.1375), deg(-49.3595), deg(-134.4062));
root.add(dot26);
const dot28 = new THREE.Mesh(circleGeo, accentMat);
dot28.name = 'dot2_8';
dot28.position.set(-0.0567, 0.0823, 0.0501);
dot28.rotation.set(deg(-20.6863), deg(-46.6398), deg(-8.997));
root.add(dot28);
const dot29 = new THREE.Mesh(circleGeo, accentMat);
dot29.name = 'dot2_9';
dot29.position.set(-0.0112, 0.0823, 0.0748);
dot29.rotation.set(deg(-14.1873), deg(-8.284), deg(-1.0327));
root.add(dot29);
const lid = new THREE.Mesh(lathe([[0.034, 0.118], [0.046, 0.119], [0.047, 0.123], [0.04, 0.128], [0.026, 0.135], [0.01, 0.138], [0, 0.1385]], 16), glazeMat);
lid.name = 'lid';
root.add(lid);
const lidRim = new THREE.Mesh(new THREE.TorusGeometry(0.045, 0.0028, 3, 16), accentMat);
lidRim.name = 'lidRim';
lidRim.position.set(0, 0.1215, 0);
lidRim.rotation.set(deg(90), 0, 0);
root.add(lidRim);
const knobStem = new THREE.Mesh(new THREE.CylinderGeometry(0.006, 0.009, 0.008, 8), glazeMat);
knobStem.name = 'knobStem';
knobStem.position.set(0, 0.14, 0);
root.add(knobStem);
const knob = new THREE.Mesh(new THREE.SphereGeometry(0.0115, 8, 6), accentMat);
knob.name = 'knob';
knob.position.set(0, 0.151, 0);
knob.scale.set(1, 0.85, 1);
root.add(knob);
const spout1 = new THREE.Mesh(new THREE.CylinderGeometry(0.013, 0.018, 0.0432, 8), glazeMat);
spout1.name = 'spout1';
spout1.position.set(0.0715, 0.048, 0);
spout1.rotation.set(0, 0, deg(-64.1336));
root.add(spout1);
const spout2 = new THREE.Mesh(new THREE.CylinderGeometry(0.0105, 0.013, 0.0378, 8), glazeMat);
spout2.name = 'spout2';
spout2.position.set(0.099, 0.068, 0);
spout2.rotation.set(0, 0, deg(-42.5104));
root.add(spout2);
const spout3 = new THREE.Mesh(new THREE.CylinderGeometry(0.0088, 0.0105, 0.0322, 8), glazeMat);
spout3.name = 'spout3';
spout3.position.set(0.117, 0.092, 0);
spout3.rotation.set(0, 0, deg(-30.2564));
root.add(spout3);
const spout4 = new THREE.Mesh(new THREE.CylinderGeometry(0.0078, 0.0088, 0.0255, 8), glazeMat);
spout4.name = 'spout4';
spout4.position.set(0.13, 0.113, 0);
spout4.rotation.set(0, 0, deg(-33.6901));
root.add(spout4);
const spoutLip = new THREE.Mesh(new THREE.CylinderGeometry(0.0105, 0.0082, 0.006, 10), accentMat);
spoutLip.name = 'spoutLip';
spoutLip.position.set(0.1371, 0.1237, 0);
spoutLip.rotation.set(0, 0, deg(-33.6901));
root.add(spoutLip);
const spoutHole = new THREE.Mesh(new THREE.CylinderGeometry(0.0062, 0.0062, 0.001, 8), footMat);
spoutHole.name = 'spoutHole';
spoutHole.position.set(0.1389, 0.1263, 0);
spoutHole.rotation.set(0, 0, deg(-33.6901));
root.add(spoutHole);
const handle = new THREE.Mesh(new THREE.TorusGeometry(0.036, 0.0075, 5, 12, 3.8327), glazeMat);
handle.name = 'handle';
handle.position.set(-0.072, 0.066, 0);
handle.rotation.set(0, 0, deg(70));
handle.scale.set(0.95, 1.08, 1);
root.add(handle);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createTeaPot;
Ratings & comments
0 comments
No comments yet. Share how you used this model or what could be better.
Related models
Same category or similar tags









