diff options
Diffstat (limited to 'public')
| -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' |
