삼각형 2.1천개6.92 × 19.6 × 7.98 m
코드에서 사용하기
에디터에서 리믹스castle-tower.js · 839줄
독립형 ES 모듈이에요 — three에만 의존해요. 팩토리 함수를 호출하고 그룹을 씬에 추가하세요.
/**
* Castle Tower — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 2,124 · Size (W × H × D): 6.92 × 19.60 × 7.98 m
*
* Usage:
* import { createCastleTower } from './castle-tower.js';
*
* const model = createCastleTower();
* 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);
}
export function createCastleTower() {
const root = new THREE.Group();
root.name = 'CastleTower';
// Materials
const stoneMat = new THREE.MeshStandardMaterial({ name: 'stone', color: 0xa19b91, roughness: 0.95, flatShading: true });
const trimMat = new THREE.MeshStandardMaterial({ name: 'trim', color: 0x7d776e, roughness: 0.95, flatShading: true });
const roofMat = new THREE.MeshStandardMaterial({ name: 'roof', color: 0x3d4b6e, roughness: 0.8, flatShading: true });
const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0x6a4529, roughness: 0.9, flatShading: true });
const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x1e1b19, roughness: 1, flatShading: true });
const flagMat = new THREE.MeshStandardMaterial({ name: 'flag', color: 0xb8322e, roughness: 0.85, flatShading: true });
// Shared geometries
const boxGeo = new THREE.BoxGeometry(0.26, 0.5, 0.42);
const boxGeo2 = new THREE.BoxGeometry(0.5909, 0.85, 0.4);
const boxGeo3 = new THREE.BoxGeometry(0.6509, 0.08, 0.46);
const boxGeo4 = new THREE.BoxGeometry(0.36, 1.15, 0.06);
const boxGeo5 = new THREE.BoxGeometry(0.12, 0.88, 0.06);
const boxGeo6 = new THREE.BoxGeometry(0.34, 0.1, 0.06);
const boxGeo7 = new THREE.BoxGeometry(0.03, 1.85, 0.02);
const boxGeo8 = new THREE.BoxGeometry(1.1, 0.07, 0.02);
// Parts
const plinth = new THREE.Mesh(new THREE.CylinderGeometry(3.06, 3.38, 0.9, 12), trimMat);
plinth.name = 'plinth';
plinth.position.set(0, 0.45, 0);
plinth.rotation.set(0, deg(15), 0);
root.add(plinth);
const tower = new THREE.Mesh(new THREE.CylinderGeometry(3, 3, 9.1, 12), stoneMat);
tower.name = 'tower';
tower.position.set(0, 5.45, 0);
tower.rotation.set(0, deg(15), 0);
root.add(tower);
const stringCourse = new THREE.Mesh(new THREE.CylinderGeometry(3.08, 3.08, 0.22, 12), trimMat);
stringCourse.name = 'stringCourse';
stringCourse.position.set(0, 4.832, 0);
stringCourse.rotation.set(0, deg(15), 0);
root.add(stringCourse);
const corbel = new THREE.Group();
corbel.name = 'corbel';
corbel.position.set(0, 9.65, 3.12);
root.add(corbel);
const box5 = new THREE.Mesh(boxGeo, trimMat);
corbel.add(box5);
const corbel2 = new THREE.Group();
corbel2.name = 'corbel';
corbel2.position.set(0.7195, 9.65, 3.0359);
corbel2.rotation.set(0, deg(13.3333), 0);
root.add(corbel2);
const box7 = new THREE.Mesh(boxGeo, trimMat);
corbel2.add(box7);
const corbel3 = new THREE.Group();
corbel3.name = 'corbel';
corbel3.position.set(1.4003, 9.65, 2.7881);
corbel3.rotation.set(0, deg(26.6667), 0);
root.add(corbel3);
const box9 = new THREE.Mesh(boxGeo, trimMat);
corbel3.add(box9);
const corbel4 = new THREE.Group();
corbel4.name = 'corbel';
corbel4.position.set(2.0055, 9.65, 2.3901);
corbel4.rotation.set(0, deg(40), 0);
root.add(corbel4);
const box11 = new THREE.Mesh(boxGeo, trimMat);
corbel4.add(box11);
const corbel5 = new THREE.Group();
corbel5.name = 'corbel';
corbel5.position.set(2.5026, 9.65, 1.8631);
corbel5.rotation.set(0, deg(53.3333), 0);
root.add(corbel5);
const box13 = new THREE.Mesh(boxGeo, trimMat);
corbel5.add(box13);
const corbel6 = new THREE.Group();
corbel6.name = 'corbel';
corbel6.position.set(2.8648, 9.65, 1.2358);
corbel6.rotation.set(0, deg(66.6667), 0);
root.add(corbel6);
const box15 = new THREE.Mesh(boxGeo, trimMat);
corbel6.add(box15);
const corbel7 = new THREE.Group();
corbel7.name = 'corbel';
corbel7.position.set(3.0726, 9.65, 0.5418);
corbel7.rotation.set(0, deg(80), 0);
root.add(corbel7);
const box17 = new THREE.Mesh(boxGeo, trimMat);
corbel7.add(box17);
const corbel8 = new THREE.Group();
corbel8.name = 'corbel';
corbel8.position.set(3.1147, 9.65, -0.1814);
corbel8.rotation.set(0, deg(93.3333), 0);
root.add(corbel8);
const box19 = new THREE.Mesh(boxGeo, trimMat);
corbel8.add(box19);
const corbel9 = new THREE.Group();
corbel9.name = 'corbel';
corbel9.position.set(2.9889, 9.65, -0.8948);
corbel9.rotation.set(0, deg(106.6667), 0);
root.add(corbel9);
const box21 = new THREE.Mesh(boxGeo, trimMat);
corbel9.add(box21);
const corbel10 = new THREE.Group();
corbel10.name = 'corbel';
corbel10.position.set(2.702, 9.65, -1.56);
corbel10.rotation.set(0, deg(120), 0);
root.add(corbel10);
const box23 = new THREE.Mesh(boxGeo, trimMat);
corbel10.add(box23);
const corbel11 = new THREE.Group();
corbel11.name = 'corbel';
corbel11.position.set(2.2694, 9.65, -2.1411);
corbel11.rotation.set(0, deg(133.3333), 0);
root.add(corbel11);
const box25 = new THREE.Mesh(boxGeo, trimMat);
corbel11.add(box25);
const corbel12 = new THREE.Group();
corbel12.name = 'corbel';
corbel12.position.set(1.7145, 9.65, -2.6067);
corbel12.rotation.set(0, deg(146.6667), 0);
root.add(corbel12);
const box27 = new THREE.Mesh(boxGeo, trimMat);
corbel12.add(box27);
const corbel13 = new THREE.Group();
corbel13.name = 'corbel';
corbel13.position.set(1.0671, 9.65, -2.9318);
corbel13.rotation.set(0, deg(160), 0);
root.add(corbel13);
const box29 = new THREE.Mesh(boxGeo, trimMat);
corbel13.add(box29);
const corbel14 = new THREE.Group();
corbel14.name = 'corbel';
corbel14.position.set(0.3622, 9.65, -3.0989);
corbel14.rotation.set(0, deg(173.3333), 0);
root.add(corbel14);
const box31 = new THREE.Mesh(boxGeo, trimMat);
corbel14.add(box31);
const corbel15 = new THREE.Group();
corbel15.name = 'corbel';
corbel15.position.set(-0.3622, 9.65, -3.0989);
corbel15.rotation.set(0, deg(186.6667), 0);
root.add(corbel15);
const box33 = new THREE.Mesh(boxGeo, trimMat);
corbel15.add(box33);
const corbel16 = new THREE.Group();
corbel16.name = 'corbel';
corbel16.position.set(-1.0671, 9.65, -2.9318);
corbel16.rotation.set(0, deg(200), 0);
root.add(corbel16);
const box35 = new THREE.Mesh(boxGeo, trimMat);
corbel16.add(box35);
const corbel17 = new THREE.Group();
corbel17.name = 'corbel';
corbel17.position.set(-1.7145, 9.65, -2.6067);
corbel17.rotation.set(0, deg(213.3333), 0);
root.add(corbel17);
const box37 = new THREE.Mesh(boxGeo, trimMat);
corbel17.add(box37);
const corbel18 = new THREE.Group();
corbel18.name = 'corbel';
corbel18.position.set(-2.2694, 9.65, -2.1411);
corbel18.rotation.set(0, deg(226.6667), 0);
root.add(corbel18);
const box39 = new THREE.Mesh(boxGeo, trimMat);
corbel18.add(box39);
const corbel19 = new THREE.Group();
corbel19.name = 'corbel';
corbel19.position.set(-2.702, 9.65, -1.56);
corbel19.rotation.set(0, deg(240), 0);
root.add(corbel19);
const box41 = new THREE.Mesh(boxGeo, trimMat);
corbel19.add(box41);
const corbel20 = new THREE.Group();
corbel20.name = 'corbel';
corbel20.position.set(-2.9889, 9.65, -0.8948);
corbel20.rotation.set(0, deg(253.3333), 0);
root.add(corbel20);
const box43 = new THREE.Mesh(boxGeo, trimMat);
corbel20.add(box43);
const corbel21 = new THREE.Group();
corbel21.name = 'corbel';
corbel21.position.set(-3.1147, 9.65, -0.1814);
corbel21.rotation.set(0, deg(266.6667), 0);
root.add(corbel21);
const box45 = new THREE.Mesh(boxGeo, trimMat);
corbel21.add(box45);
const corbel22 = new THREE.Group();
corbel22.name = 'corbel';
corbel22.position.set(-3.0726, 9.65, 0.5418);
corbel22.rotation.set(0, deg(280), 0);
root.add(corbel22);
const box47 = new THREE.Mesh(boxGeo, trimMat);
corbel22.add(box47);
const corbel23 = new THREE.Group();
corbel23.name = 'corbel';
corbel23.position.set(-2.8648, 9.65, 1.2358);
corbel23.rotation.set(0, deg(293.3333), 0);
root.add(corbel23);
const box49 = new THREE.Mesh(boxGeo, trimMat);
corbel23.add(box49);
const corbel24 = new THREE.Group();
corbel24.name = 'corbel';
corbel24.position.set(-2.5026, 9.65, 1.8631);
corbel24.rotation.set(0, deg(306.6667), 0);
root.add(corbel24);
const box51 = new THREE.Mesh(boxGeo, trimMat);
corbel24.add(box51);
const corbel25 = new THREE.Group();
corbel25.name = 'corbel';
corbel25.position.set(-2.0055, 9.65, 2.3901);
corbel25.rotation.set(0, deg(320), 0);
root.add(corbel25);
const box53 = new THREE.Mesh(boxGeo, trimMat);
corbel25.add(box53);
const corbel26 = new THREE.Group();
corbel26.name = 'corbel';
corbel26.position.set(-1.4003, 9.65, 2.7881);
corbel26.rotation.set(0, deg(333.3333), 0);
root.add(corbel26);
const box55 = new THREE.Mesh(boxGeo, trimMat);
corbel26.add(box55);
const corbel27 = new THREE.Group();
corbel27.name = 'corbel';
corbel27.position.set(-0.7195, 9.65, 3.0359);
corbel27.rotation.set(0, deg(346.6667), 0);
root.add(corbel27);
const box57 = new THREE.Mesh(boxGeo, trimMat);
corbel27.add(box57);
const parapet = new THREE.Mesh(new THREE.CylinderGeometry(3.42, 3.42, 0.55, 12), stoneMat);
parapet.name = 'parapet';
parapet.position.set(0, 10.275, 0);
parapet.rotation.set(0, deg(15), 0);
root.add(parapet);
const parapetLip = new THREE.Mesh(new THREE.CylinderGeometry(3.47, 3.47, 0.12, 12), trimMat);
parapetLip.name = 'parapetLip';
parapetLip.position.set(0, 10.55, 0);
parapetLip.rotation.set(0, deg(15), 0);
root.add(parapetLip);
const walkway = new THREE.Mesh(new THREE.CylinderGeometry(3.12, 3.12, 0.03, 12), trimMat);
walkway.name = 'walkway';
walkway.position.set(0, 10.625, 0);
walkway.rotation.set(0, deg(15), 0);
root.add(walkway);
const merlon = new THREE.Group();
merlon.name = 'merlon';
merlon.position.set(0.5037, 10.61, 3.1804);
merlon.rotation.set(0, deg(9), 0);
root.add(merlon);
const box62 = new THREE.Mesh(boxGeo2, stoneMat);
box62.position.set(0, 0.425, 0);
merlon.add(box62);
const box63 = new THREE.Mesh(boxGeo3, trimMat);
box63.position.set(0, 0.89, 0);
merlon.add(box63);
const merlon2 = new THREE.Group();
merlon2.name = 'merlon';
merlon2.position.set(1.4618, 10.61, 2.869);
merlon2.rotation.set(0, deg(27), 0);
root.add(merlon2);
const box65 = new THREE.Mesh(boxGeo2, stoneMat);
box65.position.set(0, 0.425, 0);
merlon2.add(box65);
const box66 = new THREE.Mesh(boxGeo3, trimMat);
box66.position.set(0, 0.89, 0);
merlon2.add(box66);
const merlon3 = new THREE.Group();
merlon3.name = 'merlon';
merlon3.position.set(2.2769, 10.61, 2.2769);
merlon3.rotation.set(0, deg(45), 0);
root.add(merlon3);
const box68 = new THREE.Mesh(boxGeo2, stoneMat);
box68.position.set(0, 0.425, 0);
merlon3.add(box68);
const box69 = new THREE.Mesh(boxGeo3, trimMat);
box69.position.set(0, 0.89, 0);
merlon3.add(box69);
const merlon4 = new THREE.Group();
merlon4.name = 'merlon';
merlon4.position.set(2.869, 10.61, 1.4618);
merlon4.rotation.set(0, deg(63), 0);
root.add(merlon4);
const box71 = new THREE.Mesh(boxGeo2, stoneMat);
box71.position.set(0, 0.425, 0);
merlon4.add(box71);
const box72 = new THREE.Mesh(boxGeo3, trimMat);
box72.position.set(0, 0.89, 0);
merlon4.add(box72);
const merlon5 = new THREE.Group();
merlon5.name = 'merlon';
merlon5.position.set(3.1804, 10.61, 0.5037);
merlon5.rotation.set(0, deg(81), 0);
root.add(merlon5);
const box74 = new THREE.Mesh(boxGeo2, stoneMat);
box74.position.set(0, 0.425, 0);
merlon5.add(box74);
const box75 = new THREE.Mesh(boxGeo3, trimMat);
box75.position.set(0, 0.89, 0);
merlon5.add(box75);
const merlon6 = new THREE.Group();
merlon6.name = 'merlon';
merlon6.position.set(3.1804, 10.61, -0.5037);
merlon6.rotation.set(0, deg(99), 0);
root.add(merlon6);
const box77 = new THREE.Mesh(boxGeo2, stoneMat);
box77.position.set(0, 0.425, 0);
merlon6.add(box77);
const box78 = new THREE.Mesh(boxGeo3, trimMat);
box78.position.set(0, 0.89, 0);
merlon6.add(box78);
const merlon7 = new THREE.Group();
merlon7.name = 'merlon';
merlon7.position.set(2.869, 10.61, -1.4618);
merlon7.rotation.set(0, deg(117), 0);
root.add(merlon7);
const box80 = new THREE.Mesh(boxGeo2, stoneMat);
box80.position.set(0, 0.425, 0);
merlon7.add(box80);
const box81 = new THREE.Mesh(boxGeo3, trimMat);
box81.position.set(0, 0.89, 0);
merlon7.add(box81);
const merlon8 = new THREE.Group();
merlon8.name = 'merlon';
merlon8.position.set(2.2769, 10.61, -2.2769);
merlon8.rotation.set(0, deg(135), 0);
root.add(merlon8);
const box83 = new THREE.Mesh(boxGeo2, stoneMat);
box83.position.set(0, 0.425, 0);
merlon8.add(box83);
const box84 = new THREE.Mesh(boxGeo3, trimMat);
box84.position.set(0, 0.89, 0);
merlon8.add(box84);
const merlon9 = new THREE.Group();
merlon9.name = 'merlon';
merlon9.position.set(1.4618, 10.61, -2.869);
merlon9.rotation.set(0, deg(153), 0);
root.add(merlon9);
const box86 = new THREE.Mesh(boxGeo2, stoneMat);
box86.position.set(0, 0.425, 0);
merlon9.add(box86);
const box87 = new THREE.Mesh(boxGeo3, trimMat);
box87.position.set(0, 0.89, 0);
merlon9.add(box87);
const merlon10 = new THREE.Group();
merlon10.name = 'merlon';
merlon10.position.set(0.5037, 10.61, -3.1804);
merlon10.rotation.set(0, deg(171), 0);
root.add(merlon10);
const box89 = new THREE.Mesh(boxGeo2, stoneMat);
box89.position.set(0, 0.425, 0);
merlon10.add(box89);
const box90 = new THREE.Mesh(boxGeo3, trimMat);
box90.position.set(0, 0.89, 0);
merlon10.add(box90);
const merlon11 = new THREE.Group();
merlon11.name = 'merlon';
merlon11.position.set(-0.5037, 10.61, -3.1804);
merlon11.rotation.set(0, deg(189), 0);
root.add(merlon11);
const box92 = new THREE.Mesh(boxGeo2, stoneMat);
box92.position.set(0, 0.425, 0);
merlon11.add(box92);
const box93 = new THREE.Mesh(boxGeo3, trimMat);
box93.position.set(0, 0.89, 0);
merlon11.add(box93);
const merlon12 = new THREE.Group();
merlon12.name = 'merlon';
merlon12.position.set(-1.4618, 10.61, -2.869);
merlon12.rotation.set(0, deg(207), 0);
root.add(merlon12);
const box95 = new THREE.Mesh(boxGeo2, stoneMat);
box95.position.set(0, 0.425, 0);
merlon12.add(box95);
const box96 = new THREE.Mesh(boxGeo3, trimMat);
box96.position.set(0, 0.89, 0);
merlon12.add(box96);
const merlon13 = new THREE.Group();
merlon13.name = 'merlon';
merlon13.position.set(-2.2769, 10.61, -2.2769);
merlon13.rotation.set(0, deg(225), 0);
root.add(merlon13);
const box98 = new THREE.Mesh(boxGeo2, stoneMat);
box98.position.set(0, 0.425, 0);
merlon13.add(box98);
const box99 = new THREE.Mesh(boxGeo3, trimMat);
box99.position.set(0, 0.89, 0);
merlon13.add(box99);
const merlon14 = new THREE.Group();
merlon14.name = 'merlon';
merlon14.position.set(-2.869, 10.61, -1.4618);
merlon14.rotation.set(0, deg(243), 0);
root.add(merlon14);
const box101 = new THREE.Mesh(boxGeo2, stoneMat);
box101.position.set(0, 0.425, 0);
merlon14.add(box101);
const box102 = new THREE.Mesh(boxGeo3, trimMat);
box102.position.set(0, 0.89, 0);
merlon14.add(box102);
const merlon15 = new THREE.Group();
merlon15.name = 'merlon';
merlon15.position.set(-3.1804, 10.61, -0.5037);
merlon15.rotation.set(0, deg(261), 0);
root.add(merlon15);
const box104 = new THREE.Mesh(boxGeo2, stoneMat);
box104.position.set(0, 0.425, 0);
merlon15.add(box104);
const box105 = new THREE.Mesh(boxGeo3, trimMat);
box105.position.set(0, 0.89, 0);
merlon15.add(box105);
const merlon16 = new THREE.Group();
merlon16.name = 'merlon';
merlon16.position.set(-3.1804, 10.61, 0.5037);
merlon16.rotation.set(0, deg(279), 0);
root.add(merlon16);
const box107 = new THREE.Mesh(boxGeo2, stoneMat);
box107.position.set(0, 0.425, 0);
merlon16.add(box107);
const box108 = new THREE.Mesh(boxGeo3, trimMat);
box108.position.set(0, 0.89, 0);
merlon16.add(box108);
const merlon17 = new THREE.Group();
merlon17.name = 'merlon';
merlon17.position.set(-2.869, 10.61, 1.4618);
merlon17.rotation.set(0, deg(297), 0);
root.add(merlon17);
const box110 = new THREE.Mesh(boxGeo2, stoneMat);
box110.position.set(0, 0.425, 0);
merlon17.add(box110);
const box111 = new THREE.Mesh(boxGeo3, trimMat);
box111.position.set(0, 0.89, 0);
merlon17.add(box111);
const merlon18 = new THREE.Group();
merlon18.name = 'merlon';
merlon18.position.set(-2.2769, 10.61, 2.2769);
merlon18.rotation.set(0, deg(315), 0);
root.add(merlon18);
const box113 = new THREE.Mesh(boxGeo2, stoneMat);
box113.position.set(0, 0.425, 0);
merlon18.add(box113);
const box114 = new THREE.Mesh(boxGeo3, trimMat);
box114.position.set(0, 0.89, 0);
merlon18.add(box114);
const merlon19 = new THREE.Group();
merlon19.name = 'merlon';
merlon19.position.set(-1.4618, 10.61, 2.869);
merlon19.rotation.set(0, deg(333), 0);
root.add(merlon19);
const box116 = new THREE.Mesh(boxGeo2, stoneMat);
box116.position.set(0, 0.425, 0);
merlon19.add(box116);
const box117 = new THREE.Mesh(boxGeo3, trimMat);
box117.position.set(0, 0.89, 0);
merlon19.add(box117);
const merlon20 = new THREE.Group();
merlon20.name = 'merlon';
merlon20.position.set(-0.5037, 10.61, 3.1804);
merlon20.rotation.set(0, deg(351), 0);
root.add(merlon20);
const box119 = new THREE.Mesh(boxGeo2, stoneMat);
box119.position.set(0, 0.425, 0);
merlon20.add(box119);
const box120 = new THREE.Mesh(boxGeo3, trimMat);
box120.position.set(0, 0.89, 0);
merlon20.add(box120);
const arrowSlit = new THREE.Group();
arrowSlit.name = 'arrowSlit';
arrowSlit.position.set(2.5095, 3.9, -1.4489);
arrowSlit.rotation.set(0, deg(120), 0);
root.add(arrowSlit);
const box122 = new THREE.Mesh(boxGeo4, trimMat);
arrowSlit.add(box122);
const box123 = new THREE.Mesh(boxGeo5, darkMat);
box123.position.set(0, 0, 0.014);
arrowSlit.add(box123);
const box124 = new THREE.Mesh(boxGeo6, darkMat);
box124.position.set(0, 0.12, 0.014);
arrowSlit.add(box124);
const arrowSlit2 = new THREE.Group();
arrowSlit2.name = 'arrowSlit';
arrowSlit2.position.set(-2.5095, 3.9, -1.4489);
arrowSlit2.rotation.set(0, deg(240), 0);
root.add(arrowSlit2);
const box126 = new THREE.Mesh(boxGeo4, trimMat);
arrowSlit2.add(box126);
const box127 = new THREE.Mesh(boxGeo5, darkMat);
box127.position.set(0, 0, 0.014);
arrowSlit2.add(box127);
const box128 = new THREE.Mesh(boxGeo6, darkMat);
box128.position.set(0, 0.12, 0.014);
arrowSlit2.add(box128);
const arrowSlit3 = new THREE.Group();
arrowSlit3.name = 'arrowSlit';
arrowSlit3.position.set(2.8978, 6.2, 0);
arrowSlit3.rotation.set(0, deg(90), 0);
root.add(arrowSlit3);
const box130 = new THREE.Mesh(boxGeo4, trimMat);
arrowSlit3.add(box130);
const box131 = new THREE.Mesh(boxGeo5, darkMat);
box131.position.set(0, 0, 0.014);
arrowSlit3.add(box131);
const box132 = new THREE.Mesh(boxGeo6, darkMat);
box132.position.set(0, 0.12, 0.014);
arrowSlit3.add(box132);
const arrowSlit4 = new THREE.Group();
arrowSlit4.name = 'arrowSlit';
arrowSlit4.position.set(-1.4489, 6.2, -2.5095);
arrowSlit4.rotation.set(0, deg(210), 0);
root.add(arrowSlit4);
const box134 = new THREE.Mesh(boxGeo4, trimMat);
arrowSlit4.add(box134);
const box135 = new THREE.Mesh(boxGeo5, darkMat);
box135.position.set(0, 0, 0.014);
arrowSlit4.add(box135);
const box136 = new THREE.Mesh(boxGeo6, darkMat);
box136.position.set(0, 0.12, 0.014);
arrowSlit4.add(box136);
const arrowSlit5 = new THREE.Group();
arrowSlit5.name = 'arrowSlit';
arrowSlit5.position.set(-1.4489, 6.2, 2.5095);
arrowSlit5.rotation.set(0, deg(330), 0);
root.add(arrowSlit5);
const box138 = new THREE.Mesh(boxGeo4, trimMat);
arrowSlit5.add(box138);
const box139 = new THREE.Mesh(boxGeo5, darkMat);
box139.position.set(0, 0, 0.014);
arrowSlit5.add(box139);
const box140 = new THREE.Mesh(boxGeo6, darkMat);
box140.position.set(0, 0.12, 0.014);
arrowSlit5.add(box140);
const arrowSlit6 = new THREE.Group();
arrowSlit6.name = 'arrowSlit';
arrowSlit6.position.set(2.5095, 8.5, -1.4489);
arrowSlit6.rotation.set(0, deg(120), 0);
root.add(arrowSlit6);
const box142 = new THREE.Mesh(boxGeo4, trimMat);
arrowSlit6.add(box142);
const box143 = new THREE.Mesh(boxGeo5, darkMat);
box143.position.set(0, 0, 0.014);
arrowSlit6.add(box143);
const box144 = new THREE.Mesh(boxGeo6, darkMat);
box144.position.set(0, 0.12, 0.014);
arrowSlit6.add(box144);
const arrowSlit7 = new THREE.Group();
arrowSlit7.name = 'arrowSlit';
arrowSlit7.position.set(-2.5095, 8.5, -1.4489);
arrowSlit7.rotation.set(0, deg(240), 0);
root.add(arrowSlit7);
const box146 = new THREE.Mesh(boxGeo4, trimMat);
arrowSlit7.add(box146);
const box147 = new THREE.Mesh(boxGeo5, darkMat);
box147.position.set(0, 0, 0.014);
arrowSlit7.add(box147);
const box148 = new THREE.Mesh(boxGeo6, darkMat);
box148.position.set(0, 0.12, 0.014);
arrowSlit7.add(box148);
const arrowSlit8 = new THREE.Group();
arrowSlit8.name = 'arrowSlit';
arrowSlit8.position.set(0, 8.5, 2.8978);
root.add(arrowSlit8);
const box150 = new THREE.Mesh(boxGeo4, trimMat);
arrowSlit8.add(box150);
const box151 = new THREE.Mesh(boxGeo5, darkMat);
box151.position.set(0, 0, 0.014);
arrowSlit8.add(box151);
const box152 = new THREE.Mesh(boxGeo6, darkMat);
box152.position.set(0, 0.12, 0.014);
arrowSlit8.add(box152);
const stone = new THREE.Group();
stone.name = 'stone';
stone.position.set(1.2164, 6.0408, 2.6301);
stone.rotation.set(0, deg(24.8197), 0);
root.add(stone);
const box154 = new THREE.Mesh(new THREE.BoxGeometry(0.5222, 0.2524, 0.08), stoneMat);
box154.position.set(0, 0, 0.012);
stone.add(box154);
const stone2 = new THREE.Group();
stone2.name = 'stone';
stone2.position.set(-0.2748, 7.4953, -2.8847);
stone2.rotation.set(0, deg(185.4412), 0);
root.add(stone2);
const box156 = new THREE.Mesh(new THREE.BoxGeometry(0.4036, 0.2909, 0.08), stoneMat);
box156.position.set(0, 0, 0.012);
stone2.add(box156);
const stone3 = new THREE.Group();
stone3.name = 'stone';
stone3.position.set(1.6961, 7.5959, 2.3495);
stone3.rotation.set(0, deg(35.8255), 0);
root.add(stone3);
const box158 = new THREE.Mesh(new THREE.BoxGeometry(0.5889, 0.2941, 0.08), stoneMat);
box158.position.set(0, 0, 0.012);
stone3.add(box158);
const stone4 = new THREE.Group();
stone4.name = 'stone';
stone4.position.set(1.3666, 8.6919, -2.5553);
stone4.rotation.set(0, deg(151.8625), 0);
root.add(stone4);
const box160 = new THREE.Mesh(new THREE.BoxGeometry(0.4852, 0.3046, 0.08), stoneMat);
box160.position.set(0, 0, 0.012);
stone4.add(box160);
const stone5 = new THREE.Group();
stone5.name = 'stone';
stone5.position.set(2.591, 2.479, 1.2976);
stone5.rotation.set(0, deg(63.3975), 0);
root.add(stone5);
const box162 = new THREE.Mesh(new THREE.BoxGeometry(0.6861, 0.2571, 0.08), trimMat);
box162.position.set(0, 0, 0.012);
stone5.add(box162);
const stone6 = new THREE.Group();
stone6.name = 'stone';
stone6.position.set(-1.3074, 8.0114, 2.5861);
stone6.rotation.set(0, deg(333.1811), 0);
root.add(stone6);
const box164 = new THREE.Mesh(new THREE.BoxGeometry(0.7652, 0.2846, 0.08), trimMat);
box164.position.set(0, 0, 0.012);
stone6.add(box164);
const stone7 = new THREE.Group();
stone7.name = 'stone';
stone7.position.set(-2.4194, 3.6314, -1.5949);
stone7.rotation.set(0, deg(236.6068), 0);
root.add(stone7);
const box166 = new THREE.Mesh(new THREE.BoxGeometry(0.6069, 0.3096, 0.08), trimMat);
box166.position.set(0, 0, 0.012);
stone7.add(box166);
const stone8 = new THREE.Group();
stone8.name = 'stone';
stone8.position.set(-2.8964, 3.6866, 0.0882);
stone8.rotation.set(0, deg(271.7436), 0);
root.add(stone8);
const box168 = new THREE.Mesh(new THREE.BoxGeometry(0.7629, 0.2404, 0.08), stoneMat);
box168.position.set(0, 0, 0.012);
stone8.add(box168);
const stone9 = new THREE.Group();
stone9.name = 'stone';
stone9.position.set(-2.8905, 6.4, -0.2055);
stone9.rotation.set(0, deg(265.9341), 0);
root.add(stone9);
const box170 = new THREE.Mesh(new THREE.BoxGeometry(0.7585, 0.2976, 0.08), stoneMat);
box170.position.set(0, 0, 0.012);
stone9.add(box170);
const stone10 = new THREE.Group();
stone10.name = 'stone';
stone10.position.set(-0.0183, 6.9339, -2.8977);
stone10.rotation.set(0, deg(180.3617), 0);
root.add(stone10);
const box172 = new THREE.Mesh(new THREE.BoxGeometry(0.5448, 0.2493, 0.08), stoneMat);
box172.position.set(0, 0, 0.012);
stone10.add(box172);
const stone11 = new THREE.Group();
stone11.name = 'stone';
stone11.position.set(-0.1807, 6.1583, 2.8921);
stone11.rotation.set(0, deg(-3.5761), 0);
root.add(stone11);
const box174 = new THREE.Mesh(new THREE.BoxGeometry(0.4341, 0.2775, 0.08), trimMat);
box174.position.set(0, 0, 0.012);
stone11.add(box174);
const stone12 = new THREE.Group();
stone12.name = 'stone';
stone12.position.set(-2.408, 2.5974, -1.6121);
stone12.rotation.set(0, deg(236.1991), 0);
root.add(stone12);
const box176 = new THREE.Mesh(new THREE.BoxGeometry(0.6927, 0.2751, 0.08), stoneMat);
box176.position.set(0, 0, 0.012);
stone12.add(box176);
const stone13 = new THREE.Group();
stone13.name = 'stone';
stone13.position.set(0.2004, 6.7916, 2.8908);
stone13.rotation.set(0, deg(3.9659), 0);
root.add(stone13);
const box178 = new THREE.Mesh(new THREE.BoxGeometry(0.7357, 0.2907, 0.08), stoneMat);
box178.position.set(0, 0, 0.012);
stone13.add(box178);
const stone14 = new THREE.Group();
stone14.name = 'stone';
stone14.position.set(1.5335, 6.0301, 2.4587);
stone14.rotation.set(0, deg(31.9516), 0);
root.add(stone14);
const box180 = new THREE.Mesh(new THREE.BoxGeometry(0.4874, 0.2615, 0.08), stoneMat);
box180.position.set(0, 0, 0.012);
stone14.add(box180);
const stone15 = new THREE.Group();
stone15.name = 'stone';
stone15.position.set(2.5263, 8.7609, 1.4195);
stone15.rotation.set(0, deg(60.6693), 0);
root.add(stone15);
const box182 = new THREE.Mesh(new THREE.BoxGeometry(0.4091, 0.2905, 0.08), stoneMat);
box182.position.set(0, 0, 0.012);
stone15.add(box182);
const stone16 = new THREE.Group();
stone16.name = 'stone';
stone16.position.set(1.6861, 5.6482, 2.3567);
stone16.rotation.set(0, deg(35.5825), 0);
root.add(stone16);
const box184 = new THREE.Mesh(new THREE.BoxGeometry(0.672, 0.3178, 0.08), trimMat);
box184.position.set(0, 0, 0.012);
stone16.add(box184);
const stone17 = new THREE.Group();
stone17.name = 'stone';
stone17.position.set(-2.5986, 1.7667, 1.2823);
stone17.rotation.set(0, deg(296.2642), 0);
root.add(stone17);
const box186 = new THREE.Mesh(new THREE.BoxGeometry(0.7137, 0.2821, 0.08), trimMat);
box186.position.set(0, 0, 0.012);
stone17.add(box186);
const stone18 = new THREE.Group();
stone18.name = 'stone';
stone18.position.set(-2.5696, 5.7837, -1.3395);
stone18.rotation.set(0, deg(242.4682), 0);
root.add(stone18);
const box188 = new THREE.Mesh(new THREE.BoxGeometry(0.6377, 0.2424, 0.08), trimMat);
box188.position.set(0, 0, 0.012);
stone18.add(box188);
const stone19 = new THREE.Group();
stone19.name = 'stone';
stone19.position.set(2.6403, 6.6903, 1.1941);
stone19.rotation.set(0, deg(65.6648), 0);
root.add(stone19);
const box190 = new THREE.Mesh(new THREE.BoxGeometry(0.4356, 0.2345, 0.08), trimMat);
box190.position.set(0, 0, 0.012);
stone19.add(box190);
const stone20 = new THREE.Group();
stone20.name = 'stone';
stone20.position.set(2.8826, 7.5362, 0.2959);
stone20.rotation.set(0, deg(84.1396), 0);
root.add(stone20);
const box192 = new THREE.Mesh(new THREE.BoxGeometry(0.6205, 0.2455, 0.08), trimMat);
box192.position.set(0, 0, 0.012);
stone20.add(box192);
const stone21 = new THREE.Group();
stone21.name = 'stone';
stone21.position.set(-2.6098, 3.078, 1.2594);
stone21.rotation.set(0, deg(295.7614), 0);
root.add(stone21);
const box194 = new THREE.Mesh(new THREE.BoxGeometry(0.6136, 0.2282, 0.08), stoneMat);
box194.position.set(0, 0, 0.012);
stone21.add(box194);
const door = new THREE.Group();
door.name = 'door';
door.position.set(0, 0.9, 2.8978);
root.add(door);
const doorArch = new THREE.Mesh(extrude([[-0.82, 0], [-0.82, 1.55], [-0.7576, 1.8638], [-0.5798, 2.1298], [-0.3138, 2.3076], [0, 2.37], [0.3138, 2.3076], [0.5798, 2.1298], [0.7576, 1.8638], [0.82, 1.55], [0.82, 0], [0.6, 0], [0.6, 1.55], [0.5543, 1.7796], [0.4243, 1.9743], [0.2296, 2.1043], [0, 2.15], [-0.2296, 2.1043], [-0.4243, 1.9743], [-0.5543, 1.7796], [-0.6, 1.55], [-0.6, 0]], 0.16), trimMat);
doorArch.name = 'doorArch';
doorArch.position.set(0, 0, 0.04);
door.add(doorArch);
const doorPanel = new THREE.Mesh(extrude([[-0.6, 0], [-0.6, 1.55], [-0.5543, 1.7796], [-0.4243, 1.9743], [-0.2296, 2.1043], [0, 2.15], [0.2296, 2.1043], [0.4243, 1.9743], [0.5543, 1.7796], [0.6, 1.55], [0.6, 0]], 0.06), woodMat);
doorPanel.name = 'doorPanel';
door.add(doorPanel);
const box198 = new THREE.Mesh(boxGeo7, darkMat);
box198.position.set(-0.3, 0.965, 0.035);
door.add(box198);
const box199 = new THREE.Mesh(boxGeo7, darkMat);
box199.position.set(0, 0.965, 0.035);
door.add(box199);
const box200 = new THREE.Mesh(boxGeo7, darkMat);
box200.position.set(0.3, 0.965, 0.035);
door.add(box200);
const box201 = new THREE.Mesh(boxGeo8, darkMat);
box201.position.set(0, 0.55, 0.04);
door.add(box201);
const box202 = new THREE.Mesh(boxGeo8, darkMat);
box202.position.set(0, 1.45, 0.04);
door.add(box202);
const ringHandle = new THREE.Mesh(new THREE.TorusGeometry(0.08, 0.018, 4, 8), darkMat);
ringHandle.name = 'ringHandle';
ringHandle.position.set(0.35, 1, 0.06);
door.add(ringHandle);
const step = new THREE.Mesh(new THREE.BoxGeometry(2.1, 0.3, 1.8271), trimMat);
step.name = 'step';
step.position.set(0, 0.15, 3.6113);
root.add(step);
const step2 = new THREE.Mesh(new THREE.BoxGeometry(1.98, 0.3, 1.4071), trimMat);
step2.name = 'step';
step2.position.set(0, 0.45, 3.4013);
root.add(step2);
const step3 = new THREE.Mesh(new THREE.BoxGeometry(1.86, 0.3, 0.9871), trimMat);
step3.name = 'step';
step3.position.set(0, 0.75, 3.1913);
root.add(step3);
const roof = new THREE.Mesh(lathe([[3.15, 0], [2.583, 0.702], [1.575, 2.6325], [0.63, 4.68], [0.001, 5.85]], 12), roofMat);
roof.name = 'roof';
roof.position.set(0, 10.61, 0);
roof.rotation.set(0, deg(15), 0);
root.add(roof);
const finial = new THREE.Mesh(new THREE.SphereGeometry(0.18, 6, 4), trimMat);
finial.name = 'finial';
finial.position.set(0, 16.46, 0);
root.add(finial);
const flagPole = new THREE.Mesh(new THREE.CylinderGeometry(0.05, 0.06, 3, 6), woodMat);
flagPole.name = 'flagPole';
flagPole.position.set(0, 17.96, 0);
root.add(flagPole);
const poleTip = new THREE.Mesh(new THREE.SphereGeometry(0.09, 6, 4), flagMat);
poleTip.name = 'poleTip';
poleTip.position.set(0, 19.51, 0);
root.add(poleTip);
const pennant = new THREE.Mesh(extrude([[0, 0], [2.3, 0.1], [1.7, 0.58], [2.3, 1.06], [0, 1.16]], 0.04), flagMat);
pennant.name = 'pennant';
pennant.position.set(0.04, 18.21, 0);
pennant.rotation.set(0, deg(-25), 0);
root.add(pennant);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createCastleTower;
평점 및 댓글
댓글 0개
아직 댓글이 없어요. 이 모델을 어떻게 사용했는지, 어떤 점이 더 나아질 수 있을지 공유해 주세요.
관련 모델
같은 카테고리 또는 비슷한 태그









