Codels
1,1 mil tris0,74 × 0,74 × 0,17 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.
/**
 * Round Shield — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,056 · Size (W × H × D): 0.74 × 0.74 × 0.17 m
 *
 * Usage:
 *   import { createRoundShield } from './round-shield.js';
 *   
 *   const model = createRoundShield();
 *   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 createRoundShield() {
  const root = new THREE.Group();
  root.name = 'RoundShield';

  // Materials
  const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0xa0703f, roughness: 0.9, flatShading: true });
  const seamMat = new THREE.MeshStandardMaterial({ name: 'seam', color: 0x5a3b20, roughness: 0.95, flatShading: true });
  const paintMat = new THREE.MeshStandardMaterial({ name: 'paint', color: 0xb5382d, roughness: 0.8, flatShading: true });
  const ironMat = new THREE.MeshStandardMaterial({ name: 'iron', color: 0x7d8590, roughness: 0.45, metalness: 0.7, flatShading: true });
  const bossMat = new THREE.MeshStandardMaterial({ name: 'boss', color: 0xaeb6bf, roughness: 0.35, metalness: 0.75, flatShading: true });
  const leatherMat = new THREE.MeshStandardMaterial({ name: 'leather', color: 0x5b3a22, roughness: 0.9, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(0.007, 0.5297, 0.006);
  const boxGeo2 = new THREE.BoxGeometry(0.007, 0.6613, 0.006);
  const sphereGeo = new THREE.SphereGeometry(0.009, 5, 3);
  const sphereGeo2 = new THREE.SphereGeometry(0.011, 5, 3);
  const boxGeo3 = new THREE.BoxGeometry(0.03, 0.035, 0.04);

  // Parts
  const board = new THREE.Mesh(new THREE.CylinderGeometry(0.35, 0.35, 0.03, 20), woodMat);
  board.name = 'board';
  board.position.set(0, 0.372, 0);
  board.rotation.set(deg(90), 0, 0);
  root.add(board);
  const rim = new THREE.Mesh(new THREE.TorusGeometry(0.35, 0.022, 6, 28), ironMat);
  rim.name = 'rim';
  rim.position.set(0, 0.372, 0);
  root.add(rim);
  const seamF2 = new THREE.Mesh(boxGeo, seamMat);
  seamF2.name = 'seamF2';
  seamF2.position.set(-0.21, 0.372, 0.017);
  root.add(seamF2);
  const seamB2 = new THREE.Mesh(boxGeo, seamMat);
  seamB2.name = 'seamB2';
  seamB2.position.set(-0.21, 0.372, -0.017);
  root.add(seamB2);
  const seamF4 = new THREE.Mesh(boxGeo2, seamMat);
  seamF4.name = 'seamF4';
  seamF4.position.set(-0.07, 0.372, 0.017);
  root.add(seamF4);
  const seamB4 = new THREE.Mesh(boxGeo2, seamMat);
  seamB4.name = 'seamB4';
  seamB4.position.set(-0.07, 0.372, -0.017);
  root.add(seamB4);
  const seamF6 = new THREE.Mesh(boxGeo2, seamMat);
  seamF6.name = 'seamF6';
  seamF6.position.set(0.07, 0.372, 0.017);
  root.add(seamF6);
  const seamB6 = new THREE.Mesh(boxGeo2, seamMat);
  seamB6.name = 'seamB6';
  seamB6.position.set(0.07, 0.372, -0.017);
  root.add(seamB6);
  const seamF8 = new THREE.Mesh(boxGeo, seamMat);
  seamF8.name = 'seamF8';
  seamF8.position.set(0.21, 0.372, 0.017);
  root.add(seamF8);
  const seamB8 = new THREE.Mesh(boxGeo, seamMat);
  seamB8.name = 'seamB8';
  seamB8.position.set(0.21, 0.372, -0.017);
  root.add(seamB8);
  const paint1 = new THREE.Mesh(extrude([[0, 0], [0.239, 0.239], [0.169, 0.2927], [0.0875, 0.3265], [0, 0.338], [-0.0875, 0.3265], [-0.169, 0.2927], [-0.239, 0.239]], 0.004), paintMat);
  paint1.name = 'paint1';
  paint1.position.set(0, 0.372, 0.016);
  root.add(paint1);
  const paint2 = new THREE.Mesh(extrude([[0, 0], [-0.239, -0.239], [-0.169, -0.2927], [-0.0875, -0.3265], [0, -0.338], [0.0875, -0.3265], [0.169, -0.2927], [0.239, -0.239]], 0.004), paintMat);
  paint2.name = 'paint2';
  paint2.position.set(0, 0.372, 0.016);
  root.add(paint2);
  const bossFlange = new THREE.Mesh(new THREE.CylinderGeometry(0.11, 0.11, 0.01, 12), ironMat);
  bossFlange.name = 'bossFlange';
  bossFlange.position.set(0, 0.372, 0.019);
  bossFlange.rotation.set(deg(90), 0, 0);
  root.add(bossFlange);
  const boss = new THREE.Mesh(new THREE.SphereGeometry(0.085, 12, 4, 0, Math.PI * 2, 0, Math.PI / 2), bossMat);
  boss.name = 'boss';
  boss.position.set(0, 0.372, 0.023);
  boss.rotation.set(deg(90), 0, 0);
  root.add(boss);
  const bossRivet1 = new THREE.Mesh(sphereGeo, bossMat);
  bossRivet1.name = 'bossRivet1';
  bossRivet1.position.set(0.0849, 0.421, 0.024);
  root.add(bossRivet1);
  const bossRivet2 = new THREE.Mesh(sphereGeo, bossMat);
  bossRivet2.name = 'bossRivet2';
  bossRivet2.position.set(0, 0.47, 0.024);
  root.add(bossRivet2);
  const bossRivet3 = new THREE.Mesh(sphereGeo, bossMat);
  bossRivet3.name = 'bossRivet3';
  bossRivet3.position.set(-0.0849, 0.421, 0.024);
  root.add(bossRivet3);
  const bossRivet4 = new THREE.Mesh(sphereGeo, bossMat);
  bossRivet4.name = 'bossRivet4';
  bossRivet4.position.set(-0.0849, 0.323, 0.024);
  root.add(bossRivet4);
  const bossRivet5 = new THREE.Mesh(sphereGeo, bossMat);
  bossRivet5.name = 'bossRivet5';
  bossRivet5.position.set(0, 0.274, 0.024);
  root.add(bossRivet5);
  const bossRivet6 = new THREE.Mesh(sphereGeo, bossMat);
  bossRivet6.name = 'bossRivet6';
  bossRivet6.position.set(0.0849, 0.323, 0.024);
  root.add(bossRivet6);
  const rimRivet1 = new THREE.Mesh(sphereGeo2, ironMat);
  rimRivet1.name = 'rimRivet1';
  rimRivet1.position.set(0.2996, 0.4693, 0.019);
  root.add(rimRivet1);
  const rimRivet2 = new THREE.Mesh(sphereGeo2, ironMat);
  rimRivet2.name = 'rimRivet2';
  rimRivet2.position.set(0.1852, 0.6268, 0.019);
  root.add(rimRivet2);
  const rimRivet3 = new THREE.Mesh(sphereGeo2, ironMat);
  rimRivet3.name = 'rimRivet3';
  rimRivet3.position.set(0, 0.687, 0.019);
  root.add(rimRivet3);
  const rimRivet4 = new THREE.Mesh(sphereGeo2, ironMat);
  rimRivet4.name = 'rimRivet4';
  rimRivet4.position.set(-0.1852, 0.6268, 0.019);
  root.add(rimRivet4);
  const rimRivet5 = new THREE.Mesh(sphereGeo2, ironMat);
  rimRivet5.name = 'rimRivet5';
  rimRivet5.position.set(-0.2996, 0.4693, 0.019);
  root.add(rimRivet5);
  const rimRivet6 = new THREE.Mesh(sphereGeo2, ironMat);
  rimRivet6.name = 'rimRivet6';
  rimRivet6.position.set(-0.2996, 0.2747, 0.019);
  root.add(rimRivet6);
  const rimRivet7 = new THREE.Mesh(sphereGeo2, ironMat);
  rimRivet7.name = 'rimRivet7';
  rimRivet7.position.set(-0.1852, 0.1172, 0.019);
  root.add(rimRivet7);
  const rimRivet8 = new THREE.Mesh(sphereGeo2, ironMat);
  rimRivet8.name = 'rimRivet8';
  rimRivet8.position.set(0, 0.057, 0.019);
  root.add(rimRivet8);
  const rimRivet9 = new THREE.Mesh(sphereGeo2, ironMat);
  rimRivet9.name = 'rimRivet9';
  rimRivet9.position.set(0.1852, 0.1172, 0.019);
  root.add(rimRivet9);
  const rimRivet10 = new THREE.Mesh(sphereGeo2, ironMat);
  rimRivet10.name = 'rimRivet10';
  rimRivet10.position.set(0.2996, 0.2747, 0.019);
  root.add(rimRivet10);
  const grip = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.035, 0.03), leatherMat);
  grip.name = 'grip';
  grip.position.set(0, 0.372, -0.05);
  root.add(grip);
  const gripMountR = new THREE.Mesh(boxGeo3, ironMat);
  gripMountR.name = 'gripMountR';
  gripMountR.position.set(0.11, 0.372, -0.035);
  root.add(gripMountR);
  const gripMountL = new THREE.Mesh(boxGeo3, ironMat);
  gripMountL.name = 'gripMountL';
  gripMountL.position.set(-0.11, 0.372, -0.035);
  root.add(gripMountL);

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

export default createRoundShield;

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