2760 三角面6.24 × 19.5 × 5.99 m
在代码中使用
在编辑器中改编wizard-tower.js · 669 行
自包含的 ES 模块,仅依赖 three。调用工厂函数,然后把返回的 group 添加到场景中。
/**
* Wizard Tower — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 2,760 · Size (W × H × D): 6.24 × 19.53 × 5.99 m
*
* Usage:
* import { createWizardTower } from './wizard-tower.js';
*
* const model = createWizardTower();
* 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;
}
// Revolve a 2D profile [[radius, y], ...] around the Y axis.
function lathe(points, segments, phiStart = 0, phiLength = Math.PI * 2) {
return new THREE.LatheGeometry(points.map(([x, y]) => new THREE.Vector2(x, y)), segments, phiStart, phiLength);
}
// Extrude a 2D outline along Z (centered). bevel = [thickness, size, segments].
function extrude(outline, depth, holes = [], bevel = null) {
const shape = new THREE.Shape(outline.map(([x, y]) => new THREE.Vector2(x, y)));
for (const hole of holes) shape.holes.push(new THREE.Path(hole.map(([x, y]) => new THREE.Vector2(x, y))));
const options = bevel
? { depth, bevelEnabled: true, bevelThickness: bevel[0], bevelSize: bevel[1], bevelSegments: bevel[2] }
: { depth, bevelEnabled: false };
return new THREE.ExtrudeGeometry(shape, options).translate(0, 0, -depth / 2);
}
// Tube along a smooth curve through the given points.
function tube(path, radius, tubularSegments, radialSegments, closed = false) {
const curve = new THREE.CatmullRomCurve3(path.map(([x, y, z]) => new THREE.Vector3(x, y, z)), closed);
return new THREE.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
}
export function createWizardTower() {
const root = new THREE.Group();
root.name = 'WizardTower';
// Materials
const stoneMat = new THREE.MeshStandardMaterial({ name: 'stone', color: 0x9a958c, roughness: 0.95, flatShading: true });
const stone2Mat = new THREE.MeshStandardMaterial({ name: 'stone2', color: 0x7c776f, roughness: 0.95, flatShading: true });
const roofMat = new THREE.MeshStandardMaterial({ name: 'roof', color: 0x3c3f8c, roughness: 0.8, flatShading: true });
const goldMat = new THREE.MeshStandardMaterial({ name: 'gold', color: 0xd8a93e, roughness: 0.4, metalness: 0.6, flatShading: true });
const glowMat = new THREE.MeshStandardMaterial({ name: 'glow', color: 0xc1a2ff, roughness: 0.4, emissive: 0xa070ff, emissiveIntensity: 1.2, flatShading: true });
const orbMat = new THREE.MeshStandardMaterial({ name: 'orb', color: 0xd4bfff, roughness: 0.15, emissive: 0xa070ff, emissiveIntensity: 1.4 });
const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0x6b4428, roughness: 0.9, flatShading: true });
const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x231c26, roughness: 1, flatShading: true });
// Shared geometries
const extrudeGeo = extrude([[-0.35, -0.53], [0.35, -0.53], [0.35, 0.14], [0.2832, 0.3457], [0.1082, 0.4729], [-0.1082, 0.4729], [-0.2832, 0.3457], [-0.35, 0.14]], 0.08);
const extrudeGeo2 = extrude([[-0.25, -0.45], [0.25, -0.45], [0.25, 0.2], [0.2023, 0.3469], [0.0773, 0.4378], [-0.0773, 0.4378], [-0.2023, 0.3469], [-0.25, 0.2]], 0.06);
const boxGeo = new THREE.BoxGeometry(0.8, 0.08, 0.18);
const boxGeo2 = new THREE.BoxGeometry(0.95, 0.06, 0.02);
const boxGeo3 = new THREE.BoxGeometry(0.14, 0.14, 0.95);
const boxGeo4 = new THREE.BoxGeometry(0.06, 0.9, 0.06);
const boxGeo5 = new THREE.BoxGeometry(0.26, 0.42, 0.3);
const extrudeGeo3 = extrude([[-0.35, -0.505], [0.35, -0.505], [0.35, 0.115], [0.2832, 0.3207], [0.1082, 0.4479], [-0.1082, 0.4479], [-0.2832, 0.3207], [-0.35, 0.115]], 0.08);
const extrudeGeo4 = extrude([[-0.25, -0.425], [0.25, -0.425], [0.25, 0.175], [0.2023, 0.3219], [0.0773, 0.4128], [-0.0773, 0.4128], [-0.2023, 0.3219], [-0.25, 0.175]], 0.06);
const coneGeo = new THREE.ConeGeometry(0.035, 0.32, 4);
const octahedronGeo = new THREE.OctahedronGeometry(0.1, 0);
// Parts
const foundation = new THREE.Mesh(jitter(new THREE.CylinderGeometry(2.25, 2.55, 1.2, 10), 0.04, 1), stone2Mat);
foundation.name = 'foundation';
foundation.position.set(0, 0.6346, 0);
root.add(foundation);
const boulder = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.5788, 0), 0.0868, 2), stoneMat);
boulder.name = 'boulder';
boulder.position.set(2.4554, 0.4986, 0.688);
boulder.scale.set(1.2, 0.8, 1.1);
root.add(boulder);
const boulder2 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.5315, 0), 0.0797, 3), stone2Mat);
boulder2.name = 'boulder';
boulder2.position.set(2.0689, 0.3797, -1.4908);
boulder2.scale.set(1.2, 0.8, 1.1);
root.add(boulder2);
const boulder3 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.4968, 0), 0.0745, 4), stoneMat);
boulder3.name = 'boulder';
boulder3.position.set(0.1244, 0.3743, -2.547);
boulder3.scale.set(1.2, 0.8, 1.1);
root.add(boulder3);
const boulder4 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.4087, 0), 0.0613, 5), stone2Mat);
boulder4.name = 'boulder';
boulder4.position.set(-1.9137, 0.2864, -1.6853);
boulder4.scale.set(1.2, 0.8, 1.1);
root.add(boulder4);
const boulder5 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.4412, 0), 0.0662, 6), stoneMat);
boulder5.name = 'boulder';
boulder5.position.set(-2.5108, 0.3694, 0.4455);
boulder5.scale.set(1.2, 0.8, 1.1);
root.add(boulder5);
const boulder6 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.6329, 0), 0.0949, 7), stone2Mat);
boulder6.name = 'boulder';
boulder6.position.set(-1.2172, 0.4637, 2.2408);
boulder6.scale.set(1.2, 0.8, 1.1);
root.add(boulder6);
const step = new THREE.Mesh(jitter(new THREE.BoxGeometry(1.5, 0.4, 0.42), 0.01, 8), stoneMat);
step.name = 'step';
step.position.set(0, 0.2, 2.62);
root.add(step);
const step2 = new THREE.Mesh(jitter(new THREE.BoxGeometry(1.38, 0.4, 0.42), 0.01, 9), stoneMat);
step2.name = 'step';
step2.position.set(0, 0.6, 2.24);
root.add(step2);
const step3 = new THREE.Mesh(jitter(new THREE.BoxGeometry(1.26, 0.4, 0.42), 0.01, 10), stoneMat);
step3.name = 'step';
step3.position.set(0, 1, 1.86);
root.add(step3);
const drum = new THREE.Group();
drum.name = 'drum';
drum.position.set(0, 1.15, 0);
root.add(drum);
const drum2 = new THREE.Mesh(new THREE.CylinderGeometry(1.72, 1.75, 2.48, 10), stone2Mat);
drum2.name = 'drum';
drum2.position.set(0, 1.24, 0);
drum.add(drum2);
const window = new THREE.Group();
window.name = 'window';
window.position.set(-1.0607, 1.364, -1.264);
window.rotation.set(0, deg(-140), 0);
drum.add(window);
const windowFrame = new THREE.Mesh(extrudeGeo, stone2Mat);
windowFrame.name = 'windowFrame';
windowFrame.position.set(0, 0, 0.01);
window.add(windowFrame);
const windowGlow = new THREE.Mesh(extrudeGeo2, glowMat);
windowGlow.name = 'windowGlow';
windowGlow.position.set(0, 0, 0.035);
window.add(windowGlow);
const windowSill = new THREE.Mesh(boxGeo, stone2Mat);
windowSill.name = 'windowSill';
windowSill.position.set(0, -0.53, 0.08);
window.add(windowSill);
const wallStone = new THREE.Group();
wallStone.name = 'wallStone';
wallStone.position.set(0.4185, 1.3153, 1.601);
wallStone.rotation.set(0, deg(14.6501), 0);
drum.add(wallStone);
const box18 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.6687, 0.22, 0.06), 0.008, 11), stoneMat);
box18.position.set(0, 0, 0.01);
wallStone.add(box18);
const wallStone2 = new THREE.Group();
wallStone2.name = 'wallStone';
wallStone2.position.set(0.4585, 1.1726, -1.5901);
wallStone2.rotation.set(0, deg(163.9146), 0);
drum.add(wallStone2);
const box20 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.6208, 0.22, 0.06), 0.008, 12), stoneMat);
box20.position.set(0, 0, 0.01);
wallStone2.add(box20);
const wallStone3 = new THREE.Group();
wallStone3.name = 'wallStone';
wallStone3.position.set(1.6383, 0.58, 0.2335);
wallStone3.rotation.set(0, deg(81.8874), 0);
drum.add(wallStone3);
const box22 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.5985, 0.22, 0.06), 0.008, 13), stoneMat);
box22.position.set(0, 0, 0.01);
wallStone3.add(box22);
const door = new THREE.Group();
door.name = 'door';
door.position.set(0, 0, 1.6643);
drum.add(door);
const doorFrame = new THREE.Mesh(extrude([[-0.625, 0], [0.625, 0], [0.625, 1.575], [0.5774, 1.8142], [0.4419, 2.0169], [0.2392, 2.1524], [0, 2.2], [-0.2392, 2.1524], [-0.4419, 2.0169], [-0.5774, 1.8142], [-0.625, 1.575]], 0.12), stone2Mat);
doorFrame.name = 'doorFrame';
doorFrame.position.set(0, 0, 0.02);
door.add(doorFrame);
const doorLeaf = new THREE.Mesh(extrude([[-0.475, 0], [0.475, 0], [0.475, 1.545], [0.4388, 1.7268], [0.3359, 1.8809], [0.1818, 1.9838], [0, 2.02], [-0.1818, 1.9838], [-0.3359, 1.8809], [-0.4388, 1.7268], [-0.475, 1.545]], 0.06), woodMat);
doorLeaf.name = 'doorLeaf';
doorLeaf.position.set(0, 0, 0.07);
door.add(doorLeaf);
const doorRing = new THREE.Mesh(new THREE.TorusGeometry(0.07, 0.015, 3, 8), goldMat);
doorRing.name = 'doorRing';
doorRing.position.set(0.25, 1, 0.12);
door.add(doorRing);
const doorBand = new THREE.Mesh(boxGeo2, darkMat);
doorBand.name = 'doorBand';
doorBand.position.set(0, 0.6, 0.105);
door.add(doorBand);
const doorBand2 = new THREE.Mesh(boxGeo2, darkMat);
doorBand2.name = 'doorBand';
doorBand2.position.set(0, 1.45, 0.105);
door.add(doorBand2);
const drum3 = new THREE.Group();
drum3.name = 'drum';
drum3.position.set(0, 3.51, 0);
drum3.rotation.set(deg(2.2807), 0, deg(3.5673));
root.add(drum3);
const drum4 = new THREE.Mesh(new THREE.CylinderGeometry(1.63, 1.66, 2.48, 10), stoneMat);
drum4.name = 'drum';
drum4.position.set(0, 1.24, 0);
drum4.rotation.set(0, deg(9), 0);
drum3.add(drum4);
const window2 = new THREE.Group();
window2.name = 'window';
window2.position.set(1.3549, 1.364, 0.7822);
window2.rotation.set(0, deg(60), 0);
drum3.add(window2);
const windowFrame2 = new THREE.Mesh(extrudeGeo, stone2Mat);
windowFrame2.name = 'windowFrame';
windowFrame2.position.set(0, 0, 0.01);
window2.add(windowFrame2);
const windowGlow2 = new THREE.Mesh(extrudeGeo2, glowMat);
windowGlow2.name = 'windowGlow';
windowGlow2.position.set(0, 0, 0.035);
window2.add(windowGlow2);
const windowSill2 = new THREE.Mesh(boxGeo, stone2Mat);
windowSill2.name = 'windowSill';
windowSill2.position.set(0, -0.53, 0.08);
window2.add(windowSill2);
const wallStone4 = new THREE.Group();
wallStone4.name = 'wallStone';
wallStone4.position.set(-0.6659, 0.4094, -1.4209);
wallStone4.rotation.set(0, deg(-154.8907), 0);
drum3.add(wallStone4);
const box36 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.507, 0.22, 0.06), 0.008, 14), stoneMat);
box36.position.set(0, 0, 0.01);
wallStone4.add(box36);
const wallStone5 = new THREE.Group();
wallStone5.name = 'wallStone';
wallStone5.position.set(-1.2309, 1.8996, -0.9734);
wallStone5.rotation.set(0, deg(-128.3357), 0);
drum3.add(wallStone5);
const box38 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.4328, 0.22, 0.06), 0.008, 15), stone2Mat);
box38.position.set(0, 0, 0.01);
wallStone5.add(box38);
const wallStone6 = new THREE.Group();
wallStone6.name = 'wallStone';
wallStone6.position.set(-1.3582, 0.8239, -0.786);
wallStone6.rotation.set(0, deg(-120.0567), 0);
drum3.add(wallStone6);
const box40 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.5493, 0.22, 0.06), 0.008, 16), stone2Mat);
box40.position.set(0, 0, 0.01);
wallStone6.add(box40);
const band = new THREE.Mesh(new THREE.CylinderGeometry(1.76, 1.79, 0.4, 10), stone2Mat);
band.name = 'band';
band.position.set(0, 3.56, 0);
band.rotation.set(deg(1.1403), 0, deg(1.7836));
root.add(band);
const drum5 = new THREE.Group();
drum5.name = 'drum';
drum5.position.set(-0.1468, 5.8636, 0.0937);
drum5.rotation.set(deg(-3.1885), 0, deg(0.4342));
root.add(drum5);
const drum6 = new THREE.Mesh(new THREE.CylinderGeometry(1.54, 1.57, 2.48, 10), stone2Mat);
drum6.name = 'drum';
drum6.position.set(0, 1.24, 0);
drum6.rotation.set(0, deg(18), 0);
drum5.add(drum6);
const window3 = new THREE.Group();
window3.name = 'window';
window3.position.set(-1.3712, 1.364, 0.554);
window3.rotation.set(0, deg(-68), 0);
drum5.add(window3);
const windowFrame3 = new THREE.Mesh(extrudeGeo, stone2Mat);
windowFrame3.name = 'windowFrame';
windowFrame3.position.set(0, 0, 0.01);
window3.add(windowFrame3);
const windowGlow3 = new THREE.Mesh(extrudeGeo2, glowMat);
windowGlow3.name = 'windowGlow';
windowGlow3.position.set(0, 0, 0.035);
window3.add(windowGlow3);
const windowSill3 = new THREE.Mesh(boxGeo, stone2Mat);
windowSill3.name = 'windowSill';
windowSill3.position.set(0, -0.53, 0.08);
window3.add(windowSill3);
const wallStone7 = new THREE.Group();
wallStone7.name = 'wallStone';
wallStone7.position.set(0.4538, 0.8189, 1.4125);
wallStone7.rotation.set(0, deg(17.8108), 0);
drum5.add(wallStone7);
const box49 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.5625, 0.22, 0.06), 0.008, 17), stoneMat);
box49.position.set(0, 0, 0.01);
wallStone7.add(box49);
const wallStone8 = new THREE.Group();
wallStone8.name = 'wallStone';
wallStone8.position.set(-1.2945, 1.9389, 0.725);
wallStone8.rotation.set(0, deg(-60.7495), 0);
drum5.add(wallStone8);
const box51 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.6691, 0.22, 0.06), 0.008, 18), stone2Mat);
box51.position.set(0, 0, 0.01);
wallStone8.add(box51);
const wallStone9 = new THREE.Group();
wallStone9.name = 'wallStone';
wallStone9.position.set(1.4732, 1.2016, -0.1757);
wallStone9.rotation.set(0, deg(96.8022), 0);
drum5.add(wallStone9);
const box53 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.4521, 0.22, 0.06), 0.008, 19), stoneMat);
box53.position.set(0, 0, 0.01);
wallStone9.add(box53);
const band2 = new THREE.Mesh(new THREE.CylinderGeometry(1.67, 1.7, 0.4, 10), stone2Mat);
band2.name = 'band';
band2.position.set(-0.1468, 5.9136, 0.0937);
band2.rotation.set(deg(-0.4539), 0, deg(2.0007));
root.add(band2);
const drum7 = new THREE.Group();
drum7.name = 'drum';
drum7.position.set(-0.1647, 8.2198, -0.0375);
drum7.rotation.set(deg(-4.7101), 0, deg(-0.6572));
root.add(drum7);
const drum8 = new THREE.Mesh(new THREE.CylinderGeometry(1.45, 1.48, 2.48, 10), stoneMat);
drum8.name = 'drum';
drum8.position.set(0, 1.24, 0);
drum8.rotation.set(0, deg(27), 0);
drum7.add(drum8);
const window4 = new THREE.Group();
window4.name = 'window';
window4.position.set(1.3721, 1.364, -0.2419);
window4.rotation.set(0, deg(100), 0);
drum7.add(window4);
const windowFrame4 = new THREE.Mesh(extrudeGeo, stone2Mat);
windowFrame4.name = 'windowFrame';
windowFrame4.position.set(0, 0, 0.01);
window4.add(windowFrame4);
const windowGlow4 = new THREE.Mesh(extrudeGeo2, glowMat);
windowGlow4.name = 'windowGlow';
windowGlow4.position.set(0, 0, 0.035);
window4.add(windowGlow4);
const windowSill4 = new THREE.Mesh(boxGeo, stone2Mat);
windowSill4.name = 'windowSill';
windowSill4.position.set(0, -0.53, 0.08);
window4.add(windowSill4);
const wallStone10 = new THREE.Group();
wallStone10.name = 'wallStone';
wallStone10.position.set(0.7602, 0.7646, 1.1733);
wallStone10.rotation.set(0, deg(32.9385), 0);
drum7.add(wallStone10);
const box62 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.5901, 0.22, 0.06), 0.008, 20), stone2Mat);
box62.position.set(0, 0, 0.01);
wallStone10.add(box62);
const wallStone11 = new THREE.Group();
wallStone11.name = 'wallStone';
wallStone11.position.set(-0.7232, 1.6139, 1.1965);
wallStone11.rotation.set(0, deg(-31.1505), 0);
drum7.add(wallStone11);
const box64 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.6793, 0.22, 0.06), 0.008, 21), stone2Mat);
box64.position.set(0, 0, 0.01);
wallStone11.add(box64);
const wallStone12 = new THREE.Group();
wallStone12.name = 'wallStone';
wallStone12.position.set(-1.3554, 0.7853, -0.3428);
wallStone12.rotation.set(0, deg(-104.1929), 0);
drum7.add(wallStone12);
const box66 = new THREE.Mesh(jitter(new THREE.BoxGeometry(0.4843, 0.22, 0.06), 0.008, 22), stoneMat);
box66.position.set(0, 0, 0.01);
wallStone12.add(box66);
const balcony = new THREE.Group();
balcony.name = 'balcony';
balcony.position.set(0.7964, 0.868, 1.1374);
balcony.rotation.set(0, deg(35), 0);
drum7.add(balcony);
const balconyFloor = new THREE.Mesh(extrude([[-1, -0.6], [1, -0.6], [1, 0], [0.9511, 0.309], [0.809, 0.5878], [0.5878, 0.809], [0.309, 0.9511], [0, 1], [-0.309, 0.9511], [-0.5878, 0.809], [-0.809, 0.5878], [-0.9511, 0.309], [-1, 0]], 0.14), stone2Mat);
balconyFloor.name = 'balconyFloor';
balconyFloor.rotation.set(deg(90), 0, 0);
balcony.add(balconyFloor);
const balconyBracket = new THREE.Mesh(boxGeo3, stone2Mat);
balconyBracket.name = 'balconyBracket';
balconyBracket.position.set(0.4045, -0.4, 0.2469);
balconyBracket.rotation.set(deg(-46.7516), deg(43.321), deg(36.1059));
balcony.add(balconyBracket);
const balconyBracket2 = new THREE.Mesh(boxGeo3, stone2Mat);
balconyBracket2.name = 'balconyBracket';
balconyBracket2.position.set(0, -0.4, 0.42);
balconyBracket2.rotation.set(deg(-32), 0, 0);
balcony.add(balconyBracket2);
const balconyBracket3 = new THREE.Mesh(boxGeo3, stone2Mat);
balconyBracket3.name = 'balconyBracket';
balconyBracket3.position.set(-0.4045, -0.4, 0.2469);
balconyBracket3.rotation.set(deg(-46.7516), deg(-43.321), deg(-36.1059));
balcony.add(balconyBracket3);
const balconyPost = new THREE.Mesh(boxGeo4, woodMat);
balconyPost.name = 'balconyPost';
balconyPost.position.set(0.93, 0.52, 0);
balcony.add(balconyPost);
const balconyPost2 = new THREE.Mesh(boxGeo4, woodMat);
balconyPost2.name = 'balconyPost';
balconyPost2.position.set(0.6576, 0.52, 0.6576);
balcony.add(balconyPost2);
const balconyPost3 = new THREE.Mesh(boxGeo4, woodMat);
balconyPost3.name = 'balconyPost';
balconyPost3.position.set(0, 0.52, 0.93);
balcony.add(balconyPost3);
const balconyPost4 = new THREE.Mesh(boxGeo4, woodMat);
balconyPost4.name = 'balconyPost';
balconyPost4.position.set(-0.6576, 0.52, 0.6576);
balcony.add(balconyPost4);
const balconyPost5 = new THREE.Mesh(boxGeo4, woodMat);
balconyPost5.name = 'balconyPost';
balconyPost5.position.set(-0.93, 0.52, 0);
balcony.add(balconyPost5);
const balconyRail = new THREE.Mesh(tube([[0.93, 0.95, 0], [0.8592, 0.95, 0.3559], [0.6576, 0.95, 0.6576], [0.3559, 0.95, 0.8592], [0, 0.95, 0.93], [-0.3559, 0.95, 0.8592], [-0.6576, 0.95, 0.6576], [-0.8592, 0.95, 0.3559], [-0.93, 0.95, 0]], 0.045, 10, 4), woodMat);
balconyRail.name = 'balconyRail';
balcony.add(balconyRail);
const balconyDoor = new THREE.Mesh(extrude([[-0.425, 0], [0.425, 0], [0.425, 1.325], [0.3926, 1.4876], [0.3005, 1.6255], [0.1626, 1.7176], [0, 1.75], [-0.1626, 1.7176], [-0.3005, 1.6255], [-0.3926, 1.4876], [-0.425, 1.325]], 0.06), darkMat);
balconyDoor.name = 'balconyDoor';
balconyDoor.position.set(0, 0.07, 0);
balcony.add(balconyDoor);
const balconyDoorFrame = new THREE.Mesh(extrude([[-0.525, 0], [0.525, 0], [0.525, 1.355], [0.485, 1.5559], [0.3712, 1.7262], [0.2009, 1.84], [0, 1.88], [-0.2009, 1.84], [-0.3712, 1.7262], [-0.485, 1.5559], [-0.525, 1.355]], 0.04), stone2Mat);
balconyDoorFrame.name = 'balconyDoorFrame';
balconyDoorFrame.position.set(0, 0.03, -0.02);
balcony.add(balconyDoorFrame);
const band3 = new THREE.Mesh(new THREE.CylinderGeometry(1.58, 1.61, 0.4, 10), stone2Mat);
band3.name = 'band';
band3.position.set(-0.1647, 8.2698, -0.0375);
band3.rotation.set(deg(-3.9493), 0, deg(-0.1115));
root.add(band3);
const studyRoom = new THREE.Group();
studyRoom.name = 'studyRoom';
studyRoom.position.set(-0.1377, 10.5717, -0.2313);
studyRoom.rotation.set(deg(-0.4744), 0, deg(2.8619));
root.add(studyRoom);
const flare = new THREE.Mesh(new THREE.CylinderGeometry(1.77, 1.39, 0.55, 10), stone2Mat);
flare.name = 'flare';
flare.position.set(0, 0.275, 0);
flare.rotation.set(0, deg(18), 0);
studyRoom.add(flare);
const studyWall = new THREE.Mesh(new THREE.CylinderGeometry(1.77, 1.77, 1.93, 10), stoneMat);
studyWall.name = 'studyWall';
studyWall.position.set(0, 1.515, 0);
studyWall.rotation.set(0, deg(18), 0);
studyRoom.add(studyWall);
const corbel = new THREE.Group();
corbel.name = 'corbel';
corbel.position.set(0, 0.2, 1.37);
studyRoom.add(corbel);
const box85 = new THREE.Mesh(boxGeo5, stone2Mat);
box85.position.set(0, 0, 0.1);
corbel.add(box85);
const corbel2 = new THREE.Group();
corbel2.name = 'corbel';
corbel2.position.set(0.8053, 0.2, 1.1084);
corbel2.rotation.set(0, deg(36), 0);
studyRoom.add(corbel2);
const box87 = new THREE.Mesh(boxGeo5, stone2Mat);
box87.position.set(0, 0, 0.1);
corbel2.add(box87);
const corbel3 = new THREE.Group();
corbel3.name = 'corbel';
corbel3.position.set(1.3029, 0.2, 0.4234);
corbel3.rotation.set(0, deg(72), 0);
studyRoom.add(corbel3);
const box89 = new THREE.Mesh(boxGeo5, stone2Mat);
box89.position.set(0, 0, 0.1);
corbel3.add(box89);
const corbel4 = new THREE.Group();
corbel4.name = 'corbel';
corbel4.position.set(1.3029, 0.2, -0.4234);
corbel4.rotation.set(0, deg(108), 0);
studyRoom.add(corbel4);
const box91 = new THREE.Mesh(boxGeo5, stone2Mat);
box91.position.set(0, 0, 0.1);
corbel4.add(box91);
const corbel5 = new THREE.Group();
corbel5.name = 'corbel';
corbel5.position.set(0.8053, 0.2, -1.1084);
corbel5.rotation.set(0, deg(144), 0);
studyRoom.add(corbel5);
const box93 = new THREE.Mesh(boxGeo5, stone2Mat);
box93.position.set(0, 0, 0.1);
corbel5.add(box93);
const corbel6 = new THREE.Group();
corbel6.name = 'corbel';
corbel6.position.set(0, 0.2, -1.37);
corbel6.rotation.set(0, deg(180), 0);
studyRoom.add(corbel6);
const box95 = new THREE.Mesh(boxGeo5, stone2Mat);
box95.position.set(0, 0, 0.1);
corbel6.add(box95);
const corbel7 = new THREE.Group();
corbel7.name = 'corbel';
corbel7.position.set(-0.8053, 0.2, -1.1084);
corbel7.rotation.set(0, deg(216), 0);
studyRoom.add(corbel7);
const box97 = new THREE.Mesh(boxGeo5, stone2Mat);
box97.position.set(0, 0, 0.1);
corbel7.add(box97);
const corbel8 = new THREE.Group();
corbel8.name = 'corbel';
corbel8.position.set(-1.3029, 0.2, -0.4234);
corbel8.rotation.set(0, deg(252), 0);
studyRoom.add(corbel8);
const box99 = new THREE.Mesh(boxGeo5, stone2Mat);
box99.position.set(0, 0, 0.1);
corbel8.add(box99);
const corbel9 = new THREE.Group();
corbel9.name = 'corbel';
corbel9.position.set(-1.3029, 0.2, 0.4234);
corbel9.rotation.set(0, deg(288), 0);
studyRoom.add(corbel9);
const box101 = new THREE.Mesh(boxGeo5, stone2Mat);
box101.position.set(0, 0, 0.1);
corbel9.add(box101);
const corbel10 = new THREE.Group();
corbel10.name = 'corbel';
corbel10.position.set(-0.8053, 0.2, 1.1084);
corbel10.rotation.set(0, deg(324), 0);
studyRoom.add(corbel10);
const box103 = new THREE.Mesh(boxGeo5, stone2Mat);
box103.position.set(0, 0, 0.1);
corbel10.add(box103);
const studyWindow = new THREE.Group();
studyWindow.name = 'studyWindow';
studyWindow.position.set(0.5757, 1.364, 1.5819);
studyWindow.rotation.set(0, deg(20), 0);
studyRoom.add(studyWindow);
const windowFrame5 = new THREE.Mesh(extrudeGeo3, stone2Mat);
windowFrame5.name = 'windowFrame';
windowFrame5.position.set(0, 0, 0.01);
studyWindow.add(windowFrame5);
const windowGlow5 = new THREE.Mesh(extrudeGeo4, glowMat);
windowGlow5.name = 'windowGlow';
windowGlow5.position.set(0, 0, 0.035);
studyWindow.add(windowGlow5);
const windowSill5 = new THREE.Mesh(boxGeo, stone2Mat);
windowSill5.name = 'windowSill';
windowSill5.position.set(0, -0.505, 0.08);
studyWindow.add(windowSill5);
const studyWindow2 = new THREE.Group();
studyWindow2.name = 'studyWindow';
studyWindow2.position.set(1.2895, 1.488, -1.082);
studyWindow2.rotation.set(0, deg(130), 0);
studyRoom.add(studyWindow2);
const windowFrame6 = new THREE.Mesh(extrudeGeo3, stone2Mat);
windowFrame6.name = 'windowFrame';
windowFrame6.position.set(0, 0, 0.01);
studyWindow2.add(windowFrame6);
const windowGlow6 = new THREE.Mesh(extrudeGeo4, glowMat);
windowGlow6.name = 'windowGlow';
windowGlow6.position.set(0, 0, 0.035);
studyWindow2.add(windowGlow6);
const windowSill6 = new THREE.Mesh(boxGeo, stone2Mat);
windowSill6.name = 'windowSill';
windowSill6.position.set(0, -0.505, 0.08);
studyWindow2.add(windowSill6);
const studyWindow3 = new THREE.Group();
studyWindow3.name = 'studyWindow';
studyWindow3.position.set(-1.5819, 1.364, -0.5757);
studyWindow3.rotation.set(0, deg(-110), 0);
studyRoom.add(studyWindow3);
const windowFrame7 = new THREE.Mesh(extrudeGeo3, stone2Mat);
windowFrame7.name = 'windowFrame';
windowFrame7.position.set(0, 0, 0.01);
studyWindow3.add(windowFrame7);
const windowGlow7 = new THREE.Mesh(extrudeGeo4, glowMat);
windowGlow7.name = 'windowGlow';
windowGlow7.position.set(0, 0, 0.035);
studyWindow3.add(windowGlow7);
const windowSill7 = new THREE.Mesh(boxGeo, stone2Mat);
windowSill7.name = 'windowSill';
windowSill7.position.set(0, -0.505, 0.08);
studyWindow3.add(windowSill7);
const band4 = new THREE.Mesh(new THREE.CylinderGeometry(1.49, 1.52, 0.4, 10), stone2Mat);
band4.name = 'band';
band4.position.set(-0.1377, 10.6217, -0.2313);
band4.rotation.set(deg(-2.5923), 0, deg(1.1023));
root.add(band4);
const roof = new THREE.Group();
roof.name = 'roof';
roof.position.set(-0.2555, 12.8287, -0.2508);
roof.rotation.set(deg(-0.4744), 0, deg(2.8619));
root.add(roof);
const roofBrim = new THREE.Mesh(new THREE.CylinderGeometry(1.92, 2.52, 0.32, 10), roofMat);
roofBrim.name = 'roofBrim';
roofBrim.position.set(0, 0.11, 0);
roofBrim.rotation.set(0, deg(18), 0);
roof.add(roofBrim);
const roofCone = new THREE.Mesh(lathe([[1.97, 0], [1.5366, 1.092], [1.0835, 2.4024], [0.6698, 3.64]], 9), roofMat);
roofCone.name = 'roofCone';
roofCone.position.set(0, 0.25, 0);
roof.add(roofCone);
const hatBand = new THREE.Mesh(new THREE.CylinderGeometry(1.9109, 1.97, 0.22, 9, 1, true), goldMat);
hatBand.name = 'hatBand';
hatBand.position.set(0, 0.38, 0);
roof.add(hatBand);
const spiralBand = new THREE.Mesh(tube([[0, 0.5, 1.9108], [0.885, 0.6086, 1.6447], [1.5228, 0.7171, 1.0052], [1.7743, 0.8257, 0.1597], [1.5985, 0.9343, -0.6832], [1.057, 1.0429, -1.3255], [0.295, 1.1514, -1.6257], [-0.4973, 1.26, -1.5304], [-1.1329, 1.3686, -1.0832], [-1.4747, 1.4771, -0.407], [-1.4549, 1.5857, 0.3321], [-1.0956, 1.6943, 0.9572], [-0.498, 1.8029, 1.3269], [0.1852, 1.9114, 1.3672], [0.7889, 2.02, 1.0858], [1.1754, 2.1286, 0.5661], [1.2658, 2.2371, -0.0568], [1.0555, 2.3457, -0.6306], [0.6114, 2.4543, -1.0233], [0.0518, 2.5629, -1.1533], [-0.4847, 2.6714, -1.0065], [-0.8744, 2.78, -0.6353], [-1.0351, 2.8886, -0.1402], [-0.944, 2.9971, 0.3543], [-0.6395, 3.1057, 0.732], [-0.2082, 3.2143, 0.9122], [0.2393, 3.3229, 0.867], [0.5964, 3.4314, 0.6238], [0.7863, 3.54, 0.2555]], 0.06, 36, 4), goldMat);
spiralBand.name = 'spiralBand';
roof.add(spiralBand);
const roofTip = new THREE.Mesh(new THREE.CylinderGeometry(0.4555, 0.6698, 0.68, 7), roofMat);
roofTip.name = 'roofTip';
roofTip.position.set(0.0431, 4.1462, 0.0215);
roofTip.rotation.set(deg(3.9827), deg(-0.2781), deg(-7.9848));
roof.add(roofTip);
const roofTip2 = new THREE.Mesh(new THREE.CylinderGeometry(0.3097, 0.4555, 0.62, 7), roofMat);
roofTip2.name = 'roofTip';
roofTip2.position.set(0.1752, 4.7142, 0.0876);
roofTip2.rotation.set(deg(16.4152), deg(19.314), deg(-19.7031));
roof.add(roofTip2);
const roofTip3 = new THREE.Mesh(new THREE.CylinderGeometry(0.2106, 0.3097, 0.56, 7), roofMat);
roofTip3.name = 'roofTip';
roofTip3.position.set(0.3852, 5.1862, 0.1926);
roofTip3.rotation.set(deg(38.0019), deg(34.1116), deg(-35.7297));
roof.add(roofTip3);
const roofTip4 = new THREE.Mesh(new THREE.CylinderGeometry(0.07, 0.2106, 0.5, 7), roofMat);
roofTip4.name = 'roofTip';
roofTip4.position.set(0.6442, 5.5532, 0.3221);
roofTip4.rotation.set(deg(68.3586), deg(41.0315), deg(-56.3268));
roof.add(roofTip4);
const orbCup = new THREE.Mesh(new THREE.CylinderGeometry(0.12, 0.06, 0.12, 6), goldMat);
orbCup.name = 'orbCup';
orbCup.position.set(0.7823, 5.7299, 0.3911);
roof.add(orbCup);
const orbClaw = new THREE.Mesh(coneGeo, goldMat);
orbClaw.name = 'orbClaw';
orbClaw.position.set(0.7823, 5.9099, 0.5911);
orbClaw.rotation.set(deg(26.5651), 0, 0);
roof.add(orbClaw);
const orbClaw2 = new THREE.Mesh(coneGeo, goldMat);
orbClaw2.name = 'orbClaw';
orbClaw2.position.set(0.9555, 5.9099, 0.2911);
orbClaw2.rotation.set(deg(-12.9347), deg(2.6202), deg(-22.8117));
roof.add(orbClaw2);
const orbClaw3 = new THREE.Mesh(coneGeo, goldMat);
orbClaw3.name = 'orbClaw';
orbClaw3.position.set(0.6091, 5.9099, 0.2911);
orbClaw3.rotation.set(deg(-12.9347), deg(-2.6202), deg(22.8117));
roof.add(orbClaw3);
const magicOrb = new THREE.Mesh(new THREE.SphereGeometry(0.46, 12, 8), orbMat);
magicOrb.name = 'magicOrb';
magicOrb.position.set(0.7823, 6.2099, 0.3911);
roof.add(magicOrb);
const orbRing = new THREE.Mesh(new THREE.TorusGeometry(0.72, 0.03, 3, 20), goldMat);
orbRing.name = 'orbRing';
orbRing.position.set(0.7823, 6.2099, 0.3911);
orbRing.rotation.set(deg(70), deg(20), 0);
roof.add(orbRing);
const spark = new THREE.Mesh(octahedronGeo, glowMat);
spark.name = 'spark';
spark.position.set(1.2904, 6.3497, 1.1339);
roof.add(spark);
const spark2 = new THREE.Mesh(octahedronGeo, glowMat);
spark2.name = 'spark';
spark2.position.set(1.1715, 6.0929, -0.4204);
roof.add(spark2);
const spark3 = new THREE.Mesh(octahedronGeo, glowMat);
spark3.name = 'spark';
spark3.position.set(-0.1151, 6.1871, 0.4598);
roof.add(spark3);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createWizardTower;
评分与评论
0 条评论
暂无评论。分享一下你是如何使用这个模型的,或者有哪些可以改进的地方。
相关模型
同一分类或相似标签









