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