Browse Source

test, docs updated

Inderjit Gill 7 months ago
parent
commit
e2ea8f29a0

+ 114
- 0
core/sen-core/src/interp.rs View File

@@ -0,0 +1,114 @@
1
+// Copyright (C) 2019 Inderjit Gill
2
+
3
+// This program is free software: you can redistribute it and/or modify
4
+// it under the terms of the GNU General Public License as published by
5
+// the Free Software Foundation, either version 3 of the License, or
6
+// (at your option) any later version.
7
+
8
+// This program is distributed in the hope that it will be useful,
9
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
+// GNU General Public License for more details.
12
+
13
+// You should have received a copy of the GNU General Public License
14
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
15
+
16
+use crate::ease::*;
17
+use crate::mathutil::*;
18
+
19
+pub fn interp_scalar(a: f32, b: f32, mapping: Easing, clamping: bool, t: f32) -> f32 {
20
+    let new_t = easing(t, mapping);
21
+    let res = lerp(new_t, a, b);
22
+
23
+    if clamping {
24
+        if new_t < 0.0 {
25
+            return a;
26
+        } else if new_t > 1.0 {
27
+            return b;
28
+        } else {
29
+            return res;
30
+        }
31
+    }
32
+
33
+    return res;
34
+}
35
+
36
+pub fn interp_cos(amplitude: f32, frequency: f32, t: f32) -> f32 {
37
+    amplitude * (t * frequency).cos()
38
+}
39
+
40
+pub fn interp_sin(amplitude: f32, frequency: f32, t: f32) -> f32 {
41
+    amplitude * (t * frequency).sin()
42
+}
43
+
44
+pub fn interp_bezier(coords: &[f32; 8], t: f32) -> (f32, f32) {
45
+    (
46
+        bezier_point(coords[0], coords[2], coords[4], coords[6], t),
47
+        bezier_point(coords[1], coords[3], coords[5], coords[7], t),
48
+    )
49
+}
50
+
51
+pub fn interp_bezier_tangent(coords: &[f32; 8], t: f32) -> (f32, f32) {
52
+    (
53
+        bezier_tangent(coords[0], coords[2], coords[4], coords[6], t),
54
+        bezier_tangent(coords[1], coords[3], coords[5], coords[7], t),
55
+    )
56
+}
57
+
58
+pub fn interp_circle(position: (f32, f32), radius: f32, t: f32) -> (f32, f32) {
59
+    let angle = t * TAU;
60
+
61
+    (
62
+        (angle.sin() * radius) + position.0,
63
+        (angle.cos() * radius) + position.1,
64
+    )
65
+}
66
+
67
+pub fn interp_ray(point: (f32, f32), direction: (f32, f32), t: f32) -> (f32, f32) {
68
+    // direction should be a normalized vector
69
+    (point.0 + (direction.0 * t), point.1 + (direction.1 * t))
70
+}
71
+
72
+
73
+#[cfg(test)]
74
+mod tests {
75
+    use crate::vm::tests::*;
76
+
77
+    #[test]
78
+    fn test_interp_cos() {
79
+        is_debug_str(
80
+            "(loop (x upto: 5)
81
+                   (probe scalar: (interp/cos t: (/ x 5))))",
82
+            "1 0.9800666 0.921061 0.8253356 0.6967067 0.5403023",
83
+        );
84
+        is_debug_str(
85
+            "(loop (x upto: 5)
86
+                   (probe scalar: (interp/cos amplitude: 3 t: (/ x 5))))",
87
+            "3 2.9401999 2.7631829 2.476007 2.09012 1.6209068",
88
+        );
89
+        is_debug_str(
90
+            "(loop (x upto: 5)
91
+                   (probe scalar: (interp/cos frequency: 7 t: (/ x 5))))",
92
+            "1 0.16996716 -0.9422223 -0.49026057 0.7755658 0.75390226",
93
+        );
94
+    }
95
+
96
+    #[test]
97
+    fn test_interp_sin() {
98
+        is_debug_str(
99
+            "(loop (x upto: 5)
100
+                   (probe scalar: (interp/sin t: (/ x 5))))",
101
+            "0 0.19866933 0.38941833 0.5646425 0.7173561 0.84147096",
102
+        );
103
+        is_debug_str(
104
+            "(loop (x upto: 5)
105
+                   (probe scalar: (interp/sin amplitude: 3 t: (/ x 5))))",
106
+            "0 0.596008 1.168255 1.6939275 2.1520681 2.5244129",
107
+        );
108
+        is_debug_str(
109
+            "(loop (x upto: 5)
110
+                   (probe scalar: (interp/sin frequency: 7 t: (/ x 5))))",
111
+            "0 0.98544973 0.3349882 -0.8715759 -0.6312667 0.6569866",
112
+        );
113
+    }
114
+}

