donut.c 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /**
  2. * Original author:
  3. * https://twitter.com/a1k0n
  4. * https://www.a1k0n.net/2021/01/13/optimizing-donut.html
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2006-09-15 Andy Sloane First version
  9. * 2011-07-20 Andy Sloane Second version
  10. * 2021-01-13 Andy Sloane Third version
  11. * 2021-03-25 Meco Man Port to RT-Thread RTOS
  12. */
  13. #include <rtthread.h>
  14. #define R(mul,shift,x,y) \
  15. _=x; \
  16. x -= mul*y>>shift; \
  17. y += mul*_>>shift; \
  18. _ = 3145728-x*x-y*y>>11; \
  19. x = x*_>>10; \
  20. y = y*_>>10;
  21. void donut(void)
  22. {
  23. int sA=1024,cA=0,sB=1024,cB=0,_;
  24. rt_int8_t *b = rt_malloc(1760 * sizeof(rt_int8_t));
  25. if(b == RT_NULL)
  26. {
  27. return;
  28. }
  29. rt_int8_t *z = rt_malloc(1760 * sizeof(rt_int8_t));
  30. if(z == RT_NULL)
  31. {
  32. rt_free(b);
  33. return;
  34. }
  35. rt_kprintf("\033[?25l"); // hide cursor
  36. rt_kprintf("Have a donut!\r\n");
  37. while(1)
  38. {
  39. rt_memset(b, 32, 1760); // text buffer
  40. rt_memset(z, 127, 1760); // z buffer
  41. int sj=0, cj=1024;
  42. for (int j = 0; j < 90; j++)
  43. {
  44. int si = 0, ci = 1024; // sine and cosine of angle i
  45. for (int i = 0; i < 324; i++)
  46. {
  47. int R1 = 1, R2 = 2048, K2 = 5120*1024;
  48. int x0 = R1*cj + R2,
  49. x1 = ci*x0 >> 10,
  50. x2 = cA*sj >> 10,
  51. x3 = si*x0 >> 10,
  52. x4 = R1*x2 - (sA*x3 >> 10),
  53. x5 = sA*sj >> 10,
  54. x6 = K2 + R1*1024*x5 + cA*x3,
  55. x7 = cj*si >> 10,
  56. x = 40 + 30*(cB*x1 - sB*x4)/x6,
  57. y = 12 + 15*(cB*x4 + sB*x1)/x6,
  58. N = (-cA*x7 - cB*((-sA*x7>>10) + x2) - ci*(cj*sB >> 10) >> 10) - x5 >> 7;
  59. int o = x + 80 * y;
  60. rt_int8_t zz = (x6-K2)>>15;
  61. if (22 > y && y > 0 && x > 0 && 80 > x && zz < z[o])
  62. {
  63. z[o] = zz;
  64. b[o] = ".,-~:;=!*#$@"[N > 0 ? N : 0];
  65. }
  66. R(5, 8, ci, si) // rotate i
  67. }
  68. R(9, 7, cj, sj) // rotate j
  69. }
  70. for (int k = 0; 1761 > k; k++)
  71. {
  72. rt_kprintf("%c",(k % 80 ? b[k] : 10));
  73. }
  74. R(5, 7, cA, sA);
  75. R(5, 8, cB, sB);
  76. rt_schedule();
  77. rt_kprintf("\x1b[23A");
  78. }
  79. }
  80. MSH_CMD_EXPORT(donut, a 3D spinning donut);