tracksperanto 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/.DS_Store +0 -0
  2. data/History.txt +11 -0
  3. data/Manifest.txt +64 -20
  4. data/README.txt +82 -30
  5. data/Rakefile +1 -0
  6. data/bin/tracksperanto +21 -14
  7. data/lib/export/base.rb +16 -6
  8. data/lib/export/match_mover.rb +40 -0
  9. data/lib/export/nuke_script.rb +78 -0
  10. data/lib/export/pftrack.rb +14 -14
  11. data/lib/export/shake_text.rb +7 -8
  12. data/lib/export/syntheyes.rb +9 -5
  13. data/lib/import/base.rb +45 -12
  14. data/lib/import/flame_stabilizer.rb +17 -32
  15. data/lib/import/match_mover.rb +65 -0
  16. data/lib/import/nuke_script.rb +96 -0
  17. data/lib/import/pftrack.rb +9 -2
  18. data/lib/import/shake_grammar/catcher.rb +56 -0
  19. data/lib/import/shake_grammar/lexer.rb +95 -0
  20. data/lib/import/shake_script.rb +189 -103
  21. data/lib/import/shake_text.rb +5 -3
  22. data/lib/import/syntheyes.rb +9 -2
  23. data/lib/middleware/base.rb +6 -1
  24. data/lib/middleware/golden.rb +7 -0
  25. data/lib/middleware/reformat.rb +10 -3
  26. data/lib/middleware/scaler.rb +14 -4
  27. data/lib/middleware/shift.rb +10 -0
  28. data/lib/middleware/slipper.rb +3 -0
  29. data/lib/pipeline/base.rb +111 -37
  30. data/lib/tracksperanto/block_init.rb +7 -0
  31. data/lib/tracksperanto/casts.rb +31 -0
  32. data/lib/tracksperanto/format_detector.rb +35 -0
  33. data/lib/tracksperanto/keyframe.rb +31 -0
  34. data/lib/tracksperanto/safety.rb +20 -0
  35. data/lib/tracksperanto/tracker.rb +38 -0
  36. data/lib/tracksperanto/zip_tuples.rb +20 -0
  37. data/lib/tracksperanto.rb +13 -100
  38. data/test/.DS_Store +0 -0
  39. data/test/export/.DS_Store +0 -0
  40. data/test/export/README_EXPORT_TESTS.txt +15 -0
  41. data/test/export/samples/ref_NukeScript.nk +25 -0
  42. data/test/export/samples/ref_NukeScript.nk.autosave +77 -0
  43. data/test/export/samples/ref_PFTrack.2dt +50 -0
  44. data/test/export/samples/ref_ShakeText.txt +48 -0
  45. data/test/export/samples/ref_Syntheyes.txt +42 -0
  46. data/test/export/samples/ref_matchmover.rz2 +52 -0
  47. data/test/export/test_match_mover_export.rb +16 -0
  48. data/test/export/test_mux.rb +23 -0
  49. data/test/export/test_nuke_export.rb +22 -0
  50. data/test/export/test_pftrack_export.rb +19 -0
  51. data/test/export/test_shake_export.rb +15 -0
  52. data/test/export/test_syntheyes_export.rb +15 -0
  53. data/test/helper.rb +85 -2
  54. data/test/import/.DS_Store +0 -0
  55. data/test/{samples → import/samples}/.DS_Store +0 -0
  56. data/test/{samples → import/samples}/flyover2DP_syntheyes.txt +0 -0
  57. data/test/import/samples/four_tracks_in_one_matchmove.shk +323 -0
  58. data/test/import/samples/four_tracks_in_one_stabilizer.shk +321 -0
  59. data/test/{samples → import/samples}/fromCombustion_fromMidClip_wSnap.stabilizer +0 -0
  60. data/test/{samples → import/samples}/hugeFlameSetup.stabilizer +0 -0
  61. data/test/import/samples/kipPointsMatchmover.rz2 +523 -0
  62. data/test/{samples → import/samples}/megaTrack.action.3dtrack.stabilizer +0 -0
  63. data/test/{samples → import/samples}/one_shake_tracker.txt +0 -0
  64. data/test/{samples → import/samples}/one_shake_tracker_from_first.txt +0 -0
  65. data/test/import/samples/one_tracker_with_break.nk +71 -0
  66. data/test/import/samples/one_tracker_with_break_in_grp.nk +91 -0
  67. data/test/{samples → import/samples}/shake_tracker_nodes.shk +0 -0
  68. data/test/{samples → import/samples}/shake_tracker_nodes_to_syntheyes.txt +0 -0
  69. data/test/{samples → import/samples}/sourcefile_pftrack.2dt +0 -0
  70. data/test/{samples → import/samples}/three_tracks_in_one_stabilizer.shk +0 -0
  71. data/test/{samples → import/samples}/two_shake_trackers.txt +0 -0
  72. data/test/{samples → import/samples}/two_tracks_in_one_tracker.shk +0 -0
  73. data/test/{test_flame_import.rb → import/test_flame_import.rb} +15 -9
  74. data/test/import/test_match_mover_import.rb +44 -0
  75. data/test/import/test_nuke_import.rb +63 -0
  76. data/test/{test_pftrack_import.rb → import/test_pftrack_import.rb} +10 -4
  77. data/test/import/test_shake_catcher.rb +72 -0
  78. data/test/import/test_shake_lexer.rb +95 -0
  79. data/test/import/test_shake_script_import.rb +75 -0
  80. data/test/{test_shake_text_import.rb → import/test_shake_text_import.rb} +10 -3
  81. data/test/{test_syntheyes_import.rb → import/test_syntheyes_import.rb} +8 -3
  82. data/test/middleware/test_golden_middleware.rb +32 -0
  83. data/test/middleware/test_reformat_middleware.rb +35 -0
  84. data/test/middleware/test_scaler_middleware.rb +51 -0
  85. data/test/middleware/test_shift_middleware.rb +26 -0
  86. data/test/middleware/test_slip_middleware.rb +31 -0
  87. data/test/pipeline/test_pipeline_base.rb +14 -0
  88. data/test/test_format_detector.rb +39 -0
  89. data/test/test_tracker.rb +48 -0
  90. data/tracksperanto.gemspec +9 -7
  91. metadata +101 -30
  92. data/lib/middleware/close.rb +0 -6
  93. data/test/test_shake_export.rb +0 -58
  94. data/test/test_shake_script_import.rb +0 -50