+ 2
- 0
core/sen-core/src/keywords.rs View File

@@ -388,6 +388,8 @@ pub enum Keyword {
388 388
     Volatility,
389 389
     #[strum(serialize = "width")]
390 390
     Width,
391
+    #[strum(serialize = "worldspace")]
392
+    WorldSpace,
391 393
 
392 394
     #[strum(serialize = "UnreachableKeywordEnd")]
393 395
     KeywordEnd,

+ 1
- 1
core/sen-core/src/lib.rs View File

@@ -26,13 +26,13 @@
26 26
 
27 27
 mod colour;
28 28
 mod ease;
29
+mod interp;
29 30
 mod keywords;
30 31
 mod lexer;
31 32
 mod mathutil;
32 33
 mod matrix;
33 34
 mod native;
34 35
 mod opcodes;
35
-mod parametric;
36 36
 mod path;
37 37
 mod placeholder;
38 38
 mod repeat;

+ 18
- 9
core/sen-core/src/native.rs View File

@@ -17,9 +17,9 @@ use crate::colour::{Colour, ColourFormat};
17 17
 use crate::compiler::Program;
18 18
 use crate::ease::*;
19 19
 use crate::error::{Error, Result};
20
+use crate::interp::*;
20 21
 use crate::keywords::Keyword;
21 22
 use crate::mathutil;
22
-use crate::parametric::*;
23 23
 use crate::path::*;
24 24
 use crate::repeat::*;
25 25
 use crate::uvmapper::BrushType;
@@ -657,6 +657,7 @@ pub fn bind_vector_length(vm: &mut Vm, _program: &Program, num_args: usize) -> R
657 657
 pub fn bind_probe(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<Var> {
658 658
     let mut scalar: Option<f32> = None;
659 659
     let mut vector: Option<(f32, f32)> = None;
660
+    let mut worldspace: Option<(f32, f32)> = None;
660 661
 
661 662
     let mut args_pointer = vm.sp - (num_args * 2);
662 663
     for _ in 0..num_args {
@@ -667,6 +668,7 @@ pub fn bind_probe(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<Va
667 668
         if let Var::Int(iname) = label {
668 669
             read_float!(scalar, Keyword::Scalar, iname, value);
669 670
             read_v2d!(vector, Keyword::Vector, iname, value);
671
+            read_v2d!(worldspace, Keyword::WorldSpace, iname, value);
670 672
         }
671 673
     }
672 674
 
@@ -678,6 +680,13 @@ pub fn bind_probe(vm: &mut Vm, _program: &Program, num_args: usize) -> Result<Va
678 680
         vm.debug_str_append(&format!("({},{})", x, y));
679 681
     }
680 682
 
683
+    if let Some((x, y)) = worldspace {
684
+        if let Some(matrix) = vm.matrix_stack.peek() {
685
+            let (nx, ny) = matrix.transform_vec2(x, y);
686
+            vm.debug_str_append(&format!("({},{})", nx, ny));
687
+        }
688
+    }
689
+
681 690
     Ok(Var::Bool(true))
682 691
 }
683 692
 
@@ -1674,7 +1683,7 @@ pub fn bind_interp_cos(vm: &mut Vm, _program: &Program, num_args: usize) -> Resu
1674 1683
         }
1675 1684
     }
1676 1685
 
