From bc2821adb11a30244fc4663f4fafb756877d9508 Mon Sep 17 00:00:00 2001 From: Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> Date: Wed, 7 Oct 2026 23:09:40 +0900 Subject: bluebey-studio: public/ の外へ移動し非公開化 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/bluebey-studio/src/hats.js | 135 -------------------------------------- 1 file changed, 135 deletions(-) delete mode 100644 public/bluebey-studio/src/hats.js (limited to 'public/bluebey-studio/src/hats.js') diff --git a/public/bluebey-studio/src/hats.js b/public/bluebey-studio/src/hats.js deleted file mode 100644 index 7a54c46..0000000 --- a/public/bluebey-studio/src/hats.js +++ /dev/null @@ -1,135 +0,0 @@ -import * as THREE from 'three'; - -/** - * Hats for ぶるべー. Each hat is a small group of primitives whose base sits at - * y = 0, so the app can drop it straight onto the top of the head (see - * `hatMount` in src/main.js). The character's front is +z, so a brim or a badge - * faces +z. - * - * These are deliberately not textured: like the props, they are built from a few - * rounded primitives so they take a clean outline and read in every render style. - */ - -const material = (color, opts = {}) => new THREE.MeshStandardMaterial({ - color, - roughness: 0.72, - metalness: 0, - ...opts, -}); - -function add(parent, geometry, mat, x = 0, y = 0, z = 0) { - const mesh = new THREE.Mesh(geometry, mat); - mesh.position.set(x, y, z); - mesh.castShadow = true; - mesh.receiveShadow = false; - parent.add(mesh); - return mesh; -} - -const cylinder = (rt, rb, h, seg = 24) => new THREE.CylinderGeometry(rt, rb, h, seg); -const sphere = (r, w = 24, h = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI) => ( - new THREE.SphereGeometry(r, w, h, phiStart, phiLength, thetaStart, thetaLength) -); -const box = (w, h, d) => new THREE.BoxGeometry(w, h, d); - -/** - * The 線画 fill a part takes, as how far it steps from the paper towards the ink - * (see `addMesh` in src/styles.js). Every hat part already gets the light default - * tone, but two parts of the *same* hat then come out the same shade - so a part - * that sits flush on another (a band on a crown) loses its seam. Tagging it with - * a darker tone puts that seam back, without touching リアル / フラット, where the - * part's own colour already draws it. - */ -function tone(mesh, strength) { - mesh.userData.tone = strength; - return mesh; -} - -/** シルクハット: a tall black crown, a narrow band and a flat brim. */ -function buildSilk() { - const group = new THREE.Group(); - const black = material('#1b1722'); - const band = material('#3a2f4a'); - add(group, cylinder(1.52, 1.52, 0.12, 32), black, 0, 0.06, 0); - add(group, cylinder(1.00, 1.04, 1.62, 32), black, 0, 0.93, 0); - tone(add(group, cylinder(1.05, 1.05, 0.24, 32), band, 0, 0.30, 0), 0.34); - return group; -} - -/** キャップ: a baseball cap - a low dome, a rim and a bill at the front. */ -function buildCap() { - const group = new THREE.Group(); - const blue = material('#3f6fd0'); - const dark = material('#2f54a4'); - // The crown: a hemisphere whose flat face sits on y = 0. - const crown = add(group, sphere(1.08, 28, 18, 0, Math.PI * 2, 0, Math.PI / 2), blue, 0, 0, 0); - crown.scale.set(1, 0.92, 1); - tone(add(group, cylinder(1.10, 1.10, 0.18, 28), dark, 0, 0.09, 0), 0.30); - // The bill, tipped down a little at the front. - const bill = tone(add(group, cylinder(0.86, 0.86, 0.09, 24), dark, 0, 0.06, 0.92), 0.30); - bill.scale.set(1, 1, 1.25); - bill.rotation.x = -0.12; - tone(add(group, sphere(0.13, 12, 10), dark, 0, 1.02, 0), 0.30); - return group; -} - -/** コック帽: a tall pleated toque - a cylindrical band under a big puffy crown. */ -function buildChef() { - const group = new THREE.Group(); - const white = material('#f7f6f2'); - const shade = material('#e6e3da'); - // The band: a tall cylinder that sits on the head. - add(group, cylinder(0.86, 0.92, 0.95, 28), white, 0, 0.475, 0); - tone(add(group, cylinder(0.90, 0.90, 0.10, 28), shade, 0, 0.90, 0), 0.26); - // The crown: a big squashed sphere ringed with lobes, so the top reads as the - // classic pleated toque rather than a plain dome. - const puff = add(group, sphere(1.24, 26, 20), white, 0, 1.30, 0); - puff.scale.set(1, 0.82, 1); - for (let i = 0; i < 8; i += 1) { - const a = (i / 8) * Math.PI * 2; - const lobe = add(group, sphere(0.5, 14, 12), white, Math.cos(a) * 0.92, 1.52, Math.sin(a) * 0.92); - lobe.scale.set(1, 0.9, 1); - } - const top = add(group, sphere(0.62, 16, 12), white, 0, 1.92, 0); - top.scale.set(1, 0.78, 1); - return group; -} - -/** 消防士の帽子: a red helmet with a brim, a top ridge and a small front badge. */ -function buildFire() { - const group = new THREE.Group(); - const red = material('#c5342f'); - const dark = material('#8f241f'); - const gold = material('#f0c24a', { metalness: 0.4, roughness: 0.4 }); - const dome = add(group, sphere(1.06, 28, 18, 0, Math.PI * 2, 0, Math.PI / 2), red, 0, 0, 0); - dome.scale.set(1, 0.95, 1); - const brim = tone(add(group, cylinder(1.34, 1.34, 0.12, 28), dark, 0, 0.06, 0.18), 0.28); - brim.scale.set(1, 1, 1.1); - // The ridge along the top, front to back. - const crest = tone(add(group, box(0.16, 0.42, 1.5), dark, 0, 1.02, 0), 0.28); - crest.rotation.x = -0.05; - tone(add(group, sphere(0.2, 14, 12), gold, 0, 0.62, 1.02), 0.22); - return group; -} - -const BUILDERS = { - silk: buildSilk, - cap: buildCap, - chef: buildChef, - fire: buildFire, -}; - -/** The hats offered in the panel: `none` clears it. */ -export const HAT_LIBRARY = [ - { id: 'none', label: 'なし' }, - { id: 'silk', label: 'シルクハット' }, - { id: 'cap', label: 'キャップ' }, - { id: 'chef', label: 'コック帽' }, - { id: 'fire', label: '消防士' }, -]; - -/** Builds the named hat, or `null` for `none` / an unknown name. */ -export function buildHat(id) { - const builder = BUILDERS[id]; - return builder ? builder() : null; -} -- cgit v1.3.1