FluffyWishbone

FluffyWishbone

Oct 2nd, 2025 (edited)
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.30 KB | Source Code | 0 0
  1. #include <FastLED.h>
  2.  
  3. #define LED_PIN 6
  4. #define WIDTH 120
  5. #define HEIGHT 70
  6. #define NUM_LEDS (WIDTH * HEIGHT)
  7. #define BRIGHTNESS 255
  8.  
  9. CRGB leds[NUM_LEDS];
  10.  
  11. // Cube vertices in 3D space
  12. float vertices[8][3] = {
  13. {-1, -1, -1}, {1, -1, -1}, {1, 1, -1}, {-1, 1, -1},
  14. {-1, -1, 1}, {1, -1, 1}, {1, 1, 1}, {-1, 1, 1}
  15. };
  16.  
  17. // Cube edges (pairs of vertex indices)
  18. int edges[12][2] = {
  19. {0, 1}, {1, 2}, {2, 3}, {3, 0}, // Back face
  20. {4, 5}, {5, 6}, {6, 7}, {7, 4}, // Front face
  21. {0, 4}, {1, 5}, {2, 6}, {3, 7} // Connecting edges
  22. };
  23.  
  24. float rotated[8][3];
  25. float projected[8][2];
  26.  
  27. float angleX = 0;
  28. float angleY = 0;
  29. float angleZ = 0;
  30.  
  31. void setup() {
  32. FastLED.addLeds<WS2812B,2,GRB>(leds,240); //1 240
  33. FastLED.addLeds<WS2812B,3,GRB>(leds,1*240,240); //2 480
  34. FastLED.addLeds<WS2812B,4,GRB>(leds,2*240,240); //3 720
  35. FastLED.addLeds<WS2812B,5,GRB>(leds,3*240,240); //4 960
  36. FastLED.addLeds<WS2812B,6,GRB>(leds,4*240,240); //5 1200
  37. FastLED.addLeds<WS2812B,7,GRB>(leds,5*240,240); //6 1440
  38. FastLED.addLeds<WS2812B,8,GRB>(leds,6*240,240); //7 1680
  39. FastLED.addLeds<WS2812B,9,GRB>(leds,7*240,240); //8 1920
  40. FastLED.addLeds<WS2812B,10,GRB>(leds,8*240,240); //9
  41. FastLED.addLeds<WS2812B,11,GRB>(leds,9*240,240); //10
  42. FastLED.addLeds<WS2812B,24,GRB>(leds,10*240,240); //11
  43. FastLED.addLeds<WS2812B,25,GRB>(leds,11*240,240); //12
  44. FastLED.addLeds<WS2812B,26,GRB>(leds,12*240,240); //13
  45. FastLED.addLeds<WS2812B,27,GRB>(leds,13*240,240); //14
  46. FastLED.addLeds<WS2812B,28,GRB>(leds,14*240,240); //15
  47. FastLED.addLeds<WS2812B,29,GRB>(leds,15*240,240); //16
  48. FastLED.addLeds<WS2812B,30,GRB>(leds,16*240,240); //17
  49. FastLED.addLeds<WS2812B,31,GRB>(leds,17*240,240); //18
  50. FastLED.addLeds<WS2812B,32,GRB>(leds,18*240,240); //19
  51. FastLED.addLeds<WS2812B,33,GRB>(leds,19*240,240); //20
  52. FastLED.addLeds<WS2812B,34,GRB>(leds,20*240,240); //21
  53. FastLED.addLeds<WS2812B,35,GRB>(leds,21*240,240); //22
  54. FastLED.addLeds<WS2812B,36,GRB>(leds,22*240,240); //23
  55. FastLED.addLeds<WS2812B,37,GRB>(leds,23*240,240); //24
  56. FastLED.addLeds<WS2812B,38,GRB>(leds,24*240,240); //25
  57. FastLED.addLeds<WS2812B,39,GRB>(leds,25*240,240); //26
  58. FastLED.addLeds<WS2812B,40,GRB>(leds,26*240,240); //27
  59. FastLED.addLeds<WS2812B,41,GRB>(leds,27*240,240); //28
  60. FastLED.addLeds<WS2812B,13,GRB>(leds,28*240,240); //29
  61. FastLED.addLeds<WS2812B,14,GRB>(leds,29*240,240); //30
  62. FastLED.addLeds<WS2812B,15,GRB>(leds,30*240,240); //31
  63. FastLED.addLeds<WS2812B,16,GRB>(leds,31*240,240); //32
  64. FastLED.addLeds<WS2812B,17,GRB>(leds,32*240,240); //33
  65. FastLED.addLeds<WS2812B,18,GRB>(leds,33*240,240); //34
  66. FastLED.addLeds<WS2812B,19,GRB>(leds,34*240,240); //35
  67.  
  68. FastLED.setCorrection(TypicalLEDStrip); //TypicalSMD5050 TypicalLEDStrip TypicalLEDStrip
  69. FastLED.setBrightness(75);
  70. //FastLED.setMaxPowerInVoltsAndMilliamps( 5, 5000); // optional current limiting [5V, 2000mA]
  71. FastLED.setDither(0);
  72. FastLED.clear();
  73. FastLED.show();
  74. Serial.begin(115200); // check serial monitor for current fps count
  75. }
  76.  
  77. // Get LED index from x, y coordinates
  78. int XY(int x, int y) {
  79. if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return -1;
  80.  
  81. // Adjust based on your matrix wiring (zigzag vs straight)
  82. if (y & 1) {
  83. // Odd rows run backwards
  84. return y * WIDTH + (WIDTH - 1 - x);
  85. } else {
  86. // Even rows run forwards
  87. return y * WIDTH + x;
  88. }
  89. }
  90.  
  91. // Wu's algorithm for anti-aliased pixel drawing
  92. void wu_pixel(float x, float y, CRGB color) {
  93. int x0 = (int)x;
  94. int y0 = (int)y;
  95.  
  96. float fx = x - x0;
  97. float fy = y - y0;
  98.  
  99. // Calculate weights for the 4 surrounding pixels
  100. float w00 = (1 - fx) * (1 - fy);
  101. float w10 = fx * (1 - fy);
  102. float w01 = (1 - fx) * fy;
  103. float w11 = fx * fy;
  104.  
  105. // Draw the 4 pixels with appropriate brightness
  106. int idx;
  107.  
  108. idx = XY(x0, y0);
  109. if (idx >= 0) leds[idx] += CRGB(color.r * w00, color.g * w00, color.b * w00);
  110.  
  111. idx = XY(x0 + 1, y0);
  112. if (idx >= 0) leds[idx] += CRGB(color.r * w10, color.g * w10, color.b * w10);
  113.  
  114. idx = XY(x0, y0 + 1);
  115. if (idx >= 0) leds[idx] += CRGB(color.r * w01, color.g * w01, color.b * w01);
  116.  
  117. idx = XY(x0 + 1, y0 + 1);
  118. if (idx >= 0) leds[idx] += CRGB(color.r * w11, color.g * w11, color.b * w11);
  119. }
  120.  
  121. // Draw anti-aliased line using Wu's algorithm
  122. void wu_line(float x0, float y0, float x1, float y1, CRGB color) {
  123. bool steep = abs(y1 - y0) > abs(x1 - x0);
  124.  
  125. if (steep) {
  126. float tmp;
  127. tmp = x0; x0 = y0; y0 = tmp;
  128. tmp = x1; x1 = y1; y1 = tmp;
  129. }
  130.  
  131. if (x0 > x1) {
  132. float tmp;
  133. tmp = x0; x0 = x1; x1 = tmp;
  134. tmp = y0; y0 = y1; y1 = tmp;
  135. }
  136.  
  137. float dx = x1 - x0;
  138. float dy = y1 - y0;
  139. float gradient = (dx == 0) ? 1 : dy / dx;
  140.  
  141. // Handle first endpoint
  142. float xend = round(x0);
  143. float yend = y0 + gradient * (xend - x0);
  144. float xgap = 1 - fmod(x0 + 0.5, 1);
  145. int xpxl1 = xend;
  146. int ypxl1 = (int)yend;
  147.  
  148. if (steep) {
  149. wu_pixel(ypxl1, xpxl1, CRGB(color.r * (1 - fmod(yend, 1)) * xgap,
  150. color.g * (1 - fmod(yend, 1)) * xgap,
  151. color.b * (1 - fmod(yend, 1)) * xgap));
  152. wu_pixel(ypxl1 + 1, xpxl1, CRGB(color.r * fmod(yend, 1) * xgap,
  153. color.g * fmod(yend, 1) * xgap,
  154. color.b * fmod(yend, 1) * xgap));
  155. } else {
  156. wu_pixel(xpxl1, ypxl1, CRGB(color.r * (1 - fmod(yend, 1)) * xgap,
  157. color.g * (1 - fmod(yend, 1)) * xgap,
  158. color.b * (1 - fmod(yend, 1)) * xgap));
  159. wu_pixel(xpxl1, ypxl1 + 1, CRGB(color.r * fmod(yend, 1) * xgap,
  160. color.g * fmod(yend, 1) * xgap,
  161. color.b * fmod(yend, 1) * xgap));
  162. }
  163.  
  164. float intery = yend + gradient;
  165.  
  166. // Handle second endpoint
  167. xend = round(x1);
  168. yend = y1 + gradient * (xend - x1);
  169. xgap = fmod(x1 + 0.5, 1);
  170. int xpxl2 = xend;
  171. int ypxl2 = (int)yend;
  172.  
  173. if (steep) {
  174. wu_pixel(ypxl2, xpxl2, CRGB(color.r * (1 - fmod(yend, 1)) * xgap,
  175. color.g * (1 - fmod(yend, 1)) * xgap,
  176. color.b * (1 - fmod(yend, 1)) * xgap));
  177. wu_pixel(ypxl2 + 1, xpxl2, CRGB(color.r * fmod(yend, 1) * xgap,
  178. color.g * fmod(yend, 1) * xgap,
  179. color.b * fmod(yend, 1) * xgap));
  180. } else {
  181. wu_pixel(xpxl2, ypxl2, CRGB(color.r * (1 - fmod(yend, 1)) * xgap,
  182. color.g * (1 - fmod(yend, 1)) * xgap,
  183. color.b * (1 - fmod(yend, 1)) * xgap));
  184. wu_pixel(xpxl2, ypxl2 + 1, CRGB(color.r * fmod(yend, 1) * xgap,
  185. color.g * fmod(yend, 1) * xgap,
  186. color.b * fmod(yend, 1) * xgap));
  187. }
  188.  
  189. // Main loop
  190. if (steep) {
  191. for (int x = xpxl1 + 1; x < xpxl2; x++) {
  192. wu_pixel((int)intery, x, CRGB(color.r * (1 - fmod(intery, 1)),
  193. color.g * (1 - fmod(intery, 1)),
  194. color.b * (1 - fmod(intery, 1))));
  195. wu_pixel((int)intery + 1, x, CRGB(color.r * fmod(intery, 1),
  196. color.g * fmod(intery, 1),
  197. color.b * fmod(intery, 1)));
  198. intery += gradient;
  199. }
  200. } else {
  201. for (int x = xpxl1 + 1; x < xpxl2; x++) {
  202. wu_pixel(x, (int)intery, CRGB(color.r * (1 - fmod(intery, 1)),
  203. color.g * (1 - fmod(intery, 1)),
  204. color.b * (1 - fmod(intery, 1))));
  205. wu_pixel(x, (int)intery + 1, CRGB(color.r * fmod(intery, 1),
  206. color.g * fmod(intery, 1),
  207. color.b * fmod(intery, 1)));
  208. intery += gradient;
  209. }
  210. }
  211. }
  212.  
  213. // 3D rotation and projection
  214. void rotateCube() {
  215. float cosX = cos(angleX), sinX = sin(angleX);
  216. float cosY = cos(angleY), sinY = sin(angleY);
  217. float cosZ = cos(angleZ), sinZ = sin(angleZ);
  218.  
  219. for (int i = 0; i < 8; i++) {
  220. float x = vertices[i][0];
  221. float y = vertices[i][1];
  222. float z = vertices[i][2];
  223.  
  224. // Rotate around X axis
  225. float y1 = y * cosX - z * sinX;
  226. float z1 = y * sinX + z * cosX;
  227.  
  228. // Rotate around Y axis
  229. float x2 = x * cosY + z1 * sinY;
  230. float z2 = -x * sinY + z1 * cosY;
  231.  
  232. // Rotate around Z axis
  233. float x3 = x2 * cosZ - y1 * sinZ;
  234. float y3 = x2 * sinZ + y1 * cosZ;
  235.  
  236. rotated[i][0] = x3;
  237. rotated[i][1] = y3;
  238. rotated[i][2] = z2;
  239.  
  240. // Perspective projection
  241. float scale = 22.0; //20.0 / (4.0 + z2)
  242. projected[i][0] = x3 * scale + WIDTH / 2.0;
  243. projected[i][1] = y3 * scale + HEIGHT / 2.0;
  244. }
  245. }
  246.  
  247. void loop() {
  248. FastLED.clear();
  249.  
  250. rotateCube();
  251.  
  252. // Draw all edges with rainbow colors
  253. for (int i = 0; i < 12; i++) {
  254. int v0 = edges[i][0];
  255. int v1 = edges[i][1];
  256.  
  257. CRGB color = CHSV(i * 21, 255, 255);
  258.  
  259. wu_line(projected[v0][0], projected[v0][1],
  260. projected[v1][0], projected[v1][1],
  261. color);
  262. }
  263.  
  264. FastLED.show();
  265.  
  266. // Update rotation angles
  267. angleX += 0.02;
  268. angleY += 0.03;
  269. angleZ += 0.01;
  270.  
  271. delay(20);
  272. }
Tags: FastLED
Advertisement
Add Comment
Please, Sign In to add comment