1677
-    let res = parametric_cos(amplitude.unwrap(), frequency.unwrap(), t.unwrap());
1686
+    let res = interp_cos(amplitude.unwrap(), frequency.unwrap(), t.unwrap());
1678 1687
 
1679 1688
     Ok(Var::Float(res))
1680 1689
 }
@@ -1697,7 +1706,7 @@ pub fn bind_interp_sin(vm: &mut Vm, _program: &Program, num_args: usize) -> Resu
1697 1706
         }
1698 1707
     }
1699 1708
 
1700
-    let res = parametric_sin(amplitude.unwrap(), frequency.unwrap(), t.unwrap());
1709
+    let res = interp_sin(amplitude.unwrap(), frequency.unwrap(), t.unwrap());
1701 1710
 
1702 1711
     Ok(Var::Float(res))
1703 1712
 }
@@ -1719,7 +1728,7 @@ pub fn bind_interp_bezier(vm: &mut Vm, _program: &Program, num_args: usize) -> R
1719 1728
     }
1720 1729
 
1721 1730
     let co = array_f32_8_from_vec(coords.unwrap());
1722
-    let (x, y) = parametric_bezier(&co, t.unwrap());
1731
+    let (x, y) = interp_bezier(&co, t.unwrap());
1723 1732
 
1724 1733
     Ok(Var::V2D(x, y))
1725 1734
 }
@@ -1741,7 +1750,7 @@ pub fn bind_interp_bezier_tangent(vm: &mut Vm, _program: &Program, num_args: usi
1741 1750
     }
1742 1751
 
1743 1752
     let co = array_f32_8_from_vec(coords.unwrap());
1744
-    let (x, y) = parametric_bezier_tangent(&co, t.unwrap());
1753
+    let (x, y) = interp_bezier_tangent(&co, t.unwrap());
1745 1754
 
1746 1755
     Ok(Var::V2D(x, y))
1747 1756
 }
@@ -1764,7 +1773,7 @@ pub fn bind_interp_ray(vm: &mut Vm, _program: &Program, num_args: usize) -> Resu
1764 1773
         }
1765 1774
     }
1766 1775
 
1767
-    let (x, y) = parametric_ray(point.unwrap(), direction.unwrap(), t.unwrap());
1776
+    let (x, y) = interp_ray(point.unwrap(), direction.unwrap(), t.unwrap());
1768 1777
 
1769 1778
     Ok(Var::V2D(x, y))
1770 1779
 }
@@ -1799,8 +1808,8 @@ pub fn bind_interp_line(vm: &mut Vm, _program: &Program, num_args: usize) -> Res
1799 1808
         let clamping_ = clamping.unwrap() == Keyword::True;
1800 1809
         let t_ = t.unwrap();
1801 1810
 
1802
-        let x = parametric_scalar(from_.0, to_.0, mapping, clamping_, t_);
1803
-        let y = parametric_scalar(from_.1, to_.1, mapping, clamping_, t_);
1811
+        let x = interp_scalar(from_.0, to_.0, mapping, clamping_, t_);
1812
+        let y = interp_scalar(from_.1, to_.1, mapping, clamping_, t_);
1804 1813
 
1805 1814
         return Ok(Var::V2D(x, y));
1806 1815
     }
@@ -1826,7 +1835,7 @@ pub fn bind_interp_circle(vm: &mut Vm, _program: &Program, num_args: usize) -> R
1826 1835
         }
1827 1836
     }
1828 1837
 
1829
-    let (x, y) = parametric_circle(position.unwrap(), radius.unwrap(), t.unwrap());
1838
+    let (x, y) = interp_circle(position.unwrap(), radius.unwrap(), t.unwrap());
1830 1839
 
1831 1840
     Ok(Var::V2D(x, y))
1832 1841
 }

+ 0
- 70
core/sen-core/src/parametric.rs View File

