Codels
1312 三角面9.40 × 15.1 × 9.40 m

在代码中使用

在编辑器中改编
自包含的 ES 模块,仅依赖 three。调用工厂函数,然后把返回的 group 添加到场景中。
/**
 * Hot Air Balloon — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,312 · Size (W × H × D): 9.40 × 15.10 × 9.40 m
 *
 * Usage:
 *   import { createHotAirBalloon } from './hot-air-balloon.js';
 *   
 *   const model = createHotAirBalloon();
 *   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);
}

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

  // Materials
  const fabricAMat = new THREE.MeshStandardMaterial({ name: 'fabricA', color: 0xe2483c, roughness: 0.75, flatShading: true, side: THREE.DoubleSide });
  const fabricBMat = new THREE.MeshStandardMaterial({ name: 'fabricB', color: 0xf6d25a, roughness: 0.75, flatShading: true, side: THREE.DoubleSide });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x3a2d26, roughness: 0.85, flatShading: true, side: THREE.DoubleSide });
  const wickerMat = new THREE.MeshStandardMaterial({ name: 'wicker', color: 0xb98a4e, roughness: 0.95, flatShading: true });
  const metalMat = new THREE.MeshStandardMaterial({ name: 'metal', color: 0x9aa1aa, roughness: 0.4, metalness: 0.6, flatShading: true });
  const flameMat = new THREE.MeshStandardMaterial({ name: 'flame', color: 0xffb23d, roughness: 0.6, emissive: 0xff8a1a, emissiveIntensity: 1.6, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(1.47, 0.05, 1.47);
  const cylinderGeo = new THREE.CylinderGeometry(0.03, 0.03, 1.3, 5);

  // Parts
  const envelope = new THREE.Group();
  envelope.name = 'envelope';
  envelope.position.set(0, 10.0574, 0);
  root.add(envelope);
  const gore1 = new THREE.Group();
  gore1.name = 'gore1';
  envelope.add(gore1);
  const sphere3 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, 0, Math.PI / 6, 0, Math.PI / 2), fabricAMat);
  sphere3.scale.set(4.7, 4.9, 4.7);
  gore1.add(sphere3);
  const sphere4 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, 0, Math.PI / 6, Math.PI / 2, 1.2566), fabricAMat);
  sphere4.scale.set(4.7, 7, 4.7);
  gore1.add(sphere4);
  const gore2 = new THREE.Group();
  gore2.name = 'gore2';
  envelope.add(gore2);
  const sphere6 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI / 6, Math.PI / 6, 0, Math.PI / 2), fabricBMat);
  sphere6.scale.set(4.7, 4.9, 4.7);
  gore2.add(sphere6);
  const sphere7 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI / 6, Math.PI / 6, Math.PI / 2, 1.2566), fabricBMat);
  sphere7.scale.set(4.7, 7, 4.7);
  gore2.add(sphere7);
  const gore3 = new THREE.Group();
  gore3.name = 'gore3';
  envelope.add(gore3);
  const sphere9 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI / 3, Math.PI / 6, 0, Math.PI / 2), fabricAMat);
  sphere9.scale.set(4.7, 4.9, 4.7);
  gore3.add(sphere9);
  const sphere10 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI / 3, Math.PI / 6, Math.PI / 2, 1.2566), fabricAMat);
  sphere10.scale.set(4.7, 7, 4.7);
  gore3.add(sphere10);
  const gore4 = new THREE.Group();
  gore4.name = 'gore4';
  envelope.add(gore4);
  const sphere12 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI / 2, Math.PI / 6, 0, Math.PI / 2), fabricBMat);
  sphere12.scale.set(4.7, 4.9, 4.7);
  gore4.add(sphere12);
  const sphere13 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI / 2, Math.PI / 6, Math.PI / 2, 1.2566), fabricBMat);
  sphere13.scale.set(4.7, 7, 4.7);
  gore4.add(sphere13);
  const gore5 = new THREE.Group();
  gore5.name = 'gore5';
  envelope.add(gore5);
  const sphere15 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI * 0.6667, Math.PI / 6, 0, Math.PI / 2), fabricAMat);
  sphere15.scale.set(4.7, 4.9, 4.7);
  gore5.add(sphere15);
  const sphere16 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI * 0.6667, Math.PI / 6, Math.PI / 2, 1.2566), fabricAMat);
  sphere16.scale.set(4.7, 7, 4.7);
  gore5.add(sphere16);
  const gore6 = new THREE.Group();
  gore6.name = 'gore6';
  envelope.add(gore6);
  const sphere18 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI * 0.8333, Math.PI / 6, 0, Math.PI / 2), fabricBMat);
  sphere18.scale.set(4.7, 4.9, 4.7);
  gore6.add(sphere18);
  const sphere19 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI * 0.8333, Math.PI / 6, Math.PI / 2, 1.2566), fabricBMat);
  sphere19.scale.set(4.7, 7, 4.7);
  gore6.add(sphere19);
  const gore7 = new THREE.Group();
  gore7.name = 'gore7';
  envelope.add(gore7);
  const sphere21 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI, Math.PI / 6, 0, Math.PI / 2), fabricAMat);
  sphere21.scale.set(4.7, 4.9, 4.7);
  gore7.add(sphere21);
  const sphere22 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI, Math.PI / 6, Math.PI / 2, 1.2566), fabricAMat);
  sphere22.scale.set(4.7, 7, 4.7);
  gore7.add(sphere22);
  const gore8 = new THREE.Group();
  gore8.name = 'gore8';
  envelope.add(gore8);
  const sphere24 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI * 1.1667, Math.PI / 6, 0, Math.PI / 2), fabricBMat);
  sphere24.scale.set(4.7, 4.9, 4.7);
  gore8.add(sphere24);
  const sphere25 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI * 1.1667, Math.PI / 6, Math.PI / 2, 1.2566), fabricBMat);
  sphere25.scale.set(4.7, 7, 4.7);
  gore8.add(sphere25);
  const gore9 = new THREE.Group();
  gore9.name = 'gore9';
  envelope.add(gore9);
  const sphere27 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI * 1.3333, Math.PI / 6, 0, Math.PI / 2), fabricAMat);
  sphere27.scale.set(4.7, 4.9, 4.7);
  gore9.add(sphere27);
  const sphere28 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI * 1.3333, Math.PI / 6, Math.PI / 2, 1.2566), fabricAMat);
  sphere28.scale.set(4.7, 7, 4.7);
  gore9.add(sphere28);
  const gore10 = new THREE.Group();
  gore10.name = 'gore10';
  envelope.add(gore10);
  const sphere30 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI * 1.5, Math.PI / 6, 0, Math.PI / 2), fabricBMat);
  sphere30.scale.set(4.7, 4.9, 4.7);
  gore10.add(sphere30);
  const sphere31 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI * 1.5, Math.PI / 6, Math.PI / 2, 1.2566), fabricBMat);
  sphere31.scale.set(4.7, 7, 4.7);
  gore10.add(sphere31);
  const gore11 = new THREE.Group();
  gore11.name = 'gore11';
  envelope.add(gore11);
  const sphere33 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI * 1.6667, Math.PI / 6, 0, Math.PI / 2), fabricAMat);
  sphere33.scale.set(4.7, 4.9, 4.7);
  gore11.add(sphere33);
  const sphere34 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI * 1.6667, Math.PI / 6, Math.PI / 2, 1.2566), fabricAMat);
  sphere34.scale.set(4.7, 7, 4.7);
  gore11.add(sphere34);
  const gore12 = new THREE.Group();
  gore12.name = 'gore12';
  envelope.add(gore12);
  const sphere36 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI * 1.8333, Math.PI / 6, 0, Math.PI / 2), fabricBMat);
  sphere36.scale.set(4.7, 4.9, 4.7);
  gore12.add(sphere36);
  const sphere37 = new THREE.Mesh(new THREE.SphereGeometry(1, 2, 6, Math.PI * 1.8333, Math.PI / 6, Math.PI / 2, 1.2566), fabricBMat);
  sphere37.scale.set(4.7, 7, 4.7);
  gore12.add(sphere37);
  const crown = new THREE.Mesh(new THREE.SphereGeometry(1.15, 10, 2, 0, Math.PI * 2, 0, Math.PI / 2), darkMat);
  crown.name = 'crown';
  crown.position.set(0, 4.7, 0);
  crown.scale.set(1, 0.3, 1);
  envelope.add(crown);
  const skirt = new THREE.Mesh(lathe([[1.191, 2.5], [1.3943, 3.1], [1.4724, 3.45]], 16), darkMat);
  skirt.name = 'skirt';
  root.add(skirt);
  const loadRing = new THREE.Mesh(new THREE.TorusGeometry(1.191, 0.06, 4, 16), metalMat);
  loadRing.name = 'loadRing';
  loadRing.position.set(0, 2.5, 0);
  loadRing.rotation.set(deg(90), 0, 0);
  root.add(loadRing);
  const basket = new THREE.Group();
  basket.name = 'basket';
  root.add(basket);
  const wickerBox = new THREE.Mesh(new THREE.BoxGeometry(1.45, 1.15, 1.45), wickerMat);
  wickerBox.name = 'wickerBox';
  wickerBox.position.set(0, 0.575, 0);
  basket.add(wickerBox);
  const rim = new THREE.Mesh(new THREE.BoxGeometry(1.53, 0.14, 1.53), darkMat);
  rim.name = 'rim';
  rim.position.set(0, 1.1, 0);
  basket.add(rim);
  const base = new THREE.Mesh(new THREE.BoxGeometry(1.49, 0.08, 1.49), darkMat);
  base.name = 'base';
  base.position.set(0, 0.04, 0);
  basket.add(base);
  const box45 = new THREE.Mesh(boxGeo, darkMat);
  box45.position.set(0, 0.32, 0);
  basket.add(box45);
  const box46 = new THREE.Mesh(boxGeo, darkMat);
  box46.position.set(0, 0.62, 0);
  basket.add(box46);
  const cylinder47 = new THREE.Mesh(cylinderGeo, metalMat);
  cylinder47.position.set(0.55, 1.8, 0.55);
  basket.add(cylinder47);
  const cylinder48 = new THREE.Mesh(cylinderGeo, metalMat);
  cylinder48.position.set(0.55, 1.8, -0.55);
  basket.add(cylinder48);
  const cylinder49 = new THREE.Mesh(cylinderGeo, metalMat);
  cylinder49.position.set(-0.55, 1.8, 0.55);
  basket.add(cylinder49);
  const cylinder50 = new THREE.Mesh(cylinderGeo, metalMat);
  cylinder50.position.set(-0.55, 1.8, -0.55);
  basket.add(cylinder50);
  const burnerFrame = new THREE.Mesh(new THREE.BoxGeometry(1.16, 0.05, 1.16), metalMat);
  burnerFrame.name = 'burnerFrame';
  burnerFrame.position.set(0, 2.45, 0);
  basket.add(burnerFrame);
  const burner = new THREE.Mesh(new THREE.CylinderGeometry(0.2, 0.16, 0.36, 8), metalMat);
  burner.name = 'burner';
  burner.position.set(0, 2.27, 0);
  basket.add(burner);
  const flame = new THREE.Mesh(new THREE.ConeGeometry(0.16, 0.7, 7), flameMat);
  flame.name = 'flame';
  flame.position.set(0, 2.8, 0);
  basket.add(flame);
  const rope1 = new THREE.Mesh(tube([[0.72, 1.15, 0.72], [0.7811, 1.825, 0.7811], [0.8421, 2.5, 0.8421]], 0.025, 2, 4), darkMat);
  rope1.name = 'rope1';
  root.add(rope1);
  const rope2 = new THREE.Mesh(tube([[0.72, 1.15, -0.72], [0.7811, 1.825, -0.7811], [0.8421, 2.5, -0.8421]], 0.025, 2, 4), darkMat);
  rope2.name = 'rope2';
  root.add(rope2);
  const rope3 = new THREE.Mesh(tube([[-0.72, 1.15, -0.72], [-0.7811, 1.825, -0.7811], [-0.8421, 2.5, -0.8421]], 0.025, 2, 4), darkMat);
  rope3.name = 'rope3';
  root.add(rope3);
  const rope4 = new THREE.Mesh(tube([[-0.72, 1.15, 0.72], [-0.7811, 1.825, 0.7811], [-0.8421, 2.5, 0.8421]], 0.025, 2, 4), darkMat);
  rope4.name = 'rope4';
  root.add(rope4);

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

export default createHotAirBalloon;

评分与评论

—
暂无评分,快来抢先评分吧。
5
0
4
0
3
0
2
0
1
0

登录后即可评分和评论。

0 条评论

暂无评论。分享一下你是如何使用这个模型的,或者有哪些可以改进的地方。

相关模型

同一分类或相似标签