diff options
| author | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-22 14:49:49 +0900 |
|---|---|---|
| committer | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-22 14:49:49 +0900 |
| commit | 5b2f8b7979d2fb0b8e0f5be175fdc8651e987bdf (patch) | |
| tree | cb9b7f31afa9dd0afd82aabc1a7114705ba2b413 /public/bluebey-studio/src/main.js | |
| parent | e5d1b6748a5e9d6e8e7650c657b79fc548b7393d (diff) | |
bluebey-studio: 後ろから口が見える・壁で隠れない問題を修正
口を閉じた舌出しのときだけ深度テストを外していたが、後ろ姿や見えない壁では常に深度テストを有効に戻すようにした。
Diffstat (limited to 'public/bluebey-studio/src/main.js')
| -rw-r--r-- | public/bluebey-studio/src/main.js | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/public/bluebey-studio/src/main.js b/public/bluebey-studio/src/main.js index b08ea11..bdf5697 100644 --- a/public/bluebey-studio/src/main.js +++ b/public/bluebey-studio/src/main.js @@ -1370,6 +1370,8 @@ 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); @@ -1414,6 +1416,28 @@ 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. + 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); + const facing = mouthNormal.dot(mouthToCamera) > 0; + 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; + } + } + view.controls.update(dt); const animating = (state.anim.mode ?? 'off') !== 'off' |
