From 3c7fc9271cdaf7b8ee11609d3c4e73df7ba9e0d9 Mon Sep 17 00:00:00 2001 From: Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> Date: Sun, 4 Oct 2026 00:26:59 +0900 Subject: bluebey-studio: 髪の模様の横位置を正面中央に修正 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 継ぎ目補正でキャンバスが artwork ウィンドウ(1024)より広くなったのに、正面をキャンバス中央としていたため、頭の模様が右へずれていた。正面をウィンドウ中央(512px)基準に直し、offsetX の効きも1:1にした。 --- public/bluebey-studio/src/face.js | 5 ++--- public/bluebey-studio/src/faceArt.js | 13 +++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'public') diff --git a/public/bluebey-studio/src/face.js b/public/bluebey-studio/src/face.js index de8a31c..273468a 100644 --- a/public/bluebey-studio/src/face.js +++ b/public/bluebey-studio/src/face.js @@ -262,10 +262,9 @@ export class Face { const layout = this.hairLayout; const ctx = this.hairCtx; ctx.clearRect(0, 0, layout.width, layout.height); - ctx.save(); - ctx.translate(layout.offsetX, layout.offsetY); + // `drawHeadCoverWrap` works in canvas coordinates (its x axis is the UV + // angle already normalised), so it is not shifted by the window offset. drawHeadCoverWrap(ctx, p.eyes.headMark ?? {}, layout); - ctx.restore(); this.hairTexture.needsUpdate = true; } diff --git a/public/bluebey-studio/src/faceArt.js b/public/bluebey-studio/src/faceArt.js index 1083e52..c4940d4 100644 --- a/public/bluebey-studio/src/faceArt.js +++ b/public/bluebey-studio/src/faceArt.js @@ -900,6 +900,11 @@ export function drawHeadCoverWrap(ctx, spec, layout) { const size = clamp(spec.size ?? 1, 0.02, 3); const W = layout.width; const H = layout.height; + // The horizontal axis is the angle. The *front* sits at u = 0.5, which is the + // middle of the artwork window (1024), not the middle of the canvas: after the + // seam heal the canvas is wider than the window, so using W/2 put the pattern + // a good way off centre. + const span = (layout.window ?? ART_WINDOW).width; // After the GLB's V-flip the wrap's v is 0 at the top of the head and 1 at the // model's feet, so a *larger* boundary means more hair (it reaches further // down) - the same direction as `size` and `offsetY` on the front plate. @@ -913,10 +918,10 @@ export function drawHeadCoverWrap(ctx, spec, layout) { ctx.rect(0, 0, W, H); ctx.clip(); - // `t` is -1..1 across the front (+-90 deg around u = 0.5); everything behind is - // pinned to +-1, so the hairline runs flat round the back of the head. - const half = W * 0.25; - const cx = W / 2 + (clamp(spec.offsetX ?? 0, -600, 600) / 512) * half; + // `t` is -1..1 across the front (+-90 deg around the front); everything behind + // is pinned to +-1, so the hairline runs flat round the back of the head. + const half = span * 0.25; + 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)); -- cgit v1.3.1