@@ -1,70 +0,0 @@
1
-// Copyright (C) 2019 Inderjit Gill
2
-
3
-// This program is free software: you can redistribute it and/or modify
4
-// it under the terms of the GNU General Public License as published by
5
-// the Free Software Foundation, either version 3 of the License, or
6
-// (at your option) any later version.
7
-
8
-// This program is distributed in the hope that it will be useful,
9
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
-// GNU General Public License for more details.
12
-
13
-// You should have received a copy of the GNU General Public License
14
-// along with this program.  If not, see <https://www.gnu.org/licenses/>.
15
-
16
-use crate::ease::*;
17
-use crate::mathutil::*;
18
-
19
-pub fn parametric_scalar(a: f32, b: f32, mapping: Easing, clamping: bool, t: f32) -> f32 {
20
-    let new_t = easing(t, mapping);
21
-    let res = lerp(new_t, a, b);
22
-
23
-    if clamping {
24
-        if new_t < 0.0 {
25
-            return a;
26
-        } else if new_t > 1.0 {
27
-            return b;
28
-        } else {
29
-            return res;
30
-        }
31
-    }
32
-
33
-    return res;
34
-}
35
-
36
-pub fn parametric_cos(amplitude: f32, frequency: f32, t: f32) -> f32 {
37
-    amplitude * (t * frequency).cos()
38
-}
39
-
40
-pub fn parametric_sin(amplitude: f32, frequency: f32, t: f32) -> f32 {
41
-    amplitude * (t * frequency).sin()
42
-}
43
-
44
-pub fn parametric_bezier(coords: &[f32; 8], t: f32) -> (f32, f32) {
45
-    (
46
-        bezier_point(coords[0], coords[2], coords[4], coords[6], t),
47
-        bezier_point(coords[1], coords[3], coords[5], coords[7], t),
48
-    )
49
-}
50
-
51
-pub fn parametric_bezier_tangent(coords: &[f32; 8], t: f32) -> (f32, f32) {
52
-    (
53
-        bezier_tangent(coords[0], coords[2], coords[4], coords[6], t),
54
-        bezier_tangent(coords[1], coords[3], coords[5], coords[7], t),
55
-    )
56
-}
57
-
58
-pub fn parametric_circle(position: (f32, f32), radius: f32, t: f32) -> (f32, f32) {
59
-    let angle = t * TAU;
60
-
61
-    (
62
-        (angle.sin() * radius) + position.0,
63
-        (angle.cos() * radius) + position.1,
64
-    )
65
-}
66
-
67
-pub fn parametric_ray(point: (f32, f32), direction: (f32, f32), t: f32) -> (f32, f32) {
68
-    // direction should be a normalized vector
69
-    (point.0 + (direction.0 * t), point.1 + (direction.1 * t))
70
-}

+ 1
- 1
core/sen-core/src/parser.rs View File

@@ -431,7 +431,7 @@ mod tests {
431 431
                         gene: None,
432 432
                         parameter_ast: vec![
433 433
                             Node::Whitespace(" ".to_string(), None),
434
-                            Node::List(vec![Node::Name("gen/scalar".to_string(), 389, None)], None)
434
+                            Node::List(vec![Node::Name("gen/scalar".to_string(), Native::GenScalar as i32, None)], None)
435 435
                         ],
436 436
                         parameter_prefix: vec![Node::Whitespace(" ".to_string(), None)]
437 437
                     })

+ 84
- 0
core/sen-core/src/repeat.rs View File

@@ -162,3 +162,87 @@ pub fn repeat_rotate_mirrored(
162 162
 
163 163
     Ok(())
164 164
 }
