1.3K tris10.1 × 13.6 × 8.25 m
Use it in code
Remix in the editorwindmill.js · 558 lines
Self-contained ES module — only depends on three. Call the factory and add the group to your scene.
/**
* Windmill — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 1,340 · Size (W × H × D): 10.12 × 13.61 × 8.25 m
*
* Usage:
* import { createWindmill } from './windmill.js';
*
* const model = createWindmill();
* model.position.set(0, 0, 0);
* scene.add(model);
*
* // Animations: idle
* const mixer = new THREE.AnimationMixer(model);
* mixer.clipAction(THREE.AnimationClip.findByName(model.animations, 'idle')).play();
* // in your render loop: mixer.update(clock.getDelta());
*/
import * as THREE from 'three';
const deg = THREE.MathUtils.degToRad;
// Build animation clips from simple descriptions (Codels). Play them with THREE.AnimationMixer.
function codelsClips(THREE, entries) {
var TAU = Math.PI * 2;
var DEG = Math.PI / 180;
var AX = { x: new THREE.Vector3(1, 0, 0), y: new THREE.Vector3(0, 1, 0), z: new THREE.Vector3(0, 0, 1) };
var periodOf = function (a) { return a.type === 'spin' ? 360 / Math.abs(a.speed) : a.period; };
var clips = [];
// loops → 'idle'
var loops = [];
entries.forEach(function (e) {
var l = e.anim.filter(function (a) { return a.type !== 'hinge'; });
if (l.length) loops.push({ target: e.target, anim: l });
});
if (loops.length) {
var periods = [];
loops.forEach(function (e) { e.anim.forEach(function (a) { periods.push(periodOf(a)); }); });
var longest = Math.max.apply(null, periods);
var D = longest;
var bestErr = Infinity;
for (var m = 1; m <= 6 && bestErr > 0.01; m++) {
var err = 0;
periods.forEach(function (p) {
var n = Math.max(1, Math.round((longest * m) / p));
err = Math.max(err, Math.abs((longest * m) / n - p) / p);
});
if (err < bestErr - 1e-9) { bestErr = err; D = longest * m; }
}
var cycles = function (a) { return Math.max(1, Math.round(D / periodOf(a))); };
var steps = 24;
loops.forEach(function (e) { e.anim.forEach(function (a) { steps = Math.max(steps, cycles(a) * 24); }); });
steps = Math.min(steps, 720);
var tracks = [];
loops.forEach(function (e) {
var o = e.target;
var q0 = o.quaternion.clone(), p0 = o.position.clone(), s0 = o.scale.clone();
var q = new THREE.Quaternion(), turn = new THREE.Quaternion(), p = new THREE.Vector3(), s = new THREE.Vector3();
var has = function (type) { return e.anim.some(function (a) { return a.type === type; }); };
var turns = has('spin') || has('swing'), moves = has('bob'), grows = has('pulse');
var times = [], qv = [], pv = [], sv = [];
for (var k = 0; k <= steps; k++) {
var t = (D * k) / steps;
q.copy(q0); p.copy(p0); s.copy(s0);
e.anim.forEach(function (a) {
var n = cycles(a);
var w = Math.sin(TAU * ((n * t) / D + (a.phase || 0)));
if (a.type === 'spin') q.multiply(turn.setFromAxisAngle(AX[a.axis], (a.speed < 0 ? -TAU : TAU) * ((n * t) / D)));
else if (a.type === 'swing') q.multiply(turn.setFromAxisAngle(AX[a.axis], a.angle * DEG * w));
else if (a.type === 'bob') p.addScaledVector(AX[a.axis], a.distance * w);
else if (a.type === 'pulse') s.multiplyScalar(1 + a.amount * w);
});
times.push(t);
if (turns) qv.push(q.x, q.y, q.z, q.w);
if (moves) pv.push(p.x, p.y, p.z);
if (grows) sv.push(s.x, s.y, s.z);
}
if (turns) tracks.push(new THREE.QuaternionKeyframeTrack(o.uuid + '.quaternion', times, qv));
if (moves) tracks.push(new THREE.VectorKeyframeTrack(o.uuid + '.position', times, pv));
if (grows) tracks.push(new THREE.VectorKeyframeTrack(o.uuid + '.scale', times, sv));
});
clips.push(new THREE.AnimationClip('idle', D, tracks));
}
// hinge moves → one-shot clips ('open' …)
var shots = {};
entries.forEach(function (e) {
e.anim.forEach(function (a) {
if (a.type !== 'hinge') return;
var name = a.clip || 'open';
(shots[name] = shots[name] || []).push({ target: e.target, a: a });
});
});
Object.keys(shots).forEach(function (name) {
var tracks = [];
var length = 0;
shots[name].forEach(function (h) {
var o = h.target, q0 = o.quaternion.clone(), q = new THREE.Quaternion(), turn = new THREE.Quaternion();
var n = Math.max(4, Math.ceil(Math.abs(h.a.angle) / 10));
var times = [], qv = [];
for (var k = 0; k <= n; k++) {
var f = k / n;
var eased = f * f * (3 - 2 * f);
q.copy(q0).multiply(turn.setFromAxisAngle(AX[h.a.axis], h.a.angle * DEG * eased));
times.push(h.a.duration * f);
qv.push(q.x, q.y, q.z, q.w);
}
length = Math.max(length, h.a.duration);
tracks.push(new THREE.QuaternionKeyframeTrack(o.uuid + '.quaternion', times, qv));
});
clips.push(new THREE.AnimationClip(name, length, tracks));
});
return clips;
}
export function createWindmill() {
const root = new THREE.Group();
root.name = 'Windmill';
// Materials
const wallMat = new THREE.MeshStandardMaterial({ name: 'wall', color: 0xe2d5bf, roughness: 0.95, flatShading: true });
const stoneMat = new THREE.MeshStandardMaterial({ name: 'stone', color: 0x837e77, roughness: 0.95, flatShading: true });
const roofMat = new THREE.MeshStandardMaterial({ name: 'roof', color: 0x6e4632, roughness: 0.85, flatShading: true });
const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0x7b5535, roughness: 0.9, flatShading: true });
const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x463024, roughness: 0.9, flatShading: true });
const clothMat = new THREE.MeshStandardMaterial({ name: 'cloth', color: 0xe6d6b4, roughness: 0.9, flatShading: true });
const glassMat = new THREE.MeshStandardMaterial({ name: 'glass', color: 0x3e4b57, roughness: 0.3, metalness: 0.1, flatShading: true });
// Shared geometries
const boxGeo = new THREE.BoxGeometry(0.03, 1.9, 0.02);
const boxGeo2 = new THREE.BoxGeometry(0.14, 2.15, 0.14);
const boxGeo3 = new THREE.BoxGeometry(0.6, 0.8, 0.06);
const boxGeo4 = new THREE.BoxGeometry(0.8, 0.1, 0.12);
const boxGeo5 = new THREE.BoxGeometry(0.85, 0.08, 0.18);
const boxGeo6 = new THREE.BoxGeometry(0.1, 0.8, 0.12);
const boxGeo7 = new THREE.BoxGeometry(0.05, 0.8, 0.08);
const boxGeo8 = new THREE.BoxGeometry(0.12, 3.8234, 0.12);
const boxGeo9 = new THREE.BoxGeometry(0.16, 5.2, 0.16);
const boxGeo10 = new THREE.BoxGeometry(0.07, 4.1, 0.07);
const boxGeo11 = new THREE.BoxGeometry(1.14, 0.05, 0.05);
const boxGeo12 = new THREE.BoxGeometry(1, 3.98, 0.02);
// Parts
const base = new THREE.Mesh(new THREE.CylinderGeometry(2.34, 2.4, 0.7, 8), stoneMat);
base.name = 'base';
base.position.set(0, 0.35, 0);
base.rotation.set(0, deg(22.5), 0);
root.add(base);
const tower = new THREE.Mesh(new THREE.CylinderGeometry(1.55, 2.2, 7.5, 8), wallMat);
tower.name = 'tower';
tower.position.set(0, 3.75, 0);
tower.rotation.set(0, deg(22.5), 0);
root.add(tower);
const curb = new THREE.Mesh(new THREE.CylinderGeometry(1.71, 1.71, 0.28, 8), woodMat);
curb.name = 'curb';
curb.position.set(0, 7.59, 0);
curb.rotation.set(0, deg(22.5), 0);
root.add(curb);
const capRim = new THREE.Mesh(new THREE.CylinderGeometry(1.85, 1.85, 0.3, 8), roofMat);
capRim.name = 'capRim';
capRim.position.set(0, 7.85, 0);
capRim.rotation.set(0, deg(22.5), 0);
root.add(capRim);
const cap = new THREE.Mesh(new THREE.ConeGeometry(1.85, 2.3, 8), roofMat);
cap.name = 'cap';
cap.position.set(0, 9.15, 0);
cap.rotation.set(0, deg(22.5), 0);
root.add(cap);
const finial = new THREE.Mesh(new THREE.SphereGeometry(0.16, 6, 4), woodMat);
finial.name = 'finial';
finial.position.set(0, 10.36, 0);
root.add(finial);
const door = new THREE.Group();
door.name = 'door';
door.position.set(0, 0.7, 1.9765);
root.add(door);
const tilted = new THREE.Group();
tilted.name = 'tilted';
tilted.rotation.set(deg(-4.5779), 0, 0);
door.add(tilted);
const doorPanel = new THREE.Mesh(new THREE.BoxGeometry(1.1, 2, 0.08), darkMat);
doorPanel.name = 'doorPanel';
doorPanel.position.set(0, 1, 0);
tilted.add(doorPanel);
const box10 = new THREE.Mesh(boxGeo, woodMat);
box10.position.set(-0.28, 1, 0.05);
tilted.add(box10);
const box11 = new THREE.Mesh(boxGeo, woodMat);
box11.position.set(0, 1, 0.05);
tilted.add(box11);
const box12 = new THREE.Mesh(boxGeo, woodMat);
box12.position.set(0.28, 1, 0.05);
tilted.add(box12);
const box13 = new THREE.Mesh(boxGeo2, stoneMat);
box13.position.set(-0.62, 1.07, 0.02);
tilted.add(box13);
const box14 = new THREE.Mesh(boxGeo2, stoneMat);
box14.position.set(0.62, 1.07, 0.02);
tilted.add(box14);
const lintel = new THREE.Mesh(new THREE.BoxGeometry(1.4, 0.2, 0.16), stoneMat);
lintel.name = 'lintel';
lintel.position.set(0, 2.15, 0.03);
tilted.add(lintel);
const step = new THREE.Mesh(new THREE.BoxGeometry(1.6, 0.25, 0.8), stoneMat);
step.name = 'step';
step.position.set(0, 0.125, 2.4825);
root.add(step);
const step2 = new THREE.Mesh(new THREE.BoxGeometry(1.3, 0.25, 0.5), stoneMat);
step2.name = 'step';
step2.position.set(0, 0.375, 2.3325);
root.add(step2);
const window = new THREE.Group();
window.name = 'window';
window.position.set(0, 4.5, 1.6722);
root.add(window);
const tilted2 = new THREE.Group();
tilted2.name = 'tilted';
tilted2.rotation.set(deg(-4.5779), 0, 0);
window.add(tilted2);
const box20 = new THREE.Mesh(boxGeo3, glassMat);
tilted2.add(box20);
const box21 = new THREE.Mesh(boxGeo4, woodMat);
box21.position.set(0, 0.45, 0.02);
tilted2.add(box21);
const sill = new THREE.Mesh(boxGeo5, woodMat);
sill.name = 'sill';
sill.position.set(0, -0.44, 0.05);
tilted2.add(sill);
const box23 = new THREE.Mesh(boxGeo6, woodMat);
box23.position.set(-0.35, 0, 0.02);
tilted2.add(box23);
const box24 = new THREE.Mesh(boxGeo6, woodMat);
box24.position.set(0.35, 0, 0.02);
tilted2.add(box24);
const box25 = new THREE.Mesh(boxGeo7, woodMat);
box25.position.set(0, 0, 0.02);
tilted2.add(box25);
const window2 = new THREE.Group();
window2.name = 'window';
window2.position.set(1.8163, 2.7, 0);
window2.rotation.set(0, deg(90), 0);
root.add(window2);
const tilted3 = new THREE.Group();
tilted3.name = 'tilted';
tilted3.rotation.set(deg(-4.5779), 0, 0);
window2.add(tilted3);
const box28 = new THREE.Mesh(boxGeo3, glassMat);
tilted3.add(box28);
const box29 = new THREE.Mesh(boxGeo4, woodMat);
box29.position.set(0, 0.45, 0.02);
tilted3.add(box29);
const sill2 = new THREE.Mesh(boxGeo5, woodMat);
sill2.name = 'sill';
sill2.position.set(0, -0.44, 0.05);
tilted3.add(sill2);
const box31 = new THREE.Mesh(boxGeo6, woodMat);
box31.position.set(-0.35, 0, 0.02);
tilted3.add(box31);
const box32 = new THREE.Mesh(boxGeo6, woodMat);
box32.position.set(0.35, 0, 0.02);
tilted3.add(box32);
const box33 = new THREE.Mesh(boxGeo7, woodMat);
box33.position.set(0, 0, 0.02);
tilted3.add(box33);
const window3 = new THREE.Group();
window3.name = 'window';
window3.position.set(-1.7323, 3.75, 0);
window3.rotation.set(0, deg(-90), 0);
root.add(window3);
const tilted4 = new THREE.Group();
tilted4.name = 'tilted';
tilted4.rotation.set(deg(-4.5779), 0, 0);
window3.add(tilted4);
const box36 = new THREE.Mesh(boxGeo3, glassMat);
tilted4.add(box36);
const box37 = new THREE.Mesh(boxGeo4, woodMat);
box37.position.set(0, 0.45, 0.02);
tilted4.add(box37);
const sill3 = new THREE.Mesh(boxGeo5, woodMat);
sill3.name = 'sill';
sill3.position.set(0, -0.44, 0.05);
tilted4.add(sill3);
const box39 = new THREE.Mesh(boxGeo6, woodMat);
box39.position.set(-0.35, 0, 0.02);
tilted4.add(box39);
const box40 = new THREE.Mesh(boxGeo6, woodMat);
box40.position.set(0.35, 0, 0.02);
tilted4.add(box40);
const box41 = new THREE.Mesh(boxGeo7, woodMat);
box41.position.set(0, 0, 0.02);
tilted4.add(box41);
const window4 = new THREE.Group();
window4.name = 'window';
window4.position.set(0, 3, -1.7923);
window4.rotation.set(0, deg(180), 0);
root.add(window4);
const tilted5 = new THREE.Group();
tilted5.name = 'tilted';
tilted5.rotation.set(deg(-4.5779), 0, 0);
window4.add(tilted5);
const box44 = new THREE.Mesh(boxGeo3, glassMat);
tilted5.add(box44);
const box45 = new THREE.Mesh(boxGeo4, woodMat);
box45.position.set(0, 0.45, 0.02);
tilted5.add(box45);
const sill4 = new THREE.Mesh(boxGeo5, woodMat);
sill4.name = 'sill';
sill4.position.set(0, -0.44, 0.05);
tilted5.add(sill4);
const box47 = new THREE.Mesh(boxGeo6, woodMat);
box47.position.set(-0.35, 0, 0.02);
tilted5.add(box47);
const box48 = new THREE.Mesh(boxGeo6, woodMat);
box48.position.set(0.35, 0, 0.02);
tilted5.add(box48);
const box49 = new THREE.Mesh(boxGeo7, woodMat);
box49.position.set(0, 0, 0.02);
tilted5.add(box49);
const tailPole = new THREE.Mesh(new THREE.BoxGeometry(0.2, 8.0502, 0.2), woodMat);
tailPole.name = 'tailPole';
tailPole.position.set(0, 4.075, -3.275);
tailPole.rotation.set(0, deg(-90), deg(157.736));
root.add(tailPole);
const tailBrace = new THREE.Mesh(boxGeo8, woodMat);
tailBrace.name = 'tailBrace';
tailBrace.position.set(-0.5812, 6.2105, -2.058);
tailBrace.rotation.set(0, deg(-120.8532), deg(143.6392));
root.add(tailBrace);
const tailBrace2 = new THREE.Mesh(boxGeo8, woodMat);
tailBrace2.name = 'tailBrace';
tailBrace2.position.set(0.5813, 6.2105, -2.058);
tailBrace2.rotation.set(0, deg(-59.1468), deg(143.6392));
root.add(tailBrace2);
const tailWheel = new THREE.Mesh(new THREE.CylinderGeometry(0.35, 0.35, 0.12, 8), darkMat);
tailWheel.name = 'tailWheel';
tailWheel.position.set(0, 0.35, -4.8);
tailWheel.rotation.set(0, 0, deg(90));
root.add(tailWheel);
const windshaft = new THREE.Mesh(new THREE.CylinderGeometry(0.15, 0.15, 2.7, 6), woodMat);
windshaft.name = 'windshaft';
windshaft.position.set(0, 8.55, 1.25);
windshaft.rotation.set(deg(90), 0, 0);
root.add(windshaft);
const hub = new THREE.Mesh(new THREE.CylinderGeometry(0.32, 0.32, 0.5, 8), darkMat);
hub.name = 'hub';
hub.position.set(0, 8.55, 2.55);
hub.rotation.set(deg(90), 0, 0);
root.add(hub);
const hubCap = new THREE.Mesh(new THREE.ConeGeometry(0.22, 0.3, 8), darkMat);
hubCap.name = 'hubCap';
hubCap.position.set(0, 8.55, 2.95);
hubCap.rotation.set(deg(90), 0, 0);
root.add(hubCap);
const sails = new THREE.Group();
sails.name = 'sails';
sails.position.set(0, 8.55, 2.4);
sails.rotation.set(0, 0, deg(20));
root.add(sails);
const sail1 = new THREE.Group();
sail1.name = 'sail1';
sails.add(sail1);
const stock = new THREE.Mesh(boxGeo9, woodMat);
stock.name = 'stock';
stock.position.set(0, 2.6, 0);
sail1.add(stock);
const rail = new THREE.Mesh(boxGeo10, woodMat);
rail.name = 'rail';
rail.position.set(1.1, 2.9, 0.06);
sail1.add(rail);
const box61 = new THREE.Mesh(boxGeo11, woodMat);
box61.position.set(0.55, 0.85, 0.06);
sail1.add(box61);
const box62 = new THREE.Mesh(boxGeo11, woodMat);
box62.position.set(0.55, 1.3056, 0.06);
sail1.add(box62);
const box63 = new THREE.Mesh(boxGeo11, woodMat);
box63.position.set(0.55, 1.7611, 0.06);
sail1.add(box63);
const box64 = new THREE.Mesh(boxGeo11, woodMat);
box64.position.set(0.55, 2.2167, 0.06);
sail1.add(box64);
const box65 = new THREE.Mesh(boxGeo11, woodMat);
box65.position.set(0.55, 2.6722, 0.06);
sail1.add(box65);
const box66 = new THREE.Mesh(boxGeo11, woodMat);
box66.position.set(0.55, 3.1278, 0.06);
sail1.add(box66);
const box67 = new THREE.Mesh(boxGeo11, woodMat);
box67.position.set(0.55, 3.5833, 0.06);
sail1.add(box67);
const box68 = new THREE.Mesh(boxGeo11, woodMat);
box68.position.set(0.55, 4.0389, 0.06);
sail1.add(box68);
const box69 = new THREE.Mesh(boxGeo11, woodMat);
box69.position.set(0.55, 4.4944, 0.06);
sail1.add(box69);
const box70 = new THREE.Mesh(boxGeo11, woodMat);
box70.position.set(0.55, 4.95, 0.06);
sail1.add(box70);
const cloth = new THREE.Mesh(boxGeo12, clothMat);
cloth.name = 'cloth';
cloth.position.set(0.57, 2.9, 0.015);
sail1.add(cloth);
const sail2 = new THREE.Group();
sail2.name = 'sail2';
sail2.rotation.set(0, 0, deg(90));
sails.add(sail2);
const stock2 = new THREE.Mesh(boxGeo9, woodMat);
stock2.name = 'stock';
stock2.position.set(0, 2.6, 0);
sail2.add(stock2);
const rail2 = new THREE.Mesh(boxGeo10, woodMat);
rail2.name = 'rail';
rail2.position.set(1.1, 2.9, 0.06);
sail2.add(rail2);
const box75 = new THREE.Mesh(boxGeo11, woodMat);
box75.position.set(0.55, 0.85, 0.06);
sail2.add(box75);
const box76 = new THREE.Mesh(boxGeo11, woodMat);
box76.position.set(0.55, 1.3056, 0.06);
sail2.add(box76);
const box77 = new THREE.Mesh(boxGeo11, woodMat);
box77.position.set(0.55, 1.7611, 0.06);
sail2.add(box77);
const box78 = new THREE.Mesh(boxGeo11, woodMat);
box78.position.set(0.55, 2.2167, 0.06);
sail2.add(box78);
const box79 = new THREE.Mesh(boxGeo11, woodMat);
box79.position.set(0.55, 2.6722, 0.06);
sail2.add(box79);
const box80 = new THREE.Mesh(boxGeo11, woodMat);
box80.position.set(0.55, 3.1278, 0.06);
sail2.add(box80);
const box81 = new THREE.Mesh(boxGeo11, woodMat);
box81.position.set(0.55, 3.5833, 0.06);
sail2.add(box81);
const box82 = new THREE.Mesh(boxGeo11, woodMat);
box82.position.set(0.55, 4.0389, 0.06);
sail2.add(box82);
const box83 = new THREE.Mesh(boxGeo11, woodMat);
box83.position.set(0.55, 4.4944, 0.06);
sail2.add(box83);
const box84 = new THREE.Mesh(boxGeo11, woodMat);
box84.position.set(0.55, 4.95, 0.06);
sail2.add(box84);
const cloth2 = new THREE.Mesh(boxGeo12, clothMat);
cloth2.name = 'cloth';
cloth2.position.set(0.57, 2.9, 0.015);
sail2.add(cloth2);
const sail3 = new THREE.Group();
sail3.name = 'sail3';
sail3.rotation.set(0, 0, deg(180));
sails.add(sail3);
const stock3 = new THREE.Mesh(boxGeo9, woodMat);
stock3.name = 'stock';
stock3.position.set(0, 2.6, 0);
sail3.add(stock3);
const rail3 = new THREE.Mesh(boxGeo10, woodMat);
rail3.name = 'rail';
rail3.position.set(1.1, 2.9, 0.06);
sail3.add(rail3);
const box89 = new THREE.Mesh(boxGeo11, woodMat);
box89.position.set(0.55, 0.85, 0.06);
sail3.add(box89);
const box90 = new THREE.Mesh(boxGeo11, woodMat);
box90.position.set(0.55, 1.3056, 0.06);
sail3.add(box90);
const box91 = new THREE.Mesh(boxGeo11, woodMat);
box91.position.set(0.55, 1.7611, 0.06);
sail3.add(box91);
const box92 = new THREE.Mesh(boxGeo11, woodMat);
box92.position.set(0.55, 2.2167, 0.06);
sail3.add(box92);
const box93 = new THREE.Mesh(boxGeo11, woodMat);
box93.position.set(0.55, 2.6722, 0.06);
sail3.add(box93);
const box94 = new THREE.Mesh(boxGeo11, woodMat);
box94.position.set(0.55, 3.1278, 0.06);
sail3.add(box94);
const box95 = new THREE.Mesh(boxGeo11, woodMat);
box95.position.set(0.55, 3.5833, 0.06);
sail3.add(box95);
const box96 = new THREE.Mesh(boxGeo11, woodMat);
box96.position.set(0.55, 4.0389, 0.06);
sail3.add(box96);
const box97 = new THREE.Mesh(boxGeo11, woodMat);
box97.position.set(0.55, 4.4944, 0.06);
sail3.add(box97);
const box98 = new THREE.Mesh(boxGeo11, woodMat);
box98.position.set(0.55, 4.95, 0.06);
sail3.add(box98);
const cloth3 = new THREE.Mesh(boxGeo12, clothMat);
cloth3.name = 'cloth';
cloth3.position.set(0.57, 2.9, 0.015);
sail3.add(cloth3);
const sail4 = new THREE.Group();
sail4.name = 'sail4';
sail4.rotation.set(0, 0, deg(270));
sails.add(sail4);
const stock4 = new THREE.Mesh(boxGeo9, woodMat);
stock4.name = 'stock';
stock4.position.set(0, 2.6, 0);
sail4.add(stock4);
const rail4 = new THREE.Mesh(boxGeo10, woodMat);
rail4.name = 'rail';
rail4.position.set(1.1, 2.9, 0.06);
sail4.add(rail4);
const box103 = new THREE.Mesh(boxGeo11, woodMat);
box103.position.set(0.55, 0.85, 0.06);
sail4.add(box103);
const box104 = new THREE.Mesh(boxGeo11, woodMat);
box104.position.set(0.55, 1.3056, 0.06);
sail4.add(box104);
const box105 = new THREE.Mesh(boxGeo11, woodMat);
box105.position.set(0.55, 1.7611, 0.06);
sail4.add(box105);
const box106 = new THREE.Mesh(boxGeo11, woodMat);
box106.position.set(0.55, 2.2167, 0.06);
sail4.add(box106);
const box107 = new THREE.Mesh(boxGeo11, woodMat);
box107.position.set(0.55, 2.6722, 0.06);
sail4.add(box107);
const box108 = new THREE.Mesh(boxGeo11, woodMat);
box108.position.set(0.55, 3.1278, 0.06);
sail4.add(box108);
const box109 = new THREE.Mesh(boxGeo11, woodMat);
box109.position.set(0.55, 3.5833, 0.06);
sail4.add(box109);
const box110 = new THREE.Mesh(boxGeo11, woodMat);
box110.position.set(0.55, 4.0389, 0.06);
sail4.add(box110);
const box111 = new THREE.Mesh(boxGeo11, woodMat);
box111.position.set(0.55, 4.4944, 0.06);
sail4.add(box111);
const box112 = new THREE.Mesh(boxGeo11, woodMat);
box112.position.set(0.55, 4.95, 0.06);
sail4.add(box112);
const cloth4 = new THREE.Mesh(boxGeo12, clothMat);
cloth4.name = 'cloth';
cloth4.position.set(0.57, 2.9, 0.015);
sail4.add(cloth4);
// Animations ('idle') — play them with THREE.AnimationMixer
root.animations = codelsClips(THREE, [
{ target: sails, anim: [{ type: 'spin', axis: 'z', speed: 36 }] },
]);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createWindmill;
Ratings & comments
0 comments
No comments yet. Share how you used this model or what could be better.
Related models
Same category or similar tags









