feat: eye blinking
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import type { VRMCore } from '@pixiv/three-vrm-core'
|
||||
import { useLoop, useTresContext } from '@tresjs/core'
|
||||
import { AnimationMixer } from 'three'
|
||||
import { clipFromVRMAnimation, loadVRMAnimation } from '~/composables/vrm/animation'
|
||||
import { clipFromVRMAnimation, loadVRMAnimation, useBlink } from '~/composables/vrm/animation'
|
||||
import { loadVrm } from '~/composables/vrm/core'
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -21,6 +21,7 @@ const vrm = ref<VRMCore>()
|
||||
const vrmAnimationMixer = ref<AnimationMixer>()
|
||||
const { scene } = useTresContext()
|
||||
const { onBeforeRender } = useLoop()
|
||||
const blink = useBlink()
|
||||
|
||||
watch(() => props.position, ([x, y, z]) => {
|
||||
if (vrm.value) {
|
||||
@@ -59,6 +60,7 @@ onMounted(async () => {
|
||||
onBeforeRender(({ delta }) => {
|
||||
vrmAnimationMixer.value?.update(delta)
|
||||
vrm.value?.update(delta)
|
||||
blink.update(vrm.value, delta)
|
||||
})
|
||||
|
||||
vrm.value = _vrm
|
||||
|
||||
@@ -38,3 +38,51 @@ export async function clipFromVRMAnimation(vrm?: VRMCore, animation?: VRMAnimati
|
||||
// create animation clip
|
||||
return createVRMAnimationClip(animation, vrm)
|
||||
}
|
||||
|
||||
export function useBlink() {
|
||||
/**
|
||||
* Eye blinking animation
|
||||
*/
|
||||
const isBlinking = ref(false)
|
||||
const blinkProgress = ref(0)
|
||||
const timeSinceLastBlink = ref(0)
|
||||
const BLINK_DURATION = 0.2 // Duration of a single blink in seconds
|
||||
const MIN_BLINK_INTERVAL = 1 // Minimum time between blinks
|
||||
const MAX_BLINK_INTERVAL = 6 // Maximum time between blinks
|
||||
const nextBlinkTime = ref(Math.random() * (MAX_BLINK_INTERVAL - MIN_BLINK_INTERVAL) + MIN_BLINK_INTERVAL)
|
||||
|
||||
// Function to handle blinking animation
|
||||
function update(vrm: VRMCore | undefined, delta: number) {
|
||||
if (!vrm?.expressionManager)
|
||||
return
|
||||
|
||||
timeSinceLastBlink.value += delta
|
||||
|
||||
// Check if it's time for next blink
|
||||
if (!isBlinking.value && timeSinceLastBlink.value >= nextBlinkTime.value) {
|
||||
isBlinking.value = true
|
||||
blinkProgress.value = 0
|
||||
}
|
||||
|
||||
// Handle blinking animation
|
||||
if (isBlinking.value) {
|
||||
blinkProgress.value += delta / BLINK_DURATION
|
||||
|
||||
// Calculate blink value using sine curve for smooth animation
|
||||
const blinkValue = Math.sin(Math.PI * blinkProgress.value)
|
||||
|
||||
// Apply blink expression
|
||||
vrm.expressionManager.setValue('blink', blinkValue)
|
||||
|
||||
// Reset blink when animation is complete
|
||||
if (blinkProgress.value >= 1) {
|
||||
isBlinking.value = false
|
||||
timeSinceLastBlink.value = 0
|
||||
vrm.expressionManager.setValue('blink', 0) // Reset blink value to 0
|
||||
nextBlinkTime.value = Math.random() * (MAX_BLINK_INTERVAL - MIN_BLINK_INTERVAL) + MIN_BLINK_INTERVAL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { update }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user