Codels
944 tris0,07 × 0,12 × 0,07 m

Úsalo en código

Hacer remix en el editor
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

—
Aún no hay valoraciones — sé el primero.
5
0
4
0
3
0
2
0
1
0

Inicia sesión para valorar y comentar.

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