Codels
1,2 mil tris2,13 × 1,18 × 1,27 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.
/**
 * Bridge Plank Segment — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,168 · Size (W × H × D): 2.13 × 1.18 × 1.27 m
 *
 * Usage:
 *   import { createBridgePlank } from './bridge-plank.js';
 *   
 *   const model = createBridgePlank();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// 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 createBridgePlank() {
  const root = new THREE.Group();
  root.name = 'BridgePlank';

  // Materials
  const plankMat = new THREE.MeshStandardMaterial({ name: 'plank', color: 0xa8743f, roughness: 0.9, flatShading: true });
  const plankAltMat = new THREE.MeshStandardMaterial({ name: 'plankAlt', color: 0x906436, roughness: 0.9, flatShading: true });
  const ropeMat = new THREE.MeshStandardMaterial({ name: 'rope', color: 0xd2b07a, roughness: 1, flatShading: true });
  const knotMat = new THREE.MeshStandardMaterial({ name: 'knot', color: 0x9c7a46, roughness: 1, flatShading: true });
  const postMat = new THREE.MeshStandardMaterial({ name: 'post', color: 0x76512c, roughness: 0.9, flatShading: true });

  // Shared geometries
  const cylinderGeo = new THREE.CylinderGeometry(0.028, 0.028, 2, 6);
  const boxGeo = new THREE.BoxGeometry(0.22, 0.02, 0.07);
  const cylinderGeo2 = new THREE.CylinderGeometry(0.013, 0.013, 0.8309, 5);
  const sphereGeo = new THREE.SphereGeometry(0.03, 6, 4);
  const cylinderGeo3 = new THREE.CylinderGeometry(0.013, 0.013, 0.7915, 5);
  const cylinderGeo4 = new THREE.CylinderGeometry(0.06, 0.07, 1.1, 6);
  const coneGeo = new THREE.ConeGeometry(0.07, 0.08, 6);
  const cylinderGeo5 = new THREE.CylinderGeometry(0.075, 0.075, 0.07, 6);

  // Parts
  const deckRopeBack = new THREE.Mesh(cylinderGeo, ropeMat);
  deckRopeBack.name = 'deckRopeBack';
  deckRopeBack.position.set(0, 0.028, -0.4);
  deckRopeBack.rotation.set(0, 0, deg(90));
  root.add(deckRopeBack);
  const deckRopeFront = new THREE.Mesh(cylinderGeo, ropeMat);
  deckRopeFront.name = 'deckRopeFront';
  deckRopeFront.position.set(0, 0.028, 0.4);
  deckRopeFront.rotation.set(0, 0, deg(90));
  root.add(deckRopeFront);
  const planks = new THREE.Group();
  planks.name = 'planks';
  root.add(planks);
  const plank1 = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.06, 1.0024), plankMat);
  plank1.name = 'plank1';
  plank1.position.set(-0.8747, 0.086, 0.0036);
  plank1.rotation.set(0, deg(0.6487), deg(1.0523));
  planks.add(plank1);
  const plank2 = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.06, 0.9664), plankAltMat);
  plank2.name = 'plank2';
  plank2.position.set(-0.6241, 0.086, 0.0043);
  plank2.rotation.set(0, deg(0.183), deg(-0.149));
  planks.add(plank2);
  const plank3 = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.06, 1.0275), plankMat);
  plank3.name = 'plank3';
  plank3.position.set(-0.3755, 0.086, 0.0068);
  plank3.rotation.set(0, deg(-0.4801), deg(0.5446));
  planks.add(plank3);
  const plank4 = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.06, 0.9743), plankMat);
  plank4.name = 'plank4';
  plank4.position.set(-0.1331, 0.086, -0.0042);
  plank4.rotation.set(0, deg(-1.3434), deg(-0.3691));
  planks.add(plank4);
  const plank5 = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.06, 0.9702), plankAltMat);
  plank5.name = 'plank5';
  plank5.position.set(0.127, 0.086, 0.0031);
  plank5.rotation.set(0, deg(0.5825), deg(-0.2447));
  planks.add(plank5);
  const plank6 = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.06, 1.0244), plankMat);
  plank6.name = 'plank6';
  plank6.position.set(0.3833, 0.086, -0.0073);
  plank6.rotation.set(0, deg(1.6128), deg(0.3693));
  planks.add(plank6);
  const plank7 = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.06, 0.9645), plankMat);
  plank7.name = 'plank7';
  plank7.position.set(0.619, 0.086, 0.0191);
  plank7.rotation.set(0, deg(1.4455), deg(-0.6095));
  planks.add(plank7);
  const plank8 = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.06, 1.0195), plankAltMat);
  plank8.name = 'plank8';
  plank8.position.set(0.8665, 0.086, 0.0021);
  plank8.rotation.set(0, deg(-0.9167), deg(0.23));
  planks.add(plank8);
  const box12 = new THREE.Mesh(boxGeo, knotMat);
  box12.position.set(-0.875, 0.126, -0.4);
  root.add(box12);
  const box13 = new THREE.Mesh(boxGeo, knotMat);
  box13.position.set(-0.875, 0.126, 0.4);
  root.add(box13);
  const box14 = new THREE.Mesh(boxGeo, knotMat);
  box14.position.set(-0.375, 0.126, -0.4);
  root.add(box14);
  const box15 = new THREE.Mesh(boxGeo, knotMat);
  box15.position.set(-0.375, 0.126, 0.4);
  root.add(box15);
  const box16 = new THREE.Mesh(boxGeo, knotMat);
  box16.position.set(0.125, 0.126, -0.4);
  root.add(box16);
  const box17 = new THREE.Mesh(boxGeo, knotMat);
  box17.position.set(0.125, 0.126, 0.4);
  root.add(box17);
  const box18 = new THREE.Mesh(boxGeo, knotMat);
  box18.position.set(0.625, 0.126, -0.4);
  root.add(box18);
  const box19 = new THREE.Mesh(boxGeo, knotMat);
  box19.position.set(0.625, 0.126, 0.4);
  root.add(box19);
  const handRopeBack = new THREE.Mesh(tube([[-1, 0.92, -0.56], [-0.5, 0.86, -0.56], [0, 0.84, -0.56], [0.5, 0.86, -0.56], [1, 0.92, -0.56]], 0.022, 12, 5), ropeMat);
  handRopeBack.name = 'handRopeBack';
  root.add(handRopeBack);
  const cylinder21 = new THREE.Mesh(cylinderGeo2, ropeMat);
  cylinder21.position.set(-0.75, 0.4755, -0.49);
  cylinder21.rotation.set(deg(-9.7004), 0, 0);
  root.add(cylinder21);
  const sphere22 = new THREE.Mesh(sphereGeo, knotMat);
  sphere22.position.set(-0.75, 0.885, -0.56);
  root.add(sphere22);
  const cylinder23 = new THREE.Mesh(cylinderGeo3, ropeMat);
  cylinder23.position.set(-0.25, 0.4555, -0.49);
  cylinder23.rotation.set(deg(-10.1883), 0, 0);
  root.add(cylinder23);
  const sphere24 = new THREE.Mesh(sphereGeo, knotMat);
  sphere24.position.set(-0.25, 0.845, -0.56);
  root.add(sphere24);
  const cylinder25 = new THREE.Mesh(cylinderGeo3, ropeMat);
  cylinder25.position.set(0.25, 0.4555, -0.49);
  cylinder25.rotation.set(deg(-10.1883), 0, 0);
  root.add(cylinder25);
  const sphere26 = new THREE.Mesh(sphereGeo, knotMat);
  sphere26.position.set(0.25, 0.845, -0.56);
  root.add(sphere26);
  const cylinder27 = new THREE.Mesh(cylinderGeo2, ropeMat);
  cylinder27.position.set(0.75, 0.4755, -0.49);
  cylinder27.rotation.set(deg(-9.7004), 0, 0);
  root.add(cylinder27);
  const sphere28 = new THREE.Mesh(sphereGeo, knotMat);
  sphere28.position.set(0.75, 0.885, -0.56);
  root.add(sphere28);
  const handRopeFront = new THREE.Mesh(tube([[-1, 0.92, 0.56], [-0.5, 0.86, 0.56], [0, 0.84, 0.56], [0.5, 0.86, 0.56], [1, 0.92, 0.56]], 0.022, 12, 5), ropeMat);
  handRopeFront.name = 'handRopeFront';
  root.add(handRopeFront);
  const cylinder30 = new THREE.Mesh(cylinderGeo2, ropeMat);
  cylinder30.position.set(-0.75, 0.4755, 0.49);
  cylinder30.rotation.set(deg(9.7004), 0, 0);
  root.add(cylinder30);
  const sphere31 = new THREE.Mesh(sphereGeo, knotMat);
  sphere31.position.set(-0.75, 0.885, 0.56);
  root.add(sphere31);
  const cylinder32 = new THREE.Mesh(cylinderGeo3, ropeMat);
  cylinder32.position.set(-0.25, 0.4555, 0.49);
  cylinder32.rotation.set(deg(10.1883), 0, 0);
  root.add(cylinder32);
  const sphere33 = new THREE.Mesh(sphereGeo, knotMat);
  sphere33.position.set(-0.25, 0.845, 0.56);
  root.add(sphere33);
  const cylinder34 = new THREE.Mesh(cylinderGeo3, ropeMat);
  cylinder34.position.set(0.25, 0.4555, 0.49);
  cylinder34.rotation.set(deg(10.1883), 0, 0);
  root.add(cylinder34);
  const sphere35 = new THREE.Mesh(sphereGeo, knotMat);
  sphere35.position.set(0.25, 0.845, 0.56);
  root.add(sphere35);
  const cylinder36 = new THREE.Mesh(cylinderGeo2, ropeMat);
  cylinder36.position.set(0.75, 0.4755, 0.49);
  cylinder36.rotation.set(deg(9.7004), 0, 0);
  root.add(cylinder36);
  const sphere37 = new THREE.Mesh(sphereGeo, knotMat);
  sphere37.position.set(0.75, 0.885, 0.56);
  root.add(sphere37);
  const postLBack = new THREE.Mesh(cylinderGeo4, postMat);
  postLBack.name = 'postLBack';
  postLBack.position.set(-1, 0.55, -0.56);
  root.add(postLBack);
  const cone39 = new THREE.Mesh(coneGeo, postMat);
  cone39.position.set(-1, 1.14, -0.56);
  root.add(cone39);
  const cylinder40 = new THREE.Mesh(cylinderGeo5, ropeMat);
  cylinder40.position.set(-1, 0.92, -0.56);
  root.add(cylinder40);
  const postLFront = new THREE.Mesh(cylinderGeo4, postMat);
  postLFront.name = 'postLFront';
  postLFront.position.set(-1, 0.55, 0.56);
  root.add(postLFront);
  const cone42 = new THREE.Mesh(coneGeo, postMat);
  cone42.position.set(-1, 1.14, 0.56);
  root.add(cone42);
  const cylinder43 = new THREE.Mesh(cylinderGeo5, ropeMat);
  cylinder43.position.set(-1, 0.92, 0.56);
  root.add(cylinder43);
  const postRBack = new THREE.Mesh(cylinderGeo4, postMat);
  postRBack.name = 'postRBack';
  postRBack.position.set(1, 0.55, -0.56);
  root.add(postRBack);
  const cone45 = new THREE.Mesh(coneGeo, postMat);
  cone45.position.set(1, 1.14, -0.56);
  root.add(cone45);
  const cylinder46 = new THREE.Mesh(cylinderGeo5, ropeMat);
  cylinder46.position.set(1, 0.92, -0.56);
  root.add(cylinder46);
  const postRFront = new THREE.Mesh(cylinderGeo4, postMat);
  postRFront.name = 'postRFront';
  postRFront.position.set(1, 0.55, 0.56);
  root.add(postRFront);
  const cone48 = new THREE.Mesh(coneGeo, postMat);
  cone48.position.set(1, 1.14, 0.56);
  root.add(cone48);
  const cylinder49 = new THREE.Mesh(cylinderGeo5, ropeMat);
  cylinder49.position.set(1, 0.92, 0.56);
  root.add(cylinder49);

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

export default createBridgePlank;

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