Codels
1386 Tris1,62 × 1,00 × 1,90 m

Im Code verwenden

Im Editor remixen
Eigenständiges ES-Modul — hängt nur von three ab. Ruf die Factory auf und füge die Gruppe deiner Szene hinzu.
/**
 * Pirate Cannon — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,386 · Size (W × H × D): 1.62 × 1.00 × 1.90 m
 *
 * Usage:
 *   import { createCannon } from './cannon.js';
 *   
 *   const model = createCannon();
 *   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 createCannon() {
  const root = new THREE.Group();
  root.name = 'Cannon';

  // Materials
  const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0x8a5a2b, roughness: 0.85, flatShading: true });
  const woodDarkMat = new THREE.MeshStandardMaterial({ name: 'woodDark', color: 0x613f1e, roughness: 0.9, flatShading: true });
  const ironMat = new THREE.MeshStandardMaterial({ name: 'iron', color: 0x33383f, roughness: 0.45, metalness: 0.6, flatShading: true });
  const ironDarkMat = new THREE.MeshStandardMaterial({ name: 'ironDark', color: 0x1c1f23, roughness: 0.6, metalness: 0.4, flatShading: true });
  const brassMat = new THREE.MeshStandardMaterial({ name: 'brass', color: 0xc8a24a, roughness: 0.35, metalness: 0.7, flatShading: true });
  const boreMat = new THREE.MeshStandardMaterial({ name: 'bore', color: 0x0d0e10, roughness: 1, flatShading: true });
  const sparkMat = new THREE.MeshStandardMaterial({ name: 'spark', color: 0xffd36b, roughness: 0.4, emissive: 0xff9a1f, emissiveIntensity: 1.4, flatShading: true });

  // Shared geometries
  const extrudeGeo = extrude([[0.58, 0.12], [0.58, 0.5], [0.4, 0.6], [0.36, 0.54], [0.2, 0.54], [0.14, 0.6], [0.04, 0.54], [0.04, 0.44], [-0.2, 0.44], [-0.2, 0.34], [-0.42, 0.34], [-0.42, 0.24], [-0.62, 0.24], [-0.62, 0.12]], 0.12);
  const boxGeo = new THREE.BoxGeometry(0.14, 0.04, 0.26);
  const torusGeo = new THREE.TorusGeometry(0.04, 0.012, 3, 6);
  const boxGeo2 = new THREE.BoxGeometry(0.96, 0.11, 0.13);
  const cylinderGeo = new THREE.CylinderGeometry(0.21, 0.21, 0.1, 10);
  const cylinderGeo2 = new THREE.CylinderGeometry(0.084, 0.084, 0.12, 8);
  const cylinderGeo3 = new THREE.CylinderGeometry(0.18, 0.18, 0.1, 10);
  const cylinderGeo4 = new THREE.CylinderGeometry(0.072, 0.072, 0.12, 8);
  const sphereGeo = new THREE.SphereGeometry(0.1, 7, 5);

  // Parts
  const cheekLeft = new THREE.Mesh(extrudeGeo, woodMat);
  cheekLeft.name = 'cheekLeft';
  cheekLeft.position.set(-0.3, 0, 0);
  cheekLeft.rotation.set(0, deg(-90), 0);
  root.add(cheekLeft);
  const capSquareLeft = new THREE.Mesh(boxGeo, ironDarkMat);
  capSquareLeft.name = 'capSquareLeft';
  capSquareLeft.position.set(-0.3, 0.64, 0.28);
  root.add(capSquareLeft);
  const torus3 = new THREE.Mesh(torusGeo, ironDarkMat);
  torus3.position.set(-0.37, 0.3, -0.35);
  torus3.rotation.set(0, deg(90), 0);
  root.add(torus3);
  const torus4 = new THREE.Mesh(torusGeo, ironDarkMat);
  torus4.position.set(-0.37, 0.3, 0.45);
  torus4.rotation.set(0, deg(90), 0);
  root.add(torus4);
  const cheekRight = new THREE.Mesh(extrudeGeo, woodMat);
  cheekRight.name = 'cheekRight';
  cheekRight.position.set(0.3, 0, 0);
  cheekRight.rotation.set(0, deg(-90), 0);
  root.add(cheekRight);
  const capSquareRight = new THREE.Mesh(boxGeo, ironDarkMat);
  capSquareRight.name = 'capSquareRight';
  capSquareRight.position.set(0.3, 0.64, 0.28);
  root.add(capSquareRight);
  const torus7 = new THREE.Mesh(torusGeo, ironDarkMat);
  torus7.position.set(0.37, 0.3, -0.35);
  torus7.rotation.set(0, deg(90), 0);
  root.add(torus7);
  const torus8 = new THREE.Mesh(torusGeo, ironDarkMat);
  torus8.position.set(0.37, 0.3, 0.45);
  torus8.rotation.set(0, deg(90), 0);
  root.add(torus8);
  const bed = new THREE.Mesh(new THREE.BoxGeometry(0.6, 0.06, 0.95), woodDarkMat);
  bed.name = 'bed';
  bed.position.set(0, 0.19, -0.05);
  root.add(bed);
  const transom = new THREE.Mesh(new THREE.BoxGeometry(0.48, 0.18, 0.1), woodMat);
  transom.name = 'transom';
  transom.position.set(0, 0.31, 0.46);
  root.add(transom);
  const quoin = new THREE.Mesh(new THREE.BoxGeometry(0.3, 0.1, 0.36), woodMat);
  quoin.name = 'quoin';
  quoin.position.set(0, 0.27, -0.32);
  quoin.rotation.set(deg(-8), 0, 0);
  root.add(quoin);
  const axleFront = new THREE.Mesh(boxGeo2, woodDarkMat);
  axleFront.name = 'axleFront';
  axleFront.position.set(0, 0.21, 0.4);
  root.add(axleFront);
  const wheelFL = new THREE.Mesh(cylinderGeo, woodMat);
  wheelFL.name = 'wheelFL';
  wheelFL.position.set(-0.45, 0.21, 0.4);
  wheelFL.rotation.set(0, 0, deg(90));
  root.add(wheelFL);
  const cylinder14 = new THREE.Mesh(cylinderGeo2, ironDarkMat);
  cylinder14.position.set(-0.45, 0.21, 0.4);
  cylinder14.rotation.set(0, 0, deg(90));
  root.add(cylinder14);
  const wheelFR = new THREE.Mesh(cylinderGeo, woodMat);
  wheelFR.name = 'wheelFR';
  wheelFR.position.set(0.45, 0.21, 0.4);
  wheelFR.rotation.set(0, 0, deg(90));
  root.add(wheelFR);
  const cylinder16 = new THREE.Mesh(cylinderGeo2, ironDarkMat);
  cylinder16.position.set(0.45, 0.21, 0.4);
  cylinder16.rotation.set(0, 0, deg(90));
  root.add(cylinder16);
  const axleRear = new THREE.Mesh(boxGeo2, woodDarkMat);
  axleRear.name = 'axleRear';
  axleRear.position.set(0, 0.18, -0.46);
  root.add(axleRear);
  const wheelRL = new THREE.Mesh(cylinderGeo3, woodMat);
  wheelRL.name = 'wheelRL';
  wheelRL.position.set(-0.45, 0.18, -0.46);
  wheelRL.rotation.set(0, 0, deg(90));
  root.add(wheelRL);
  const cylinder19 = new THREE.Mesh(cylinderGeo4, ironDarkMat);
  cylinder19.position.set(-0.45, 0.18, -0.46);
  cylinder19.rotation.set(0, 0, deg(90));
  root.add(cylinder19);
  const wheelRR = new THREE.Mesh(cylinderGeo3, woodMat);
  wheelRR.name = 'wheelRR';
  wheelRR.position.set(0.45, 0.18, -0.46);
  wheelRR.rotation.set(0, 0, deg(90));
  root.add(wheelRR);
  const cylinder21 = new THREE.Mesh(cylinderGeo4, ironDarkMat);
  cylinder21.position.set(0.45, 0.18, -0.46);
  cylinder21.rotation.set(0, 0, deg(90));
  root.add(cylinder21);
  const barrel = new THREE.Group();
  barrel.name = 'barrel';
  barrel.position.set(0, 0.62, 0.28);
  barrel.rotation.set(deg(-12), 0, 0);
  root.add(barrel);
  const tube2 = new THREE.Mesh(lathe([[0, -0.6], [0.055, -0.585], [0.065, -0.55], [0.035, -0.52], [0.06, -0.5], [0.17, -0.46], [0.205, -0.42], [0.205, -0.37], [0.19, -0.35], [0.19, -0.03], [0.205, -0.01], [0.205, 0.05], [0.18, 0.07], [0.15, 0.72], [0.165, 0.74], [0.165, 0.79], [0.15, 0.81], [0.15, 0.84], [0.18, 0.9], [0.18, 0.96], [0.1, 0.96], [0, 0.96]], 10), ironMat);
  tube2.name = 'tube';
  tube2.rotation.set(deg(90), 0, 0);
  barrel.add(tube2);
  const bore = new THREE.Mesh(new THREE.CircleGeometry(0.1, 10), boreMat);
  bore.name = 'bore';
  bore.position.set(0, 0, 0.962);
  barrel.add(bore);
  const trunnions = new THREE.Mesh(new THREE.CylinderGeometry(0.065, 0.065, 0.672, 8), ironMat);
  trunnions.name = 'trunnions';
  trunnions.rotation.set(0, 0, deg(90));
  barrel.add(trunnions);
  const vent = new THREE.Mesh(new THREE.CylinderGeometry(0.025, 0.03, 0.04, 6), brassMat);
  vent.name = 'vent';
  vent.position.set(0, 0.19, -0.3);
  barrel.add(vent);
  const fuse = new THREE.Mesh(tube([[0, 0.2, -0.3], [0.02, 0.26, -0.32], [0.05, 0.29, -0.36]], 0.008, 6, 4), woodDarkMat);
  fuse.name = 'fuse';
  barrel.add(fuse);
  const fuseSpark = new THREE.Mesh(new THREE.OctahedronGeometry(0.035, 0), sparkMat);
  fuseSpark.name = 'fuseSpark';
  fuseSpark.position.set(0.05, 0.3, -0.37);
  fuseSpark.rotation.set(deg(20), deg(30), 0);
  barrel.add(fuseSpark);
  const cannonballs = new THREE.Group();
  cannonballs.name = 'cannonballs';
  cannonballs.position.set(0.92, 0, -0.25);
  root.add(cannonballs);
  const sphere30 = new THREE.Mesh(sphereGeo, ironDarkMat);
  sphere30.position.set(0, 0.1, -0.1155);
  cannonballs.add(sphere30);
  const sphere31 = new THREE.Mesh(sphereGeo, ironDarkMat);
  sphere31.position.set(0.1, 0.1, 0.0577);
  cannonballs.add(sphere31);
  const sphere32 = new THREE.Mesh(sphereGeo, ironDarkMat);
  sphere32.position.set(-0.1, 0.1, 0.0577);
  cannonballs.add(sphere32);
  const sphere33 = new THREE.Mesh(sphereGeo, ironDarkMat);
  sphere33.position.set(0, 0.2633, 0);
  cannonballs.add(sphere33);

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

export default createCannon;

Bewertungen & Kommentare

—
Noch keine Bewertungen — gib die erste ab.
5
0
4
0
3
0
2
0
1
0

Melde dich an, um zu bewerten und zu kommentieren.

0 Kommentare

Noch keine Kommentare. Erzähl, wie du dieses Modell genutzt hast oder was besser sein könnte.

Ähnliche Modelle

Gleiche Kategorie oder ähnliche Tags