@@ -0,0 +1,7 @@
1
+ # Implements the conventional constructor with "hash of attributes" and block support
2
+ module Tracksperanto::BlockInit
3
+ def initialize(object_attribute_hash = {})
4
+ object_attribute_hash.map { |(k, v)| send("#{k}=", v) }
5
+ yield(self) if block_given?
6
+ end
7
+ end
@@ -0,0 +1,31 @@
1
+ # Helps to define things that will forcibly become floats, integers or strings
2
+ module Tracksperanto::Casts
3
+ def self.included(into)
4
+ into.extend(self)
5
+ super
6
+ end
7
+
8
+ # Same as attr_accessor but will always convert to Float internally
9
+ def cast_to_float(*attributes)
10
+ attributes.each do | an_attr |
11
+ define_method(an_attr) { instance_variable_get("@#{an_attr}").to_f }
12
+ define_method("#{an_attr}=") { |to| instance_variable_set("@#{an_attr}", to.to_f) }
13
+ end
14
+ end
15
+
16
+ # Same as attr_accessor but will always convert to Integer/Bignum internally
17
+ def cast_to_int(*attributes)
18
+ attributes.each do | an_attr |
19
+ define_method(an_attr) { instance_variable_get("@#{an_attr}").to_i }
20
+ define_method("#{an_attr}=") { |to| instance_variable_set("@#{an_attr}", to.to_i) }
21
+ end
22
+ end
23
+
24
+ # Same as attr_accessor but will always convert to String internally
25
+ def cast_to_string(*attributes)
26
+ attributes.each do | an_attr |
27
+ define_method(an_attr) { instance_variable_get("@#{an_attr}").to_s }
28
+ define_method("#{an_attr}=") { |to| instance_variable_set("@#{an_attr}", to.to_s) }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,35 @@
1
+ # Finds a suitable importer for the chosen file path. Or at least tries to, based on the file extension.
2
+ # Will then examine all the importers and ask them if they can handle the specified file
3
+ class Tracksperanto::FormatDetector
4
+ def initialize(with_path)
5
+ perform_detection(with_path)
6
+ freeze
7
+ end
8
+
9
+ private
10
+ def perform_detection(for_path)
11
+ ext = File.extname(for_path.downcase)
12
+ @importer_klass = Tracksperanto.importers.find{ |i| i.distinct_file_ext == ext }
13
+ end
14
+ public
15
+
16
+ # Tells if an importer has been found for this extension
17
+ def match?
18
+ !!@importer_klass
19
+ end
20
+
21
+ # Returns the importer if there is one
22
+ def importer_klass
23
+ @importer_klass
24
+ end
25
+
26
+ # Tells if comp size needs to be provided
27
+ def auto_size?
28
+ match? ? importer_klass.autodetects_size? : false
29
+ end
30
+
31
+ # Returns the human name of the importer
32
+ def human_importer_name
33
+ match? ? importer_klass.human_name : "Unknown format"
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ # Internal representation of a keyframe, that carries info on the frame location in the clip, x y and residual
2
+ # Frame numbers start from zero (frame 0 is first frame of the clip).
3
+ # Tracksperanto uses Shake coordinates as base. Image is Y-positive, X-positive, absolute
4
+ # pixel values up and right (zero is in the lower left corner). Some apps use a different
5
+ # coordinate system so translation will take place on import or on export, respectively.
6
+ # We also use residual and not correlation (residual is how far the tracker strolls away,
7
+ # correlation is how sure the tracker is about what it's doing). Residual is the inverse of
8
+ # correlation (with total correlation of one the residual excursion becomes zero).
9
+ class Tracksperanto::Keyframe
10
+ include Tracksperanto::Casts
11
+ include Tracksperanto::BlockInit
12
+
13
+ # Absolute integer frame where this keyframe is placed, 0 based
14
+ attr_accessor :frame
15
+
16
+ # Absolute float X value of the point, zero is lower left
17
+ attr_accessor :abs_x
18
+
19
+ # Absolute float Y value of the point, zero is lower left
20
+ attr_accessor :abs_y
21
+
22
+ # Absolute float residual (0 is "spot on")
23
+ attr_accessor :residual
24
+
25
+ cast_to_float :abs_x, :abs_y, :residual
26
+ cast_to_int :frame
27
+
28
+ def inspect
29
+ [frame, abs_x, abs_y].inspect
30
+ end
31
+ end
@@ -0,0 +1,20 @@
1
+ # Implements the +safe_reader+ class method which will define (or override) readers that
2
+ # raise if ivar is nil
3
+ module Tracksperanto::Safety
4
+ def self.included(into)
5
+ into.extend(self)
6
+ super
7
+ end
8
+
9
+ # Inject a reader that checks for nil
10
+ def safe_reader(*attributes)
11
+ attributes.each do | an_attr |
12
+ alias_method "#{an_attr}_without_nil_protection", an_attr
13
+ define_method(an_attr) do
14
+ val = send("#{an_attr}_without_nil_protection")
15
+ raise "Expected #{an_attr} on #{self} not to be nil" if val.nil?
16
+ val
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,38 @@
1
+ # Internal representation of a tracker point with keyframes. A Tracker is an array of Keyframe objects and should act and work like one
2
+ class Tracksperanto::Tracker < DelegateClass(Array)
3
+ include Tracksperanto::Casts
4
+ include Comparable
5
+
6
+ # Contains the name of the tracker
7
+ attr_accessor :name
8
+ cast_to_string :name
9
+
10
+ def initialize(object_attribute_hash = {})
11
+ @name = "Tracker"
12
+ __setobj__(Array.new)
13
+ object_attribute_hash.map { |(k, v)| send("#{k}=", v) }
14
+ yield(self) if block_given?
15
+ end
16
+
17
+ def keyframes=(new_kf_array)
18
+ __setobj__(new_kf_array.dup)
19
+ end
20
+
21
+ def keyframes
22
+ __getobj__
23
+ end
24
+
25
+ # Trackers sort by the position of the first keyframe
26
+ def <=>(other_tracker)
27
+ self[0].frame <=> other_tracker[0].frame
28
+ end
29
+
30
+ # Create and save a keyframe in this tracker
31
+ def keyframe!(options)
32
+ push(Tracksperanto::Keyframe.new(options))
33
+ end
34
+
35
+ def inspect
36
+ "<T #{name.inspect} with #{length} keyframes>"
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ # Implements the zip_curve_tuples method
2
+ module Tracksperanto::ZipTuples
3
+ # Zip arrays of "value at" tuples into an array of "values at" tuples.
4
+ # The first value of each tuple will be the frame number
5
+ # and keyframes which are not present in all arrays will be discarded. For example:
6
+ #
7
+ # zip_curve_tuples( [[0, 12], [1, 23]], [[1, 12]]) #=> [[1, 23, 12]]
8
+ #
9
+ def zip_curve_tuples(*curves)
10
+ tuples = []
11
+ curves.each do | curve |
12
+ curve.each do | keyframe |
13
+ frame, value = keyframe
14
+ tuples[frame] ? tuples[frame].push(value) : (tuples[frame] = [frame, value])
15
+ end
16
+ end
17
+
18
+ tuples.compact.reject{|e| e.length < (curves.length + 1) }
19
+ end
20
+ end
data/lib/tracksperanto.rb CHANGED
@@ -1,5 +1,10 @@
1
+ require 'stringio'
2
+ require 'delegate'
3
+
4
+
1
5
  module Tracksperanto
