First working implementation
This commit is contained in:
parent
cdd9fba25c
commit
66b8909e67
@ -8,31 +8,126 @@
|
||||
|
||||
#include "Whirling.hpp"
|
||||
#include <libscscreensaver.hpp>
|
||||
#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]);
|
||||
}
|
||||
|
||||
class Whirling : public ScreensaverPlugin {
|
||||
public:
|
||||
Whirling() = default;
|
||||
Whirling();
|
||||
~Whirling() = default;
|
||||
|
||||
int fps() const override;
|
||||
void update() override;
|
||||
void render() override;
|
||||
|
||||
private:
|
||||
std::vector<Lissajous> knots;
|
||||
|
||||
void render_knot(const Lissajous& knot);
|
||||
};
|
||||
|
||||
ScreensaverPlugin* create_instance() {
|
||||
return new Whirling;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int Whirling::fps() const {
|
||||
return 30;
|
||||
}
|
||||
|
||||
void Whirling::update() {
|
||||
// adjust state for next render
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void Whirling::render() {
|
||||
// render one frame based on current state
|
||||
|
||||
make_black();
|
||||
for (const Lissajous& knot : knots) {
|
||||
render_knot(knot);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user