FastLED 3.9.15
Loading...
Searching...
No Matches
engine_core.h
Go to the documentation of this file.
1#pragma once
2
3// Engine core methods for Animartrix2
4// Extracted from animartrix_detail.hpp ANIMartRIX class to enable standalone operation
5
6#include "fl/stl/vector.h"
7#include "fl/math/math.h"
8#include "fl/stl/chrono.h"
12
13#ifndef PI
14#define PI 3.1415926535897932384626433832795
15#endif
16
17#define FL_SIN_F(x) fl::sinf(x)
18#define FL_COS_F(x) fl::cosf(x)
19
22
23namespace fl {
24
25// Polar coordinate pre-computation
26// Builds polar_theta[x][y] and distance[x][y] lookup tables
27inline void render_polar_lookup_table(float cx, float cy,
28 fl::vector<fl::vector<float>> &polar_theta,
30 int num_x, int num_y) {
31 polar_theta.resize(num_x, fl::vector<float>(num_y, 0.0f));
32 distance.resize(num_x, fl::vector<float>(num_y, 0.0f));
33
34 for (int xx = 0; xx < num_x; xx++) {
35 for (int yy = 0; yy < num_y; yy++) {
36 float dx = xx - cx;
37 float dy = yy - cy;
38 distance[xx][yy] = fl::hypotf(dx, dy);
39 polar_theta[xx][yy] = fl::atan2f(dy, dx);
40 }
41 }
42}
43
44// Calculate oscillators from timing ratios
45// Computes linear, radial, directional, and noise_angle modulators
47 fl::u32 current_time, float speed_factor) {
48 double runtime = current_time * timings.master_speed * speed_factor;
49
50 for (int i = 0; i < num_oscillators; i++) {
51 move.linear[i] = (runtime + timings.offset[i]) * timings.ratio[i];
52 move.radial[i] = fl::fmodf(move.linear[i], 2.0f * static_cast<float>(PI));
53 move.directional[i] = FL_SIN_F(move.radial[i]);
54 move.noise_angle[i] = PI * (1 + pnoise(move.linear[i], 0, 0));
55 }
56}
57
58// Set up standard oscillator configuration
60 fl::u32 current_time, float speed_factor,
61 float master_speed = 0.005) {
62 timings.master_speed = master_speed;
63
64 timings.ratio[0] = 1;
65 timings.ratio[1] = 2;
66 timings.ratio[2] = 3;
67 timings.ratio[3] = 4;
68 timings.ratio[4] = 5;
69 timings.ratio[5] = 6;
70 timings.ratio[6] = 7;
71 timings.ratio[7] = 8;
72 timings.ratio[8] = 9;
73 timings.ratio[9] = 10;
74
75 timings.offset[0] = 000;
76 timings.offset[1] = 100;
77 timings.offset[2] = 200;
78 timings.offset[3] = 300;
79 timings.offset[4] = 400;
80 timings.offset[5] = 500;
81 timings.offset[6] = 600;
82 timings.offset[7] = 700;
83 timings.offset[8] = 800;
84 timings.offset[9] = 900;
85
86 calculate_oscillators(timings, move, current_time, speed_factor);
87}
88
89// Float mapping maintaining 32 bit precision
90FASTLED_FORCE_INLINE float map_float(float x, float in_min, float in_max, float out_min,
91 float out_max) {
92 float result =
93 (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
94 if (result < out_min)
95 result = out_min;
96 if (result > out_max)
97 result = out_max;
98 return result;
99}
100
101// Main noise field renderer with clamping
102// Converts polar coordinates to cartesian, applies transformations, and renders Perlin noise
104 // Convert polar coordinates back to cartesian ones
105 float newx = (animation.offset_x + animation.center_x -
106 (FL_COS_F(animation.angle) * animation.dist)) *
107 animation.scale_x;
108 float newy = (animation.offset_y + animation.center_y -
109 (FL_SIN_F(animation.angle) * animation.dist)) *
110 animation.scale_y;
111 float newz = (animation.offset_z + animation.z) * animation.scale_z;
112
113 // Render noise value at this new cartesian point
114 float raw_noise_field_value = pnoise(newx, newy, newz);
115
116 // Enhance histogram (improve contrast) by setting black and white point
117 if (raw_noise_field_value < animation.low_limit)
118 raw_noise_field_value = animation.low_limit;
119 if (raw_noise_field_value > animation.high_limit)
120 raw_noise_field_value = animation.high_limit;
121
122 float scaled_noise_value =
123 map_float(raw_noise_field_value, animation.low_limit,
124 animation.high_limit, 0, 255);
125
126 return scaled_noise_value;
127}
128
129// Clamp RGB values to [0, 255]
131 if (pixel.red < 0)
132 pixel.red = 0;
133 if (pixel.green < 0)
134 pixel.green = 0;
135 if (pixel.blue < 0)
136 pixel.blue = 0;
137
138 if (pixel.red > 255)
139 pixel.red = 255;
140 if (pixel.green > 255)
141 pixel.green = 255;
142 if (pixel.blue > 255)
143 pixel.blue = 255;
144
145 return pixel;
146}
147
148// Color blend functions
149inline float subtract(float &a, float &b) { return a - b; }
150
151inline float multiply(float &a, float &b) { return a * b / 255.f; }
152
153inline float add(float &a, float &b) { return a + b; }
154
155inline float screen(float &a, float &b) {
156 return (1 - (1 - a / 255.f) * (1 - b / 255.f)) * 255.f;
157}
158
159inline float colordodge(float &a, float &b) { return (a / (255.f - b)) * 255.f; }
160
161inline float colorburn(float &a, float &b) {
162 return (1 - ((1 - a / 255.f) / (b / 255.f))) * 255.f;
163}
164
165// Timing functions (performance measurement)
166inline void get_ready(unsigned long &a, unsigned long &b) {
167 a = fl::micros();
168 b = fl::micros(); // logOutput
169}
170
171inline void logOutput(unsigned long &b) {
172 b = fl::micros();
173}
174
175inline void logFrame(unsigned long &c) {
176 c = fl::micros();
177}
178
179} // namespace fl
180
#define PI
FastLED chrono implementation - duration types for time measurements.
#define num_oscillators
Definition core_types.h:9
#define FL_SIN_F(x)
Definition engine_core.h:17
#define FL_COS_F(x)
Definition engine_core.h:18
void get_ready(unsigned long &a, unsigned long &b)
constexpr remove_reference< T >::type && move(T &&t) FL_NOEXCEPT
Definition move.h:28
FASTLED_FORCE_INLINE float render_value(render_parameters &animation)
float colorburn(float &a, float &b)
void render_polar_lookup_table(float cx, float cy, fl::vector< fl::vector< float > > &polar_theta, fl::vector< fl::vector< float > > &distance, int num_x, int num_y)
Definition engine_core.h:27
void logOutput(unsigned long &b)
void calculate_oscillators(oscillators &timings, modulators &move, fl::u32 current_time, float speed_factor)
Definition engine_core.h:46
float screen(float &a, float &b)
FASTLED_FORCE_INLINE float map_float(float x, float in_min, float in_max, float out_min, float out_max)
Definition engine_core.h:90
float fmodf(float x, float y) FL_NOEXCEPT
Definition math.h:336
void run_default_oscillators(oscillators &timings, modulators &move, fl::u32 current_time, float speed_factor, float master_speed=0.005)
Definition engine_core.h:59
expected< T, E > result
Alias for expected (Rust-style naming)
Definition result.h:31
fl::u32 micros()
Universal microsecond timer - returns microseconds since system startup.
FASTLED_FORCE_INLINE rgb rgb_sanity_check(rgb &pixel)
float subtract(float &a, float &b)
void logFrame(unsigned long &c)
float add(float &a, float &b)
float hypotf(float x, float y) FL_NOEXCEPT
Definition math.h:500
FASTLED_FORCE_INLINE float pnoise(float x, float y, float z)
float colordodge(float &a, float &b)
float atan2f(float y, float x) FL_NOEXCEPT
Definition math.h:390
float multiply(float &a, float &b)
Base definition for an LED controller.
Definition crgb.hpp:179
float offset[num_oscillators]
Definition core_types.h:32
float green
Definition core_types.h:45
float ratio[num_oscillators]
Definition core_types.h:33
float red
Definition core_types.h:44
float blue
Definition core_types.h:46
#define FL_OPTIMIZATION_LEVEL_O3_BEGIN
#define FASTLED_FORCE_INLINE
#define FL_FAST_MATH_BEGIN
#define FL_FAST_MATH_END
#define FL_OPTIMIZATION_LEVEL_O3_END