Codels
2.1K tris8.00 × 17.3 × 7.96 m

Use it in code

Remix in the editor
Self-contained ES module — only depends on three. Call the factory and add the group to your scene.
/**
 * Lighthouse — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 2,120 · Size (W × H × D): 8.00 × 17.31 × 7.96 m
 *
 * Usage:
 *   import { createLighthouse } from './lighthouse.js';
 *   
 *   const model = createLighthouse();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// Deterministic vertex displacement (organic low-poly look).
function jitter(geometry, amount, seed) {
  const pos = geometry.attributes.position;
  const h = (a, b, c, s) => {
    let x = Math.imul(a, 73856093) ^ Math.imul(b, 19349663) ^ Math.imul(c, 83492791) ^ Math.imul(s, 2654435761);
    x = Math.imul(x ^ (x >>> 16), 2246822507);
    x = Math.imul(x ^ (x >>> 13), 3266489909);
    return ((x ^ (x >>> 16)) >>> 0) / 4294967295 - 0.5;
  };
  for (let i = 0; i < pos.count; i++) {
    const x = pos.getX(i), y = pos.getY(i), z = pos.getZ(i);
    const qx = Math.round(x * 1000), qy = Math.round(y * 1000), qz = Math.round(z * 1000);
    pos.setXYZ(i, x + h(qx, qy, qz, seed) * 2 * amount, y + h(qx, qy, qz, seed + 1) * 2 * amount, z + h(qx, qy, qz, seed + 2) * 2 * amount);
  }
  pos.needsUpdate = true;
  geometry.computeVertexNormals();
  return geometry;
}

export function createLighthouse() {
  const root = new THREE.Group();
  root.name = 'Lighthouse';

  // Materials
  const whiteMat = new THREE.MeshStandardMaterial({ name: 'white', color: 0xf1ede4, roughness: 0.8, flatShading: true });
  const stripeMat = new THREE.MeshStandardMaterial({ name: 'stripe', color: 0xc7372f, roughness: 0.8, flatShading: true });
  const stoneMat = new THREE.MeshStandardMaterial({ name: 'stone', color: 0x6d6963, roughness: 0.95, flatShading: true });
  const metalMat = new THREE.MeshStandardMaterial({ name: 'metal', color: 0x2f3338, roughness: 0.45, metalness: 0.6, flatShading: true });
  const glassMat = new THREE.MeshStandardMaterial({ name: 'glass', color: 0xffe7a3, roughness: 0.2, emissive: 0xffcf5a, emissiveIntensity: 1.1, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x2c2a29, roughness: 0.9, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(0.12, 2, 0.12);
  const boxGeo2 = new THREE.BoxGeometry(0.55, 0.9, 0.06);
  const boxGeo3 = new THREE.BoxGeometry(0.72, 0.1, 0.14);
  const boxGeo4 = new THREE.BoxGeometry(0.22, 0.6, 0.6);
  const boxGeo5 = new THREE.BoxGeometry(0.06, 0.95, 0.06);
  const boxGeo6 = new THREE.BoxGeometry(0.07, 1.5, 0.07);

  // Parts
  const rock = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.5771, 0), 0.0462, 1), stoneMat);
  rock.name = 'rock';
  rock.position.set(0.2357, 0.4155, 3.3211);
  rock.scale.set(1.2, 0.7, 1);
  root.add(rock);
  const rock2 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.5351, 0), 0.0428, 2), stoneMat);
  rock2.name = 'rock';
  rock2.position.set(1.8175, 0.3853, 2.8714);
  rock2.scale.set(1.2, 0.7, 1);
  root.add(rock2);
  const rock3 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.7186, 0), 0.0575, 3), stoneMat);
  rock3.name = 'rock';
  rock3.position.set(3.1365, 0.5174, 0.84);
  rock3.scale.set(1.2, 0.7, 1);
  root.add(rock3);
  const rock4 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.8186, 0), 0.0655, 4), stoneMat);
  rock4.name = 'rock';
  rock4.position.set(2.6974, 0.5894, -1.8334);
  rock4.scale.set(1.2, 0.7, 1);
  root.add(rock4);
  const rock5 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.5794, 0), 0.0464, 5), stoneMat);
  rock5.name = 'rock';
  rock5.position.set(1.4753, 0.4172, -3.0179);
  rock5.scale.set(1.2, 0.7, 1);
  root.add(rock5);
  const rock6 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.6174, 0), 0.0494, 6), stoneMat);
  rock6.name = 'rock';
  rock6.position.set(-1.4259, 0.4445, -2.9928);
  rock6.scale.set(1.2, 0.7, 1);
  root.add(rock6);
  const rock7 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.768, 0), 0.0614, 7), stoneMat);
  rock7.name = 'rock';
  rock7.position.set(-3.0088, 0.5529, -1.4428);
  rock7.scale.set(1.2, 0.7, 1);
  root.add(rock7);
  const rock8 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.7261, 0), 0.0581, 8), stoneMat);
  rock8.name = 'rock';
  rock8.position.set(-3.2139, 0.5228, 0.7119);
  rock8.scale.set(1.2, 0.7, 1);
  root.add(rock8);
  const rock9 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.5256, 0), 0.042, 9), stoneMat);
  rock9.name = 'rock';
  rock9.position.set(-2.6297, 0.3784, 2.2068);
  rock9.scale.set(1.2, 0.7, 1);
  root.add(rock9);
  const plinth = new THREE.Mesh(new THREE.CylinderGeometry(3.07, 3.32, 1, 12), stoneMat);
  plinth.name = 'plinth';
  plinth.position.set(0, 0.5, 0);
  plinth.rotation.set(0, deg(15), 0);
  root.add(plinth);
  const band = new THREE.Mesh(new THREE.CylinderGeometry(2.5183, 2.72, 1.8333, 12), whiteMat);
  band.name = 'band';
  band.position.set(0, 1.9167, 0);
  band.rotation.set(0, deg(15), 0);
  root.add(band);
  const band2 = new THREE.Mesh(new THREE.CylinderGeometry(2.3167, 2.5183, 1.8333, 12), stripeMat);
  band2.name = 'band';
  band2.position.set(0, 3.75, 0);
  band2.rotation.set(0, deg(15), 0);
  root.add(band2);
  const band3 = new THREE.Mesh(new THREE.CylinderGeometry(2.115, 2.3167, 1.8333, 12), whiteMat);
  band3.name = 'band';
  band3.position.set(0, 5.5833, 0);
  band3.rotation.set(0, deg(15), 0);
  root.add(band3);
  const band4 = new THREE.Mesh(new THREE.CylinderGeometry(1.9133, 2.115, 1.8333, 12), stripeMat);
  band4.name = 'band';
  band4.position.set(0, 7.4167, 0);
  band4.rotation.set(0, deg(15), 0);
  root.add(band4);
  const band5 = new THREE.Mesh(new THREE.CylinderGeometry(1.7117, 1.9133, 1.8333, 12), whiteMat);
  band5.name = 'band';
  band5.position.set(0, 9.25, 0);
  band5.rotation.set(0, deg(15), 0);
  root.add(band5);
  const band6 = new THREE.Mesh(new THREE.CylinderGeometry(1.51, 1.7117, 1.8333, 12), stripeMat);
  band6.name = 'band';
  band6.position.set(0, 11.0833, 0);
  band6.rotation.set(0, deg(15), 0);
  root.add(band6);
  const door = new THREE.Group();
  door.name = 'door';
  door.position.set(0, 1, 2.6273);
  root.add(door);
  const tilt = new THREE.Group();
  tilt.name = 'tilt';
  tilt.rotation.set(deg(-6.065), 0, 0);
  door.add(tilt);
  const doorPanel = new THREE.Mesh(new THREE.BoxGeometry(1, 2, 0.08), darkMat);
  doorPanel.name = 'doorPanel';
  doorPanel.position.set(0, 1, 0);
  tilt.add(doorPanel);
  const doorHood = new THREE.Mesh(new THREE.BoxGeometry(1.3, 0.16, 0.16), metalMat);
  doorHood.name = 'doorHood';
  doorHood.position.set(0, 2.1, 0.06);
  tilt.add(doorHood);
  const box21 = new THREE.Mesh(boxGeo, whiteMat);
  box21.position.set(-0.56, 1, 0.02);
  tilt.add(box21);
  const box22 = new THREE.Mesh(boxGeo, whiteMat);
  box22.position.set(0.56, 1, 0.02);
  tilt.add(box22);
  const steps = new THREE.Mesh(new THREE.BoxGeometry(1.5, 1, 1), stoneMat);
  steps.name = 'steps';
  steps.position.set(0, 0.5, 3.412);
  root.add(steps);
  const steps2 = new THREE.Mesh(new THREE.BoxGeometry(1.5, 0.5, 0.5), stoneMat);
  steps2.name = 'steps';
  steps2.position.set(0, 0.25, 4.112);
  root.add(steps2);
  const window = new THREE.Group();
  window.name = 'window';
  window.position.set(0, 4.6, 2.2448);
  root.add(window);
  const tilt2 = new THREE.Group();
  tilt2.name = 'tilt';
  tilt2.rotation.set(deg(-6.065), 0, 0);
  window.add(tilt2);
  const box27 = new THREE.Mesh(boxGeo2, darkMat);
  tilt2.add(box27);
  const box28 = new THREE.Mesh(boxGeo3, metalMat);
  box28.position.set(0, -0.5, 0.04);
  tilt2.add(box28);
  const box29 = new THREE.Mesh(boxGeo3, metalMat);
  box29.position.set(0, 0.5, 0.04);
  tilt2.add(box29);
  const window2 = new THREE.Group();
  window2.name = 'window';
  window2.position.set(0.8143, 10.4, -1.4104);
  window2.rotation.set(0, deg(150), 0);
  root.add(window2);
  const tilt3 = new THREE.Group();
  tilt3.name = 'tilt';
  tilt3.rotation.set(deg(-6.065), 0, 0);
  window2.add(tilt3);
  const box32 = new THREE.Mesh(boxGeo2, darkMat);
  tilt3.add(box32);
  const box33 = new THREE.Mesh(boxGeo3, metalMat);
  box33.position.set(0, -0.5, 0.04);
  tilt3.add(box33);
  const box34 = new THREE.Mesh(boxGeo3, metalMat);
  box34.position.set(0, 0.5, 0.04);
  tilt3.add(box34);
  const corbel = new THREE.Group();
  corbel.name = 'corbel';
  corbel.position.set(0, 11.55, 1.5064);
  root.add(corbel);
  const tilt4 = new THREE.Group();
  tilt4.name = 'tilt';
  tilt4.rotation.set(deg(-6.065), 0, 0);
  corbel.add(tilt4);
  const box37 = new THREE.Mesh(boxGeo4, whiteMat);
  box37.position.set(0, 0, 0.18);
  tilt4.add(box37);
  const corbel2 = new THREE.Group();
  corbel2.name = 'corbel';
  corbel2.position.set(0.7532, 11.55, 1.3045);
  corbel2.rotation.set(0, deg(30), 0);
  root.add(corbel2);
  const tilt5 = new THREE.Group();
  tilt5.name = 'tilt';
  tilt5.rotation.set(deg(-6.065), 0, 0);
  corbel2.add(tilt5);
  const box40 = new THREE.Mesh(boxGeo4, whiteMat);
  box40.position.set(0, 0, 0.18);
  tilt5.add(box40);
  const corbel3 = new THREE.Group();
  corbel3.name = 'corbel';
  corbel3.position.set(1.3045, 11.55, 0.7532);
  corbel3.rotation.set(0, deg(60), 0);
  root.add(corbel3);
  const tilt6 = new THREE.Group();
  tilt6.name = 'tilt';
  tilt6.rotation.set(deg(-6.065), 0, 0);
  corbel3.add(tilt6);
  const box43 = new THREE.Mesh(boxGeo4, whiteMat);
  box43.position.set(0, 0, 0.18);
  tilt6.add(box43);
  const corbel4 = new THREE.Group();
  corbel4.name = 'corbel';
  corbel4.position.set(1.5064, 11.55, 0);
  corbel4.rotation.set(0, deg(90), 0);
  root.add(corbel4);
  const tilt7 = new THREE.Group();
  tilt7.name = 'tilt';
  tilt7.rotation.set(deg(-6.065), 0, 0);
  corbel4.add(tilt7);
  const box46 = new THREE.Mesh(boxGeo4, whiteMat);
  box46.position.set(0, 0, 0.18);
  tilt7.add(box46);
  const corbel5 = new THREE.Group();
  corbel5.name = 'corbel';
  corbel5.position.set(1.3045, 11.55, -0.7532);
  corbel5.rotation.set(0, deg(120), 0);
  root.add(corbel5);
  const tilt8 = new THREE.Group();
  tilt8.name = 'tilt';
  tilt8.rotation.set(deg(-6.065), 0, 0);
  corbel5.add(tilt8);
  const box49 = new THREE.Mesh(boxGeo4, whiteMat);
  box49.position.set(0, 0, 0.18);
  tilt8.add(box49);
  const corbel6 = new THREE.Group();
  corbel6.name = 'corbel';
  corbel6.position.set(0.7532, 11.55, -1.3045);
  corbel6.rotation.set(0, deg(150), 0);
  root.add(corbel6);
  const tilt9 = new THREE.Group();
  tilt9.name = 'tilt';
  tilt9.rotation.set(deg(-6.065), 0, 0);
  corbel6.add(tilt9);
  const box52 = new THREE.Mesh(boxGeo4, whiteMat);
  box52.position.set(0, 0, 0.18);
  tilt9.add(box52);
  const corbel7 = new THREE.Group();
  corbel7.name = 'corbel';
  corbel7.position.set(0, 11.55, -1.5064);
  corbel7.rotation.set(0, deg(180), 0);
  root.add(corbel7);
  const tilt10 = new THREE.Group();
  tilt10.name = 'tilt';
  tilt10.rotation.set(deg(-6.065), 0, 0);
  corbel7.add(tilt10);
  const box55 = new THREE.Mesh(boxGeo4, whiteMat);
  box55.position.set(0, 0, 0.18);
  tilt10.add(box55);
  const corbel8 = new THREE.Group();
  corbel8.name = 'corbel';
  corbel8.position.set(-0.7532, 11.55, -1.3045);
  corbel8.rotation.set(0, deg(210), 0);
  root.add(corbel8);
  const tilt11 = new THREE.Group();
  tilt11.name = 'tilt';
  tilt11.rotation.set(deg(-6.065), 0, 0);
  corbel8.add(tilt11);
  const box58 = new THREE.Mesh(boxGeo4, whiteMat);
  box58.position.set(0, 0, 0.18);
  tilt11.add(box58);
  const corbel9 = new THREE.Group();
  corbel9.name = 'corbel';
  corbel9.position.set(-1.3045, 11.55, -0.7532);
  corbel9.rotation.set(0, deg(240), 0);
  root.add(corbel9);
  const tilt12 = new THREE.Group();
  tilt12.name = 'tilt';
  tilt12.rotation.set(deg(-6.065), 0, 0);
  corbel9.add(tilt12);
  const box61 = new THREE.Mesh(boxGeo4, whiteMat);
  box61.position.set(0, 0, 0.18);
  tilt12.add(box61);
  const corbel10 = new THREE.Group();
  corbel10.name = 'corbel';
  corbel10.position.set(-1.5064, 11.55, 0);
  corbel10.rotation.set(0, deg(270), 0);
  root.add(corbel10);
  const tilt13 = new THREE.Group();
  tilt13.name = 'tilt';
  tilt13.rotation.set(deg(-6.065), 0, 0);
  corbel10.add(tilt13);
  const box64 = new THREE.Mesh(boxGeo4, whiteMat);
  box64.position.set(0, 0, 0.18);
  tilt13.add(box64);
  const corbel11 = new THREE.Group();
  corbel11.name = 'corbel';
  corbel11.position.set(-1.3045, 11.55, 0.7532);
  corbel11.rotation.set(0, deg(300), 0);
  root.add(corbel11);
  const tilt14 = new THREE.Group();
  tilt14.name = 'tilt';
  tilt14.rotation.set(deg(-6.065), 0, 0);
  corbel11.add(tilt14);
  const box67 = new THREE.Mesh(boxGeo4, whiteMat);
  box67.position.set(0, 0, 0.18);
  tilt14.add(box67);
  const corbel12 = new THREE.Group();
  corbel12.name = 'corbel';
  corbel12.position.set(-0.7532, 11.55, 1.3045);
  corbel12.rotation.set(0, deg(330), 0);
  root.add(corbel12);
  const tilt15 = new THREE.Group();
  tilt15.name = 'tilt';
  tilt15.rotation.set(deg(-6.065), 0, 0);
  corbel12.add(tilt15);
  const box70 = new THREE.Mesh(boxGeo4, whiteMat);
  box70.position.set(0, 0, 0.18);
  tilt15.add(box70);
  const galleryDeck = new THREE.Mesh(new THREE.CylinderGeometry(2.36, 2.26, 0.25, 12), metalMat);
  galleryDeck.name = 'galleryDeck';
  galleryDeck.position.set(0, 12.125, 0);
  galleryDeck.rotation.set(0, deg(15), 0);
  root.add(galleryDeck);
  const railPost = new THREE.Mesh(boxGeo5, metalMat);
  railPost.name = 'railPost';
  railPost.position.set(0, 12.725, 2.28);
  root.add(railPost);
  const railPost2 = new THREE.Mesh(boxGeo5, metalMat);
  railPost2.name = 'railPost';
  railPost2.position.set(0.8725, 12.725, 2.1064);
  root.add(railPost2);
  const railPost3 = new THREE.Mesh(boxGeo5, metalMat);
  railPost3.name = 'railPost';
  railPost3.position.set(1.6122, 12.725, 1.6122);
  root.add(railPost3);
  const railPost4 = new THREE.Mesh(boxGeo5, metalMat);
  railPost4.name = 'railPost';
  railPost4.position.set(2.1064, 12.725, 0.8725);
  root.add(railPost4);
  const railPost5 = new THREE.Mesh(boxGeo5, metalMat);
  railPost5.name = 'railPost';
  railPost5.position.set(2.28, 12.725, 0);
  root.add(railPost5);
  const railPost6 = new THREE.Mesh(boxGeo5, metalMat);
  railPost6.name = 'railPost';
  railPost6.position.set(2.1064, 12.725, -0.8725);
  root.add(railPost6);
  const railPost7 = new THREE.Mesh(boxGeo5, metalMat);
  railPost7.name = 'railPost';
  railPost7.position.set(1.6122, 12.725, -1.6122);
  root.add(railPost7);
  const railPost8 = new THREE.Mesh(boxGeo5, metalMat);
  railPost8.name = 'railPost';
  railPost8.position.set(0.8725, 12.725, -2.1064);
  root.add(railPost8);
  const railPost9 = new THREE.Mesh(boxGeo5, metalMat);
  railPost9.name = 'railPost';
  railPost9.position.set(0, 12.725, -2.28);
  root.add(railPost9);
  const railPost10 = new THREE.Mesh(boxGeo5, metalMat);
  railPost10.name = 'railPost';
  railPost10.position.set(-0.8725, 12.725, -2.1064);
  root.add(railPost10);
  const railPost11 = new THREE.Mesh(boxGeo5, metalMat);
  railPost11.name = 'railPost';
  railPost11.position.set(-1.6122, 12.725, -1.6122);
  root.add(railPost11);
  const railPost12 = new THREE.Mesh(boxGeo5, metalMat);
  railPost12.name = 'railPost';
  railPost12.position.set(-2.1064, 12.725, -0.8725);
  root.add(railPost12);
  const railPost13 = new THREE.Mesh(boxGeo5, metalMat);
  railPost13.name = 'railPost';
  railPost13.position.set(-2.28, 12.725, 0);
  root.add(railPost13);
  const railPost14 = new THREE.Mesh(boxGeo5, metalMat);
  railPost14.name = 'railPost';
  railPost14.position.set(-2.1064, 12.725, 0.8725);
  root.add(railPost14);
  const railPost15 = new THREE.Mesh(boxGeo5, metalMat);
  railPost15.name = 'railPost';
  railPost15.position.set(-1.6122, 12.725, 1.6122);
  root.add(railPost15);
  const railPost16 = new THREE.Mesh(boxGeo5, metalMat);
  railPost16.name = 'railPost';
  railPost16.position.set(-0.8725, 12.725, 2.1064);
  root.add(railPost16);
  const railTop = new THREE.Mesh(new THREE.TorusGeometry(2.28, 0.045, 4, 24), metalMat);
  railTop.name = 'railTop';
  railTop.position.set(0, 13.2, 0);
  railTop.rotation.set(deg(90), 0, 0);
  root.add(railTop);
  const railMid = new THREE.Mesh(new THREE.TorusGeometry(2.28, 0.03, 4, 24), metalMat);
  railMid.name = 'railMid';
  railMid.position.set(0, 12.72, 0);
  railMid.rotation.set(deg(90), 0, 0);
  root.add(railMid);
  const lanternBase = new THREE.Mesh(new THREE.CylinderGeometry(1.1778, 1.1778, 0.75, 12), whiteMat);
  lanternBase.name = 'lanternBase';
  lanternBase.position.set(0, 12.625, 0);
  lanternBase.rotation.set(0, deg(15), 0);
  root.add(lanternBase);
  const lanternGlass = new THREE.Mesh(new THREE.CylinderGeometry(1.1178, 1.1178, 1.5, 12), glassMat);
  lanternGlass.name = 'lanternGlass';
  lanternGlass.position.set(0, 13.75, 0);
  lanternGlass.rotation.set(0, deg(15), 0);
  root.add(lanternGlass);
  const mullion = new THREE.Mesh(boxGeo6, metalMat);
  mullion.name = 'mullion';
  mullion.position.set(0, 13.75, 1.1378);
  root.add(mullion);
  const mullion2 = new THREE.Mesh(boxGeo6, metalMat);
  mullion2.name = 'mullion';
  mullion2.position.set(0.5689, 13.75, 0.9854);
  root.add(mullion2);
  const mullion3 = new THREE.Mesh(boxGeo6, metalMat);
  mullion3.name = 'mullion';
  mullion3.position.set(0.9854, 13.75, 0.5689);
  root.add(mullion3);
  const mullion4 = new THREE.Mesh(boxGeo6, metalMat);
  mullion4.name = 'mullion';
  mullion4.position.set(1.1378, 13.75, 0);
  root.add(mullion4);
  const mullion5 = new THREE.Mesh(boxGeo6, metalMat);
  mullion5.name = 'mullion';
  mullion5.position.set(0.9854, 13.75, -0.5689);
  root.add(mullion5);
  const mullion6 = new THREE.Mesh(boxGeo6, metalMat);
  mullion6.name = 'mullion';
  mullion6.position.set(0.5689, 13.75, -0.9854);
  root.add(mullion6);
  const mullion7 = new THREE.Mesh(boxGeo6, metalMat);
  mullion7.name = 'mullion';
  mullion7.position.set(0, 13.75, -1.1378);
  root.add(mullion7);
  const mullion8 = new THREE.Mesh(boxGeo6, metalMat);
  mullion8.name = 'mullion';
  mullion8.position.set(-0.5689, 13.75, -0.9854);
  root.add(mullion8);
  const mullion9 = new THREE.Mesh(boxGeo6, metalMat);
  mullion9.name = 'mullion';
  mullion9.position.set(-0.9854, 13.75, -0.5689);
  root.add(mullion9);
  const mullion10 = new THREE.Mesh(boxGeo6, metalMat);
  mullion10.name = 'mullion';
  mullion10.position.set(-1.1378, 13.75, 0);
  root.add(mullion10);
  const mullion11 = new THREE.Mesh(boxGeo6, metalMat);
  mullion11.name = 'mullion';
  mullion11.position.set(-0.9854, 13.75, 0.5689);
  root.add(mullion11);
  const mullion12 = new THREE.Mesh(boxGeo6, metalMat);
  mullion12.name = 'mullion';
  mullion12.position.set(-0.5689, 13.75, 0.9854);
  root.add(mullion12);
  const lanternRing = new THREE.Mesh(new THREE.CylinderGeometry(1.2278, 1.2278, 0.1, 12), metalMat);
  lanternRing.name = 'lanternRing';
  lanternRing.position.set(0, 13.75, 0);
  lanternRing.rotation.set(0, deg(15), 0);
  root.add(lanternRing);
  const roofRim = new THREE.Mesh(new THREE.CylinderGeometry(1.4778, 1.4778, 0.14, 12), metalMat);
  roofRim.name = 'roofRim';
  roofRim.position.set(0, 14.57, 0);
  roofRim.rotation.set(0, deg(15), 0);
  root.add(roofRim);
  const roof = new THREE.Mesh(new THREE.SphereGeometry(1.3978, 12, 4, 0, Math.PI * 2, 0, Math.PI / 2), stripeMat);
  roof.name = 'roof';
  roof.position.set(0, 14.64, 0);
  roof.rotation.set(0, deg(15), 0);
  roof.scale.set(1, 0.8, 1);
  root.add(roof);
  const ventStem = new THREE.Mesh(new THREE.CylinderGeometry(0.12, 0.16, 0.25, 8), metalMat);
  ventStem.name = 'ventStem';
  ventStem.position.set(0, 15.8232, 0);
  root.add(ventStem);
  const ventBall = new THREE.Mesh(new THREE.SphereGeometry(0.24, 8, 6), metalMat);
  ventBall.name = 'ventBall';
  ventBall.position.set(0, 16.1382, 0);
  root.add(ventBall);
  const lightningRod = new THREE.Mesh(new THREE.CylinderGeometry(0.025, 0.025, 1, 4), metalMat);
  lightningRod.name = 'lightningRod';
  lightningRod.position.set(0, 16.8082, 0);
  root.add(lightningRod);

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

export default createLighthouse;

Ratings & comments

—
No ratings yet — be the first.
5
0
4
0
3
0
2
0
1
0

Sign in to rate and comment.

0 comments

No comments yet. Share how you used this model or what could be better.

Related models

Same category or similar tags