1+ import * as faceapi from 'face-api.js' ;
2+ import { BloomEffect , ChromaticAberrationEffect , EffectComposer , EffectPass , RenderPass } from 'postprocessing' ;
13import React , { useEffect , useRef , useState } from 'react' ;
2- import { EffectComposer , RenderPass , EffectPass , BloomEffect , ChromaticAberrationEffect } from 'postprocessing' ;
34import * as THREE from 'three' ;
4- import * as faceapi from 'face-api.js' ;
55
66type GridScanProps = {
77 enableWebcam ?: boolean ;
@@ -360,6 +360,23 @@ export const GridScan: React.FC<GridScanProps> = ({
360360 const MAX_SCANS = 8 ;
361361 const scanStartsRef = useRef < number [ ] > ( [ ] ) ;
362362
363+ const skewScaleRef = useRef ( 0 ) ;
364+ const tiltScaleRef = useRef ( 0 ) ;
365+ const yawScaleRef = useRef ( 0 ) ;
366+ const depthResponseRef = useRef ( 0 ) ;
367+ const smoothTimeRef = useRef ( 0 ) ;
368+ const yBoostRef = useRef ( 0 ) ;
369+
370+ useEffect ( ( ) => {
371+ const s = THREE . MathUtils . clamp ( sensitivity , 0 , 1 ) ;
372+ skewScaleRef . current = THREE . MathUtils . lerp ( 0.06 , 0.2 , s ) ;
373+ tiltScaleRef . current = THREE . MathUtils . lerp ( 0.12 , 0.3 , s ) ;
374+ yawScaleRef . current = THREE . MathUtils . lerp ( 0.1 , 0.28 , s ) ;
375+ depthResponseRef . current = THREE . MathUtils . lerp ( 0.25 , 0.45 , s ) ;
376+ smoothTimeRef . current = THREE . MathUtils . lerp ( 0.45 , 0.12 , s ) ;
377+ yBoostRef . current = THREE . MathUtils . lerp ( 1.2 , 1.6 , s ) ;
378+ } , [ sensitivity ] ) ;
379+
363380 const pushScan = ( t : number ) => {
364381 const arr = scanStartsRef . current . slice ( ) ;
365382 if ( arr . length >= MAX_SCANS ) arr . shift ( ) ;
@@ -379,16 +396,8 @@ export const GridScan: React.FC<GridScanProps> = ({
379396 const bufT = useRef < number [ ] > ( [ ] ) ;
380397 const bufYaw = useRef < number [ ] > ( [ ] ) ;
381398
382- const s = THREE . MathUtils . clamp ( sensitivity , 0 , 1 ) ;
383- const skewScale = THREE . MathUtils . lerp ( 0.06 , 0.2 , s ) ;
384- const tiltScale = THREE . MathUtils . lerp ( 0.12 , 0.3 , s ) ;
385- const yawScale = THREE . MathUtils . lerp ( 0.1 , 0.28 , s ) ;
386- const depthResponse = THREE . MathUtils . lerp ( 0.25 , 0.45 , s ) ;
387- const smoothTime = THREE . MathUtils . lerp ( 0.45 , 0.12 , s ) ;
388399 const maxSpeed = Infinity ;
389400
390- const yBoost = THREE . MathUtils . lerp ( 1.2 , 1.6 , s ) ;
391-
392401 useEffect ( ( ) => {
393402 const el = containerRef . current ;
394403 if ( ! el ) return ;
@@ -545,6 +554,8 @@ export const GridScan: React.FC<GridScanProps> = ({
545554 const dt = Math . max ( 0 , Math . min ( 0.1 , ( now - last ) / 1000 ) ) ;
546555 last = now ;
547556
557+ const smoothTime = smoothTimeRef . current ;
558+
548559 lookCurrent . current . copy (
549560 smoothDampVec2 ( lookCurrent . current , lookTarget . current , lookVel . current , smoothTime , maxSpeed , dt )
550561 ) ;
@@ -571,10 +582,12 @@ export const GridScan: React.FC<GridScanProps> = ({
571582 yawCurrent . current = yawSm . value ;
572583 yawVel . current = yawSm . v ;
573584
574- const skew = new THREE . Vector2 ( lookCurrent . current . x * skewScale , - lookCurrent . current . y * yBoost * skewScale ) ;
575- material . uniforms . uSkew . value . set ( skew . x , skew . y ) ;
576- material . uniforms . uTilt . value = tiltCurrent . current * tiltScale ;
577- material . uniforms . uYaw . value = THREE . MathUtils . clamp ( yawCurrent . current * yawScale , - 0.6 , 0.6 ) ;
585+ material . uniforms . uSkew . value . set (
586+ lookCurrent . current . x * skewScaleRef . current ,
587+ - lookCurrent . current . y * yBoostRef . current * skewScaleRef . current
588+ ) ;
589+ material . uniforms . uTilt . value = tiltCurrent . current * tiltScaleRef . current ;
590+ material . uniforms . uYaw . value = THREE . MathUtils . clamp ( yawCurrent . current * yawScaleRef . current , - 0.6 , 0.6 ) ;
578591
579592 material . uniforms . iTime . value = now / 1000 ;
580593 renderer . clear ( true , true , true ) ;
@@ -590,6 +603,7 @@ export const GridScan: React.FC<GridScanProps> = ({
590603 return ( ) => {
591604 if ( rafRef . current ) cancelAnimationFrame ( rafRef . current ) ;
592605 window . removeEventListener ( 'resize' , onResize ) ;
606+ scene . clear ( ) ;
593607 material . dispose ( ) ;
594608 ( quad . geometry as THREE . BufferGeometry ) . dispose ( ) ;
595609 if ( composerRef . current ) {
@@ -599,18 +613,7 @@ export const GridScan: React.FC<GridScanProps> = ({
599613 renderer . dispose ( ) ;
600614 container . removeChild ( renderer . domElement ) ;
601615 } ;
602- } , [
603- sensitivity ,
604- lineThickness ,
605- linesColor ,
606- scanColor ,
607- scanOpacity ,
608- gridScale ,
609- lineStyle ,
610- lineJitter ,
611- scanDirection ,
612- enablePost
613- ] ) ;
616+ } , [ lineThickness , linesColor , scanColor , scanOpacity , gridScale , lineStyle , lineJitter , scanDirection , enablePost ] ) ;
614617
615618 useEffect ( ( ) => {
616619 const m = materialRef . current ;
@@ -744,7 +747,7 @@ export const GridScan: React.FC<GridScanProps> = ({
744747 const look = new THREE . Vector2 ( Math . tanh ( nxm ) , Math . tanh ( nym ) ) ;
745748
746749 const faceSize = Math . min ( 1 , Math . hypot ( box . width / vw , box . height / vh ) ) ;
747- const depthScale = 1 + depthResponse * ( faceSize - 0.25 ) ;
750+ const depthScale = 1 + depthResponseRef . current * ( faceSize - 0.25 ) ;
748751 lookTarget . current . copy ( look . multiplyScalar ( depthScale ) ) ;
749752
750753 const leftEye = res . landmarks . getLeftEye ( ) ;
@@ -799,14 +802,14 @@ export const GridScan: React.FC<GridScanProps> = ({
799802 video . srcObject = null ;
800803 }
801804 } ;
802- } , [ enableWebcam , modelsReady , depthResponse ] ) ;
805+ } , [ enableWebcam , modelsReady ] ) ;
803806
804807 return (
805808 < div ref = { containerRef } className = { `relative w-full h-full overflow-hidden ${ className ?? '' } ` } style = { style } >
806809 { showPreview && (
807- < div className = "absolute right-3 bottom-3 w-[220px] h-[132px] rounded-lg overflow-hidden border border-white/25 shadow-[0_4px_16px_rgba(0,0,0,0.4)] bg-black text -white text-[12px] leading-[1.2] font-sans pointer-events-none" >
810+ < div className = "right-3 bottom-3 absolute bg-black shadow-[0_4px_16px_rgba(0,0,0,0.4)] border border -white/25 rounded-lg w-[220px] h-[132px] overflow-hidden font-sans text-[12px] text-white leading-[1.2] pointer-events-none" >
808811 < video ref = { videoRef } muted playsInline autoPlay className = "w-full h-full object-cover -scale-x-100" />
809- < div className = "absolute left-2 top-2 px-[6px] py-[2px] bg-black/50 rounded-[6px] backdrop-blur-[4px ]" >
812+ < div className = "top-2 left-2 absolute bg-black/50 backdrop-blur-[4px] px-[6px] py-[2px] rounded-[6px]" >
810813 { enableWebcam
811814 ? modelsReady
812815 ? uiFaceActive
0 commit comments