2021-09-05 23:21:41 +02:00
|
|
|
//
|
|
|
|
// Whirling.cpp
|
|
|
|
// Whirling
|
|
|
|
//
|
|
|
|
// Created by Bob Polis at 2021-09-05
|
|
|
|
// Copyright (c) 2021 SwiftCoder. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "Whirling.hpp"
|
|
|
|
#include <libscscreensaver.hpp>
|
2021-10-04 15:44:46 +02:00
|
|
|
#include <vector>
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
struct Lissajous {
|
|
|
|
double f[4]; // frequencies
|
|
|
|
double p[4]; // phases
|
|
|
|
int steps; // number of line segments
|
|
|
|
double delta; // phase shift per frame
|
|
|
|
RGB color;
|
|
|
|
double alpha;
|
|
|
|
double line_width;
|
|
|
|
cairo_rectangle_t frame;
|
|
|
|
|
|
|
|
Lissajous(double f0,
|
|
|
|
double f1,
|
|
|
|
double f2,
|
|
|
|
double f3,
|
|
|
|
double p0,
|
|
|
|
double p1,
|
|
|
|
double p2,
|
|
|
|
double p3,
|
|
|
|
int segments,
|
|
|
|
double shift);
|
|
|
|
|
|
|
|
double calc_x(double phi) const;
|
|
|
|
double calc_y(double phi) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
Lissajous::Lissajous(double f0,
|
|
|
|
double f1,
|
|
|
|
double f2,
|
|
|
|
double f3,
|
|
|
|
double p0,
|
|
|
|
double p1,
|
|
|
|
double p2,
|
|
|
|
double p3,
|
|
|
|
int segments,
|
|
|
|
double shift)
|
|
|
|
{
|
|
|
|
f[0] = f0; f[1] = f1; f[2] = f2; f[3] = f3;
|
|
|
|
p[0] = p0; p[1] = p1; p[2] = p2; p[3] = p3;
|
|
|
|
steps = segments;
|
|
|
|
delta = shift;
|
|
|
|
}
|
|
|
|
|
|
|
|
double Lissajous::calc_x(double phi) const {
|
|
|
|
return sin(f[0] * phi + p[0]) * cos(f[1] * phi + p[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
double Lissajous::calc_y(double phi) const {
|
|
|
|
return sin(f[2] * phi + p[2]) * cos(f[3] * phi + p[3]);
|
|
|
|
}
|
2021-09-05 23:21:41 +02:00
|
|
|
|
|
|
|
class Whirling : public ScreensaverPlugin {
|
|
|
|
public:
|
2021-10-04 15:44:46 +02:00
|
|
|
Whirling();
|
2021-09-05 23:21:41 +02:00
|
|
|
~Whirling() = default;
|
|
|
|
|
|
|
|
int fps() const override;
|
|
|
|
void update() override;
|
|
|
|
void render() override;
|
2021-10-04 15:44:46 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
std::vector<Lissajous> knots;
|
|
|
|
|
|
|
|
void render_knot(const Lissajous& knot);
|
2021-09-05 23:21:41 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
ScreensaverPlugin* create_instance() {
|
|
|
|
return new Whirling;
|
|
|
|
}
|
|
|
|
|
2021-10-04 15:44:46 +02:00
|
|
|
Whirling::Whirling() {
|
|
|
|
knots.emplace_back(9, 7, 5, 7,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
1000,
|
|
|
|
2 * M_PI / 360.0);
|
|
|
|
Lissajous& knot = knots.back();
|
|
|
|
knot.color = {1.0, 1.0, 1.0}; // white
|
|
|
|
knot.alpha = 1.0; // opaque
|
|
|
|
knot.line_width = 1.0;
|
|
|
|
}
|
|
|
|
|
2021-09-05 23:21:41 +02:00
|
|
|
int Whirling::fps() const {
|
|
|
|
return 30;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Whirling::update() {
|
2021-10-04 15:44:46 +02:00
|
|
|
for (Lissajous& knot : knots) {
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
knot.p[i] += knot.delta;
|
|
|
|
}
|
|
|
|
knot.frame.x = _r.width * 0.5;
|
|
|
|
knot.frame.y = _r.height * 0.5;
|
|
|
|
double sz = _r.width < _r.height ? _r.width : _r.height;
|
|
|
|
knot.frame.width = sz * 0.45;
|
|
|
|
knot.frame.height = sz * 0.45;
|
|
|
|
}
|
2021-09-05 23:21:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Whirling::render() {
|
2021-10-04 15:44:46 +02:00
|
|
|
make_black();
|
|
|
|
for (const Lissajous& knot : knots) {
|
|
|
|
render_knot(knot);
|
|
|
|
}
|
|
|
|
}
|
2021-09-05 23:21:41 +02:00
|
|
|
|
2021-10-04 15:44:46 +02:00
|
|
|
void Whirling::render_knot(const Lissajous& knot) {
|
|
|
|
cairo_new_path(_c);
|
|
|
|
cairo_move_to(_c,
|
|
|
|
knot.frame.width * knot.calc_x(0) + knot.frame.x,
|
|
|
|
knot.frame.height * knot.calc_y(0) + knot.frame.y);
|
|
|
|
for (int step = 1; step < knot.steps; ++step) {
|
|
|
|
double phi = step * 2 * M_PI / knot.steps;
|
|
|
|
cairo_line_to(_c,
|
|
|
|
knot.frame.width * knot.calc_x(phi) + knot.frame.x,
|
|
|
|
knot.frame.height * knot.calc_y(phi) + knot.frame.y);
|
|
|
|
}
|
|
|
|
cairo_close_path(_c);
|
|
|
|
cairo_set_source_rgba(_c, knot.color.r, knot.color.g, knot.color.b, knot.alpha);
|
|
|
|
cairo_set_line_width(_c, knot.line_width);
|
|
|
|
cairo_stroke(_c);
|
2021-09-05 23:21:41 +02:00
|
|
|
}
|