interpolate.py (2882B)
1 ### EXESOFT PYIGNITION ### 2 # Copyright David Barker 2010 3 # 4 # Utility module for interpolating between keyframed values 5 6 7 import math 8 from constants import * 9 10 11 def LinearInterpolate(val1, val2, t): 12 diff = val2 - val1 13 dist = float(diff) * t 14 15 return val1 + dist 16 17 def CosineInterpolate(val1, val2, t): 18 amplitude = float(val2 - val1) / 2.0 19 midpoint = float(val1 + val2) / 2.0 20 21 return (amplitude * math.cos(math.pi * (1.0 - t))) + midpoint 22 23 24 def LinearInterpolateKeyframes(curframe, key1, key2, val1, val2): 25 if key1 == key2: 26 return val2 27 28 factor = float(curframe - key1) / float(key2 - key1) 29 30 return LinearInterpolate(val1, val2, factor) 31 32 def CosineInterpolateKeyframes(curframe, key1, key2, val1, val2): 33 if key1 == key2: 34 return val2 35 36 factor = float(curframe - key1) / float(key2 - key1) 37 38 return CosineInterpolate(val1, val2, factor) 39 40 41 def InterpolateKeyframes(curframe, variables, keyframes): 42 if len(keyframes) == 1: 43 return keyframes[0].variables 44 45 finalvariables = {} 46 47 if not ('interpolationtype' in variables): 48 variables['interpolationtype'] = INTERPOLATIONTYPE_LINEAR 49 50 keys = list(variables.keys()) 51 52 for i in range(len(keys)): # Determine current keyframe and next one for this variable 53 key = keys[i] 54 curkeyframe = None 55 nextkeyframe = None 56 57 for i in range(len(keyframes)): 58 try: 59 frame = keyframes[i] 60 if (frame.variables[key] != None): # If the current keyframe has a keyed value for the current variable 61 if frame.frame <= curframe: # If its frame is below or equal to the current, it is the current keyframe 62 curkeyframe = i 63 if (nextkeyframe == None) and (frame.frame > curframe): # If this is the first keyframe with a frame higher than the current, it is the next keyframe 64 nextkeyframe = i 65 except KeyError: 66 pass 67 68 if nextkeyframe == None or key == "interpolationtype": # If there is no next key frame, maintain the value specified by the current one 69 finalvariables[key] = keyframes[curkeyframe].variables[key] # (Also do this if it is an interpolation type variable; they should only change once their next keyframe has been reached 70 71 else: # Interpolate between the current and next keyframes 72 if keyframes[nextkeyframe].variables['interpolationtype'] == INTERPOLATIONTYPE_LINEAR: 73 finalvariables[key] = LinearInterpolateKeyframes(curframe, keyframes[curkeyframe].frame, keyframes[nextkeyframe].frame, keyframes[curkeyframe].variables[key], keyframes[nextkeyframe].variables[key]) 74 elif keyframes[nextkeyframe].variables['interpolationtype'] == INTERPOLATIONTYPE_COSINE: 75 finalvariables[key] = CosineInterpolateKeyframes(curframe, keyframes[curkeyframe].frame, keyframes[nextkeyframe].frame, keyframes[curkeyframe].variables[key], keyframes[nextkeyframe].variables[key]) 76 77 return finalvariables