Codels
1,5 mil tris1,20 × 2,28 × 1,25 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.
/**
 * Cryo Pod — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,478 · Size (W × H × D): 1.20 × 2.28 × 1.25 m
 *
 * Usage:
 *   import { createCryoPod } from './cryo-pod.js';
 *   
 *   const model = createCryoPod();
 *   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);
}

// Tube along a smooth curve through the given points.
function tube(path, radius, tubularSegments, radialSegments, closed = false) {
  const curve = new THREE.CatmullRomCurve3(path.map(([x, y, z]) => new THREE.Vector3(x, y, z)), closed);
  return new THREE.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
}

export function createCryoPod() {
  const root = new THREE.Group();
  root.name = 'CryoPod';

  // Materials
  const shellMat = new THREE.MeshStandardMaterial({ name: 'shell', color: 0xd4dae1, roughness: 0.45, metalness: 0.3, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x2f343c, roughness: 0.6, metalness: 0.35, flatShading: true });
  const metalMat = new THREE.MeshStandardMaterial({ name: 'metal', color: 0x8a929c, roughness: 0.4, metalness: 0.6, flatShading: true });
  const glowMat = new THREE.MeshStandardMaterial({ name: 'glow', color: 0x5ee2ff, roughness: 0.4, emissive: 0x5ee2ff, emissiveIntensity: 1.2, flatShading: true });
  const innerMat = new THREE.MeshStandardMaterial({ name: 'inner', color: 0x2a3a46, roughness: 0.7, emissive: 0x5ee2ff, emissiveIntensity: 0.25, flatShading: true });
  const glassMat = new THREE.MeshStandardMaterial({ name: 'glass', color: 0xdcf5ff, roughness: 0.15, metalness: 0.1, transparent: true, opacity: 0.55, side: THREE.DoubleSide });
  const sleeperMat = new THREE.MeshStandardMaterial({ name: 'sleeper', color: 0xa9c4d2, roughness: 0.75, flatShading: true });
  const redMat = new THREE.MeshStandardMaterial({ name: 'red', color: 0xff5a4a, roughness: 0.4, emissive: 0xff3b2f, emissiveIntensity: 1.2, flatShading: true });
  const greenMat = new THREE.MeshStandardMaterial({ name: 'green', color: 0x8cff6a, roughness: 0.4, emissive: 0x66ff3c, emissiveIntensity: 1.1, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(0.04, 0.04, 0.02);
  const boxGeo2 = new THREE.BoxGeometry(0.03, 1.2, 0.03);
  const boxGeo3 = new THREE.BoxGeometry(0.1, 1.5, 0.14);
  const boxGeo4 = new THREE.BoxGeometry(0.12, 0.12, 0.17);
  const cylinderGeo = new THREE.CylinderGeometry(0.055, 0.055, 0.06, 6);
  const capsuleGeo = new THREE.CapsuleGeometry(0.07, 0.62, 2, 5);
  const capsuleGeo2 = new THREE.CapsuleGeometry(0.055, 0.5, 2, 5);

  // Parts
  const plinth = new THREE.Mesh(extrude([[-0.44, -0.56], [0.44, -0.56], [0.6, -0.4], [0.6, 0.4], [0.44, 0.56], [-0.44, 0.56], [-0.6, 0.4], [-0.6, -0.4]], 0.18), shellMat);
  plinth.name = 'plinth';
  plinth.position.set(0, 0.09, 0);
  plinth.rotation.set(deg(90), 0, 0);
  root.add(plinth);
  const plinthTop = new THREE.Mesh(extrude([[-0.396, -0.504], [0.396, -0.504], [0.54, -0.36], [0.54, 0.36], [0.396, 0.504], [-0.396, 0.504], [-0.54, 0.36], [-0.54, -0.36]], 0.06), darkMat);
  plinthTop.name = 'plinthTop';
  plinthTop.position.set(0, 0.21, 0);
  plinthTop.rotation.set(deg(90), 0, 0);
  root.add(plinthTop);
  const collar = new THREE.Mesh(new THREE.CylinderGeometry(0.52, 0.54, 0.12, 10), darkMat);
  collar.name = 'collar';
  collar.position.set(0, 0.3, 0);
  root.add(collar);
  const collarLight = new THREE.Mesh(new THREE.TorusGeometry(0.53, 0.014, 3, 10), glowMat);
  collarLight.name = 'collarLight';
  collarLight.position.set(0, 0.33, 0);
  collarLight.rotation.set(deg(90), 0, 0);
  root.add(collarLight);
  const statusPanel = new THREE.Mesh(new THREE.BoxGeometry(0.5, 0.11, 0.03), darkMat);
  statusPanel.name = 'statusPanel';
  statusPanel.position.set(0, 0.1, 0.565);
  root.add(statusPanel);
  const statusDisplay = new THREE.Mesh(new THREE.BoxGeometry(0.16, 0.06, 0.02), glowMat);
  statusDisplay.name = 'statusDisplay';
  statusDisplay.position.set(-0.12, 0.1, 0.58);
  root.add(statusDisplay);
  const statusLight1 = new THREE.Mesh(boxGeo, greenMat);
  statusLight1.name = 'statusLight1';
  statusLight1.position.set(0.06, 0.1, 0.58);
  root.add(statusLight1);
  const statusLight2 = new THREE.Mesh(boxGeo, glowMat);
  statusLight2.name = 'statusLight2';
  statusLight2.position.set(0.125, 0.1, 0.58);
  root.add(statusLight2);
  const statusLight3 = new THREE.Mesh(boxGeo, redMat);
  statusLight3.name = 'statusLight3';
  statusLight3.position.set(0.19, 0.1, 0.58);
  root.add(statusLight3);
  const backShell = new THREE.Mesh(lathe([[0.46, 0.36], [0.46, 1.78], [0.4048, 2], [0.2392, 2.15], [0.001, 2.2], [0.001, 2.15], [0.1892, 2.1], [0.3548, 1.95], [0.41, 1.73], [0.41, 0.36]], 8, Math.PI / 2, Math.PI), shellMat);
  backShell.name = 'backShell';
  root.add(backShell);
  const innerLining = new THREE.Mesh(lathe([[0.001, 2.15], [0.1792, 2.1], [0.3448, 1.95], [0.4, 1.73], [0.4, 0.36]], 8, Math.PI / 2, Math.PI), innerMat);
  innerLining.name = 'innerLining';
  root.add(innerLining);
  const innerStripL = new THREE.Mesh(boxGeo2, glowMat);
  innerStripL.name = 'innerStripL';
  innerStripL.position.set(-0.2, 1.15, -0.33);
  innerStripL.rotation.set(0, deg(-25), 0);
  root.add(innerStripL);
  const innerStripR = new THREE.Mesh(boxGeo2, glowMat);
  innerStripR.name = 'innerStripR';
  innerStripR.position.set(0.2, 1.15, -0.33);
  innerStripR.rotation.set(0, deg(25), 0);
  root.add(innerStripR);
  const headRest = new THREE.Mesh(new THREE.BoxGeometry(0.3, 0.06, 0.1), darkMat);
  headRest.name = 'headRest';
  headRest.position.set(0, 1.96, -0.33);
  root.add(headRest);
  const railL = new THREE.Mesh(boxGeo3, shellMat);
  railL.name = 'railL';
  railL.position.set(-0.48, 1.11, 0);
  root.add(railL);
  const railLightL = new THREE.Mesh(boxGeo2, glowMat);
  railLightL.name = 'railLightL';
  railLightL.position.set(-0.535, 1.11, 0);
  root.add(railLightL);
  const hingeTopL = new THREE.Mesh(boxGeo4, darkMat);
  hingeTopL.name = 'hingeTopL';
  hingeTopL.position.set(-0.48, 1.84, 0);
  root.add(hingeTopL);
  const railR = new THREE.Mesh(boxGeo3, shellMat);
  railR.name = 'railR';
  railR.position.set(0.48, 1.11, 0);
  root.add(railR);
  const railLightR = new THREE.Mesh(boxGeo2, glowMat);
  railLightR.name = 'railLightR';
  railLightR.position.set(0.535, 1.11, 0);
  root.add(railLightR);
  const hingeTopR = new THREE.Mesh(boxGeo4, darkMat);
  hingeTopR.name = 'hingeTopR';
  hingeTopR.position.set(0.48, 1.84, 0);
  root.add(hingeTopR);
  const sideScreenFrame = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.26, 0.03), darkMat);
  sideScreenFrame.name = 'sideScreenFrame';
  sideScreenFrame.position.set(-0.2573, 1.2, -0.3851);
  sideScreenFrame.rotation.set(deg(-180), deg(-33.75), deg(-180));
  root.add(sideScreenFrame);
  const sideScreen = new THREE.Mesh(new THREE.BoxGeometry(0.15, 0.2, 0.02), glowMat);
  sideScreen.name = 'sideScreen';
  sideScreen.position.set(-0.2651, 1.2, -0.3967);
  sideScreen.rotation.set(deg(-180), deg(-33.75), deg(-180));
  root.add(sideScreen);
  const topVent = new THREE.Mesh(new THREE.CylinderGeometry(0.16, 0.2, 0.08, 8), darkMat);
  topVent.name = 'topVent';
  topVent.position.set(0, 2.21, -0.05);
  root.add(topVent);
  const topLight = new THREE.Mesh(new THREE.CylinderGeometry(0.1, 0.1, 0.03, 8), glowMat);
  topLight.name = 'topLight';
  topLight.position.set(0, 2.265, -0.05);
  root.add(topLight);
  const pipeL = new THREE.Mesh(tube([[-0.14, 2, -0.3], [-0.2, 1.9, -0.58], [-0.22, 1.2, -0.6], [-0.22, 0.45, -0.6], [-0.2, 0.2, -0.5]], 0.035, 8, 5), metalMat);
  pipeL.name = 'pipeL';
  root.add(pipeL);
  const pipeClampL = new THREE.Mesh(cylinderGeo, darkMat);
  pipeClampL.name = 'pipeClampL';
  pipeClampL.position.set(-0.22, 1.2, -0.6);
  root.add(pipeClampL);
  const pipeR = new THREE.Mesh(tube([[0.14, 2, -0.3], [0.2, 1.9, -0.58], [0.22, 1.2, -0.6], [0.22, 0.45, -0.6], [0.2, 0.2, -0.5]], 0.035, 8, 5), metalMat);
  pipeR.name = 'pipeR';
  root.add(pipeR);
  const pipeClampR = new THREE.Mesh(cylinderGeo, darkMat);
  pipeClampR.name = 'pipeClampR';
  pipeClampR.position.set(0.22, 1.2, -0.6);
  root.add(pipeClampR);
  const coolantBox = new THREE.Mesh(new THREE.BoxGeometry(0.34, 0.5, 0.12), darkMat);
  coolantBox.name = 'coolantBox';
  coolantBox.position.set(0, 1, -0.5);
  root.add(coolantBox);
  const coolantLight = new THREE.Mesh(new THREE.BoxGeometry(0.22, 0.04, 0.02), glowMat);
  coolantLight.name = 'coolantLight';
  coolantLight.position.set(0, 1.12, -0.565);
  coolantLight.rotation.set(0, deg(180), 0);
  root.add(coolantLight);
  const sleeper = new THREE.Group();
  sleeper.name = 'sleeper';
  sleeper.position.set(0, 0, -0.08);
  root.add(sleeper);
  const legL = new THREE.Mesh(capsuleGeo, sleeperMat);
  legL.name = 'legL';
  legL.position.set(-0.09, 0.79, 0);
  sleeper.add(legL);
  const armL = new THREE.Mesh(capsuleGeo2, sleeperMat);
  armL.name = 'armL';
  armL.position.set(-0.23, 1.35, 0.02);
  armL.rotation.set(0, 0, deg(-6));
  sleeper.add(armL);
  const legR = new THREE.Mesh(capsuleGeo, sleeperMat);
  legR.name = 'legR';
  legR.position.set(0.09, 0.79, 0);
  sleeper.add(legR);
  const armR = new THREE.Mesh(capsuleGeo2, sleeperMat);
  armR.name = 'armR';
  armR.position.set(0.23, 1.35, 0.02);
  armR.rotation.set(0, 0, deg(6));
  sleeper.add(armR);
  const torso = new THREE.Mesh(new THREE.CapsuleGeometry(0.15, 0.32, 2, 7), sleeperMat);
  torso.name = 'torso';
  torso.position.set(0, 1.42, 0);
  torso.scale.set(1, 1, 0.7);
  sleeper.add(torso);
  const neck = new THREE.Mesh(new THREE.CylinderGeometry(0.05, 0.06, 0.08, 6), sleeperMat);
  neck.name = 'neck';
  neck.position.set(0, 1.74, 0);
  sleeper.add(neck);
  const head = new THREE.Mesh(new THREE.SphereGeometry(0.11, 6, 5), sleeperMat);
  head.name = 'head';
  head.position.set(0, 1.86, 0.01);
  sleeper.add(head);
  const door = new THREE.Group();
  door.name = 'door';
  door.position.set(0.46, 0, 0);
  root.add(door);
  const glassDoor = new THREE.Mesh(lathe([[0.44, 0.4], [0.44, 1.76], [0.3848, 1.98], [0.2192, 2.13], [0.001, 2.18]], 8, -Math.PI / 2, Math.PI), glassMat);
  glassDoor.name = 'glassDoor';
  glassDoor.position.set(-0.46, 0, 0);
  door.add(glassDoor);
  const doorFrame = new THREE.Mesh(tube([[-0.02, 0.4, 0], [-0.02, 1.76, 0], [-0.0752, 1.98, 0], [-0.2408, 2.13, 0], [-0.459, 2.18, 0], [-0.6792, 2.13, 0], [-0.8448, 1.98, 0], [-0.9, 1.76, 0], [-0.9, 0.4, 0]], 0.025, 16, 4), darkMat);
  doorFrame.name = 'doorFrame';
  door.add(doorFrame);
  const frostBand = new THREE.Mesh(lathe([[0.448, 0.41], [0.448, 0.62], [0.448, 0.8]], 8, -Math.PI / 2, Math.PI), glassMat);
  frostBand.name = 'frostBand';
  frostBand.position.set(-0.46, 0, 0);
  door.add(frostBand);
  const doorSill = new THREE.Mesh(new THREE.TorusGeometry(0.44, 0.03, 3, 8, Math.PI), darkMat);
  doorSill.name = 'doorSill';
  doorSill.position.set(-0.46, 0.4, 0);
  doorSill.rotation.set(deg(90), 0, 0);
  door.add(doorSill);
  const handle = new THREE.Mesh(new THREE.BoxGeometry(0.04, 0.32, 0.05), metalMat);
  handle.name = 'handle';
  handle.position.set(-0.76, 1.2, 0.34);
  door.add(handle);

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

export default createCryoPod;

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