FastLED 3.9.15
Loading...
Searching...
No Matches
transform.cpp
Go to the documentation of this file.
1
2#include <math.h>
3
4#include "fl/lut.h"
5#include "fl/math_macros.h"
6#include "fl/transform.h"
7#include "lib8tion/intmap.h"
8#include "lib8tion/trig8.h"
9
10#pragma GCC diagnostic push
11#pragma GCC diagnostic ignored "-Wfloat-equal"
12
13namespace fl {
14
16 if (is_identity()) {
17 return xy;
18 }
19 float x = xy.x;
20 float y = xy.y;
21 if (scale_x != 1.0f) {
22 x *= scale_x;
23 }
24 if (scale_y != 1.0f) {
25 y *= scale_y;
26 }
27 // Assume that adding floats is fast when offset_x == 0.0f
28 x += offset_x;
29 y += offset_y;
30
31 const bool has_rotation = (rotation != 0.0f);
32
33 if (has_rotation) {
34 float radians = rotation * 2 * PI;
35 float cos_theta = cosf(radians);
36 float sin_theta = sinf(radians);
37 float x_rotated = x * cos_theta - y * sin_theta;
38 float y_rotated = x * sin_theta + y * cos_theta;
39 return vec2f(x_rotated, y_rotated);
40 }
41 return vec2f(x, y);
42}
43
45 Transform16 tx;
46 // Compute a Q16 “scale” so that:
47 // (alpha16 * scale) >> 16 == max_value when alpha16==0xFFFF
48 alpha16 scale16 = 0;
49 if (max_value) {
50 // numerator = max_value * 2^16
51 uint32_t numer = static_cast<uint32_t>(max_value) << 16;
52 // denom = 0xFFFF; use ceil so 0xFFFF→max_value exactly:
53 uint32_t scale32 = numer / 0xFFFF;
54 scale16 = static_cast<alpha16>(scale32);
55 }
56 tx.scale_x = scale16;
57 tx.scale_y = scale16;
58 tx.offset_x = 0;
59 tx.offset_y = 0;
60 tx.rotation = 0;
61 return tx;
62}
63
65 const vec2<alpha16> &max, alpha16 rotation) {
66 Transform16 tx;
67 // Compute a Q16 “scale” so that:
68 // (alpha16 * scale) >> 16 == max_value when alpha16==0xFFFF
69 alpha16 scale16 = 0;
70 if (max.x > min.x) {
71 // numerator = max_value * 2^16
72 uint32_t numer = static_cast<uint32_t>(max.x - min.x) << 16;
73 // denom = 0xFFFF; use ceil so 0xFFFF→max_value exactly:
74 uint32_t scale32 = numer / 0xFFFF;
75 scale16 = static_cast<alpha16>(scale32);
76 }
77 tx.scale_x = scale16;
78 if (max.y > min.y) {
79 // numerator = max_value * 2^16
80 uint32_t numer = static_cast<uint32_t>(max.y - min.y) << 16;
81 // denom = 0xFFFF; use ceil so 0xFFFF→max_value exactly:
82 uint32_t scale32 = numer / 0xFFFF;
83 scale16 = static_cast<alpha16>(scale32);
84 }
85 tx.scale_y = scale16;
86 tx.offset_x = min.x;
87 tx.offset_y = min.y;
88 tx.rotation = rotation;
89 return tx;
90}
91
93 vec2<alpha16> out = xy;
94
95 // 1) Rotate around the 16‑bit center first
96 if (rotation != 0) {
97 constexpr int32_t MID = 0x7FFF; // center of 0…0xFFFF interval
98
99 // bring into signed centered coords
100 int32_t x = int32_t(out.x) - MID;
101 int32_t y = int32_t(out.y) - MID;
102
103 // Q15 cosine & sine
104 int32_t c = cos16(rotation); // [-32768..+32767]
105 int32_t s = sin16(rotation);
106
107 // rotate & truncate
108 int32_t xr = (x * c - y * s) >> 15;
109 int32_t yr = (x * s + y * c) >> 15;
110
111 // shift back into [0…0xFFFF]
112 out.x = alpha16(xr + MID);
113 out.y = alpha16(yr + MID);
114 }
115
116 // 2) Then scale in X/Y (Q16 → map32_to_16)
117 if (scale_x != 0xFFFF) {
118 uint32_t tx = uint32_t(out.x) * scale_x;
119 out.x = map32_to_16(tx);
120 }
121 if (scale_y != 0xFFFF) {
122 uint32_t ty = uint32_t(out.y) * scale_y;
123 out.y = map32_to_16(ty);
124 }
125
126 // 3) Finally translate
127 if (offset_x)
128 out.x = alpha16(out.x + offset_x);
129 if (offset_y)
130 out.y = alpha16(out.y + offset_y);
131
132 return out;
133}
134
135float TransformFloatImpl::scale() const { return MIN(scale_x, scale_y); }
136
141
143 return (scale_x == 1.0f && scale_y == 1.0f && offset_x == 0.0f &&
144 offset_y == 0.0f && rotation == 0.0f);
145}
146
148 Matrix3x3f out;
149 out.m[0][0] = scale_x() * cosf(rotation() * 2.0f * PI);
150 out.m[0][1] = -scale_y() * sinf(rotation() * 2.0f * PI);
151 out.m[0][2] = offset_x();
152 out.m[1][0] = scale_x() * sinf(rotation() * 2.0f * PI);
153 out.m[1][1] = scale_y() * cosf(rotation() * 2.0f * PI);
154 out.m[1][2] = offset_y();
155 out.m[2][2] = 1.0f;
156 return out;
157}
158
159} // namespace fl
160
161#pragma GCC diagnostic pop
uint32_t x[NUM_LAYERS]
Definition Fire2023.ino:82
uint32_t y[NUM_LAYERS]
Definition Fire2023.ino:83
unsigned int xy(unsigned int x, unsigned int y)
bool is_identity() const
void set_scale(float scale)
vec2f transform(const vec2f &xy) const
Definition transform.cpp:15
LIB8STATIC uint16_t scale16(uint16_t i, fract16 scale)
Scale a 16-bit unsigned value by an 16-bit value, which is treated as the numerator of a fraction who...
Definition scale8.h:546
LIB8STATIC int16_t cos16(uint16_t theta)
Fast 16-bit approximation of cos(x).
Definition trig8.h:148
#define sin16
Platform-independent alias of the fast sin implementation.
Definition trig8.h:103
LIB8STATIC_ALWAYS_INLINE uint16_t map32_to_16(uint32_t x)
Definition intmap.h:43
Defines integer mapping functions.
#define MIN(a, b)
Definition math_macros.h:15
#define PI
Definition math_macros.h:57
uint16_t alpha16
Definition transform.h:21
vec2< float > vec2f
Definition geometry.h:151
Implements a simple red square effect for 2D LED grids.
Definition crgb.h:16
float m[3][3]
Definition transform.h:82
Transform16()=default
vec2< alpha16 > transform(const vec2< alpha16 > &xy) const
Definition transform.cpp:92
alpha16 scale_x
Definition transform.h:42
alpha16 scale_y
Definition transform.h:43
alpha16 rotation
Definition transform.h:46
static Transform16 ToBounds(alpha16 max_value)
Definition transform.cpp:44
alpha16 offset_x
Definition transform.h:44
alpha16 offset_y
Definition transform.h:45
float offset_x() const
Definition transform.h:95
float scale_x() const
Definition transform.h:93
float offset_y() const
Definition transform.h:96
float rotation() const
Definition transform.h:98
float scale_y() const
Definition transform.h:94
Matrix3x3f compile() const
Fast, efficient 8-bit trigonometry functions specifically designed for high-performance LED programmi...