Codels
1,3 B üçgen0,46 × 0,44 × 0,45 m
Bağımsız bir ES modülü — yalnızca three paketine bağımlıdır. Fabrika fonksiyonunu çağırıp dönen grubu sahnene ekle.
/**
 * Wizard Hat — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,252 · Size (W × H × D): 0.46 × 0.44 × 0.45 m
 *
 * Usage:
 *   import { createWizardHat } from './wizard-hat.js';
 *   
 *   const model = createWizardHat();
 *   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);
}

export function createWizardHat() {
  const root = new THREE.Group();
  root.name = 'WizardHat';

  // Materials
  const hatMat = new THREE.MeshStandardMaterial({ name: 'hat', color: 0x33358c, roughness: 0.9, flatShading: true });
  const bandMat = new THREE.MeshStandardMaterial({ name: 'band', color: 0x7a3d9e, roughness: 0.85, flatShading: true });
  const goldMat = new THREE.MeshStandardMaterial({ name: 'gold', color: 0xe9b949, roughness: 0.35, metalness: 0.7, flatShading: true });
  const starMat = new THREE.MeshStandardMaterial({ name: 'star', color: 0xffd84a, roughness: 0.5, emissive: 0xffc93a, emissiveIntensity: 0.55, flatShading: true });
  const moonMat = new THREE.MeshStandardMaterial({ name: 'moon', color: 0xfff1b8, roughness: 0.5, emissive: 0xffe58a, emissiveIntensity: 0.45, flatShading: true });
  const insideMat = new THREE.MeshStandardMaterial({ name: 'inside', color: 0x141538, roughness: 1, flatShading: true });

  // Shared geometries
  const extrudeGeo = extrude([[0, 0.026], [-0.0069, 0.0095], [-0.0247, 0.008], [-0.0111, -0.0036], [-0.0153, -0.021], [0, -0.0117], [0.0153, -0.021], [0.0111, -0.0036], [0.0247, 0.008], [0.0069, 0.0095]], 0.004);
  const extrudeGeo2 = extrude([[0, 0.02], [-0.0053, 0.0073], [-0.019, 0.0062], [-0.0086, -0.0028], [-0.0118, -0.0162], [0, -0.009], [0.0118, -0.0162], [0.0086, -0.0028], [0.019, 0.0062], [0.0053, 0.0073]], 0.004);

  // Parts
  const brim = new THREE.Mesh(jitter(lathe([[0.1, 0.014], [0.16, 0.007], [0.205, 0], [0.222, 0.002], [0.227, 0.008], [0.213, 0.012], [0.16, 0.019], [0.1, 0.028], [0.1, 0.014]], 20), 0.0035, 3), hatMat);
  brim.name = 'brim';
  root.add(brim);
  const opening = new THREE.Mesh(new THREE.CylinderGeometry(0.104, 0.104, 0.004, 16), insideMat);
  opening.name = 'opening';
  opening.position.set(0, 0.014, 0);
  root.add(opening);
  const cone = new THREE.Mesh(lathe([[0.118, 0.016], [0.11, 0.06], [0.096, 0.12], [0.08, 0.17], [0.066, 0.205]], 16), hatMat);
  cone.name = 'cone';
  root.add(cone);
  const tip1 = new THREE.Mesh(new THREE.CylinderGeometry(0.0559, 0.066, 0.051, 10), hatMat);
  tip1.name = 'tip1';
  tip1.position.set(0.0005, 0.2265, -0.0004);
  tip1.rotation.set(deg(-0.9351), deg(0.011), deg(-1.3453));
  root.add(tip1);
  const tip2 = new THREE.Mesh(new THREE.CylinderGeometry(0.0464, 0.0559, 0.0586, 10), hatMat);
  tip2.name = 'tip2';
  tip2.position.set(0.0036, 0.2692, -0.0025);
  tip2.rotation.set(deg(-4.8473), deg(0.2959), deg(-6.9823));
  root.add(tip2);
  const tip3 = new THREE.Mesh(new THREE.CylinderGeometry(0.0377, 0.0464, 0.056, 10), hatMat);
  tip3.name = 'tip3';
  tip3.position.set(0.0118, 0.3109, -0.0082);
  tip3.rotation.set(deg(-10.338), deg(1.3611), deg(-14.961));
  root.add(tip3);
  const tip4 = new THREE.Mesh(new THREE.CylinderGeometry(0.0296, 0.0377, 0.0535, 10), hatMat);
  tip4.name = 'tip4';
  tip4.position.set(0.0263, 0.3499, -0.0182);
  tip4.rotation.set(deg(-16.7984), deg(3.6828), deg(-24.5673));
  root.add(tip4);
  const tip5 = new THREE.Mesh(new THREE.CylinderGeometry(0.0222, 0.0296, 0.0513, 10), hatMat);
  tip5.name = 'tip5';
  tip5.position.set(0.0475, 0.3838, -0.033);
  tip5.rotation.set(deg(-23.6975), deg(7.6433), deg(-35.3228));
  root.add(tip5);
  const tip6 = new THREE.Mesh(new THREE.CylinderGeometry(0.0154, 0.0222, 0.0492, 10), hatMat);
  tip6.name = 'tip6';
  tip6.position.set(0.075, 0.41, -0.0522);
  tip6.rotation.set(deg(-30.4896), deg(13.4777), deg(-46.8794));
  root.add(tip6);
  const tip7 = new THREE.Mesh(new THREE.CylinderGeometry(0.0094, 0.0154, 0.0473, 10), hatMat);
  tip7.name = 'tip7';
  tip7.position.set(0.1075, 0.4257, -0.0747);
  tip7.rotation.set(deg(-36.6123), deg(21.2417), deg(-59.0899));
  root.add(tip7);
  const tip8 = new THREE.Mesh(new THREE.CylinderGeometry(0.004, 0.0094, 0.0456, 10), hatMat);
  tip8.name = 'tip8';
  tip8.position.set(0.1422, 0.4285, -0.0988);
  tip8.rotation.set(deg(-41.4266), deg(30.8045), deg(-72.15));
  root.add(tip8);
  const band = new THREE.Mesh(new THREE.CylinderGeometry(0.1136, 0.1223, 0.046, 16), bandMat);
  band.name = 'band';
  band.position.set(0, 0.043, 0);
  root.add(band);
  const buckle = new THREE.Mesh(extrude([[-0.026, -0.022], [0.026, -0.022], [0.026, 0.022], [-0.026, 0.022]], 0.006, [[[-0.015, -0.012], [0.015, -0.012], [0.015, 0.012], [-0.015, 0.012]]]), goldMat);
  buckle.name = 'buckle';
  buckle.position.set(0, 0.043, 0.1221);
  buckle.rotation.set(deg(-10.6771), 0, 0);
  root.add(buckle);
  const buckleBar = new THREE.Mesh(new THREE.BoxGeometry(0.006, 0.026, 0.006), goldMat);
  buckleBar.name = 'buckleBar';
  buckleBar.position.set(0, 0.043, 0.1241);
  buckleBar.rotation.set(deg(-10.6771), 0, 0);
  root.add(buckleBar);
  const moon = new THREE.Mesh(extrude([[0.0291, 0.0212], [0.0135, 0.0334], [-0.0063, 0.0355], [-0.0241, 0.0268], [-0.0346, 0.0099], [-0.0346, -0.0099], [-0.0241, -0.0268], [-0.0063, -0.0355], [0.0135, -0.0334], [0.0291, -0.0212], [-0.0104, -0.028], [-0.0235, -0.026], [-0.0342, -0.0183], [-0.0403, -0.0066], [-0.0403, 0.0066], [-0.0342, 0.0183], [-0.0235, 0.026], [-0.0104, 0.028]], 0.004), moonMat);
  moon.name = 'moon';
  moon.position.set(0, 0.125, 0.0964);
  moon.rotation.set(deg(-10.6771), 0, deg(-20));
  root.add(moon);
  const star1 = new THREE.Mesh(extrudeGeo, starMat);
  star1.name = 'star1';
  star1.position.set(0.078, 0.09, 0.0703);
  star1.rotation.set(deg(-15.736), deg(46.9098), deg(23.8625));
  root.add(star1);
  const star2 = new THREE.Mesh(extrude([[0, 0.022], [-0.0058, 0.008], [-0.0209, 0.0068], [-0.0094, -0.0031], [-0.0129, -0.0178], [0, -0.0099], [0.0129, -0.0178], [0.0094, -0.0031], [0.0209, 0.0068], [0.0058, 0.008]], 0.004), starMat);
  star2.name = 'star2';
  star2.position.set(-0.0687, 0.1, 0.0763);
  star2.rotation.set(deg(-14.2357), deg(-41.113), deg(28.6378));
  root.add(star2);
  const star3 = new THREE.Mesh(extrude([[0, 0.018], [-0.0048, 0.0066], [-0.0171, 0.0056], [-0.0077, -0.0025], [-0.0106, -0.0146], [0, -0.0081], [0.0106, -0.0146], [0.0077, -0.0025], [0.0171, 0.0056], [0.0048, 0.0066]], 0.004), starMat);
  star3.name = 'star3';
  star3.position.set(0.04, 0.175, 0.0693);
  star3.rotation.set(deg(-12.2819), deg(29.4289), deg(54.237));
  root.add(star3);
  const star4 = new THREE.Mesh(extrudeGeo2, starMat);
  star4.name = 'star4';
  star4.position.set(-0.0786, 0.165, 0.0286);
  star4.rotation.set(deg(-28.8656), deg(-67.4319), deg(48.5095));
  root.add(star4);
  const star5 = new THREE.Mesh(extrude([[0, 0.024], [-0.0063, 0.0087], [-0.0228, 0.0074], [-0.0103, -0.0033], [-0.0141, -0.0194], [0, -0.0108], [0.0141, -0.0194], [0.0103, -0.0033], [0.0228, 0.0074], [0.0063, 0.0087]], 0.004), starMat);
  star5.name = 'star5';
  star5.position.set(0.0885, 0.14, -0.0237);
  star5.rotation.set(deg(-143.9284), deg(71.6594), deg(-143.5486));
  root.add(star5);
  const star6 = new THREE.Mesh(extrudeGeo, starMat);
  star6.name = 'star6';
  star6.position.set(-0.0822, 0.11, -0.0575);
  star6.rotation.set(deg(-161.804), deg(-53.6074), deg(-42.826));
  root.add(star6);
  const star7 = new THREE.Mesh(extrudeGeo2, starMat);
  star7.name = 'star7';
  star7.position.set(0.0148, 0.16, -0.0839);
  star7.rotation.set(deg(-169.1621), deg(9.8251), deg(-156.6425));
  root.add(star7);

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

export default createWizardHat;

Puanlar ve yorumlar

—
Henüz puan yok — ilk puanı sen ver.
5
0
4
0
3
0
2
0
1
0

Puan vermek ve yorum yapmak için giriş yap.

0 yorum

Henüz yorum yok. Bu modeli nasıl kullandığını ya da neyin daha iyi olabileceğini paylaş.

Benzer modeller

Aynı kategori ya da benzer etiketler