944 tris0,07 × 0,12 × 0,07 m
Úsalo en código
Hacer remix en el editorsoda-can.js · 113 líneas
Módulo ES autónomo — solo depende de three. Llama a la función factory y añade el grupo a tu escena.
/**
* Soda Can — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 944 · Size (W × H × D): 0.07 × 0.12 × 0.07 m
*
* Usage:
* import { createSodaCan } from './soda-can.js';
*
* const model = createSodaCan();
* 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);
}
// 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 createSodaCan() {
const root = new THREE.Group();
root.name = 'SodaCan';
// Materials
const aluMat = new THREE.MeshStandardMaterial({ name: 'alu', color: 0xc9ced6, roughness: 0.3, metalness: 0.85, flatShading: true });
const paintMat = new THREE.MeshStandardMaterial({ name: 'paint', color: 0xd62f35, roughness: 0.3, metalness: 0.35 });
const accentMat = new THREE.MeshStandardMaterial({ name: 'accent', color: 0xffffff, roughness: 0.35, metalness: 0.2 });
const logoMat = new THREE.MeshStandardMaterial({ name: 'logo', color: 0xf5a93d, roughness: 0.35, metalness: 0.2, flatShading: true });
// Parts
const bottom = new THREE.Mesh(lathe([[0, 0.006], [0.018, 0.0035], [0.025, 0], [0.029, 0.0015], [0.0325, 0.007], [0.033, 0.012]], 24), aluMat);
bottom.name = 'bottom';
root.add(bottom);
const body = new THREE.Mesh(lathe([[0.033, 0.012], [0.033, 0.104]], 24), paintMat);
body.name = 'body';
root.add(body);
const top = new THREE.Mesh(lathe([[0.033, 0.104], [0.0325, 0.108], [0.0295, 0.1135], [0.0272, 0.1185], [0.0276, 0.1215], [0.026, 0.1225], [0.0252, 0.1195], [0.0245, 0.1175], [0, 0.1175]], 24), aluMat);
top.name = 'top';
root.add(top);
const stripe = new THREE.Group();
stripe.name = 'stripe';
stripe.position.set(0, 0.052, 0);
stripe.rotation.set(deg(49.0795), 0, 0);
stripe.scale.set(1, 0.8669, 1.1536);
root.add(stripe);
const stripeBand = new THREE.Mesh(new THREE.CylinderGeometry(0.0335, 0.0335, 0.012, 24, 1, true), accentMat);
stripeBand.name = 'stripeBand';
stripeBand.rotation.set(deg(-40.9205), 0, 0);
stripe.add(stripeBand);
const stripeThin = new THREE.Group();
stripeThin.name = 'stripeThin';
stripeThin.position.set(0, 0.068, 0);
stripeThin.rotation.set(deg(49.0795), 0, 0);
stripeThin.scale.set(1, 0.8669, 1.1536);
root.add(stripeThin);
const stripeThinBand = new THREE.Mesh(new THREE.CylinderGeometry(0.0335, 0.0335, 0.0035, 24, 1, true), accentMat);
stripeThinBand.name = 'stripeThinBand';
stripeThinBand.rotation.set(deg(-40.9205), 0, 0);
stripeThin.add(stripeThinBand);
const logoPanel = new THREE.Mesh(new THREE.CylinderGeometry(0.0339, 0.0339, 0.03, 8, 1, true, -0.42, 0.84), accentMat);
logoPanel.name = 'logoPanel';
logoPanel.position.set(0, 0.083, 0);
root.add(logoPanel);
const logoStar = new THREE.Mesh(extrude([[0, 0.0085], [-0.0022, 0.0031], [-0.0081, 0.0026], [-0.0036, -0.0012], [-0.005, -0.0069], [0, -0.0038], [0.005, -0.0069], [0.0036, -0.0012], [0.0081, 0.0026], [0.0022, 0.0031]], 0.002), logoMat);
logoStar.name = 'logoStar';
logoStar.position.set(0, 0.083, 0.0338);
root.add(logoStar);
const logoLine = new THREE.Mesh(new THREE.CylinderGeometry(0.0339, 0.0339, 0.004, 8, 1, true, -0.42, 0.84), logoMat);
logoLine.name = 'logoLine';
logoLine.position.set(0, 0.029, 0);
root.add(logoLine);
const tearPanel = new THREE.Mesh(extrude([[-0.008, 0.004], [0.008, 0.004], [0.0095, 0.012], [0.006, 0.018], [-0.006, 0.018], [-0.0095, 0.012]], 0.0008), aluMat);
tearPanel.name = 'tearPanel';
tearPanel.position.set(0, 0.1179, 0);
tearPanel.rotation.set(deg(-90), 0, deg(180));
root.add(tearPanel);
const rivet = new THREE.Mesh(new THREE.CylinderGeometry(0.0022, 0.0022, 0.0016, 8), aluMat);
rivet.name = 'rivet';
rivet.position.set(0, 0.1183, 0);
root.add(rivet);
const tabHinge = new THREE.Group();
tabHinge.name = 'tabHinge';
tabHinge.position.set(0, 0.1193, 0);
tabHinge.rotation.set(deg(2), 0, 0);
root.add(tabHinge);
const tab = new THREE.Mesh(extrude([[-0.006, -0.004], [0.006, -0.004], [0.0075, 0.006], [0.0072, 0.012], [0.004, 0.016], [-0.004, 0.016], [-0.0072, 0.012], [-0.0075, 0.006]], 0.0012, [[[-0.0042, 0.006], [0.0042, 0.006], [0.0045, 0.0105], [0.0025, 0.013], [-0.0025, 0.013], [-0.0045, 0.0105]]]), aluMat);
tab.name = 'tab';
tab.rotation.set(deg(-90), 0, 0);
tabHinge.add(tab);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createSodaCan;
Valoraciones y comentarios
0 comentarios
Aún no hay comentarios. Cuenta cómo usaste este modelo o qué se podría mejorar.
Modelos relacionados
Misma categoría o etiquetas similares