2
- VERSION = '1.1.1'
6
+ PATH = File.expand_path(File.dirname(__FILE__))
7
+ VERSION = '1.2.0'
3
8
 
4
9
  module Import; end
5
10
  module Export; end
@@ -15,110 +20,18 @@ module Tracksperanto
15
20
 
16
21
  # Returns the array of all available middlewares
17
22
  attr_accessor :middlewares
18
- end
19
- self.exporters, self.importers, self.middlewares = [], [], []
20
-
21
- # Helps to define things that will forcibly become floats, integers or strings
22
- module Casts
23
- def self.included(into)
24
- into.extend(self)
25
- super
26
- end
27
-
28
- # Same as attr_accessor but will always convert to Float internally
29
- def cast_to_float(*attributes)
30
- attributes.each do | an_attr |
31
- define_method(an_attr) { instance_variable_get("@#{an_attr}").to_f }
32
- define_method("#{an_attr}=") { |to| instance_variable_set("@#{an_attr}", to.to_f) }
33
- end
34
- end
35
23
 
36
- # Same as attr_accessor but will always convert to Integer/Bignum internally
37
- def cast_to_int(*attributes)
38
- attributes.each do | an_attr |
39
- define_method(an_attr) { instance_variable_get("@#{an_attr}").to_i }
40
- define_method("#{an_attr}=") { |to| instance_variable_set("@#{an_attr}", to.to_i) }
41
- end
42
- end
43
-
44
- # Same as attr_accessor but will always convert to String internally
45
- def cast_to_string(*attributes)
46
- attributes.each do | an_attr |
47
- define_method(an_attr) { instance_variable_get("@#{an_attr}").to_s }
48
- define_method("#{an_attr}=") { |to| instance_variable_set("@#{an_attr}", to.to_s) }
49
- end
50
- end
51
- end
52
-
53
- module Safety
54
- def self.included(into)
55
- into.extend(self)
56
- super
57
- end
58
-
59
- # Inject a reader that checks for nil
60
- def safe_reader(*attributes)
61
- attributes.each do | an_attr |
62
- alias_method "#{an_attr}_without_nil_protection", an_attr
63
- define_method(an_attr) do
64
- val = send("#{an_attr}_without_nil_protection")
65
- raise "Expected #{an_attr} on #{self} not to be nil" if val.nil?
66
- val
67
- end
68
- end
69
- end
70
- end
71
-
72
- module BlockInit
73
- def initialize(evt_hash = {})
74
- evt_hash.map { |(k, v)| send("#{k}=", v) }
75
- yield(self) if block_given?
24
+ # Returns the names of all the importers
25
+ def importer_names
26
+ importers.map{|e| e.to_s.split('::').pop }
76
27
  end