165
+
166
+
167
+#[cfg(test)]
168
+mod tests {
169
+    use crate::vm::tests::*;
170
+
171
+    #[test]
172
+    fn test_symmetry_vertical() {
173
+        is_debug_str(
174
+            "(fn (f) (probe worldspace: [20 20]))
175
+             (repeat/symmetry-vertical fn: (address-of f))",
176
+            "(20,20) (-20,20)",
177
+        );
178
+    }
179
+
180
+    #[test]
181
+    fn test_symmetry_horizontal() {
182
+        is_debug_str(
183
+            "(fn (f) (probe worldspace: [20 20]))
184
+             (repeat/symmetry-horizontal fn: (address-of f))",
185
+            "(20,20) (20,-20)",
186
+        );
187
+    }
188
+
189
+    #[test]
190
+    fn test_symmetry_4() {
191
+        is_debug_str(
192
+            "(fn (f) (probe worldspace: [10 20]))
193
+             (repeat/symmetry-4 fn: (address-of f))",
194
+            "(10,20) (-10,20) (10,-20) (-10,-20)",
195
+        );
196
+    }
197
+
198
+    #[test]
199
+    fn test_symmetry_8() {
200
+        is_debug_str(
201
+            "(fn (f) (probe worldspace: [10 20]))
202
+             (repeat/symmetry-8 fn: (address-of f))",
203
+            "(10,20) (-10,20) (10,-20) (-10,-20) (-20,9.999999) (-20,-10.000001) (20,10.000001) (20,-9.999999)",
204
+        );
205
+    }
206
+
207
+    #[test]
208
+    fn test_rotate() {
209
+        is_debug_str(
210
+            "(fn (f angle: 0 copy: 0) (probe scalar: angle))
211
+             (repeat/rotate fn: (address-of f) copies: 3)",
212
+            "0 120 240",
213
+        );
214
+
215
+        is_debug_str(
216
+            "(fn (f angle: 0 copy: 0) (probe scalar: copy))
217
+             (repeat/rotate fn: (address-of f) copies: 3)",
218
+            "0 1 2",
219
+        );
220
+
221
+        is_debug_str(
222
+            "(fn (f) (probe worldspace: [0 1]))
223
+             (repeat/rotate fn: (address-of f) copies: 3)",
224
+            "(0,1) (-0.8660254,-0.50000006) (0.86602545,-0.4999999)",
225
+        );
226
+    }
227
+
228
+    #[test]
229
+    fn test_rotate_mirrored() {
230
+        is_debug_str(
231
+            "(fn (f angle: 0 copy: 0) (probe scalar: angle))
232
+             (repeat/rotate-mirrored fn: (address-of f) copies: 3)",
233
+            "0 120 240 0 -120 -240",
234
+        );
235
+
236
+        is_debug_str(
237
+            "(fn (f angle: 0 copy: 0) (probe scalar: copy))
238
+             (repeat/rotate-mirrored fn: (address-of f) copies: 3)",
239
+            "0 1 2 3 4 5",
240
+        );
241
+
242
+        is_debug_str(
243
+            "(fn (f) (probe worldspace: [0 1]))
244
+             (repeat/rotate-mirrored fn: (address-of f) copies: 3)",
245
+            "(0,1) (-0.8660254,-0.50000006) (0.86602545,-0.4999999) (0,1) (0.8660254,-0.50000006) (-0.86602545,-0.4999999)",
246
+        );
247
+    }
248
+}

+ 8
- 4
docs/api.org View File

@@ -36,7 +36,7 @@
36 36
  | [[nth]]           |                                                      |
37 37
  | [[debug/print]]   | prints debug                                         |
38 38
  | [[vector/length]] |                                                      |
39
- | probe         | writes to the vm's debug_str (used for testing only) |
39
+ | [[probe]]       | writes to the vm's debug_str (used for testing only) |
40 40
 
41 41
 ** shapes
42 42
 
@@ -211,9 +211,11 @@
211 211
 
212 212
 *** probe
213 213
 
214
-    | parameter | default | description                     |
215
-    |-----------+---------+---------------------------------|
216
-    | scalar    | NULL    | appends value onto vm.debug_str |
214
+    | parameter  | default | description                                 |
215
+    |------------+---------+---------------------------------------------|
216
+    | scalar     | NULL    | appends value onto vm.debug_str             |
217
+    | vector     | NULL    | appends v2d onto vm.debug_str               |
218
+    | worldspace | NULL    | appends v2d in worldspace onto vm.debug_str |
217 219
 
218 220
 ** shapes
219 221
 
@@ -822,6 +824,8 @@
822 824
 
823 825
 ** repeat
824 826
 
827
+   the given fn can accept a 'copy' parameter
828
+
825 829
 *** repeat/symmetry-vertical
826 830
 
827 831
     | parameter | default | description |

Loading…
Cancel
Save