1.2K tris0.98 × 1.22 × 0.98 m
Use it in code
Remix in the editorcabinet.js · 316 lines
Self-contained ES module — only depends on three. Call the factory and add the group to your scene.
/**
* Cabinet — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 1,152 · Size (W × H × D): 0.98 × 1.22 × 0.97 m
*
* Usage:
* import { createCabinet } from './cabinet.js';
*
* const model = createCabinet();
* 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 createCabinet() {
const root = new THREE.Group();
root.name = 'Cabinet';
// Materials
const paintMat = new THREE.MeshStandardMaterial({ name: 'paint', color: 0x8fae9c, roughness: 0.6, flatShading: true });
const trimMat = new THREE.MeshStandardMaterial({ name: 'trim', color: 0xa3bdae, roughness: 0.6, flatShading: true });
const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x4f6056, roughness: 0.9, flatShading: true });
const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0xc48a52, roughness: 0.8, flatShading: true });
const chromeMat = new THREE.MeshStandardMaterial({ name: 'chrome', color: 0xc9ccd0, roughness: 0.25, metalness: 0.7, flatShading: true });
const whiteMat = new THREE.MeshStandardMaterial({ name: 'white', color: 0xeeeee8, roughness: 0.5, flatShading: true });
const redMat = new THREE.MeshStandardMaterial({ name: 'red', color: 0xc23b32, roughness: 0.6, flatShading: true });
const amberMat = new THREE.MeshStandardMaterial({ name: 'amber', color: 0xa45a1c, roughness: 0.25, flatShading: true });
// Shared geometries
const boxGeo = new THREE.BoxGeometry(0.02, 0.76, 0.58);
const boxGeo2 = new THREE.BoxGeometry(0.76, 0.02, 0.56);
const boxGeo3 = new THREE.BoxGeometry(0.012, 0.012, 0.026);
const boxGeo4 = new THREE.BoxGeometry(0.396, 0.578, 0.02);
const boxGeo5 = new THREE.BoxGeometry(0.396, 0.07, 0.01);
const boxGeo6 = new THREE.BoxGeometry(0.07, 0.438, 0.01);
const cylinderGeo = new THREE.CylinderGeometry(0.006, 0.006, 0.12, 6);
const cylinderGeo2 = new THREE.CylinderGeometry(0.007, 0.007, 0.26, 5);
const sphereGeo = new THREE.SphereGeometry(0.025, 6, 4);
const cylinderGeo3 = new THREE.CylinderGeometry(0.11, 0.09, 0.014, 10);
const cylinderGeo4 = new THREE.CylinderGeometry(0.045, 0.045, 0.12, 7);
const cylinderGeo5 = new THREE.CylinderGeometry(0.048, 0.048, 0.025, 7);
// Parts
const toeKick = new THREE.Mesh(new THREE.BoxGeometry(0.78, 0.1, 0.5), darkMat);
toeKick.name = 'toeKick';
toeKick.position.set(0, 0.05, -0.04);
root.add(toeKick);
const side = new THREE.Mesh(boxGeo, paintMat);
side.name = 'side';
side.position.set(-0.39, 0.48, 0);
root.add(side);
const side2 = new THREE.Mesh(boxGeo, paintMat);
side2.name = 'side';
side2.position.set(0.39, 0.48, 0);
root.add(side2);
const bottom = new THREE.Mesh(boxGeo2, paintMat);
bottom.name = 'bottom';
bottom.position.set(0, 0.11, 0.01);
root.add(bottom);
const backPanel = new THREE.Mesh(new THREE.BoxGeometry(0.76, 0.76, 0.012), darkMat);
backPanel.name = 'backPanel';
backPanel.position.set(0, 0.48, -0.284);
root.add(backPanel);
const rail = new THREE.Mesh(boxGeo2, paintMat);
rail.name = 'rail';
rail.position.set(0, 0.7, 0.01);
root.add(rail);
const topRail = new THREE.Mesh(boxGeo2, paintMat);
topRail.name = 'topRail';
topRail.position.set(0, 0.85, 0.01);
root.add(topRail);
const counter = new THREE.Mesh(new THREE.BoxGeometry(0.83, 0.04, 0.61), woodMat);
counter.name = 'counter';
counter.position.set(0, 0.88, 0.015);
root.add(counter);
const drawer = new THREE.Mesh(extrude([[0.388, 0.0523], [0.3788, 0.0615], [-0.3788, 0.0615], [-0.388, 0.0523], [-0.388, -0.0523], [-0.3788, -0.0615], [0.3788, -0.0615], [0.388, -0.0523]], 0.008, [], [0.006, 0.006, 1]), paintMat);
drawer.name = 'drawer';
drawer.position.set(0, 0.78, 0.3);
root.add(drawer);
const pull = new THREE.Group();
pull.name = 'pull';
pull.position.set(0, 0.785, 0.31);
root.add(pull);
const pullPost = new THREE.Mesh(boxGeo3, chromeMat);
pullPost.name = 'pullPost';
pullPost.position.set(-0.074, 0, 0.013);
pull.add(pullPost);
const pullPost2 = new THREE.Mesh(boxGeo3, chromeMat);
pullPost2.name = 'pullPost';
pullPost2.position.set(0.074, 0, 0.013);
pull.add(pullPost2);
const pullBar = new THREE.Mesh(new THREE.CylinderGeometry(0.006, 0.006, 0.16, 6), chromeMat);
pullBar.name = 'pullBar';
pullBar.position.set(0, 0, 0.026);
pullBar.rotation.set(0, 0, deg(90));
pull.add(pullBar);
const doorLeft = new THREE.Group();
doorLeft.name = 'doorLeft';
doorLeft.position.set(-0.4, 0.106, 0.29);
doorLeft.rotation.set(0, deg(-105), 0);
root.add(doorLeft);
const doorSlab = new THREE.Mesh(boxGeo4, paintMat);
doorSlab.name = 'doorSlab';
doorSlab.position.set(0.198, 0.289, 0.01);
doorLeft.add(doorSlab);
const doorRail = new THREE.Mesh(boxGeo5, trimMat);
doorRail.name = 'doorRail';
doorRail.position.set(0.198, 0.035, 0.025);
doorLeft.add(doorRail);
const doorRail2 = new THREE.Mesh(boxGeo5, trimMat);
doorRail2.name = 'doorRail';
doorRail2.position.set(0.198, 0.543, 0.025);
doorLeft.add(doorRail2);
const doorStile = new THREE.Mesh(boxGeo6, trimMat);
doorStile.name = 'doorStile';
doorStile.position.set(0.035, 0.289, 0.025);
doorLeft.add(doorStile);
const doorStile2 = new THREE.Mesh(boxGeo6, trimMat);
doorStile2.name = 'doorStile';
doorStile2.position.set(0.361, 0.289, 0.025);
doorLeft.add(doorStile2);
const pull2 = new THREE.Group();
pull2.name = 'pull';
pull2.position.set(0.361, 0.448, 0.03);
pull2.rotation.set(0, 0, deg(90));
doorLeft.add(pull2);
const pullPost3 = new THREE.Mesh(boxGeo3, chromeMat);
pullPost3.name = 'pullPost';
pullPost3.position.set(-0.054, 0, 0.013);
pull2.add(pullPost3);
const pullPost4 = new THREE.Mesh(boxGeo3, chromeMat);
pullPost4.name = 'pullPost';
pullPost4.position.set(0.054, 0, 0.013);
pull2.add(pullPost4);
const pullBar2 = new THREE.Mesh(cylinderGeo, chromeMat);
pullBar2.name = 'pullBar';
pullBar2.position.set(0, 0, 0.026);
pullBar2.rotation.set(0, 0, deg(90));
pull2.add(pullBar2);
const doorRight = new THREE.Group();
doorRight.name = 'doorRight';
doorRight.position.set(0.4, 0.106, 0.29);
doorRight.rotation.set(0, deg(80), 0);
root.add(doorRight);
const doorSlab2 = new THREE.Mesh(boxGeo4, paintMat);
doorSlab2.name = 'doorSlab';
doorSlab2.position.set(-0.198, 0.289, 0.01);
doorRight.add(doorSlab2);
const doorRail3 = new THREE.Mesh(boxGeo5, trimMat);
doorRail3.name = 'doorRail';
doorRail3.position.set(-0.198, 0.035, 0.025);
doorRight.add(doorRail3);
const doorRail4 = new THREE.Mesh(boxGeo5, trimMat);
doorRail4.name = 'doorRail';
doorRail4.position.set(-0.198, 0.543, 0.025);
doorRight.add(doorRail4);
const doorStile3 = new THREE.Mesh(boxGeo6, trimMat);
doorStile3.name = 'doorStile';
doorStile3.position.set(-0.361, 0.289, 0.025);
doorRight.add(doorStile3);
const doorStile4 = new THREE.Mesh(boxGeo6, trimMat);
doorStile4.name = 'doorStile';
doorStile4.position.set(-0.035, 0.289, 0.025);
doorRight.add(doorStile4);
const pull3 = new THREE.Group();
pull3.name = 'pull';
pull3.position.set(-0.361, 0.448, 0.03);
pull3.rotation.set(0, 0, deg(90));
doorRight.add(pull3);
const pullPost5 = new THREE.Mesh(boxGeo3, chromeMat);
pullPost5.name = 'pullPost';
pullPost5.position.set(-0.054, 0, 0.013);
pull3.add(pullPost5);
const pullPost6 = new THREE.Mesh(boxGeo3, chromeMat);
pullPost6.name = 'pullPost';
pullPost6.position.set(0.054, 0, 0.013);
pull3.add(pullPost6);
const pullBar3 = new THREE.Mesh(cylinderGeo, chromeMat);
pullBar3.name = 'pullBar';
pullBar3.position.set(0, 0, 0.026);
pullBar3.rotation.set(0, 0, deg(90));
pull3.add(pullBar3);
const crock = new THREE.Mesh(new THREE.CylinderGeometry(0.055, 0.05, 0.13, 8), whiteMat);
crock.name = 'crock';
crock.position.set(-0.24, 0.965, -0.14);
root.add(crock);
const crockOpening = new THREE.Mesh(new THREE.CylinderGeometry(0.048, 0.048, 0.005, 8), darkMat);
crockOpening.name = 'crockOpening';
crockOpening.position.set(-0.24, 1.0295, -0.14);
root.add(crockOpening);
const spoon = new THREE.Group();
spoon.name = 'spoon';
spoon.position.set(-0.252, 0.92, -0.13);
spoon.rotation.set(deg(-6), 0, deg(-12));
root.add(spoon);
const spoonHandle = new THREE.Mesh(cylinderGeo2, woodMat);
spoonHandle.name = 'spoonHandle';
spoonHandle.position.set(0, 0.13, 0);
spoon.add(spoonHandle);
const spoonBowl = new THREE.Mesh(sphereGeo, woodMat);
spoonBowl.name = 'spoonBowl';
spoonBowl.position.set(0, 0.27, 0);
spoonBowl.scale.set(1, 1.3, 0.45);
spoon.add(spoonBowl);
const spoon2 = new THREE.Group();
spoon2.name = 'spoon';
spoon2.position.set(-0.225, 0.92, -0.148);
spoon2.rotation.set(deg(5), 0, deg(10));
root.add(spoon2);
const spoonHandle2 = new THREE.Mesh(cylinderGeo2, woodMat);
spoonHandle2.name = 'spoonHandle';
spoonHandle2.position.set(0, 0.13, 0);
spoon2.add(spoonHandle2);
const spoonBowl2 = new THREE.Mesh(sphereGeo, woodMat);
spoonBowl2.name = 'spoonBowl';
spoonBowl2.position.set(0, 0.27, 0);
spoonBowl2.scale.set(1, 1.3, 0.45);
spoon2.add(spoonBowl2);
const cuttingBoard = new THREE.Mesh(new THREE.BoxGeometry(0.32, 0.022, 0.22), woodMat);
cuttingBoard.name = 'cuttingBoard';
cuttingBoard.position.set(0.14, 0.911, 0.04);
cuttingBoard.rotation.set(0, deg(-10), 0);
root.add(cuttingBoard);
const tomato = new THREE.Mesh(new THREE.SphereGeometry(0.038, 7, 5), redMat);
tomato.name = 'tomato';
tomato.position.set(0.2, 0.954, 0.06);
tomato.scale.set(1, 0.85, 1);
root.add(tomato);
const shelf = new THREE.Mesh(new THREE.BoxGeometry(0.76, 0.016, 0.5), paintMat);
shelf.name = 'shelf';
shelf.position.set(0, 0.408, -0.03);
root.add(shelf);
const plate = new THREE.Mesh(cylinderGeo3, whiteMat);
plate.name = 'plate';
plate.position.set(-0.17, 0.127, 0.02);
root.add(plate);
const plate2 = new THREE.Mesh(cylinderGeo3, whiteMat);
plate2.name = 'plate';
plate2.position.set(-0.17, 0.143, 0.02);
root.add(plate2);
const plate3 = new THREE.Mesh(cylinderGeo3, whiteMat);
plate3.name = 'plate';
plate3.position.set(-0.17, 0.159, 0.02);
root.add(plate3);
const plate4 = new THREE.Mesh(cylinderGeo3, whiteMat);
plate4.name = 'plate';
plate4.position.set(-0.17, 0.175, 0.02);
root.add(plate4);
const pot = new THREE.Mesh(new THREE.CylinderGeometry(0.12, 0.11, 0.15, 9), chromeMat);
pot.name = 'pot';
pot.position.set(0.17, 0.195, -0.02);
root.add(pot);
const potLid = new THREE.Mesh(new THREE.CylinderGeometry(0.125, 0.125, 0.012, 9), darkMat);
potLid.name = 'potLid';
potLid.position.set(0.17, 0.276, -0.02);
root.add(potLid);
const potKnob = new THREE.Mesh(new THREE.SphereGeometry(0.018, 5, 3), darkMat);
potKnob.name = 'potKnob';
potKnob.position.set(0.17, 0.29, -0.02);
root.add(potKnob);
const jar = new THREE.Mesh(cylinderGeo4, amberMat);
jar.name = 'jar';
jar.position.set(-0.25, 0.476, -0.06);
root.add(jar);
const jarLid = new THREE.Mesh(cylinderGeo5, whiteMat);
jarLid.name = 'jarLid';
jarLid.position.set(-0.25, 0.5485, -0.06);
root.add(jarLid);
const jar2 = new THREE.Mesh(cylinderGeo4, redMat);
jar2.name = 'jar';
jar2.position.set(-0.1, 0.476, -0.06);
root.add(jar2);
const jarLid2 = new THREE.Mesh(cylinderGeo5, whiteMat);
jarLid2.name = 'jarLid';
jarLid2.position.set(-0.1, 0.5485, -0.06);
root.add(jarLid2);
const jar3 = new THREE.Mesh(cylinderGeo4, woodMat);
jar3.name = 'jar';
jar3.position.set(0.06, 0.476, -0.06);
root.add(jar3);
const jarLid3 = new THREE.Mesh(cylinderGeo5, whiteMat);
jarLid3.name = 'jarLid';
jarLid3.position.set(0.06, 0.5485, -0.06);
root.add(jarLid3);
const jar4 = new THREE.Mesh(cylinderGeo4, amberMat);
jar4.name = 'jar';
jar4.position.set(0.22, 0.476, -0.06);
root.add(jar4);
const jarLid4 = new THREE.Mesh(cylinderGeo5, whiteMat);
jarLid4.name = 'jarLid';
jarLid4.position.set(0.22, 0.5485, -0.06);
root.add(jarLid4);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createCabinet;
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