77
28
  end
29
+ self.exporters, self.importers, self.middlewares = [], [], []
78
30
 
79
- # Internal representation of a tracker
80
- class Tracker
81
- include Casts
82
- include BlockInit
31
+ end
83
32
 
84
- # Contains the array of all Keyframe objects for this tracker
85
- attr_accessor :name
86
-
87
- # Contains the array of all Keyframe objects for this tracker
88
- attr_accessor :keyframes
89
-
90
- cast_to_string :name
91
-
92
- def initialize(h = {})
93
- @name, @keyframes = 'Tracker', []
94
- super
95
- end
96
- end
97
-
98
- # Internal representation of a keyframe
99
- class Keyframe
100
- include Casts
101
- include BlockInit
102
-
103
- # Absolute integer frame where this keyframe is placed, 0 based
104
- attr_accessor :frame
105
-
106
- # Absolute float X value of the point, zero is lower left
107
- attr_accessor :abs_x
108
-
109
- # Absolute float Y value of the point, zero is lower left
110
- attr_accessor :abs_y
111
-
112
- # Absolute float residual (0 is "spot on")
113
- attr_accessor :residual
114
-
115
- cast_to_float :abs_x, :abs_y, :residual
116
- cast_to_int :frame
117
-
118
- def inspect
119
- [frame, abs_x, abs_y].inspect
120
- end
121
- end
33
+ %w( casts block_init safety zip_tuples keyframe tracker format_detector).each do | submodule |
34
+ require File.join(Tracksperanto::PATH, "tracksperanto", submodule)
122
35
  end
123
36
 
124
37
  # Load importers
