aboutsummaryrefslogtreecommitdiffhomepage
path: root/public/bluebey-studio/src/faceArt.js
diff options
context:
space:
mode:
Diffstat (limited to 'public/bluebey-studio/src/faceArt.js')
-rw-r--r--public/bluebey-studio/src/faceArt.js46
1 files changed, 21 insertions, 25 deletions
diff --git a/public/bluebey-studio/src/faceArt.js b/public/bluebey-studio/src/faceArt.js
index c4940d4..7b5f7de 100644
--- a/public/bluebey-studio/src/faceArt.js
+++ b/public/bluebey-studio/src/faceArt.js
@@ -796,7 +796,7 @@ function drawCheeks(ctx, spec) {
*/
function drawHeadCover(ctx, spec, limits) {
const shape = spec?.shape ?? 'off';
- if (shape === 'off' || shape === 'none') return;
+ if (shape === 'off' || shape === 'none' || shape === 'wave') return;
const size = clamp(spec.size ?? 1, 0.02, 3);
const left = limits.left;
@@ -828,23 +828,14 @@ function drawHeadCover(ctx, spec, limits) {
const halfSpan = width / 2;
const boundary = (x) => {
const t = clamp((x - cx) / halfSpan, -1, 1);
- if (shape === 'fringe') {
- // Bangs: a soft point dipping in the middle, with side lobes.
- return base + 150 * (1 - Math.abs(t)) - 55 * Math.abs(Math.sin(t * Math.PI));
- }
- if (shape === 'fringe-up') {
- // The mirror image: a fringe that peaks *up* in the middle (a widow's peak
- // or centre part), so more forehead shows in the middle than at the sides.
- return base - 150 * (1 - Math.abs(t)) + 55 * Math.abs(Math.sin(t * Math.PI));
- }
- if (shape === 'wave') {
- // A single smooth sweep across the forehead.
- return base + 120 * Math.sin(t * Math.PI * 0.9 + 0.5);
- }
- if (shape === 'side') {
- // A side part: high on one side, low on the other.
- return base + 260 * t;
- }
+ // まえがみ: a narrow, deep V pointing down the middle (Atom / Mickey).
+ if (shape === 'fringe') return base + 175 * Math.max(0, 1 - Math.abs(t) * 1.6);
+ // はちわれ: the same V upside down - a widow's peak.
+ if (shape === 'fringe-up') return base - 320 * Math.max(0, 1 - Math.abs(t) * 1.5);
+ // カーブ: a plain shallow curve, higher (more hair) round the sides.
+ if (shape === 'curve') return base + 160 * t * t;
+ // わけめ: a 7:3 parting - a step at 30% from the left.
+ if (shape === 'side') return base + 60 - 320 / (1 + Math.exp(-(t + 0.4) * 10));
// `cap`: a rounded helmet, lowest in the middle.
return base - 100 * (1 - t * t);
};
@@ -864,7 +855,7 @@ function drawHeadCover(ctx, spec, limits) {
if (shape === 'side') {
// わけめ: cut a real parting in the hair, so the two halves read as combed
// apart rather than as one smooth sweep.
- const partX = cx - halfSpan * 0.45;
+ const partX = cx - halfSpan * 0.4;
const gw = Math.max(5, width * 0.02) * (0.6 + size);
ctx.save();
ctx.globalCompositeOperation = 'destination-out';
@@ -894,8 +885,8 @@ function drawHeadCover(ctx, spec, limits) {
*/
export function drawHeadCoverWrap(ctx, spec, layout) {
const shape = spec?.shape ?? 'off';
- // `split` is a retired front-plate shape; it has no wrap equivalent.
- if (shape === 'off' || shape === 'none' || shape === 'split') return;
+ // `split` and `wave` are retired front-plate shapes; they have no wrap equal.
+ if (shape === 'off' || shape === 'none' || shape === 'split' || shape === 'wave') return;
const size = clamp(spec.size ?? 1, 0.02, 3);
const W = layout.width;
@@ -924,10 +915,15 @@ export function drawHeadCoverWrap(ctx, spec, layout) {
const cx = layout.offsetX + span * 0.5 + clamp(spec.offsetX ?? 0, -600, 600);
const vBound = (x) => {
const t = clamp((x - cx) / half, -1, 1);
- if (shape === 'fringe') return base + 0.14 * (1 - Math.abs(t)) - 0.05 * Math.abs(Math.sin(t * Math.PI));
- if (shape === 'fringe-up') return base - 0.14 * (1 - Math.abs(t)) + 0.05 * Math.abs(Math.sin(t * Math.PI));
- if (shape === 'wave') return base + 0.10 * Math.sin(t * Math.PI * 0.9 + 0.5);
- if (shape === 'side') return base + 0.20 * t;
+ // まえがみ: a narrow, deep V pointing down the middle (Atom / Mickey).
+ if (shape === 'fringe') return base + 0.15 * Math.max(0, 1 - Math.abs(t) * 1.6);
+ // はちわれ: the same V upside down - a widow's peak.
+ if (shape === 'fringe-up') return base - 0.18 * Math.max(0, 1 - Math.abs(t) * 1.5);
+ // カーブ: a plain shallow curve, lower (more hair) round the sides.
+ if (shape === 'curve') return base + 0.10 * t * t;
+ // わけめ: a 7:3 parting - a step at 30% from the left, so the larger side
+ // sits lower (more hair).
+ if (shape === 'side') return base + 0.08 - 0.16 / (1 + Math.exp(-(t + 0.4) * 10));
return base - 0.07 * (1 - t * t); // `cap`
};