class Tracksperanto::Import::ShakeScript::TrackExtractor

Extractor. Here we define copies of Shake's standard node creation functions.

Public Instance Methods

atom_is_tracker_assignment?(a) click to toggle source

An atom that is a tracker node will look like this

:assign, [:vardef, “Stabilize2”], [:retval, [:trk, <T “track1” with 116 keyframes>, <T “track2” with 116 keyframes>, <T “track3” with 116 keyframes>, <T “track4” with 89 keyframes>]]

a Stabilize though will look like this

:assign, [:vardef, “Stabilize1”], [:retval, [:trk, <T “track1” with 116 keyframes>, <T “track2” with 116 keyframes>, <T “track3” with 116 keyframes>]]
# File lib/import/shake_script.rb, line 77
def atom_is_tracker_assignment?(a)
  deep_include?(a, :trk)
end
deep_include?(array_or_element, atom_name) click to toggle source

Find whether the passed atom includes a [:trk] on any level

# File lib/import/shake_script.rb, line 62
def deep_include?(array_or_element, atom_name)
  return false unless array_or_element.is_a?(Array)
  return true if array_or_element[0] == atom_name
  
  array_or_element.each do | elem |
     return true if deep_include?(elem, atom_name)
  end
  
  false
end
hermite(extrapolation_type, *keyframes) click to toggle source

Hermite interpolation looks like this Hermite(0,@1,@2) The first value in the array is the keyframe value, the other two are tangent positions (which we discard)

# File lib/import/shake_script.rb, line 95
def hermite(extrapolation_type, *keyframes)
  report_progress("Translating Hermite curve, removing tangents")
  remap_keyframes_against_negative_at!(keyframes)
  keyframes.map{ |kf| [kf.at, kf.value[0]] }
end
jspline(extrapolation_type, *keyframes)
Alias for: linear
linear(extrapolation_type, *keyframes) click to toggle source

For Linear() curve calls. If someone selected JSpline or Hermite it's his problem. We put the frame number at the beginning since it works witih oru tuple zipper

# File lib/import/shake_script.rb, line 83
def linear(extrapolation_type, *keyframes)
  report_progress("Translating Linear animation")
  remap_keyframes_against_negative_at!(keyframes)
  keyframes.map { |kf| [kf.at , kf.value] }
end
Also aliased as: nspline, jspline
matchmove(bgImage, fgImage, applyTransform, trackType, track1X, track1Y, matchX, matchY, track2X, track2Y, scale, rotation, track3X, track3Y, track4X, track4Y, *others) click to toggle source

image = MatchMove(

 Background,
 Foreground,
 applyTransform,
 "trackType",
 track1X,
 track1Y,
 matchX,
 matchY,
 track2X,
 track2Y,
 scale,
 rotation,
 track3X,
 track3Y,
 track4X,
 track4Y,
 x1, 
 y1,
 x2,
 y2,
 x3,
 y3,
 x4,
 y4,
 "xFilter",
 "yFilter",
 motionBlur, 
 shutterTiming,
 shutterOffset,
 referenceFrame,
 "compositeType",
 clipMode,
"trackRange",
 "subPixelRes",
 "matchSpace",
 float referenceTolerance,
 "referenceBehavior",
 float failureTolerance,
 "failureBehavior",
 int limitProcessing,
 ...

);

# File lib/import/shake_script.rb, line 222
def matchmove(bgImage, fgImage, applyTransform,
  trackType,
  track1X,
  track1Y,
  matchX,
  matchY,
  track2X,
  track2Y,
  scale,
  rotation,
  track3X,
  track3Y,
  track4X,
  track4Y, *others)
  
  report_progress("Parsing MatchMove node")
  [
    collect_stabilizer_tracker("track1", track1X, track1Y),
    collect_stabilizer_tracker("track2", track2X, track2Y),
    collect_stabilizer_tracker("track3", track3X, track3Y),
    collect_stabilizer_tracker("track4", track4X, track4Y),
  ].compact.unshift(:trk)
end
nspline(extrapolation_type, *keyframes)
Alias for: linear
push(atom) click to toggle source

Normally, we wouldn't need to look for the variable name from inside of the funcall. However, in this case we DO want to take this shortcut so we know how the tracker node is called

# File lib/import/shake_script.rb, line 49
def push(atom)
  return super unless atom_is_tracker_assignment?(atom)
  
  node_name = atom[1][-1]
  trackers = atom[2][1][1..-1]
  trackers.map do | tracker |
    tracker.name = [node_name, tracker.name].join("_")
    # THIS IS THE MOST IMPORTANT THINGO
    sentinel.tracker_proc.call(tracker)
  end
end
settimerange(str) click to toggle source

SetTimeRange(“-5-15”) // sets time range of comp We use it to avoid producing keyframes which start at negative frames

# File lib/import/shake_script.rb, line 43
def settimerange(str)
  sentinel.start_frame = str.to_i if str.to_i < 0
end
stabilize(imageIn, applyTransform, inverseTransform, trackType, track1X, track1Y, stabilizeX, stabilizeY, track2X, track2Y, matchScale, matchRotation, track3X, track3Y, track4X, track4Y, *useless_args) click to toggle source

stabilize {

image In,
int applyTransform,
int inverseTransform
const char * trackType,
float track1X,
float track1Y,
int stabilizeX,
int stabilizeY,
float track2X,
float track2Y,
int matchScale,
int matchRotation,
float track3X,
float track3Y,
float track4X,
float track4Y,
const char * xFilter,
const char * yFilter,
const char * transformationOrder,
float motionBlur, 
float shutterTiming,
float shutterOffset,
float referenceFrame,
float aspectRatio,
...

};