data/test/.DS_Store CHANGED
Binary file
Binary file
@@ -0,0 +1,15 @@
1
+ Export tests are conformance tests. That means that:
2
+
3
+ 1) An export is made using Tracksperanto
4
+ 2) This export gets checked by importing it into the main app
5
+ that accepts such files
6
+ 3) The export is compared with Tracksperanto output in the test
7
+
8
+ This means that unless you own an app that accepts this particular format
9
+ you cannot overwrite the export with your own since you got no way to verify
10
+ that the export works
11
+
12
+ The current test set consists of the two parabolic curves that cross. The second
13
+ parabolic curve goes left, the first one - right, and they start at opposite
14
+ corners of the reference 1920x1080 export. At the first point the track has the residual of 0,
15
+ at the end of the curve - the biggest residual (PFTrack marks it red exactly at the last keyframe)
@@ -0,0 +1,25 @@
1
+
2
+ version 5.1200
3
+ Constant {
4
+ inputs 0
5
+ channels rgb
6
+ format "1920 1080 0 0 1920 1080 1"
7
+ name CompSize_1920x1080
8
+ postage_stamp false
9
+ xpos 0
10
+ ypos -60
11
+ }
12
+
13
+ Tracker3 {
14
+ track1 {{curve i x1 0.0000 96.0000 192.0000 288.0000 384.0000 480.0000 576.0000 672.0000 768.0000 864.0000 960.0000 1056.0000 1152.0000 1248.0000 1344.0000 1440.0000 1536.0000 1632.0000 1728.0000 1824.0000 1920.0000} {curve i x1 1080.0000 874.8000 691.2000 529.2000 388.8000 270.0000 172.8000 97.2000 43.2000 10.8000 0.0000 10.8000 43.2000 97.2000 172.8000 270.0000 388.8000 529.2000 691.2000 874.8000 1080.0000}}
15
+ name Parabolic_1_from_top_left
16
+ xpos 0
17
+ ypos 30
18
+ }
19
+
20
+ Tracker3 {
21
+ track1 {{curve i x1 1920.0000 1824.0000 1728.0000 1632.0000 1536.0000 1440.0000 1344.0000 1248.0000 1152.0000 1056.0000 960.0000 864.0000 768.0000 672.0000 576.0000 480.0000 384.0000 288.0000 192.0000 96.0000 0.0000} {curve i x1 0.0000 205.2000 388.8000 550.8000 691.2000 810.0000 907.2000 982.8000 1036.8000 1069.2000 1080.0000 1069.2000 1036.8000 982.8000 907.2000 810.0000 691.2000 550.8000 388.8000 205.2000 0.0000}}
22
+ name Parabolic_2_from_bottom_right
23
+ xpos 0
24
+ ypos 60
25
+ }
@@ -0,0 +1,77 @@
1
+ #! /Applications/Nuke5.1v2/Nuke5.1v2.app/Contents/MacOS/Nuke5.1v2 -nx
2
+ version 5.1200
3
+ define_window_layout_xml {<?xml version="1.0" encoding="UTF-8"?>
4
+ <layout version="1.0">
5
+ <window x="0" y="22" w="1680" h="1024" screen="0">
6
+ <splitter orientation="1">
7
+ <split size="1062"></split>
8
+ <splitter orientation="1">
9
+ <split size="40"></split>
10
+ <dock id="" hideTitles="1" activePageId="Toolbar.1">
11
+ <page id="Toolbar.1"></page>
12
+ </dock>
13
+ <split size="1018"></split>
14
+ <splitter orientation="2">
15
+ <split size="499"></split>
16
+ <dock id="" activePageId="Viewer.1">
17
+ <page id="Viewer.1"></page>
18
+ </dock>
19
+ <split size="499"></split>
20
+ <dock id="" activePageId="Curve Editor.1">
21
+ <page id="DAG.1"></page>
22
+ <page id="Curve Editor.1"></page>
23
+ </dock>
24
+ </splitter>
25
+ </splitter>
26
+ <split size="614"></split>
27
+ <dock id="" activePageId="Properties.1">
28
+ <page id="Properties.1"></page>
29
+ </dock>
30
+ </splitter>
31
+ </window>
32
+ </layout>
33
+ }
34
+ Root {
35
+ inputs 0
36
+ name /Code/apps/tracksperanto/test/export/samples/ref_NukeScript.nk
37
+ frame 11
38
+ format "640 480 0 0 640 480 1 PC_Video"
39
+ proxy_format "640 480 0 0 640 480 1 PC_Video"
40
+ }
41
+ Constant {
42
+ inputs 0
43
+ channels rgb
44
+ format "1920 1080 0 0 1920 1080 1 HD"
45
+ name CompSize_1920x1080
46
+ xpos 0
47
+ ypos -60
48
+ postage_stamp false
49
+ }
50
+ Tracker3 {
51
+ track1 {{curve x1 0 96 192 288 384 480 576 672 768 864 960 1056 1152 1248 1344 1440 1536 1632 1728 1824 1920} {curve x1 1080 874.8 691.2 529.2 388.8 270 172.8 97.2 43.2 10.8 0 10.8 43.2 97.2 172.8 270 388.8 529.2 691.2 874.8 1080}}
52
+ translate {{curve x1 0 96 192 288 384 480 576 672 768 864 960 1056 1152 1248 1344 1440 1536 1632 1728 1824 1920} {curve x1 0 -205.2000122 -388.7999878 -550.7999878 -691.2000122 -810 -907.2000122 -982.7999878 -1036.800049 -1069.199951 -1080 -1069.199951 -1036.800049 -982.7999878 -907.2000122 -810 -691.2000122 -550.7999878 -388.7999878 -205.2000122 0}}
53
+ center {{curve x1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} {curve x1 1080 1080 1080 1080 1080 1080 1080 1080 1080 1080 1080 1080 1080 1080 1080 1080 1080 1080 1080 1080 1080}}
54
+ name Parabolic_1_from_top_left
55
+ xpos 0
56
+ ypos 30
57
+ }
58
+ Tracker3 {
59
+ track1 {{curve i x1 1920 1824 1728 1632 1536 1440 1344 1248 1152 1056 960 864 768 672 576 480 384 288 192 96 0} {curve i x1 0 205.2 388.8 550.8 691.2 810 907.2 982.8 1036.8 1069.2 1080 1069.2 1036.8 982.8 907.2 810 691.2 550.8 388.8 205.2 0}}
60
+ center {320 240}
61
+ name Parabolic_2_from_bottom_right
62
+ xpos 0
63
+ ypos 60
64
+ }
65
+ Viewer {
66
+ frame 11
67
+ name Viewer1
68
+ xpos 0
69
+ ypos 87
70
+ }
71
+ Viewer {
72
+ inputs 0
73
+ name Viewer2
74
+ selected true
75
+ xpos 22
76
+ ypos 67
77
+ }
@@ -0,0 +1,50 @@
1
+
2
+
3
+ "Parabolic_1_from_top_left"
4
+ 21
5
+ 0 0.000 1080.000 0.000
6
+ 1 96.000 874.800 0.006
7
+ 2 192.000 691.200 0.012
8
+ 3 288.000 529.200 0.018
9
+ 4 384.000 388.800 0.024
10
+ 5 480.000 270.000 0.030
11
+ 6 576.000 172.800 0.036
12
+ 7 672.000 97.200 0.042
13
+ 8 768.000 43.200 0.048
14
+ 9 864.000 10.800 0.054
15
+ 10 960.000 0.000 0.060
16
+ 11 1056.000 10.800 0.065
17
+ 12 1152.000 43.200 0.071
18
+ 13 1248.000 97.200 0.077
19
+ 14 1344.000 172.800 0.083
20
+ 15 1440.000 270.000 0.089
21
+ 16 1536.000 388.800 0.095
22
+ 17 1632.000 529.200 0.101
23
+ 18 1728.000 691.200 0.107
24
+ 19 1824.000 874.800 0.113
25
+ 20 1920.000 1080.000 0.119
26
+
27
+
28
+ "Parabolic_2_from_bottom_right"
29
+ 21
30
+ 0 1920.000 0.000 0.000
31
+ 1 1824.000 205.200 0.006
32
+ 2 1728.000 388.800 0.012
33
+ 3 1632.000 550.800 0.018
34
+ 4 1536.000 691.200 0.024
35
+ 5 1440.000 810.000 0.030
36
+ 6 1344.000 907.200 0.036
37
+ 7 1248.000 982.800 0.042
38
+ 8 1152.000 1036.800 0.048
39
+ 9 1056.000 1069.200 0.054
40
+ 10 960.000 1080.000 0.060
41
+ 11 864.000 1069.200 0.065
42
+ 12 768.000 1036.800 0.071
43
+ 13 672.000 982.800 0.077
44
+ 14 576.000 907.200 0.083
45
+ 15 480.000 810.000 0.089
46
+ 16 384.000 691.200 0.095
47
+ 17 288.000 550.800 0.101
48
+ 18 192.000 388.800 0.107
49
+ 19 96.000 205.200 0.113
50
+ 20 0.000 0.000 0.119
@@ -0,0 +1,48 @@
1
+ TrackName Parabolic_1_from_top_left
2
+ Frame X Y Correlation
3
+ 1.00 0.000 1080.000 1.000
4
+ 2.00 96.000 874.800 0.952
5
+ 3.00 192.000 691.200 0.905
6
+ 4.00 288.000 529.200 0.857
7
+ 5.00 384.000 388.800 0.810
8
+ 6.00 480.000 270.000 0.762
9
+ 7.00 576.000 172.800 0.714
10
+ 8.00 672.000 97.200 0.667
11
+ 9.00 768.000 43.200 0.619
12
+ 10.00 864.000 10.800 0.571
13
+ 11.00 960.000 0.000 0.524
14
+ 12.00 1056.000 10.800 0.476
15
+ 13.00 1152.000 43.200 0.429
16
+ 14.00 1248.000 97.200 0.381
17
+ 15.00 1344.000 172.800 0.333
18
+ 16.00 1440.000 270.000 0.286
19
+ 17.00 1536.000 388.800 0.238
20
+ 18.00 1632.000 529.200 0.190
21
+ 19.00 1728.000 691.200 0.143
22
+ 20.00 1824.000 874.800 0.095
23
+ 21.00 1920.000 1080.000 0.048
24
+
25
+ TrackName Parabolic_2_from_bottom_right
26
+ Frame X Y Correlation
27
+ 1.00 1920.000 0.000 1.000
28
+ 2.00 1824.000 205.200 0.952
29
+ 3.00 1728.000 388.800 0.905
30
+ 4.00 1632.000 550.800 0.857
31
+ 5.00 1536.000 691.200 0.810
32
+ 6.00 1440.000 810.000 0.762
33
+ 7.00 1344.000 907.200 0.714
34
+ 8.00 1248.000 982.800 0.667
35
+ 9.00 1152.000 1036.800 0.619
36
+ 10.00 1056.000 1069.200 0.571
37
+ 11.00 960.000 1080.000 0.524
38
+ 12.00 864.000 1069.200 0.476
39
+ 13.00 768.000 1036.800 0.429
40
+ 14.00 672.000 982.800 0.381
41
+ 15.00 576.000 907.200 0.333
42
+ 16.00 480.000 810.000 0.286
43
+ 17.00 384.000 691.200 0.238
44
+ 18.00 288.000 550.800 0.190
45
+ 19.00 192.000 388.800 0.143
46
+ 20.00 96.000 205.200 0.095
47
+ 21.00 0.000 0.000 0.048
48
+
@@ -0,0 +1,42 @@
1
+ Parabolic_1_from_top_left 0 -1.000000 -1.000000 30
2
+ Parabolic_1_from_top_left 1 -0.900000 -0.620000 30
3
+ Parabolic_1_from_top_left 2 -0.800000 -0.280000 30
4
+ Parabolic_1_from_top_left 3 -0.700000 0.020000 30
5
+ Parabolic_1_from_top_left 4 -0.600000 0.280000 30
6
+ Parabolic_1_from_top_left 5 -0.500000 0.500000 30
7
+ Parabolic_1_from_top_left 6 -0.400000 0.680000 30
8
+ Parabolic_1_from_top_left 7 -0.300000 0.820000 30
9
+ Parabolic_1_from_top_left 8 -0.200000 0.920000 30
10
+ Parabolic_1_from_top_left 9 -0.100000 0.980000 30
11
+ Parabolic_1_from_top_left 10 0.000000 1.000000 30
12
+ Parabolic_1_from_top_left 11 0.100000 0.980000 30
13
+ Parabolic_1_from_top_left 12 0.200000 0.920000 30
14
+ Parabolic_1_from_top_left 13 0.300000 0.820000 30
15
+ Parabolic_1_from_top_left 14 0.400000 0.680000 30
16
+ Parabolic_1_from_top_left 15 0.500000 0.500000 30
17
+ Parabolic_1_from_top_left 16 0.600000 0.280000 30
18
+ Parabolic_1_from_top_left 17 0.700000 0.020000 30
19
+ Parabolic_1_from_top_left 18 0.800000 -0.280000 30
20
+ Parabolic_1_from_top_left 19 0.900000 -0.620000 30
21
+ Parabolic_1_from_top_left 20 1.000000 -1.000000 30
22
+ Parabolic_2_from_bottom_right 0 1.000000 1.000000 30
23
+ Parabolic_2_from_bottom_right 1 0.900000 0.620000 30
24
+ Parabolic_2_from_bottom_right 2 0.800000 0.280000 30
25
+ Parabolic_2_from_bottom_right 3 0.700000 -0.020000 30
26
+ Parabolic_2_from_bottom_right 4 0.600000 -0.280000 30
27
+ Parabolic_2_from_bottom_right 5 0.500000 -0.500000 30
28
+ Parabolic_2_from_bottom_right 6 0.400000 -0.680000 30
29
+ Parabolic_2_from_bottom_right 7 0.300000 -0.820000 30
30
+ Parabolic_2_from_bottom_right 8 0.200000 -0.920000 30
31
+ Parabolic_2_from_bottom_right 9 0.100000 -0.980000 30
32
+ Parabolic_2_from_bottom_right 10 0.000000 -1.000000 30
33
+ Parabolic_2_from_bottom_right 11 -0.100000 -0.980000 30
34
+ Parabolic_2_from_bottom_right 12 -0.200000 -0.920000 30
35
+ Parabolic_2_from_bottom_right 13 -0.300000 -0.820000 30
36
+ Parabolic_2_from_bottom_right 14 -0.400000 -0.680000 30
37
+ Parabolic_2_from_bottom_right 15 -0.500000 -0.500000 30
38
+ Parabolic_2_from_bottom_right 16 -0.600000 -0.280000 30
39
+ Parabolic_2_from_bottom_right 17 -0.700000 -0.020000 30
40
+ Parabolic_2_from_bottom_right 18 -0.800000 0.280000 30
41
+ Parabolic_2_from_bottom_right 19 -0.900000 0.620000 30
42
+ Parabolic_2_from_bottom_right 20 -1.000000 1.000000 30
@@ -0,0 +1,52 @@
1
+ imageSequence "Sequence 01"
2
+ {
3
+ 1920 1080 f( "D:/temp/sequence.%04d.dpx" ) b( 1 211 1 )
4
+ }
5
+ pointTrack "Parabolic_1_from_top_left" rgb( 255 0 0 )
6
+ {
7
+ 1 0.000 1080.000 ki( 0.8 ) s( 66 66 64 64 ) p( 24 24 25 25 )
8
+ 2 96.000 874.800 p+( 0.952381 )
9
+ 3 192.000 691.200 p+( 0.904762 )
10
+ 4 288.000 529.200 p+( 0.857143 )
11
+ 5 384.000 388.800 p+( 0.809524 )
12
+ 6 480.000 270.000 p+( 0.761905 )
13
+ 7 576.000 172.800 p+( 0.714286 )
14
+ 8 672.000 97.200 p+( 0.666667 )
15
+ 9 768.000 43.200 p+( 0.619048 )
16
+ 10 864.000 10.800 p+( 0.571429 )
17
+ 11 960.000 0.000 p+( 0.523810 )
18
+ 12 1056.000 10.800 p+( 0.476190 )
19
+ 13 1152.000 43.200 p+( 0.428571 )
20
+ 14 1248.000 97.200 p+( 0.380952 )
21
+ 15 1344.000 172.800 p+( 0.333333 )
22
+ 16 1440.000 270.000 p+( 0.285714 )
23
+ 17 1536.000 388.800 p+( 0.238095 )
24
+ 18 1632.000 529.200 p+( 0.190476 )
25
+ 19 1728.000 691.200 p+( 0.142857 )
26
+ 20 1824.000 874.800 p+( 0.095238 )
27
+ 21 1920.000 1080.000 p+( 0.047619 )
28
+ }
29
+ pointTrack "Parabolic_2_from_bottom_right" rgb( 255 0 0 )
30
+ {
31
+ 1 1920.000 0.000 ki( 0.8 ) s( 66 66 64 64 ) p( 24 24 25 25 )
32
+ 2 1824.000 205.200 p+( 0.952381 )
33
+ 3 1728.000 388.800 p+( 0.904762 )
34
+ 4 1632.000 550.800 p+( 0.857143 )
35
+ 5 1536.000 691.200 p+( 0.809524 )
36
+ 6 1440.000 810.000 p+( 0.761905 )
37
+ 7 1344.000 907.200 p+( 0.714286 )
38
+ 8 1248.000 982.800 p+( 0.666667 )
39
+ 9 1152.000 1036.800 p+( 0.619048 )
40
+ 10 1056.000 1069.200 p+( 0.571429 )
41
+ 11 960.000 1080.000 p+( 0.523810 )
42
+ 12 864.000 1069.200 p+( 0.476190 )
43
+ 13 768.000 1036.800 p+( 0.428571 )
44
+ 14 672.000 982.800 p+( 0.380952 )
45
+ 15 576.000 907.200 p+( 0.333333 )
46
+ 16 480.000 810.000 p+( 0.285714 )
47
+ 17 384.000 691.200 p+( 0.238095 )
48
+ 18 288.000 550.800 p+( 0.190476 )
49
+ 19 192.000 388.800 p+( 0.142857 )
50
+ 20 96.000 205.200 p+( 0.095238 )
51
+ 21 0.000 0.000 p+( 0.047619 )
52
+ }
@@ -0,0 +1,16 @@
1
+ require File.dirname(__FILE__) + '/../helper'
2
+
3
+ class MatchmoverExportTest < Test::Unit::TestCase
4
+ include ParabolicTracks
5
+ P = File.dirname(__FILE__) + "/samples/ref_matchmover.rz2"
6
+
7
+ def test_export_output_written
8
+ ensure_same_output Tracksperanto::Export::MatchMover, P
9
+ end
10
+
11
+ def test_exporter_meta
12
+ assert_equal "matchmover.rz2", Tracksperanto::Export::MatchMover.desc_and_extension
13
+ assert_equal "Matchmover 2D export .rz2 file", Tracksperanto::Export::MatchMover.human_name
14
+ end
15
+
16
+ end
@@ -0,0 +1,23 @@
1
+ require File.dirname(__FILE__) + '/../helper'
2
+
3
+ class MuxTest < Test::Unit::TestCase
4
+
5
+ def test_mux_replays
6
+ outs = (0..25).map do
7
+ o = flexmock
8
+ o.should_receive(:start_export).once.with(720, 576)
9
+ o.should_receive(:start_tracker_segment).once.with("FooT")
10
+ o.should_receive(:export_point).once.with(0, 45.0, 67.0, 0.3)
11
+ o.should_receive(:end_tracker_segment).once
12
+ o.should_receive(:end_export).once
13
+ o
14
+ end
15
+
16
+ mux = Tracksperanto::Export::Mux.new(outs)
17
+ mux.start_export(720, 576)
18
+ mux.start_tracker_segment("FooT")
19
+ mux.export_point(0, 45.0, 67.0, 0.3)
20
+ mux.end_tracker_segment
21
+ mux.end_export
22
+ end
23
+ end