Codels
3.1K tris13.9 × 12.9 × 6.35 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.
/**
 * Castle Gatehouse — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 3,092 · Size (W × H × D): 13.92 × 12.86 × 6.35 m
 *
 * Usage:
 *   import { createCastleGate } from './castle-gate.js';
 *   
 *   const model = createCastleGate();
 *   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;
}

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

  // Materials
  const stoneMat = new THREE.MeshStandardMaterial({ name: 'stone', color: 0xa39c90, roughness: 0.95, flatShading: true });
  const trimMat = new THREE.MeshStandardMaterial({ name: 'trim', color: 0x868076, roughness: 0.95, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x2e2c28, roughness: 1, flatShading: true });
  const pavingMat = new THREE.MeshStandardMaterial({ name: 'paving', color: 0x6a655e, roughness: 1, flatShading: true });
  const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0x6a4529, roughness: 0.9, flatShading: true });
  const ironMat = new THREE.MeshStandardMaterial({ name: 'iron', color: 0x303236, roughness: 0.5, metalness: 0.7, flatShading: true });
  const bannerMat = new THREE.MeshStandardMaterial({ name: 'banner', color: 0x2f4f8f, roughness: 0.85, flatShading: true });
  const goldMat = new THREE.MeshStandardMaterial({ name: 'gold', color: 0xd1a23a, roughness: 0.45, metalness: 0.5, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(7.1, 0.2, 0.12);
  const extrudeGeo = extrude([[-1.7999, 2.9216], [-1.7527, 3.3098], [-2.2883, 3.435], [-2.3498, 2.9282]], 0.16);
  const extrudeGeo2 = extrude([[-1.7424, 3.3517], [-1.6037, 3.7173], [-2.0938, 3.9671], [-2.2748, 3.4897]], 0.16);
  const extrudeGeo3 = extrude([[-1.5837, 3.7556], [-1.3615, 4.0774], [-1.7776, 4.4371], [-2.0676, 4.017]], 0.16);
  const extrudeGeo4 = extrude([[-1.3329, 4.1097], [-1.0402, 4.369], [-1.3581, 4.8179], [-1.7402, 4.4793]], 0.16);
  const extrudeGeo5 = extrude([[-1.0047, 4.3935], [-0.6584, 4.5752], [-0.8596, 5.0871], [-1.3116, 4.8499]], 0.16);
  const extrudeGeo6 = extrude([[-0.618, 4.5906], [-0.2384, 4.6841], [-0.3112, 5.2293], [-0.8069, 5.1071]], 0.16);
  const extrudeGeo7 = extrude([[-0.1955, 4.6894], [0.1955, 4.6894], [0.277, 5.4349], [-0.277, 5.4349]], 0.26);
  const extrudeGeo8 = extrude([[0.2384, 4.6841], [0.618, 4.5906], [0.8069, 5.1071], [0.3112, 5.2293]], 0.16);
  const extrudeGeo9 = extrude([[0.6584, 4.5752], [1.0047, 4.3935], [1.3116, 4.8499], [0.8596, 5.0871]], 0.16);
  const extrudeGeo10 = extrude([[1.0402, 4.369], [1.3329, 4.1097], [1.7402, 4.4793], [1.3581, 4.8179]], 0.16);
  const extrudeGeo11 = extrude([[1.3615, 4.0774], [1.5837, 3.7556], [2.0676, 4.017], [1.7776, 4.4371]], 0.16);
  const extrudeGeo12 = extrude([[1.6037, 3.7173], [1.7424, 3.3517], [2.2748, 3.4897], [2.0938, 3.9671]], 0.16);
  const extrudeGeo13 = extrude([[1.7527, 3.3098], [1.7999, 2.9216], [2.3498, 2.9282], [2.2883, 3.435]], 0.16);
  const boxGeo2 = new THREE.BoxGeometry(0.08, 3.15, 0.2);
  const boxGeo3 = new THREE.BoxGeometry(0.24, 0.55, 0.42);
  const boxGeo4 = new THREE.BoxGeometry(1.04, 0.08, 0.58);
  const cylinderGeo = new THREE.CylinderGeometry(2.28, 2.62, 1.1, 12);
  const cylinderGeo2 = new THREE.CylinderGeometry(2.2, 2.2, 8.5, 12);
  const cylinderGeo3 = new THREE.CylinderGeometry(2.28, 2.28, 0.2, 12);
  const boxGeo5 = new THREE.BoxGeometry(0.3, 0.5, 0.4);
  const cylinderGeo4 = new THREE.CylinderGeometry(2.58, 2.58, 0.6, 12);
  const cylinderGeo5 = new THREE.CylinderGeometry(2.63, 2.63, 0.1, 12);
  const boxGeo6 = new THREE.BoxGeometry(0.8916, 0.8, 0.4);
  const boxGeo7 = new THREE.BoxGeometry(0.9516, 0.08, 0.46);
  const boxGeo8 = new THREE.BoxGeometry(0.36, 1.1, 0.06);
  const boxGeo9 = new THREE.BoxGeometry(0.12, 0.85, 0.06);
  const boxGeo10 = new THREE.BoxGeometry(0.32, 0.1, 0.06);
  const cylinderGeo6 = new THREE.CylinderGeometry(0.035, 0.035, 1.25, 5);
  const extrudeGeo14 = extrude([[-0.5, 0], [0.5, 0], [0.5, -2.9], [0, -2.45], [-0.5, -2.9]], 0.04);
  const boxGeo11 = new THREE.BoxGeometry(0.12, 1.6, 0.02);
  const cylinderGeo7 = new THREE.CylinderGeometry(1.95, 1.95, 0.05, 12);
  const boxGeo12 = new THREE.BoxGeometry(0.07, 4.8, 0.07);
  const coneGeo = new THREE.ConeGeometry(0.055, 0.14, 4);
  const boxGeo13 = new THREE.BoxGeometry(3.52, 0.07, 0.06);
  const boxGeo14 = new THREE.BoxGeometry(1.76, 3.25, 0.12);
  const boxGeo15 = new THREE.BoxGeometry(1.71, 0.12, 0.03);

  // Parts
  const gatehouse = new THREE.Mesh(extrude([[-3.5, 0], [-1.8, 0], [-1.8, 2.9], [-1.7387, 3.3659], [-1.5588, 3.8], [-1.2728, 4.1728], [-0.9, 4.4588], [-0.4659, 4.6387], [0, 4.7], [0.4659, 4.6387], [0.9, 4.4588], [1.2728, 4.1728], [1.5588, 3.8], [1.7387, 3.3659], [1.8, 2.9], [1.8, 0], [3.5, 0], [3.5, 7.2], [-3.5, 7.2]], 5), stoneMat);
  gatehouse.name = 'gatehouse';
  root.add(gatehouse);
  const passageFloor = new THREE.Mesh(new THREE.BoxGeometry(3.58, 0.05, 6.2), pavingMat);
  passageFloor.name = 'passageFloor';
  passageFloor.position.set(0, 0.025, 0.6);
  root.add(passageFloor);
  const plinth = new THREE.Mesh(jitter(new THREE.BoxGeometry(1.8, 0.6, 5.2), 0.01, 1), trimMat);
  plinth.name = 'plinth';
  plinth.position.set(-2.65, 0.3, 0);
  root.add(plinth);
  const plinth2 = new THREE.Mesh(jitter(new THREE.BoxGeometry(1.8, 0.6, 5.2), 0.01, 2), trimMat);
  plinth2.name = 'plinth';
  plinth2.position.set(2.65, 0.3, 0);
  root.add(plinth2);
  const stringCourse = new THREE.Mesh(boxGeo, trimMat);
  stringCourse.name = 'stringCourse';
  stringCourse.position.set(0, 5.45, -2.55);
  root.add(stringCourse);
  const stringCourse2 = new THREE.Mesh(boxGeo, trimMat);
  stringCourse2.name = 'stringCourse';
  stringCourse2.position.set(0, 5.45, 2.55);
  root.add(stringCourse2);
  const voussoir = new THREE.Mesh(extrudeGeo, stoneMat);
  voussoir.name = 'voussoir';
  voussoir.position.set(0, 0, -2.52);
  root.add(voussoir);
  const voussoir2 = new THREE.Mesh(extrudeGeo2, trimMat);
  voussoir2.name = 'voussoir';
  voussoir2.position.set(0, 0, -2.52);
  root.add(voussoir2);
  const voussoir3 = new THREE.Mesh(extrudeGeo3, stoneMat);
  voussoir3.name = 'voussoir';
  voussoir3.position.set(0, 0, -2.52);
  root.add(voussoir3);
  const voussoir4 = new THREE.Mesh(extrudeGeo4, trimMat);
  voussoir4.name = 'voussoir';
  voussoir4.position.set(0, 0, -2.52);
  root.add(voussoir4);
  const voussoir5 = new THREE.Mesh(extrudeGeo5, stoneMat);
  voussoir5.name = 'voussoir';
  voussoir5.position.set(0, 0, -2.52);
  root.add(voussoir5);
  const voussoir6 = new THREE.Mesh(extrudeGeo6, trimMat);
  voussoir6.name = 'voussoir';
  voussoir6.position.set(0, 0, -2.52);
  root.add(voussoir6);
  const keystone = new THREE.Mesh(extrudeGeo7, stoneMat);
  keystone.name = 'keystone';
  keystone.position.set(0, 0, -2.52);
  root.add(keystone);
  const voussoir7 = new THREE.Mesh(extrudeGeo8, trimMat);
  voussoir7.name = 'voussoir';
  voussoir7.position.set(0, 0, -2.52);
  root.add(voussoir7);
  const voussoir8 = new THREE.Mesh(extrudeGeo9, stoneMat);
  voussoir8.name = 'voussoir';
  voussoir8.position.set(0, 0, -2.52);
  root.add(voussoir8);
  const voussoir9 = new THREE.Mesh(extrudeGeo10, trimMat);
  voussoir9.name = 'voussoir';
  voussoir9.position.set(0, 0, -2.52);
  root.add(voussoir9);
  const voussoir10 = new THREE.Mesh(extrudeGeo11, stoneMat);
  voussoir10.name = 'voussoir';
  voussoir10.position.set(0, 0, -2.52);
  root.add(voussoir10);
  const voussoir11 = new THREE.Mesh(extrudeGeo12, trimMat);
  voussoir11.name = 'voussoir';
  voussoir11.position.set(0, 0, -2.52);
  root.add(voussoir11);
  const voussoir12 = new THREE.Mesh(extrudeGeo13, stoneMat);
  voussoir12.name = 'voussoir';
  voussoir12.position.set(0, 0, -2.52);
  root.add(voussoir12);
  const voussoir13 = new THREE.Mesh(extrudeGeo, stoneMat);
  voussoir13.name = 'voussoir';
  voussoir13.position.set(0, 0, 2.52);
  root.add(voussoir13);
  const voussoir14 = new THREE.Mesh(extrudeGeo2, trimMat);
  voussoir14.name = 'voussoir';
  voussoir14.position.set(0, 0, 2.52);
  root.add(voussoir14);
  const voussoir15 = new THREE.Mesh(extrudeGeo3, stoneMat);
  voussoir15.name = 'voussoir';
  voussoir15.position.set(0, 0, 2.52);
  root.add(voussoir15);
  const voussoir16 = new THREE.Mesh(extrudeGeo4, trimMat);
  voussoir16.name = 'voussoir';
  voussoir16.position.set(0, 0, 2.52);
  root.add(voussoir16);
  const voussoir17 = new THREE.Mesh(extrudeGeo5, stoneMat);
  voussoir17.name = 'voussoir';
  voussoir17.position.set(0, 0, 2.52);
  root.add(voussoir17);
  const voussoir18 = new THREE.Mesh(extrudeGeo6, trimMat);
  voussoir18.name = 'voussoir';
  voussoir18.position.set(0, 0, 2.52);
  root.add(voussoir18);
  const keystone2 = new THREE.Mesh(extrudeGeo7, stoneMat);
  keystone2.name = 'keystone';
  keystone2.position.set(0, 0, 2.52);
  root.add(keystone2);
  const voussoir19 = new THREE.Mesh(extrudeGeo8, trimMat);
  voussoir19.name = 'voussoir';
  voussoir19.position.set(0, 0, 2.52);
  root.add(voussoir19);
  const voussoir20 = new THREE.Mesh(extrudeGeo9, stoneMat);
  voussoir20.name = 'voussoir';
  voussoir20.position.set(0, 0, 2.52);
  root.add(voussoir20);
  const voussoir21 = new THREE.Mesh(extrudeGeo10, trimMat);
  voussoir21.name = 'voussoir';
  voussoir21.position.set(0, 0, 2.52);
  root.add(voussoir21);
  const voussoir22 = new THREE.Mesh(extrudeGeo11, stoneMat);
  voussoir22.name = 'voussoir';
  voussoir22.position.set(0, 0, 2.52);
  root.add(voussoir22);
  const voussoir23 = new THREE.Mesh(extrudeGeo12, trimMat);
  voussoir23.name = 'voussoir';
  voussoir23.position.set(0, 0, 2.52);
  root.add(voussoir23);
  const voussoir24 = new THREE.Mesh(extrudeGeo13, stoneMat);
  voussoir24.name = 'voussoir';
  voussoir24.position.set(0, 0, 2.52);
  root.add(voussoir24);
  const faceStone = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.4746, 0.3173, 0.06), 0.008, 3), trimMat);
  faceStone.name = 'faceStone';
  faceStone.position.set(-2.7013, 5.3972, 2.515);
  root.add(faceStone);
  const faceStone2 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.8275, 0.2988, 0.06), 0.008, 4), stoneMat);
  faceStone2.name = 'faceStone';
  faceStone2.position.set(2.813, 4.4241, 2.515);
  root.add(faceStone2);
  const faceStone3 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.51, 0.3064, 0.06), 0.008, 5), trimMat);
  faceStone3.name = 'faceStone';
  faceStone3.position.set(2.9791, 4.0467, 2.515);
  root.add(faceStone3);
  const faceStone4 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.767, 0.2579, 0.06), 0.008, 6), stoneMat);
  faceStone4.name = 'faceStone';
  faceStone4.position.set(2.7652, 5.2711, 2.515);
  root.add(faceStone4);
  const faceStone5 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.5204, 0.2512, 0.06), 0.008, 7), stoneMat);
  faceStone5.name = 'faceStone';
  faceStone5.position.set(-2.6572, 4.3764, 2.515);
  root.add(faceStone5);
  const faceStone6 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.6424, 0.2484, 0.06), 0.008, 8), trimMat);
  faceStone6.name = 'faceStone';
  faceStone6.position.set(2.8063, 6.0559, 2.515);
  root.add(faceStone6);
  const faceStone7 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.4768, 0.3051, 0.06), 0.008, 9), stoneMat);
  faceStone7.name = 'faceStone';
  faceStone7.position.set(-1.5173, 5.7723, 2.515);
  root.add(faceStone7);
  const faceStone8 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.814, 0.3082, 0.06), 0.008, 10), stoneMat);
  faceStone8.name = 'faceStone';
  faceStone8.position.set(-2.5019, 6.1497, 2.515);
  root.add(faceStone8);
  const portcullisGroove = new THREE.Mesh(boxGeo2, darkMat);
  portcullisGroove.name = 'portcullisGroove';
  portcullisGroove.position.set(-1.78, 1.615, 1.75);
  root.add(portcullisGroove);
  const portcullisGroove2 = new THREE.Mesh(boxGeo2, darkMat);
  portcullisGroove2.name = 'portcullisGroove';
  portcullisGroove2.position.set(1.78, 1.615, 1.75);
  root.add(portcullisGroove2);
  const corbel = new THREE.Mesh(boxGeo3, trimMat);
  corbel.name = 'corbel';
  corbel.position.set(-3.15, 6.9, 2.67);
  root.add(corbel);
  const corbel2 = new THREE.Mesh(boxGeo3, trimMat);
  corbel2.name = 'corbel';
  corbel2.position.set(-2.3625, 6.9, 2.67);
  root.add(corbel2);
  const corbel3 = new THREE.Mesh(boxGeo3, trimMat);
  corbel3.name = 'corbel';
  corbel3.position.set(-1.575, 6.9, 2.67);
  root.add(corbel3);
  const corbel4 = new THREE.Mesh(boxGeo3, trimMat);
  corbel4.name = 'corbel';
  corbel4.position.set(-0.7875, 6.9, 2.67);
  root.add(corbel4);
  const corbel5 = new THREE.Mesh(boxGeo3, trimMat);
  corbel5.name = 'corbel';
  corbel5.position.set(0, 6.9, 2.67);
  root.add(corbel5);
  const corbel6 = new THREE.Mesh(boxGeo3, trimMat);
  corbel6.name = 'corbel';
  corbel6.position.set(0.7875, 6.9, 2.67);
  root.add(corbel6);
  const corbel7 = new THREE.Mesh(boxGeo3, trimMat);
  corbel7.name = 'corbel';
  corbel7.position.set(1.575, 6.9, 2.67);
  root.add(corbel7);
  const corbel8 = new THREE.Mesh(boxGeo3, trimMat);
  corbel8.name = 'corbel';
  corbel8.position.set(2.3625, 6.9, 2.67);
  root.add(corbel8);
  const corbel9 = new THREE.Mesh(boxGeo3, trimMat);
  corbel9.name = 'corbel';
  corbel9.position.set(3.15, 6.9, 2.67);
  root.add(corbel9);
  const frontParapet = new THREE.Mesh(new THREE.BoxGeometry(7.05, 0.75, 0.5), stoneMat);
  frontParapet.name = 'frontParapet';
  frontParapet.position.set(0, 7.525, 2.63);
  root.add(frontParapet);
  const backParapet = new THREE.Mesh(new THREE.BoxGeometry(6.9, 0.6, 0.4), stoneMat);
  backParapet.name = 'backParapet';
  backParapet.position.set(0, 7.5, -2.3);
  root.add(backParapet);
  const walkway = new THREE.Mesh(new THREE.BoxGeometry(6.6, 0.05, 4.2), pavingMat);
  walkway.name = 'walkway';
  walkway.position.set(0, 7.225, 0);
  root.add(walkway);
  const merlon = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.96, 0.75, 0.5), 0.012, 11), stoneMat);
  merlon.name = 'merlon';
  merlon.position.set(-3, 8.275, 2.63);
  root.add(merlon);
  const merlonCap = new THREE.Mesh(boxGeo4, trimMat);
  merlonCap.name = 'merlonCap';
  merlonCap.position.set(-3, 8.69, 2.63);
  root.add(merlonCap);
  const merlon2 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.96, 0.7, 0.4), 0.012, 12), stoneMat);
  merlon2.name = 'merlon';
  merlon2.position.set(-3, 8.15, -2.3);
  root.add(merlon2);
  const merlon3 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.96, 0.75, 0.5), 0.012, 13), stoneMat);
  merlon3.name = 'merlon';
  merlon3.position.set(-1, 8.275, 2.63);
  root.add(merlon3);
  const merlonCap2 = new THREE.Mesh(boxGeo4, trimMat);
  merlonCap2.name = 'merlonCap';
  merlonCap2.position.set(-1, 8.69, 2.63);
  root.add(merlonCap2);
  const merlon4 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.96, 0.7, 0.4), 0.012, 14), stoneMat);
  merlon4.name = 'merlon';
  merlon4.position.set(-1, 8.15, -2.3);
  root.add(merlon4);
  const merlon5 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.96, 0.75, 0.5), 0.012, 15), stoneMat);
  merlon5.name = 'merlon';
  merlon5.position.set(1, 8.275, 2.63);
  root.add(merlon5);
  const merlonCap3 = new THREE.Mesh(boxGeo4, trimMat);
  merlonCap3.name = 'merlonCap';
  merlonCap3.position.set(1, 8.69, 2.63);
  root.add(merlonCap3);
  const merlon6 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.96, 0.7, 0.4), 0.012, 16), stoneMat);
  merlon6.name = 'merlon';
  merlon6.position.set(1, 8.15, -2.3);
  root.add(merlon6);
  const merlon7 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.96, 0.75, 0.5), 0.012, 17), stoneMat);
  merlon7.name = 'merlon';
  merlon7.position.set(3, 8.275, 2.63);
  root.add(merlon7);
  const merlonCap4 = new THREE.Mesh(boxGeo4, trimMat);
  merlonCap4.name = 'merlonCap';
  merlonCap4.position.set(3, 8.69, 2.63);
  root.add(merlonCap4);
  const merlon8 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.96, 0.7, 0.4), 0.012, 18), stoneMat);
  merlon8.name = 'merlon';
  merlon8.position.set(3, 8.15, -2.3);
  root.add(merlon8);
  const coatOfArms = new THREE.Mesh(extrude([[-0.55, 0.45], [0.55, 0.45], [0.55, -0.1], [0.3, -0.48], [0, -0.62], [-0.3, -0.48], [-0.55, -0.1]], 0.1), bannerMat);
  coatOfArms.name = 'coatOfArms';
  coatOfArms.position.set(0, 6.45, 2.57);
  root.add(coatOfArms);
  const armsCross = new THREE.Mesh(new THREE.BoxGeometry(0.14, 0.75, 0.06), goldMat);
  armsCross.name = 'armsCross';
  armsCross.position.set(0, 6.4, 2.64);
  root.add(armsCross);
  const armsCross2 = new THREE.Mesh(new THREE.BoxGeometry(0.75, 0.14, 0.06), goldMat);
  armsCross2.name = 'armsCross';
  armsCross2.position.set(0, 6.53, 2.64);
  root.add(armsCross2);
  const leftTower = new THREE.Group();
  leftTower.name = 'leftTower';
  leftTower.position.set(-4.35, 0, 0.7);
  root.add(leftTower);
  const towerPlinth = new THREE.Mesh(cylinderGeo, trimMat);
  towerPlinth.name = 'towerPlinth';
  towerPlinth.position.set(0, 0.55, 0);
  towerPlinth.rotation.set(0, deg(15), 0);
  leftTower.add(towerPlinth);
  const towerBody = new THREE.Mesh(cylinderGeo2, stoneMat);
  towerBody.name = 'towerBody';
  towerBody.position.set(0, 5.35, 0);
  towerBody.rotation.set(0, deg(15), 0);
  leftTower.add(towerBody);
  const towerString = new THREE.Mesh(cylinderGeo3, trimMat);
  towerString.name = 'towerString';
  towerString.position.set(0, 5.45, 0);
  towerString.rotation.set(0, deg(15), 0);
  leftTower.add(towerString);
  const towerCorbel = new THREE.Group();
  towerCorbel.name = 'towerCorbel';
  towerCorbel.position.set(0.5953, 9.28, 2.2216);
  towerCorbel.rotation.set(0, deg(15), 0);
  leftTower.add(towerCorbel);
  const box75 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel.add(box75);
  const towerCorbel2 = new THREE.Group();
  towerCorbel2.name = 'towerCorbel';
  towerCorbel2.position.set(1.6263, 9.28, 1.6263);
  towerCorbel2.rotation.set(0, deg(45), 0);
  leftTower.add(towerCorbel2);
  const box77 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel2.add(box77);
  const towerCorbel3 = new THREE.Group();
  towerCorbel3.name = 'towerCorbel';
  towerCorbel3.position.set(2.2216, 9.28, 0.5953);
  towerCorbel3.rotation.set(0, deg(75), 0);
  leftTower.add(towerCorbel3);
  const box79 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel3.add(box79);
  const towerCorbel4 = new THREE.Group();
  towerCorbel4.name = 'towerCorbel';
  towerCorbel4.position.set(2.2216, 9.28, -0.5953);
  towerCorbel4.rotation.set(0, deg(105), 0);
  leftTower.add(towerCorbel4);
  const box81 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel4.add(box81);
  const towerCorbel5 = new THREE.Group();
  towerCorbel5.name = 'towerCorbel';
  towerCorbel5.position.set(1.6263, 9.28, -1.6263);
  towerCorbel5.rotation.set(0, deg(135), 0);
  leftTower.add(towerCorbel5);
  const box83 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel5.add(box83);
  const towerCorbel6 = new THREE.Group();
  towerCorbel6.name = 'towerCorbel';
  towerCorbel6.position.set(0.5953, 9.28, -2.2216);
  towerCorbel6.rotation.set(0, deg(165), 0);
  leftTower.add(towerCorbel6);
  const box85 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel6.add(box85);
  const towerCorbel7 = new THREE.Group();
  towerCorbel7.name = 'towerCorbel';
  towerCorbel7.position.set(-0.5953, 9.28, -2.2216);
  towerCorbel7.rotation.set(0, deg(195), 0);
  leftTower.add(towerCorbel7);
  const box87 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel7.add(box87);
  const towerCorbel8 = new THREE.Group();
  towerCorbel8.name = 'towerCorbel';
  towerCorbel8.position.set(-1.6263, 9.28, -1.6263);
  towerCorbel8.rotation.set(0, deg(225), 0);
  leftTower.add(towerCorbel8);
  const box89 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel8.add(box89);
  const towerCorbel9 = new THREE.Group();
  towerCorbel9.name = 'towerCorbel';
  towerCorbel9.position.set(-2.2216, 9.28, -0.5953);
  towerCorbel9.rotation.set(0, deg(255), 0);
  leftTower.add(towerCorbel9);
  const box91 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel9.add(box91);
  const towerCorbel10 = new THREE.Group();
  towerCorbel10.name = 'towerCorbel';
  towerCorbel10.position.set(-2.2216, 9.28, 0.5953);
  towerCorbel10.rotation.set(0, deg(285), 0);
  leftTower.add(towerCorbel10);
  const box93 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel10.add(box93);
  const towerCorbel11 = new THREE.Group();
  towerCorbel11.name = 'towerCorbel';
  towerCorbel11.position.set(-1.6263, 9.28, 1.6263);
  towerCorbel11.rotation.set(0, deg(315), 0);
  leftTower.add(towerCorbel11);
  const box95 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel11.add(box95);
  const towerCorbel12 = new THREE.Group();
  towerCorbel12.name = 'towerCorbel';
  towerCorbel12.position.set(-0.5953, 9.28, 2.2216);
  towerCorbel12.rotation.set(0, deg(345), 0);
  leftTower.add(towerCorbel12);
  const box97 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel12.add(box97);
  const towerParapet = new THREE.Mesh(cylinderGeo4, stoneMat);
  towerParapet.name = 'towerParapet';
  towerParapet.position.set(0, 9.9, 0);
  towerParapet.rotation.set(0, deg(15), 0);
  leftTower.add(towerParapet);
  const towerLip = new THREE.Mesh(cylinderGeo5, trimMat);
  towerLip.name = 'towerLip';
  towerLip.position.set(0, 10.2, 0);
  towerLip.rotation.set(0, deg(15), 0);
  leftTower.add(towerLip);
  const towerMerlon = new THREE.Group();
  towerMerlon.name = 'towerMerlon';
  towerMerlon.position.set(0.7355, 10.22, 2.2635);
  towerMerlon.rotation.set(0, deg(18), 0);
  leftTower.add(towerMerlon);
  const box101 = new THREE.Mesh(boxGeo6, stoneMat);
  box101.position.set(0, 0.4, 0);
  towerMerlon.add(box101);
  const box102 = new THREE.Mesh(boxGeo7, trimMat);
  box102.position.set(0, 0.84, 0);
  towerMerlon.add(box102);
  const towerMerlon2 = new THREE.Group();
  towerMerlon2.name = 'towerMerlon';
  towerMerlon2.position.set(1.9255, 10.22, 1.3989);
  towerMerlon2.rotation.set(0, deg(54), 0);
  leftTower.add(towerMerlon2);
  const box104 = new THREE.Mesh(boxGeo6, stoneMat);
  box104.position.set(0, 0.4, 0);
  towerMerlon2.add(box104);
  const box105 = new THREE.Mesh(boxGeo7, trimMat);
  box105.position.set(0, 0.84, 0);
  towerMerlon2.add(box105);
  const towerMerlon3 = new THREE.Group();
  towerMerlon3.name = 'towerMerlon';
  towerMerlon3.position.set(2.38, 10.22, 0);
  towerMerlon3.rotation.set(0, deg(90), 0);
  leftTower.add(towerMerlon3);
  const box107 = new THREE.Mesh(boxGeo6, stoneMat);
  box107.position.set(0, 0.4, 0);
  towerMerlon3.add(box107);
  const box108 = new THREE.Mesh(boxGeo7, trimMat);
  box108.position.set(0, 0.84, 0);
  towerMerlon3.add(box108);
  const towerMerlon4 = new THREE.Group();
  towerMerlon4.name = 'towerMerlon';
  towerMerlon4.position.set(1.9255, 10.22, -1.3989);
  towerMerlon4.rotation.set(0, deg(126), 0);
  leftTower.add(towerMerlon4);
  const box110 = new THREE.Mesh(boxGeo6, stoneMat);
  box110.position.set(0, 0.4, 0);
  towerMerlon4.add(box110);
  const box111 = new THREE.Mesh(boxGeo7, trimMat);
  box111.position.set(0, 0.84, 0);
  towerMerlon4.add(box111);
  const towerMerlon5 = new THREE.Group();
  towerMerlon5.name = 'towerMerlon';
  towerMerlon5.position.set(0.7355, 10.22, -2.2635);
  towerMerlon5.rotation.set(0, deg(162), 0);
  leftTower.add(towerMerlon5);
  const box113 = new THREE.Mesh(boxGeo6, stoneMat);
  box113.position.set(0, 0.4, 0);
  towerMerlon5.add(box113);
  const box114 = new THREE.Mesh(boxGeo7, trimMat);
  box114.position.set(0, 0.84, 0);
  towerMerlon5.add(box114);
  const towerMerlon6 = new THREE.Group();
  towerMerlon6.name = 'towerMerlon';
  towerMerlon6.position.set(-0.7355, 10.22, -2.2635);
  towerMerlon6.rotation.set(0, deg(198), 0);
  leftTower.add(towerMerlon6);
  const box116 = new THREE.Mesh(boxGeo6, stoneMat);
  box116.position.set(0, 0.4, 0);
  towerMerlon6.add(box116);
  const box117 = new THREE.Mesh(boxGeo7, trimMat);
  box117.position.set(0, 0.84, 0);
  towerMerlon6.add(box117);
  const towerMerlon7 = new THREE.Group();
  towerMerlon7.name = 'towerMerlon';
  towerMerlon7.position.set(-1.9255, 10.22, -1.3989);
  towerMerlon7.rotation.set(0, deg(234), 0);
  leftTower.add(towerMerlon7);
  const box119 = new THREE.Mesh(boxGeo6, stoneMat);
  box119.position.set(0, 0.4, 0);
  towerMerlon7.add(box119);
  const box120 = new THREE.Mesh(boxGeo7, trimMat);
  box120.position.set(0, 0.84, 0);
  towerMerlon7.add(box120);
  const towerMerlon8 = new THREE.Group();
  towerMerlon8.name = 'towerMerlon';
  towerMerlon8.position.set(-2.38, 10.22, 0);
  towerMerlon8.rotation.set(0, deg(270), 0);
  leftTower.add(towerMerlon8);
  const box122 = new THREE.Mesh(boxGeo6, stoneMat);
  box122.position.set(0, 0.4, 0);
  towerMerlon8.add(box122);
  const box123 = new THREE.Mesh(boxGeo7, trimMat);
  box123.position.set(0, 0.84, 0);
  towerMerlon8.add(box123);
  const towerMerlon9 = new THREE.Group();
  towerMerlon9.name = 'towerMerlon';
  towerMerlon9.position.set(-1.9255, 10.22, 1.3989);
  towerMerlon9.rotation.set(0, deg(306), 0);
  leftTower.add(towerMerlon9);
  const box125 = new THREE.Mesh(boxGeo6, stoneMat);
  box125.position.set(0, 0.4, 0);
  towerMerlon9.add(box125);
  const box126 = new THREE.Mesh(boxGeo7, trimMat);
  box126.position.set(0, 0.84, 0);
  towerMerlon9.add(box126);
  const towerMerlon10 = new THREE.Group();
  towerMerlon10.name = 'towerMerlon';
  towerMerlon10.position.set(-0.7355, 10.22, 2.2635);
  towerMerlon10.rotation.set(0, deg(342), 0);
  leftTower.add(towerMerlon10);
  const box128 = new THREE.Mesh(boxGeo6, stoneMat);
  box128.position.set(0, 0.4, 0);
  towerMerlon10.add(box128);
  const box129 = new THREE.Mesh(boxGeo7, trimMat);
  box129.position.set(0, 0.84, 0);
  towerMerlon10.add(box129);
  const arrowSlit = new THREE.Group();
  arrowSlit.name = 'arrowSlit';
  arrowSlit.position.set(-1.8403, 2.4, 1.0625);
  arrowSlit.rotation.set(0, deg(-60), 0);
  leftTower.add(arrowSlit);
  const box131 = new THREE.Mesh(boxGeo8, trimMat);
  arrowSlit.add(box131);
  const box132 = new THREE.Mesh(boxGeo9, darkMat);
  box132.position.set(0, 0, 0.014);
  arrowSlit.add(box132);
  const box133 = new THREE.Mesh(boxGeo10, darkMat);
  box133.position.set(0, 0.12, 0.014);
  arrowSlit.add(box133);
  const arrowSlit2 = new THREE.Group();
  arrowSlit2.name = 'arrowSlit';
  arrowSlit2.position.set(-2.0526, 4.8, -0.55);
  arrowSlit2.rotation.set(0, deg(-105), 0);
  leftTower.add(arrowSlit2);
  const box135 = new THREE.Mesh(boxGeo8, trimMat);
  arrowSlit2.add(box135);
  const box136 = new THREE.Mesh(boxGeo9, darkMat);
  box136.position.set(0, 0, 0.014);
  arrowSlit2.add(box136);
  const box137 = new THREE.Mesh(boxGeo10, darkMat);
  box137.position.set(0, 0.12, 0.014);
  arrowSlit2.add(box137);
  const arrowSlit3 = new THREE.Group();
  arrowSlit3.name = 'arrowSlit';
  arrowSlit3.position.set(-1.0625, 6, 1.8403);
  arrowSlit3.rotation.set(0, deg(-30), 0);
  leftTower.add(arrowSlit3);
  const box139 = new THREE.Mesh(boxGeo8, trimMat);
  arrowSlit3.add(box139);
  const box140 = new THREE.Mesh(boxGeo9, darkMat);
  box140.position.set(0, 0, 0.014);
  arrowSlit3.add(box140);
  const box141 = new THREE.Mesh(boxGeo10, darkMat);
  box141.position.set(0, 0.12, 0.014);
  arrowSlit3.add(box141);
  const arrowSlit4 = new THREE.Group();
  arrowSlit4.name = 'arrowSlit';
  arrowSlit4.position.set(0.369, 3.4, 2.0928);
  arrowSlit4.rotation.set(0, deg(10), 0);
  leftTower.add(arrowSlit4);
  const box143 = new THREE.Mesh(boxGeo8, trimMat);
  arrowSlit4.add(box143);
  const box144 = new THREE.Mesh(boxGeo9, darkMat);
  box144.position.set(0, 0, 0.014);
  arrowSlit4.add(box144);
  const box145 = new THREE.Mesh(boxGeo10, darkMat);
  box145.position.set(0, 0.12, 0.014);
  arrowSlit4.add(box145);
  const banner = new THREE.Group();
  banner.name = 'banner';
  banner.position.set(0.2957, 8.6, 2.1044);
  banner.rotation.set(0, deg(8), 0);
  leftTower.add(banner);
  const bannerRod = new THREE.Mesh(cylinderGeo6, woodMat);
  bannerRod.name = 'bannerRod';
  bannerRod.position.set(0, 0, 0.12);
  bannerRod.rotation.set(0, 0, deg(90));
  banner.add(bannerRod);
  const bannerCloth = new THREE.Mesh(extrudeGeo14, bannerMat);
  bannerCloth.name = 'bannerCloth';
  bannerCloth.position.set(0, -0.02, 0.1);
  banner.add(bannerCloth);
  const bannerStripe = new THREE.Mesh(boxGeo11, goldMat);
  bannerStripe.name = 'bannerStripe';
  bannerStripe.position.set(0, -1.1, 0.125);
  banner.add(bannerStripe);
  const rightTower = new THREE.Group();
  rightTower.name = 'rightTower';
  rightTower.position.set(4.35, 0, 0.7);
  root.add(rightTower);
  const towerPlinth2 = new THREE.Mesh(cylinderGeo, trimMat);
  towerPlinth2.name = 'towerPlinth';
  towerPlinth2.position.set(0, 0.55, 0);
  towerPlinth2.rotation.set(0, deg(15), 0);
  rightTower.add(towerPlinth2);
  const towerBody2 = new THREE.Mesh(cylinderGeo2, stoneMat);
  towerBody2.name = 'towerBody';
  towerBody2.position.set(0, 5.35, 0);
  towerBody2.rotation.set(0, deg(15), 0);
  rightTower.add(towerBody2);
  const towerString2 = new THREE.Mesh(cylinderGeo3, trimMat);
  towerString2.name = 'towerString';
  towerString2.position.set(0, 5.45, 0);
  towerString2.rotation.set(0, deg(15), 0);
  rightTower.add(towerString2);
  const towerCorbel13 = new THREE.Group();
  towerCorbel13.name = 'towerCorbel';
  towerCorbel13.position.set(0.5953, 9.28, 2.2216);
  towerCorbel13.rotation.set(0, deg(15), 0);
  rightTower.add(towerCorbel13);
  const box155 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel13.add(box155);
  const towerCorbel14 = new THREE.Group();
  towerCorbel14.name = 'towerCorbel';
  towerCorbel14.position.set(1.6263, 9.28, 1.6263);
  towerCorbel14.rotation.set(0, deg(45), 0);
  rightTower.add(towerCorbel14);
  const box157 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel14.add(box157);
  const towerCorbel15 = new THREE.Group();
  towerCorbel15.name = 'towerCorbel';
  towerCorbel15.position.set(2.2216, 9.28, 0.5953);
  towerCorbel15.rotation.set(0, deg(75), 0);
  rightTower.add(towerCorbel15);
  const box159 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel15.add(box159);
  const towerCorbel16 = new THREE.Group();
  towerCorbel16.name = 'towerCorbel';
  towerCorbel16.position.set(2.2216, 9.28, -0.5953);
  towerCorbel16.rotation.set(0, deg(105), 0);
  rightTower.add(towerCorbel16);
  const box161 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel16.add(box161);
  const towerCorbel17 = new THREE.Group();
  towerCorbel17.name = 'towerCorbel';
  towerCorbel17.position.set(1.6263, 9.28, -1.6263);
  towerCorbel17.rotation.set(0, deg(135), 0);
  rightTower.add(towerCorbel17);
  const box163 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel17.add(box163);
  const towerCorbel18 = new THREE.Group();
  towerCorbel18.name = 'towerCorbel';
  towerCorbel18.position.set(0.5953, 9.28, -2.2216);
  towerCorbel18.rotation.set(0, deg(165), 0);
  rightTower.add(towerCorbel18);
  const box165 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel18.add(box165);
  const towerCorbel19 = new THREE.Group();
  towerCorbel19.name = 'towerCorbel';
  towerCorbel19.position.set(-0.5953, 9.28, -2.2216);
  towerCorbel19.rotation.set(0, deg(195), 0);
  rightTower.add(towerCorbel19);
  const box167 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel19.add(box167);
  const towerCorbel20 = new THREE.Group();
  towerCorbel20.name = 'towerCorbel';
  towerCorbel20.position.set(-1.6263, 9.28, -1.6263);
  towerCorbel20.rotation.set(0, deg(225), 0);
  rightTower.add(towerCorbel20);
  const box169 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel20.add(box169);
  const towerCorbel21 = new THREE.Group();
  towerCorbel21.name = 'towerCorbel';
  towerCorbel21.position.set(-2.2216, 9.28, -0.5953);
  towerCorbel21.rotation.set(0, deg(255), 0);
  rightTower.add(towerCorbel21);
  const box171 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel21.add(box171);
  const towerCorbel22 = new THREE.Group();
  towerCorbel22.name = 'towerCorbel';
  towerCorbel22.position.set(-2.2216, 9.28, 0.5953);
  towerCorbel22.rotation.set(0, deg(285), 0);
  rightTower.add(towerCorbel22);
  const box173 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel22.add(box173);
  const towerCorbel23 = new THREE.Group();
  towerCorbel23.name = 'towerCorbel';
  towerCorbel23.position.set(-1.6263, 9.28, 1.6263);
  towerCorbel23.rotation.set(0, deg(315), 0);
  rightTower.add(towerCorbel23);
  const box175 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel23.add(box175);
  const towerCorbel24 = new THREE.Group();
  towerCorbel24.name = 'towerCorbel';
  towerCorbel24.position.set(-0.5953, 9.28, 2.2216);
  towerCorbel24.rotation.set(0, deg(345), 0);
  rightTower.add(towerCorbel24);
  const box177 = new THREE.Mesh(boxGeo5, trimMat);
  towerCorbel24.add(box177);
  const towerParapet2 = new THREE.Mesh(cylinderGeo4, stoneMat);
  towerParapet2.name = 'towerParapet';
  towerParapet2.position.set(0, 9.9, 0);
  towerParapet2.rotation.set(0, deg(15), 0);
  rightTower.add(towerParapet2);
  const towerLip2 = new THREE.Mesh(cylinderGeo5, trimMat);
  towerLip2.name = 'towerLip';
  towerLip2.position.set(0, 10.2, 0);
  towerLip2.rotation.set(0, deg(15), 0);
  rightTower.add(towerLip2);
  const towerMerlon11 = new THREE.Group();
  towerMerlon11.name = 'towerMerlon';
  towerMerlon11.position.set(0.7355, 10.22, 2.2635);
  towerMerlon11.rotation.set(0, deg(18), 0);
  rightTower.add(towerMerlon11);
  const box181 = new THREE.Mesh(boxGeo6, stoneMat);
  box181.position.set(0, 0.4, 0);
  towerMerlon11.add(box181);
  const box182 = new THREE.Mesh(boxGeo7, trimMat);
  box182.position.set(0, 0.84, 0);
  towerMerlon11.add(box182);
  const towerMerlon12 = new THREE.Group();
  towerMerlon12.name = 'towerMerlon';
  towerMerlon12.position.set(1.9255, 10.22, 1.3989);
  towerMerlon12.rotation.set(0, deg(54), 0);
  rightTower.add(towerMerlon12);
  const box184 = new THREE.Mesh(boxGeo6, stoneMat);
  box184.position.set(0, 0.4, 0);
  towerMerlon12.add(box184);
  const box185 = new THREE.Mesh(boxGeo7, trimMat);
  box185.position.set(0, 0.84, 0);
  towerMerlon12.add(box185);
  const towerMerlon13 = new THREE.Group();
  towerMerlon13.name = 'towerMerlon';
  towerMerlon13.position.set(2.38, 10.22, 0);
  towerMerlon13.rotation.set(0, deg(90), 0);
  rightTower.add(towerMerlon13);
  const box187 = new THREE.Mesh(boxGeo6, stoneMat);
  box187.position.set(0, 0.4, 0);
  towerMerlon13.add(box187);
  const box188 = new THREE.Mesh(boxGeo7, trimMat);
  box188.position.set(0, 0.84, 0);
  towerMerlon13.add(box188);
  const towerMerlon14 = new THREE.Group();
  towerMerlon14.name = 'towerMerlon';
  towerMerlon14.position.set(1.9255, 10.22, -1.3989);
  towerMerlon14.rotation.set(0, deg(126), 0);
  rightTower.add(towerMerlon14);
  const box190 = new THREE.Mesh(boxGeo6, stoneMat);
  box190.position.set(0, 0.4, 0);
  towerMerlon14.add(box190);
  const box191 = new THREE.Mesh(boxGeo7, trimMat);
  box191.position.set(0, 0.84, 0);
  towerMerlon14.add(box191);
  const towerMerlon15 = new THREE.Group();
  towerMerlon15.name = 'towerMerlon';
  towerMerlon15.position.set(0.7355, 10.22, -2.2635);
  towerMerlon15.rotation.set(0, deg(162), 0);
  rightTower.add(towerMerlon15);
  const box193 = new THREE.Mesh(boxGeo6, stoneMat);
  box193.position.set(0, 0.4, 0);
  towerMerlon15.add(box193);
  const box194 = new THREE.Mesh(boxGeo7, trimMat);
  box194.position.set(0, 0.84, 0);
  towerMerlon15.add(box194);
  const towerMerlon16 = new THREE.Group();
  towerMerlon16.name = 'towerMerlon';
  towerMerlon16.position.set(-0.7355, 10.22, -2.2635);
  towerMerlon16.rotation.set(0, deg(198), 0);
  rightTower.add(towerMerlon16);
  const box196 = new THREE.Mesh(boxGeo6, stoneMat);
  box196.position.set(0, 0.4, 0);
  towerMerlon16.add(box196);
  const box197 = new THREE.Mesh(boxGeo7, trimMat);
  box197.position.set(0, 0.84, 0);
  towerMerlon16.add(box197);
  const towerMerlon17 = new THREE.Group();
  towerMerlon17.name = 'towerMerlon';
  towerMerlon17.position.set(-1.9255, 10.22, -1.3989);
  towerMerlon17.rotation.set(0, deg(234), 0);
  rightTower.add(towerMerlon17);
  const box199 = new THREE.Mesh(boxGeo6, stoneMat);
  box199.position.set(0, 0.4, 0);
  towerMerlon17.add(box199);
  const box200 = new THREE.Mesh(boxGeo7, trimMat);
  box200.position.set(0, 0.84, 0);
  towerMerlon17.add(box200);
  const towerMerlon18 = new THREE.Group();
  towerMerlon18.name = 'towerMerlon';
  towerMerlon18.position.set(-2.38, 10.22, 0);
  towerMerlon18.rotation.set(0, deg(270), 0);
  rightTower.add(towerMerlon18);
  const box202 = new THREE.Mesh(boxGeo6, stoneMat);
  box202.position.set(0, 0.4, 0);
  towerMerlon18.add(box202);
  const box203 = new THREE.Mesh(boxGeo7, trimMat);
  box203.position.set(0, 0.84, 0);
  towerMerlon18.add(box203);
  const towerMerlon19 = new THREE.Group();
  towerMerlon19.name = 'towerMerlon';
  towerMerlon19.position.set(-1.9255, 10.22, 1.3989);
  towerMerlon19.rotation.set(0, deg(306), 0);
  rightTower.add(towerMerlon19);
  const box205 = new THREE.Mesh(boxGeo6, stoneMat);
  box205.position.set(0, 0.4, 0);
  towerMerlon19.add(box205);
  const box206 = new THREE.Mesh(boxGeo7, trimMat);
  box206.position.set(0, 0.84, 0);
  towerMerlon19.add(box206);
  const towerMerlon20 = new THREE.Group();
  towerMerlon20.name = 'towerMerlon';
  towerMerlon20.position.set(-0.7355, 10.22, 2.2635);
  towerMerlon20.rotation.set(0, deg(342), 0);
  rightTower.add(towerMerlon20);
  const box208 = new THREE.Mesh(boxGeo6, stoneMat);
  box208.position.set(0, 0.4, 0);
  towerMerlon20.add(box208);
  const box209 = new THREE.Mesh(boxGeo7, trimMat);
  box209.position.set(0, 0.84, 0);
  towerMerlon20.add(box209);
  const arrowSlit5 = new THREE.Group();
  arrowSlit5.name = 'arrowSlit';
  arrowSlit5.position.set(1.8403, 2.4, 1.0625);
  arrowSlit5.rotation.set(0, deg(60), 0);
  rightTower.add(arrowSlit5);
  const box211 = new THREE.Mesh(boxGeo8, trimMat);
  arrowSlit5.add(box211);
  const box212 = new THREE.Mesh(boxGeo9, darkMat);
  box212.position.set(0, 0, 0.014);
  arrowSlit5.add(box212);
  const box213 = new THREE.Mesh(boxGeo10, darkMat);
  box213.position.set(0, 0.12, 0.014);
  arrowSlit5.add(box213);
  const arrowSlit6 = new THREE.Group();
  arrowSlit6.name = 'arrowSlit';
  arrowSlit6.position.set(2.0526, 4.8, -0.55);
  arrowSlit6.rotation.set(0, deg(105), 0);
  rightTower.add(arrowSlit6);
  const box215 = new THREE.Mesh(boxGeo8, trimMat);
  arrowSlit6.add(box215);
  const box216 = new THREE.Mesh(boxGeo9, darkMat);
  box216.position.set(0, 0, 0.014);
  arrowSlit6.add(box216);
  const box217 = new THREE.Mesh(boxGeo10, darkMat);
  box217.position.set(0, 0.12, 0.014);
  arrowSlit6.add(box217);
  const arrowSlit7 = new THREE.Group();
  arrowSlit7.name = 'arrowSlit';
  arrowSlit7.position.set(1.0625, 6, 1.8403);
  arrowSlit7.rotation.set(0, deg(30), 0);
  rightTower.add(arrowSlit7);
  const box219 = new THREE.Mesh(boxGeo8, trimMat);
  arrowSlit7.add(box219);
  const box220 = new THREE.Mesh(boxGeo9, darkMat);
  box220.position.set(0, 0, 0.014);
  arrowSlit7.add(box220);
  const box221 = new THREE.Mesh(boxGeo10, darkMat);
  box221.position.set(0, 0.12, 0.014);
  arrowSlit7.add(box221);
  const arrowSlit8 = new THREE.Group();
  arrowSlit8.name = 'arrowSlit';
  arrowSlit8.position.set(-0.369, 3.4, 2.0928);
  arrowSlit8.rotation.set(0, deg(-10), 0);
  rightTower.add(arrowSlit8);
  const box223 = new THREE.Mesh(boxGeo8, trimMat);
  arrowSlit8.add(box223);
  const box224 = new THREE.Mesh(boxGeo9, darkMat);
  box224.position.set(0, 0, 0.014);
  arrowSlit8.add(box224);
  const box225 = new THREE.Mesh(boxGeo10, darkMat);
  box225.position.set(0, 0.12, 0.014);
  arrowSlit8.add(box225);
  const banner2 = new THREE.Group();
  banner2.name = 'banner';
  banner2.position.set(-0.2957, 8.6, 2.1044);
  banner2.rotation.set(0, deg(-8), 0);
  rightTower.add(banner2);
  const bannerRod2 = new THREE.Mesh(cylinderGeo6, woodMat);
  bannerRod2.name = 'bannerRod';
  bannerRod2.position.set(0, 0, 0.12);
  bannerRod2.rotation.set(0, 0, deg(90));
  banner2.add(bannerRod2);
  const bannerCloth2 = new THREE.Mesh(extrudeGeo14, bannerMat);
  bannerCloth2.name = 'bannerCloth';
  bannerCloth2.position.set(0, -0.02, 0.1);
  banner2.add(bannerCloth2);
  const bannerStripe2 = new THREE.Mesh(boxGeo11, goldMat);
  bannerStripe2.name = 'bannerStripe';
  bannerStripe2.position.set(0, -1.1, 0.125);
  banner2.add(bannerStripe2);
  const flagPole = new THREE.Mesh(new THREE.CylinderGeometry(0.05, 0.06, 3.2, 6), woodMat);
  flagPole.name = 'flagPole';
  flagPole.position.set(4.35, 11.25, 0.7);
  root.add(flagPole);
  const pennant = new THREE.Mesh(extrude([[0, 0], [1.9, 0.08], [1.4, 0.5], [1.9, 0.92], [0, 1]], 0.04), bannerMat);
  pennant.name = 'pennant';
  pennant.position.set(4.39, 11.7, 0.7);
  pennant.rotation.set(0, deg(-20), 0);
  root.add(pennant);
  const towerFloor = new THREE.Mesh(cylinderGeo7, pavingMat);
  towerFloor.name = 'towerFloor';
  towerFloor.position.set(-4.35, 10.225, 0.7);
  towerFloor.rotation.set(0, deg(15), 0);
  root.add(towerFloor);
  const towerFloor2 = new THREE.Mesh(cylinderGeo7, pavingMat);
  towerFloor2.name = 'towerFloor';
  towerFloor2.position.set(4.35, 10.225, 0.7);
  towerFloor2.rotation.set(0, deg(15), 0);
  root.add(towerFloor2);
  const portcullisBar = new THREE.Mesh(boxGeo12, ironMat);
  portcullisBar.name = 'portcullisBar';
  portcullisBar.position.set(-1.6, 4.3875, 1.75);
  root.add(portcullisBar);
  const portcullisSpike = new THREE.Mesh(coneGeo, ironMat);
  portcullisSpike.name = 'portcullisSpike';
  portcullisSpike.position.set(-1.6, 1.9375, 1.75);
  portcullisSpike.rotation.set(deg(180), deg(45), 0);
  root.add(portcullisSpike);
  const portcullisBar2 = new THREE.Mesh(boxGeo12, ironMat);
  portcullisBar2.name = 'portcullisBar';
  portcullisBar2.position.set(-1.28, 4.3875, 1.75);
  root.add(portcullisBar2);
  const portcullisSpike2 = new THREE.Mesh(coneGeo, ironMat);
  portcullisSpike2.name = 'portcullisSpike';
  portcullisSpike2.position.set(-1.28, 1.9375, 1.75);
  portcullisSpike2.rotation.set(deg(180), deg(45), 0);
  root.add(portcullisSpike2);
  const portcullisBar3 = new THREE.Mesh(boxGeo12, ironMat);
  portcullisBar3.name = 'portcullisBar';
  portcullisBar3.position.set(-0.96, 4.3875, 1.75);
  root.add(portcullisBar3);
  const portcullisSpike3 = new THREE.Mesh(coneGeo, ironMat);
  portcullisSpike3.name = 'portcullisSpike';
  portcullisSpike3.position.set(-0.96, 1.9375, 1.75);
  portcullisSpike3.rotation.set(deg(180), deg(45), 0);
  root.add(portcullisSpike3);
  const portcullisBar4 = new THREE.Mesh(boxGeo12, ironMat);
  portcullisBar4.name = 'portcullisBar';
  portcullisBar4.position.set(-0.64, 4.3875, 1.75);
  root.add(portcullisBar4);
  const portcullisSpike4 = new THREE.Mesh(coneGeo, ironMat);
  portcullisSpike4.name = 'portcullisSpike';
  portcullisSpike4.position.set(-0.64, 1.9375, 1.75);
  portcullisSpike4.rotation.set(deg(180), deg(45), 0);
  root.add(portcullisSpike4);
  const portcullisBar5 = new THREE.Mesh(boxGeo12, ironMat);
  portcullisBar5.name = 'portcullisBar';
  portcullisBar5.position.set(-0.32, 4.3875, 1.75);
  root.add(portcullisBar5);
  const portcullisSpike5 = new THREE.Mesh(coneGeo, ironMat);
  portcullisSpike5.name = 'portcullisSpike';
  portcullisSpike5.position.set(-0.32, 1.9375, 1.75);
  portcullisSpike5.rotation.set(deg(180), deg(45), 0);
  root.add(portcullisSpike5);
  const portcullisBar6 = new THREE.Mesh(boxGeo12, ironMat);
  portcullisBar6.name = 'portcullisBar';
  portcullisBar6.position.set(0, 4.3875, 1.75);
  root.add(portcullisBar6);
  const portcullisSpike6 = new THREE.Mesh(coneGeo, ironMat);
  portcullisSpike6.name = 'portcullisSpike';
  portcullisSpike6.position.set(0, 1.9375, 1.75);
  portcullisSpike6.rotation.set(deg(180), deg(45), 0);
  root.add(portcullisSpike6);
  const portcullisBar7 = new THREE.Mesh(boxGeo12, ironMat);
  portcullisBar7.name = 'portcullisBar';
  portcullisBar7.position.set(0.32, 4.3875, 1.75);
  root.add(portcullisBar7);
  const portcullisSpike7 = new THREE.Mesh(coneGeo, ironMat);
  portcullisSpike7.name = 'portcullisSpike';
  portcullisSpike7.position.set(0.32, 1.9375, 1.75);
  portcullisSpike7.rotation.set(deg(180), deg(45), 0);
  root.add(portcullisSpike7);
  const portcullisBar8 = new THREE.Mesh(boxGeo12, ironMat);
  portcullisBar8.name = 'portcullisBar';
  portcullisBar8.position.set(0.64, 4.3875, 1.75);
  root.add(portcullisBar8);
  const portcullisSpike8 = new THREE.Mesh(coneGeo, ironMat);
  portcullisSpike8.name = 'portcullisSpike';
  portcullisSpike8.position.set(0.64, 1.9375, 1.75);
  portcullisSpike8.rotation.set(deg(180), deg(45), 0);
  root.add(portcullisSpike8);
  const portcullisBar9 = new THREE.Mesh(boxGeo12, ironMat);
  portcullisBar9.name = 'portcullisBar';
  portcullisBar9.position.set(0.96, 4.3875, 1.75);
  root.add(portcullisBar9);
  const portcullisSpike9 = new THREE.Mesh(coneGeo, ironMat);
  portcullisSpike9.name = 'portcullisSpike';
  portcullisSpike9.position.set(0.96, 1.9375, 1.75);
  portcullisSpike9.rotation.set(deg(180), deg(45), 0);
  root.add(portcullisSpike9);
  const portcullisBar10 = new THREE.Mesh(boxGeo12, ironMat);
  portcullisBar10.name = 'portcullisBar';
  portcullisBar10.position.set(1.28, 4.3875, 1.75);
  root.add(portcullisBar10);
  const portcullisSpike10 = new THREE.Mesh(coneGeo, ironMat);
  portcullisSpike10.name = 'portcullisSpike';
  portcullisSpike10.position.set(1.28, 1.9375, 1.75);
  portcullisSpike10.rotation.set(deg(180), deg(45), 0);
  root.add(portcullisSpike10);
  const portcullisBar11 = new THREE.Mesh(boxGeo12, ironMat);
  portcullisBar11.name = 'portcullisBar';
  portcullisBar11.position.set(1.6, 4.3875, 1.75);
  root.add(portcullisBar11);
  const portcullisSpike11 = new THREE.Mesh(coneGeo, ironMat);
  portcullisSpike11.name = 'portcullisSpike';
  portcullisSpike11.position.set(1.6, 1.9375, 1.75);
  portcullisSpike11.rotation.set(deg(180), deg(45), 0);
  root.add(portcullisSpike11);
  const portcullisRail = new THREE.Mesh(boxGeo13, ironMat);
  portcullisRail.name = 'portcullisRail';
  portcullisRail.position.set(0, 2.4375, 1.8);
  root.add(portcullisRail);
  const portcullisRail2 = new THREE.Mesh(boxGeo13, ironMat);
  portcullisRail2.name = 'portcullisRail';
  portcullisRail2.position.set(0, 2.9175, 1.8);
  root.add(portcullisRail2);
  const portcullisRail3 = new THREE.Mesh(boxGeo13, ironMat);
  portcullisRail3.name = 'portcullisRail';
  portcullisRail3.position.set(0, 3.3975, 1.8);
  root.add(portcullisRail3);
  const portcullisRail4 = new THREE.Mesh(boxGeo13, ironMat);
  portcullisRail4.name = 'portcullisRail';
  portcullisRail4.position.set(0, 3.8775, 1.8);
  root.add(portcullisRail4);
  const portcullisRail5 = new THREE.Mesh(boxGeo13, ironMat);
  portcullisRail5.name = 'portcullisRail';
  portcullisRail5.position.set(0, 4.3575, 1.8);
  root.add(portcullisRail5);
  const portcullisRail6 = new THREE.Mesh(boxGeo13, ironMat);
  portcullisRail6.name = 'portcullisRail';
  portcullisRail6.position.set(0, 4.8375, 1.8);
  root.add(portcullisRail6);
  const portcullisRail7 = new THREE.Mesh(boxGeo13, ironMat);
  portcullisRail7.name = 'portcullisRail';
  portcullisRail7.position.set(0, 5.3175, 1.8);
  root.add(portcullisRail7);
  const portcullisRail8 = new THREE.Mesh(boxGeo13, ironMat);
  portcullisRail8.name = 'portcullisRail';
  portcullisRail8.position.set(0, 5.7975, 1.8);
  root.add(portcullisRail8);
  const portcullisRail9 = new THREE.Mesh(boxGeo13, ironMat);
  portcullisRail9.name = 'portcullisRail';
  portcullisRail9.position.set(0, 6.2775, 1.8);
  root.add(portcullisRail9);
  const gateLeaf = new THREE.Group();
  gateLeaf.name = 'gateLeaf';
  gateLeaf.position.set(-1.76, 0.05, -0.6);
  gateLeaf.rotation.set(0, deg(82), 0);
  root.add(gateLeaf);
  const leaf = new THREE.Mesh(boxGeo14, woodMat);
  leaf.name = 'leaf';
  leaf.position.set(0.88, 1.625, 0);
  gateLeaf.add(leaf);
  const leafBand = new THREE.Mesh(boxGeo15, ironMat);
  leafBand.name = 'leafBand';
  leafBand.position.set(0.88, 0.5, 0.075);
  gateLeaf.add(leafBand);
  const leafBand2 = new THREE.Mesh(boxGeo15, ironMat);
  leafBand2.name = 'leafBand';
  leafBand2.position.set(0.88, 1.625, 0.075);
  gateLeaf.add(leafBand2);
  const leafBand3 = new THREE.Mesh(boxGeo15, ironMat);
  leafBand3.name = 'leafBand';
  leafBand3.position.set(0.88, 2.75, 0.075);
  gateLeaf.add(leafBand3);
  const gateLeaf2 = new THREE.Group();
  gateLeaf2.name = 'gateLeaf';
  gateLeaf2.position.set(1.76, 0.05, -0.6);
  gateLeaf2.rotation.set(0, deg(98), 0);
  root.add(gateLeaf2);
  const leaf2 = new THREE.Mesh(boxGeo14, woodMat);
  leaf2.name = 'leaf';
  leaf2.position.set(0.88, 1.625, 0);
  gateLeaf2.add(leaf2);
  const leafBand4 = new THREE.Mesh(boxGeo15, ironMat);
  leafBand4.name = 'leafBand';
  leafBand4.position.set(0.88, 0.5, 0.075);
  gateLeaf2.add(leafBand4);
  const leafBand5 = new THREE.Mesh(boxGeo15, ironMat);
  leafBand5.name = 'leafBand';
  leafBand5.position.set(0.88, 1.625, 0.075);
  gateLeaf2.add(leafBand5);
  const leafBand6 = new THREE.Mesh(boxGeo15, ironMat);
  leafBand6.name = 'leafBand';
  leafBand6.position.set(0.88, 2.75, 0.075);
  gateLeaf2.add(leafBand6);

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

export default createCastleGate;

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