aboutsummaryrefslogtreecommitdiffhomepage
path: root/public/bluebey-studio
diff options
context:
space:
mode:
Diffstat (limited to 'public/bluebey-studio')
-rw-r--r--public/bluebey-studio/src/hats.js73
1 files changed, 50 insertions, 23 deletions
diff --git a/public/bluebey-studio/src/hats.js b/public/bluebey-studio/src/hats.js
index 3763f82..571b136 100644
--- a/public/bluebey-studio/src/hats.js
+++ b/public/bluebey-studio/src/hats.js
@@ -72,27 +72,36 @@ function buildSilk() {
return group;
}
-/** キャップ: a low six-panel crown with a button, a band and a long curved bill. */
+/** キャップ: a six-panel crown, a band, a button and a bill that slopes down. */
function buildCap() {
const group = new THREE.Group();
const cloth = material('#3f6fd0', { roughness: 0.82 });
const dark = material('#2c4d96', { roughness: 0.86 });
const button = material('#243c74', { roughness: 0.7 });
- // The crown: a hemisphere whose flat face sits on y = 0, squashed and leaning
- // a touch forward so it reads as fabric, not a bowl.
- const crown = add(group, sphere(1.05, 32, 20, 0, Math.PI * 2, 0, Math.PI / 2), cloth, 0, 0.02, 0.02);
- crown.scale.set(1, 0.88, 1.03);
+ // The crown: a dome big enough to sit over the top of the head.
+ const crown = add(group, sphere(1.25, 30, 20, 0, Math.PI * 2, 0, Math.PI / 2), cloth, 0, 0.0, 0.02);
+ crown.scale.set(1, 0.82, 1.04);
+
+ // Six panel seams. A quarter torus per seam lies on the dome and carries the
+ // eye from the button down to the rim, which is what makes it read as a cap.
+ for (let i = 0; i < 6; i += 1) {
+ const a = (i / 6) * Math.PI * 2;
+ const seam = add(group, new THREE.TorusGeometry(1.245, 0.018, 5, 14, Math.PI / 2), dark, 0, 0.0, 0.02);
+ seam.scale.set(1, 0.82, 1.04);
+ seam.rotation.y = -a;
+ }
// The band around the rim, and the button on top.
- tone(add(group, cylinder(1.075, 1.075, 0.14, 32), dark, 0, 0.07, 0.02), 0.22);
- tone(add(group, sphere(0.10, 14, 10), button, 0, 0.925, 0.02), 0.18);
+ tone(add(group, cylinder(1.27, 1.27, 0.15, 32), dark, 0, 0.075, 0.02), 0.22);
+ tone(add(group, sphere(0.11, 14, 10), button, 0, 1.03, 0.02), 0.18);
- // The bill: an oval that is long at the front and tucked under the crown at
- // the back, tipped down a little.
- const bill = tone(add(group, cylinder(1.12, 1.12, 0.075, 32), material('#5b86e0', { roughness: 0.82 }), 0, 0.075, 0.75), 0.26);
- bill.scale.set(1, 1, 1.9);
- bill.rotation.x = -0.28;
+ // The bill: the front half of a disc, tilted down at the front (`rotation.x`
+ // positive lowers +z). It sits a little above the rim because the hat is worn
+ // sunk into the round head; at y = 0 the head hides the whole bill.
+ const bill = tone(add(group, new THREE.CylinderGeometry(1.24, 1.24, 0.08, 32, 1, false, -Math.PI / 2, Math.PI), cloth, 0, 0.45, 0.06), 0.26);
+ bill.scale.set(1, 1, 1.85);
+ bill.rotation.x = 0.30;
return group;
}
@@ -131,20 +140,38 @@ function buildChef() {
return group;
}
-/** 消防士の帽子: a red helmet with a brim, a top ridge and a small front badge. */
+/** 消防士の帽子: a red helmet with a wide brim that runs long at the back, a
+ * ridge along the top and a gold front shield. */
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);
+ const red = material('#c5342f', { roughness: 0.58 });
+ const dark = material('#8f241f', { roughness: 0.62 });
+ const gold = material('#f0c24a', { metalness: 0.35, roughness: 0.35 });
+ const cream = material('#f7efdc', { roughness: 0.55 });
+
+ // The dome, wide enough to cover the top of the head.
+ const dome = add(group, sphere(1.42, 32, 20, 0, Math.PI * 2, 0, Math.PI / 2), red, 0, 0, 0);
+ dome.scale.set(1, 0.90, 1.05);
+
+ // The brim: an oval, pushed back so it protects the neck, with a rolled edge.
+ const brim = add(group, cylinder(1.80, 1.70, 0.13, 36), dark, 0, 0.02, -0.16);
+ brim.scale.set(1, 1, 1.50);
+ const rim = add(group, new THREE.TorusGeometry(1.775, 0.085, 10, 48), dark, 0, 0.085, -0.16);
+ rim.scale.set(1, 1.50, 1);
+ rim.rotation.x = Math.PI / 2;
+ tone(rim, 0.26);
+
// 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);
+ const crest = tone(add(group, sphere(0.5, 18, 14), dark, 0, 1.14, -0.05), 0.26);
+ crest.scale.set(0.34, 0.70, 2.05);
+
+ // The front shield, lying on the dome's face.
+ const shield = tone(add(group, sphere(0.52, 20, 16), gold, 0, 0.50, 1.30), 0.20);
+ shield.scale.set(0.76, 1.0, 0.20);
+ shield.rotation.x = -0.30;
+ const badge = tone(add(group, sphere(0.38, 18, 14), cream, 0, 0.50, 1.44), 0.14);
+ badge.scale.set(0.64, 0.94, 0.18);
+ badge.rotation.x = -0.30;
return group;
}