diff options
| author | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-22 15:06:22 +0900 |
|---|---|---|
| committer | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-22 15:06:22 +0900 |
| commit | 76cc6003f79df78613b21bd9114dff02874632bf (patch) | |
| tree | b4ec4f8df2d44828ef050a84ae71eb66881a0772 | |
| parent | c891299737dd0c73a54f9bd1510dc00d6f140f1f (diff) | |
bluebey-studio: 口の透過を根本修正し、操作の割り当てを戻す
口は常に深度テストを有効にして体・壁で隠れるようにした。通常ドラッグ=ぶるべー移動、Shift+ドラッグ=視点移動に戻し、ダブルクリック/ボタンで回転中心をぶるべーに合わせられるようにした。
| -rw-r--r-- | public/bluebey-studio/guide.html | 5 | ||||
| -rw-r--r-- | public/bluebey-studio/index.html | 2 | ||||
| -rw-r--r-- | public/bluebey-studio/src/main.js | 50 | ||||
| -rw-r--r-- | public/bluebey-studio/src/panel.js | 7 | ||||
| -rw-r--r-- | public/bluebey/guide.pdf | bin | 3888035 -> 3889085 bytes | |||
| -rw-r--r-- | src/content/docs/bluebey/guide.mdx | 5 |
6 files changed, 39 insertions, 30 deletions
diff --git a/public/bluebey-studio/guide.html b/public/bluebey-studio/guide.html index a6cba9f..73d903d 100644 --- a/public/bluebey-studio/guide.html +++ b/public/bluebey-studio/guide.html @@ -110,8 +110,9 @@ </ol> <h3>パソコンでの操作</h3> <ul> - <li>ぶるべーをつかんでドラッグすると、カメラ(見ている基準点)を動かせます。ぶるべーは画面の中心に残ります。</li> - <li>Shift を押しながらドラッグすると、ぶるべーを移動できます。</li> + <li>ぶるべーをつかんでドラッグすると、ぶるべーを移動できます。</li> + <li>Shift を押しながらドラッグすると、カメラ(見ている基準点)を動かせます。ぶるべーは画面の中心に残ります。</li> + <li>回転の中心をぶるべーに合わせたいときは、ぶるべーをダブルクリックします(「シーン」タブの「画面・光」にある「中心をぶるべーに合わせる」でも同じです)。</li> <li>向きは、全身とボーンのスライダーや回転ギズモで調整できます。</li> <li>モデルをクリックすると、その場所に近いボーンが選ばれます。</li> <li>「元に戻す/やり直す(パネル上部の矢印アイコン)」「すべてをランダムに(?!アイコン)」は、どのタブでも使えます。</li> diff --git a/public/bluebey-studio/index.html b/public/bluebey-studio/index.html index 9f2e089..77e527a 100644 --- a/public/bluebey-studio/index.html +++ b/public/bluebey-studio/index.html @@ -136,7 +136,7 @@ if (window.matchMedia('(max-width: 768px), (max-height: 500px) and (pointer: coa <h3>ポーズ</h3> <ul> <li>右パネルの「ポーズ」でボーンを選び、X/Y/Zのスライダーを動かします。「ポーズ例」から始めると早いです。</li> - <li>ぶるべーをつかんでドラッグすると、カメラ(見ている基準点)を動かせます(ぶるべーは中心に残ります)。Shiftを押しながらドラッグすると、ぶるべーを移動できます。</li> + <li>ぶるべーをつかんでドラッグすると、ぶるべーを移動できます。Shiftを押しながらドラッグすると、カメラ(見ている基準点)を動かせます(ぶるべーは中心に残ります)。回転の中心をぶるべーに合わせたいときは、ぶるべーをダブルクリックします。</li> <li>モデルをクリックすると、その場所にいちばん近いボーンが選ばれます。</li> <li>ギズモ(回転の輪)を直接ドラッグしても回せます。</li> <li>スライダーの値は「休めの姿勢(レストポーズ)」からの差分です。<code>0,0,0</code> で元の姿勢。</li> diff --git a/public/bluebey-studio/src/main.js b/public/bluebey-studio/src/main.js index 6507bf4..d2de72c 100644 --- a/public/bluebey-studio/src/main.js +++ b/public/bluebey-studio/src/main.js @@ -1291,11 +1291,22 @@ async function init() { window.addEventListener('resize', clearOnDesktop); } + /** Put the orbit centre back on ぶるべー (e.g. after moving it off-centre). */ + function recenterCamera() { + const root = state.pose.root ?? [0, 0, 0]; + state.view.targetX = round2(root[0] ?? 0); + state.view.targetY = round2(halfHeight + (root[1] ?? 0)); + state.view.targetZ = round2(root[2] ?? 0); + refresh('view'); + app.panel?.sync(); + } + Object.assign(app.actions, { capturePose, applyState, refresh, loadHatModel, + recenterCamera, patch: (scope, value) => applyState({ [scope]: value }, { scope }), syncPanel: () => app.panel?.sync(), imageCanvas: (options) => captureImage(options), @@ -1370,8 +1381,6 @@ async function init() { const warmupUntil = performance.now() + 2500; let snotSignature = null; - const mouthNormal = new THREE.Vector3(); - const mouthToCamera = new THREE.Vector3(); const loop = (now) => { const rawDelta = now - last; const dt = Math.min(0.05, rawDelta / 1000); @@ -1416,29 +1425,14 @@ async function init() { } if (face.flush(now, 26)) app.needsRender = true; - // The mouth artwork normally lets a closed-lip tongue win the depth test so - // it reads over the 3D nose. That would also draw it through the back of the - // head and over a 見えない壁, so switch depth testing back on when the camera - // is behind the face or a wall is in play. + // The face artwork used to switch depth testing off so a closed-lip tongue + // could draw over the 3D nose. That also let the mouth show through the body + // at an angle, so depth testing now always stays on - the tongue still reads + // over the nose without it. const mouthMesh = model.parts.mouthMesh; - if (mouthMesh?.material) { - const mouth = state.face.mouth ?? {}; - const tongueOverLip = (mouth.round ?? 0) <= 0.004 - && (mouth.open ?? 0) <= 0.004 - && (mouth.tongue ?? 1) > 0.01; - mouthMesh.getWorldDirection(mouthNormal); - mouthMesh.getWorldPosition(mouthToCamera); - mouthToCamera.subVectors(view.camera.position, mouthToCamera).normalize(); - // Only let the artwork win the depth test when the camera is actually in - // front of the face. At a side view the dot product is near zero, and the - // mouth must lose to the body (or it shows through the far side). - const facing = mouthNormal.dot(mouthToCamera) > 0.5; - const wallOn = state.render.wall?.on === true || state.render.wall2?.on === true; - const depthTest = !tongueOverLip || !facing || wallOn; - if (mouthMesh.material.depthTest !== depthTest) { - mouthMesh.material.depthTest = depthTest; - app.needsRender = true; - } + if (mouthMesh?.material && mouthMesh.material.depthTest !== true) { + mouthMesh.material.depthTest = true; + app.needsRender = true; } view.controls.update(dt); @@ -2386,7 +2380,7 @@ async function init() { const root = state.pose.root ?? [0, 0, 0]; modelDrag = { pointerId: event.pointerId, - pan: event.pointerType === 'mouse' ? !event.shiftKey : false, + pan: event.shiftKey, x: event.clientX, y: event.clientY, lastX: event.clientX, @@ -2465,6 +2459,12 @@ async function init() { }; canvas.addEventListener('pointerup', endModelDrag); canvas.addEventListener('pointercancel', endModelDrag); + + canvas.addEventListener('dblclick', (event) => { + if (!dragHitAt(event)) return; + recenterCamera(); + toast('回転の中心をぶるべーに合わせました'); + }); } function togglePanel() { diff --git a/public/bluebey-studio/src/panel.js b/public/bluebey-studio/src/panel.js index 2b405bd..a0b2611 100644 --- a/public/bluebey-studio/src/panel.js +++ b/public/bluebey-studio/src/panel.js @@ -2076,6 +2076,13 @@ export function buildPanel(app, root) { label: '回す速さ', min: 0.2, max: 4, step: 0.1, value: 0.8, format: (v) => v.toFixed(1), onInput: (v) => { state.view.autoRotateSpeed = v; app.actions.refresh('view'); }, })); + cameraSection.add(buttons({ + items: [{ + id: 'recenter', + label: '中心をぶるべーに合わせる', + onClick: () => app.actions.recenterCamera?.(), + }], + })); /* ------------------------------------------------------------------ export */ diff --git a/public/bluebey/guide.pdf b/public/bluebey/guide.pdf Binary files differindex 6ef3dd7..d5c36e4 100644 --- a/public/bluebey/guide.pdf +++ b/public/bluebey/guide.pdf diff --git a/src/content/docs/bluebey/guide.mdx b/src/content/docs/bluebey/guide.mdx index 0749144..82e10db 100644 --- a/src/content/docs/bluebey/guide.mdx +++ b/src/content/docs/bluebey/guide.mdx @@ -82,8 +82,9 @@ description: 小平市のマスコットキャラクタ「ぶるべー」の3Dã‚ ### パソコンでの操作 -- ぶるべーをつかんでドラッグすると、カメラ(見ている基準点)を動かせます。ぶるべーは画面の中心に残ります。 -- Shift を押しながらドラッグすると、ぶるべーを移動できます。 +- ぶるべーをつかんでドラッグすると、ぶるべーを移動できます。 +- Shift を押しながらドラッグすると、カメラ(見ている基準点)を動かせます。ぶるべーは画面の中心に残ります。 +- 回転の中心をぶるべーに合わせたいときは、ぶるべーをダブルクリックします(「シーン」タブの「画面・光」にある「中心をぶるべーに合わせる」でも同じです)。 - 向きは、全身とボーンのスライダーや回転ギズモで調整できます。 - モデルをクリックすると、その場所に近いボーンが選ばれます。 - 「元に戻す/やり直す(パネル上部の矢印アイコン)」「すべてをランダムに(?!アイコン)」は、どのタブでも使えます。 |
