Path Manipulation
General path manipulation can be performed on the Polygon type. We can construct a Polygon from any type implementing Iterator<Item=P2>, which Ngon does.
1
let square = Polygon::from(Ngon::square(world.center(), 200.));
2
canvas.paint(Filled(square));
Copied!
Polygon provides an iterator over its vertices we can use to manipulate them, and build a new polygon. In this code we use that to distort the polygon by sampling Fbm noise with time as the z position:
1
let fbm = Fbm::new().set_seed(world.seed as u32);
2
let shift_by_timed_noise = |v| {
3
let sample_point = P3::new(v.x, v.y, ctx.time.as_secs_f32().sin() / 5.);
4
let t = fbm.noise(sample_point) * 60.;
5
v.translate(V2::new(t, t))
6
};
7
​
8
let square = Polygon::from(Ngon::square(world.center(), 200.));
9
let square = Polygon::from(square.vertices().map(shift_by_timed_noise));
Copied!
A square whose vertices are translated by noise.
Further, we can iteratively subdivide and apply this same distortion to make more interesting shapes:
1
let fbm = Fbm::new().set_seed(world.seed as u32);
2
let shift_by_timed_noise = |(v, strength): (P2, f32)| {
3
let sample_point =
4
P3::new(v.x / 100., v.y / 100., ctx.time.as_secs_f32().sin() / 2.);
5
let t = fbm.noise(sample_point) * strength;
6
v.translate(V2::new(t, t))
7
};
8
​
9
let square = Polygon::from(Ngon::square(world.center(), 200.));
10
let initial_strength = 15.;
11
let splotches =
12
std::iter::successors(Some((square, initial_strength)), |(shape, strength)| {
13
let next_strength = strength / 1.5;
14
let next_shape = Polygon::from(
15
shape
16
.clone()
17
.subdivide()
18
.vertices()
19
.map(|v| (v, *strength))
20
.map(shift_by_timed_noise),
21
);
22
23
Some((next_shape, next_strength))
24
})
25
.map(|(s, _)| s);
26
​
27
for splotch in splotches.skip(8).take(1) {
28
canvas.paint(Filled(splotch));
29
}
Copied!
An animated low-poly cloth.
Copy link