# File lib/import/shake_script.rb, line 160
def stabilize(imageIn, applyTransform, inverseTransform, trackType,
  track1X, track1Y,
  stabilizeX, stabilizeY,
  track2X, track2Y,
  matchScale,
  matchRotation,
  track3X, track3Y,
  track4X, track4Y,
  *useless_args)
  
  report_progress("Parsing Stabilize node")
  [
    collect_stabilizer_tracker("track1", track1X, track1Y),
    collect_stabilizer_tracker("track2", track2X, track2Y),
    collect_stabilizer_tracker("track3", track3X, track3Y),
    collect_stabilizer_tracker("track4", track4X, track4Y),
  ].compact.unshift(:trk)
end
tracker(input, trackRange, subPixelRes, matchSpace, referenceTolerance, referenceBehavior, failureTolerance, failureBehavior, limitProcessing, referencFrame, s1, s2, s3, s4, s5, s6, *trackers) click to toggle source

image Tracker(

 image In,
 const char * trackRange,
 const char * subPixelRes,
 const char * matchSpace,
 float referenceTolerance,
 const char * referenceBehavior,
 float failureTolerance,
 const char * failureBehavior,
 int limitProcessing,
 float referencFrame 
 ...
);
# File lib/import/shake_script.rb, line 120
def tracker(input, trackRange, subPixelRes, matchSpace,
    referenceTolerance, referenceBehavior, failureTolerance, failureBehavior, limitProcessing, referencFrame, 
    s1, s2, s3, s4, s5, s6, *trackers)
  flat_tracks = if (s1 == "v2.0") # The Shake version stupid Winfucks users didn't get
    trackers
  else
    [s1, s2, s3, s4, s4, s6] + trackers
  end
  
  report_progress("Parsing Tracker node")
  collect_trackers_from(flat_tracks).unshift(:trk)
end

Private Instance Methods

clean_tuples(frame_and_value_tuples) click to toggle source

Remove tuples which have more than 2 values, and tuples that have non-Numeric members

# File lib/import/shake_script.rb, line 266
def clean_tuples(frame_and_value_tuples)
  frame_and_value_tuples.reject do | element |
    element.length > 2
  end.reject do | element |
    element.any?{|e| !e.is_a?(Numeric) }
  end 
end
collect_stabilizer_tracker(name, x_curve, y_curve) click to toggle source
# File lib/import/shake_script.rb, line 274
def collect_stabilizer_tracker(name, x_curve, y_curve)
  return unless valid_curves?(x_curve, y_curve)
  
  report_progress("Assembling Stabilizer node tracker #{name}")
  
  keyframes = zip_curve_tuples(clean_tuples(x_curve), clean_tuples(y_curve)).map do | (frame, x, y) |
    Tracksperanto::Keyframe.new(:frame => frame - 1, :abs_x => x, :abs_y => y)
  end
  Tracksperanto::Tracker.new(:name => name, :keyframes => keyframes)
end
collect_tracker(name, x_curve, y_curve, corr_curve, *discard) click to toggle source
# File lib/import/shake_script.rb, line 285
def collect_tracker(name, x_curve, y_curve, corr_curve, *discard)
  return unless valid_curves?(x_curve, y_curve)
  
  report_progress("Scavenging tracker #{name}")
  
  curve_set = combine_curves(x_curve, y_curve, corr_curve)
  
  keyframes = zip_curve_tuples(*curve_set).map do | (frame, x, y, corr) |
    Tracksperanto::Keyframe.new(:frame => frame - 1, :abs_x => x, :abs_y => y, :residual => (1 - corr.to_f))
  end
  
  Tracksperanto::Tracker.new(:name => name, :keyframes => keyframes)
end
collect_trackers_from(array) click to toggle source
# File lib/import/shake_script.rb, line 252
def collect_trackers_from(array)
  parameters_per_node = 16
  nb_trackers = array.length / parameters_per_node
  
  (0...nb_trackers).map do | idx |
    from_index, to_index = (idx * parameters_per_node), (idx+1) * parameters_per_node
    tracker_args = array[from_index...to_index]
    tracker_args[0] = "#{tracker_args[0]}"
    collect_tracker(*tracker_args)
  end.compact
end
combine_curves(x, y, corr_curve) click to toggle source
# File lib/import/shake_script.rb, line 299
def combine_curves(x, y, corr_curve)
  curve_set = [x, y]
  curve_set << corr_curve if (corr_curve.respond_to?(:length) && corr_curve.length >= x.length)
  curve_set
end
remap_keyframes_against_negative_at!(kfs) click to toggle source
# File lib/import/shake_script.rb, line 101
def remap_keyframes_against_negative_at!(kfs)
  frame_start_of_script = sentinel.start_frame
  kfs.each{|k| k.at = (k.at - frame_start_of_script) }
end
report_progress(with_message) click to toggle source
# File lib/import/shake_script.rb, line 248
def report_progress(with_message)
  sentinel.progress_proc.call(with_message)
end
valid_curves?(x_curve, y_curve) click to toggle source
# File lib/import/shake_script.rb, line 307
def valid_curves?(x_curve, y_curve)
  return false if (x_curve == :unknown || y_curve == :unknown)
  return false unless x_curve.is_a?(Array) && y_curve.is_a?(Array)
  true
end