How do I interpolate 2 animations
Hello!
I am dealing with the transitions between 2 states.
I am trying to mimick a Unity transition.
I am experiencing weird color flashes while I expect gradual transitions.
This makes me wonder if I am not aware of a problem.
Thank you for having a look at my code.
This is the code of a cTransition class:
Code:
Public Sub UpdateTransition()
If Not Me.IsActive Then
Exit Sub
End If
Dim lNow&
lNow = GetTickCount
Dim lTaken&
lTaken = lNow - m_lStartTime
Me.Progress = lTaken / GetEffectiveDuration(Me.Duration)
Debug.Print "----------"
m_s = "Progress: " & Me.Progress & vbNewLine
Clamp Me.Progress, 0, 1
' Update animations
modAnim.UpdateAnimation m_StartAnimationConfig, lNow
modAnim.UpdateAnimation m_TargetAnimationConfig, lNow
If lTaken >= GetEffectiveDuration(Me.Duration) Then
' Transition is complete
m_bIsTransitionComplete = True
Me.IsActive = False
Exit Sub
End If
' Calculate current size using weighted interpolation
Dim currentSizeStart As Double
Dim currentSizeTarget As Double
currentSizeStart = m_StartAnimationConfig.StartSizeFactor + _
(m_StartAnimationConfig.TargetSizeFactor - m_StartAnimationConfig.StartSizeFactor) * _
Ease(Me.Progress, m_StartAnimationConfig.FunctionType, m_StartAnimationConfig.ModeType)
currentSizeTarget = m_TargetAnimationConfig.StartSizeFactor + _
(m_TargetAnimationConfig.TargetSizeFactor - m_TargetAnimationConfig.StartSizeFactor) * _
Ease(Me.Progress, m_TargetAnimationConfig.FunctionType, m_TargetAnimationConfig.ModeType)
Me.CurrentSize = (currentSizeTarget * Me.Progress) + (currentSizeStart * (1 - Me.Progress))
' Calculate current alpha using weighted interpolation
Dim currentAlphaStart As Double
Dim currentAlphaTarget As Double
currentAlphaStart = m_StartAnimationConfig.StartAlpha + _
(m_StartAnimationConfig.TargetAlpha - m_StartAnimationConfig.StartAlpha) * _
Ease(Me.Progress, m_StartAnimationConfig.FunctionType, m_StartAnimationConfig.ModeType)
currentAlphaTarget = m_TargetAnimationConfig.StartAlpha + _
(m_TargetAnimationConfig.TargetAlpha - m_TargetAnimationConfig.StartAlpha) * _
Ease(Me.Progress, m_TargetAnimationConfig.FunctionType, m_TargetAnimationConfig.ModeType)
Me.CurrentAlpha = (currentAlphaTarget * Me.Progress) + (currentAlphaStart * (1 - Me.Progress))
' Calculate current color using BlendColors
Me.CurrentColor = BlendColors(m_TargetAnimationConfig.TargetColor, m_StartAnimationConfig.StartColor, Me.Progress)
And this is sub to apply the current progress to the size and color of the objects that I want to animate:
Code:
Public Function GetEffectiveDuration(ByVal u As Double) As Double
If g_Slowmo = 0 Then
g_Slowmo = 1
End If
GetEffectiveDuration = u * g_Slowmo
End Function
Public Sub UpdateAnimation(ByRef u As cAnimationConfig, ByVal uCurrentTime As Long)
Dim lDur&
lDur = uCurrentTime - u.StartTime
u.DontUseThisForEndResult_Progress = lDur / GetEffectiveDuration(u.Duration) 'GetEffectiveDuration is a helper function to make Duration bigger to slow down the animation for inspecting
'clamp
Clamp u.DontUseThisForEndResult_Progress, 0, 1
If u.DontUseThisForEndResult_Progress > 1 Then
u.DontUseThisForEndResult_Progress = 1
ElseIf u.DontUseThisForEndResult_Progress < 0 Then
u.DontUseThisForEndResult_Progress = 0
End If
If lDur >= GetEffectiveDuration(u.Duration) Then
u.IsActive = False
If u.IsOneShot Then
'can not repeat
Exit Sub
Else
u.IsActive = True 'start again
u.StartTime = GetTickCount
'reset and make it play again
If u.PlayMirroredIfLooped Then
u.IsPlayingMirrored = Not u.IsPlayingMirrored
End If
u.DontUseThisForEndResult_Progress = 0
End If
End If
u.EffectiveProgress = modAnim.GetAnimationProgress(u.DontUseThisForEndResult_Progress, u.IsPlayingMirrored)
u.EasedEffectiveProgress = Ease(u.EffectiveProgress, u.FunctionType, u.ModeType)
u.CurrentSize = u.SizeFactorAtStart + ((u.SizeFactorAtEnd - u.SizeFactorAtStart) * u.EasedEffectiveProgress)
u.CurrentColor = BlendColors(u.StartColor, u.TargetColor, 1 - u.EffectiveProgress) 'dont use easing for color, instead use linear
End Sub
Re: How do I interpolate 2 animations
I can describe the problem now:
I need to transition from one animation to another.
Each animation has a StartColor and a TargetColor and a StartAlpha and a TargetAlpha.
So I need to interpolate between these 4 RGB values and 4 Alpha values in respect to the progress of the transition.
Additionally, I must fade the Start Animation out, and I must fade the Target Animation out during the transition.
I don't know if I should use yet another Alpha value for that.
But that is what my head is currently spinning around and which won't work as I get crazy colors.
Re: How do I interpolate 2 animations
Could somebody tell me (reliably) how to do this? This would help me really much.
Already knowing how to fade color 1 out and color 2 in using alpha would be helpful.
Re: How do I interpolate 2 animations
Quote:
Originally Posted by
tmighty2
Could somebody tell me (reliably) how to do this?
As far as "blending between 2 colors" is the problem -
I don't see "two animations" - but only one instead:
Below is a demo for an empty Form (Project needs an RC6-reference) -
...a Form_Click starts an animation from Blue(0.7) to Red(0.7)...
Code:
Option Explicit
Private WithEvents E As cEasing, CC As cCairoContext
Private C1 As Long, A1 As Double, C2 As Long, A2 As Double
Private Sub Form_Load()
Set E = New_c.Easing
Set CC = Cairo.CreateSurface(256, 256).CreateContext
End Sub
Private Sub Form_Click()
C1 = vbBlue: A1 = 0.7 'start-color and start-alpha
C2 = vbRed: A2 = 0.7 'end-color and end-alpha
'now we use the Animate-HelperMethod in "non-Ctl-bound mode" with 1.5sec duration...
E.Animate Nothing, 0, 0, 0, 0, 0, 0, 0, 0, _
1.5, easeCubic, easeIn '...meaning, the above line contains all Zero-Params
End Sub
Private Sub E_AnimationProgress(ByVal DurationPerc As Double, ByVal EaseRes As Double)
Caption = Format$(DurationPerc, "0%")
RedrawWith EaseRes
End Sub
Private Sub E_AnimationFinished()
Caption = Format$(1, "0%")
RedrawWith 1
End Sub
Sub RedrawWith(ByVal EaseRes As Double)
CC.Paint 1, Cairo.CreateCheckerPattern
CC.Arc CC.Surface.Width / 2, CC.Surface.Height / 2, 100
CC.Fill True, Cairo.CreateSolidPatternLng(C1, A1 * (1 - EaseRes)) 'use the Alpha-Param "multiplicative"
CC.Fill False, Cairo.CreateSolidPatternLng(C2, A2 * EaseRes) 'use the Alpha-Param "multiplicative"
Set Picture = CC.Surface.Picture
End Sub
Olaf
Re: How do I interpolate 2 animations
Thank you. This demo is very nice.
I was however trying to get to know what would be a legitimate way to really get a new color instead of drawing 2 colors over each other.
Here is what I came up with:
Code:
Public Sub CombineTransitionColorsWithAlpha(ByVal uStartColor As Long, ByVal uStartAlpha As Double, ByVal uTargetColor As Long, ByVal uTargetAlpha As Double, ByVal uProgress As Double, ByRef uResultRGB As Long, ByRef uResultAlpha As Double)
Dim r1 As Integer, g1 As Integer, b1 As Integer
Dim r2 As Integer, g2 As Integer, b2 As Integer
Dim rBlend As Integer, gBlend As Integer, bBlend As Integer
Dim effectiveStartAlpha As Double, effectiveTargetAlpha As Double
Dim combinedAlpha As Double
If uProgress < 0 Or uProgress > 1 Then
Debug.Assert False
Exit Sub
End If
' Extract RGB components from uStartColor
r1 = uStartColor And &HFF
g1 = (uStartColor \ &H100) And &HFF
b1 = (uStartColor \ &H10000) And &HFF
' Extract RGB components from uTargetColor
r2 = uTargetColor And &HFF
g2 = (uTargetColor \ &H100) And &HFF
b2 = (uTargetColor \ &H10000) And &HFF
' Calculate effective alpha for each color based on progress
effectiveStartAlpha = uStartAlpha * (1 - uProgress) ' Fade out the start color
effectiveTargetAlpha = uTargetAlpha * uProgress ' Fade in the target color
' Calculate combined alpha (final alpha for the blended color)
combinedAlpha = effectiveStartAlpha + effectiveTargetAlpha
' Blend RGB components based on the effective alpha of each color
If combinedAlpha > 0 Then
rBlend = (r1 * effectiveStartAlpha + r2 * effectiveTargetAlpha) / combinedAlpha
gBlend = (g1 * effectiveStartAlpha + g2 * effectiveTargetAlpha) / combinedAlpha
bBlend = (b1 * effectiveStartAlpha + b2 * effectiveTargetAlpha) / combinedAlpha
Else
rBlend = 0
gBlend = 0
bBlend = 0
End If
' Ensure RGB values are within valid range [0, 255]
rBlend = IIf(rBlend > 255, 255, IIf(rBlend < 0, 0, rBlend))
gBlend = IIf(gBlend > 255, 255, IIf(gBlend < 0, 0, gBlend))
bBlend = IIf(bBlend > 255, 255, IIf(bBlend < 0, 0, bBlend))
' Return the blended RGB and alpha results
uResultRGB = RGB(CLng(rBlend), CLng(gBlend), CLng(bBlend))
uResultAlpha = combinedAlpha
End Sub