acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
Demo_3D_cube.ino (7463B)
1 /* 2 3 Example sketch for TFT_eSPI library. 4 5 No fonts are needed. 6 7 Draws a 3d rotating cube on the TFT screen. 8 9 Original code was found at http://forum.freetronics.com/viewtopic.php?f=37&t=5495 10 11 */ 12 13 #define BLACK 0x0000 14 #define WHITE 0xFFFF 15 16 #include <SPI.h> 17 18 #include <TFT_eSPI.h> // Hardware-specific library 19 20 TFT_eSPI tft = TFT_eSPI(); // Invoke custom library 21 22 int16_t h; 23 int16_t w; 24 25 int inc = -2; 26 27 float xx, xy, xz; 28 float yx, yy, yz; 29 float zx, zy, zz; 30 31 float fact; 32 33 int Xan, Yan; 34 35 int Xoff; 36 int Yoff; 37 int Zoff; 38 39 struct Point3d 40 { 41 int x; 42 int y; 43 int z; 44 }; 45 46 struct Point2d 47 { 48 int x; 49 int y; 50 }; 51 52 int LinestoRender; // lines to render. 53 int OldLinestoRender; // lines to render just in case it changes. this makes sure the old lines all get erased. 54 55 struct Line3d 56 { 57 Point3d p0; 58 Point3d p1; 59 }; 60 61 struct Line2d 62 { 63 Point2d p0; 64 Point2d p1; 65 }; 66 67 Line3d Lines[20]; 68 Line2d Render[20]; 69 Line2d ORender[20]; 70 71 /***********************************************************************************************************************************/ 72 void setup() { 73 74 tft.init(); 75 76 h = tft.height(); 77 w = tft.width(); 78 79 tft.setRotation(1); 80 81 tft.fillScreen(TFT_BLACK); 82 83 cube(); 84 85 fact = 180 / 3.14159259; // conversion from degrees to radians. 86 87 Xoff = 240; // Position the centre of the 3d conversion space into the centre of the TFT screen. 88 Yoff = 160; 89 Zoff = 550; // Z offset in 3D space (smaller = closer and bigger rendering) 90 } 91 92 /***********************************************************************************************************************************/ 93 void loop() { 94 95 // Rotate around x and y axes in 1 degree increments 96 Xan++; 97 Yan++; 98 99 Yan = Yan % 360; 100 Xan = Xan % 360; // prevents overflow. 101 102 SetVars(); //sets up the global vars to do the 3D conversion. 103 104 // Zoom in and out on Z axis within limits 105 // the cube intersects with the screen for values < 160 106 Zoff += inc; 107 if (Zoff > 500) inc = -1; // Switch to zoom in 108 else if (Zoff < 160) inc = 1; // Switch to zoom out 109 110 for (int i = 0; i < LinestoRender ; i++) 111 { 112 ORender[i] = Render[i]; // stores the old line segment so we can delete it later. 113 ProcessLine(&Render[i], Lines[i]); // converts the 3d line segments to 2d. 114 } 115 RenderImage(); // go draw it! 116 117 delay(14); // Delay to reduce loop rate (reduces flicker caused by aliasing with TFT screen refresh rate) 118 } 119 120 /***********************************************************************************************************************************/ 121 void RenderImage( void) 122 { 123 // renders all the lines after erasing the old ones. 124 // in here is the only code actually interfacing with the OLED. so if you use a different lib, this is where to change it. 125 126 for (int i = 0; i < OldLinestoRender; i++ ) 127 { 128 tft.drawLine(ORender[i].p0.x, ORender[i].p0.y, ORender[i].p1.x, ORender[i].p1.y, BLACK); // erase the old lines. 129 } 130 131 132 for (int i = 0; i < LinestoRender; i++ ) 133 { 134 uint16_t color = TFT_BLUE; 135 if (i < 4) color = TFT_RED; 136 if (i > 7) color = TFT_GREEN; 137 tft.drawLine(Render[i].p0.x, Render[i].p0.y, Render[i].p1.x, Render[i].p1.y, color); 138 } 139 OldLinestoRender = LinestoRender; 140 } 141 142 /***********************************************************************************************************************************/ 143 // Sets the global vars for the 3d transform. Any points sent through "process" will be transformed using these figures. 144 // only needs to be called if Xan or Yan are changed. 145 void SetVars(void) 146 { 147 float Xan2, Yan2, Zan2; 148 float s1, s2, s3, c1, c2, c3; 149 150 Xan2 = Xan / fact; // convert degrees to radians. 151 Yan2 = Yan / fact; 152 153 // Zan is assumed to be zero 154 155 s1 = sin(Yan2); 156 s2 = sin(Xan2); 157 158 c1 = cos(Yan2); 159 c2 = cos(Xan2); 160 161 xx = c1; 162 xy = 0; 163 xz = -s1; 164 165 yx = (s1 * s2); 166 yy = c2; 167 yz = (c1 * s2); 168 169 zx = (s1 * c2); 170 zy = -s2; 171 zz = (c1 * c2); 172 } 173 174 175 /***********************************************************************************************************************************/ 176 // processes x1,y1,z1 and returns rx1,ry1 transformed by the variables set in SetVars() 177 // fairly heavy on floating point here. 178 // uses a bunch of global vars. Could be rewritten with a struct but not worth the effort. 179 void ProcessLine(struct Line2d *ret, struct Line3d vec) 180 { 181 float zvt1; 182 int xv1, yv1, zv1; 183 184 float zvt2; 185 int xv2, yv2, zv2; 186 187 int rx1, ry1; 188 int rx2, ry2; 189 190 int x1; 191 int y1; 192 int z1; 193 194 int x2; 195 int y2; 196 int z2; 197 198 int Ok; 199 200 x1 = vec.p0.x; 201 y1 = vec.p0.y; 202 z1 = vec.p0.z; 203 204 x2 = vec.p1.x; 205 y2 = vec.p1.y; 206 z2 = vec.p1.z; 207 208 Ok = 0; // defaults to not OK 209 210 xv1 = (x1 * xx) + (y1 * xy) + (z1 * xz); 211 yv1 = (x1 * yx) + (y1 * yy) + (z1 * yz); 212 zv1 = (x1 * zx) + (y1 * zy) + (z1 * zz); 213 214 zvt1 = zv1 - Zoff; 215 216 if ( zvt1 < -5) { 217 rx1 = 256 * (xv1 / zvt1) + Xoff; 218 ry1 = 256 * (yv1 / zvt1) + Yoff; 219 Ok = 1; // ok we are alright for point 1. 220 } 221 222 xv2 = (x2 * xx) + (y2 * xy) + (z2 * xz); 223 yv2 = (x2 * yx) + (y2 * yy) + (z2 * yz); 224 zv2 = (x2 * zx) + (y2 * zy) + (z2 * zz); 225 226 zvt2 = zv2 - Zoff; 227 228 if ( zvt2 < -5) { 229 rx2 = 256 * (xv2 / zvt2) + Xoff; 230 ry2 = 256 * (yv2 / zvt2) + Yoff; 231 } else 232 { 233 Ok = 0; 234 } 235 236 if (Ok == 1) { 237 238 ret->p0.x = rx1; 239 ret->p0.y = ry1; 240 241 ret->p1.x = rx2; 242 ret->p1.y = ry2; 243 } 244 // The ifs here are checks for out of bounds. needs a bit more code here to "safe" lines that will be way out of whack, so they don't get drawn and cause screen garbage. 245 246 } 247 248 /***********************************************************************************************************************************/ 249 // line segments to draw a cube. basically p0 to p1. p1 to p2. p2 to p3 so on. 250 void cube(void) 251 { 252 // Front Face. 253 254 Lines[0].p0.x = -50; 255 Lines[0].p0.y = -50; 256 Lines[0].p0.z = 50; 257 Lines[0].p1.x = 50; 258 Lines[0].p1.y = -50; 259 Lines[0].p1.z = 50; 260 261 Lines[1].p0.x = 50; 262 Lines[1].p0.y = -50; 263 Lines[1].p0.z = 50; 264 Lines[1].p1.x = 50; 265 Lines[1].p1.y = 50; 266 Lines[1].p1.z = 50; 267 268 Lines[2].p0.x = 50; 269 Lines[2].p0.y = 50; 270 Lines[2].p0.z = 50; 271 Lines[2].p1.x = -50; 272 Lines[2].p1.y = 50; 273 Lines[2].p1.z = 50; 274 275 Lines[3].p0.x = -50; 276 Lines[3].p0.y = 50; 277 Lines[3].p0.z = 50; 278 Lines[3].p1.x = -50; 279 Lines[3].p1.y = -50; 280 Lines[3].p1.z = 50; 281 282 283 //back face. 284 285 Lines[4].p0.x = -50; 286 Lines[4].p0.y = -50; 287 Lines[4].p0.z = -50; 288 Lines[4].p1.x = 50; 289 Lines[4].p1.y = -50; 290 Lines[4].p1.z = -50; 291 292 Lines[5].p0.x = 50; 293 Lines[5].p0.y = -50; 294 Lines[5].p0.z = -50; 295 Lines[5].p1.x = 50; 296 Lines[5].p1.y = 50; 297 Lines[5].p1.z = -50; 298 299 Lines[6].p0.x = 50; 300 Lines[6].p0.y = 50; 301 Lines[6].p0.z = -50; 302 Lines[6].p1.x = -50; 303 Lines[6].p1.y = 50; 304 Lines[6].p1.z = -50; 305 306 Lines[7].p0.x = -50; 307 Lines[7].p0.y = 50; 308 Lines[7].p0.z = -50; 309 Lines[7].p1.x = -50; 310 Lines[7].p1.y = -50; 311 Lines[7].p1.z = -50; 312 313 314 // now the 4 edge lines. 315 316 Lines[8].p0.x = -50; 317 Lines[8].p0.y = -50; 318 Lines[8].p0.z = 50; 319 Lines[8].p1.x = -50; 320 Lines[8].p1.y = -50; 321 Lines[8].p1.z = -50; 322 323 Lines[9].p0.x = 50; 324 Lines[9].p0.y = -50; 325 Lines[9].p0.z = 50; 326 Lines[9].p1.x = 50; 327 Lines[9].p1.y = -50; 328 Lines[9].p1.z = -50; 329 330 Lines[10].p0.x = -50; 331 Lines[10].p0.y = 50; 332 Lines[10].p0.z = 50; 333 Lines[10].p1.x = -50; 334 Lines[10].p1.y = 50; 335 Lines[10].p1.z = -50; 336 337 Lines[11].p0.x = 50; 338 Lines[11].p0.y = 50; 339 Lines[11].p0.z = 50; 340 Lines[11].p1.x = 50; 341 Lines[11].p1.y = 50; 342 Lines[11].p1.z = -50; 343 344 LinestoRender = 12; 345 OldLinestoRender = LinestoRender; 346 347 } 348