ARM application development SDK for MNT ZZ9000 graphics and coprocessor card for classic Amiga computers.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

vector.c 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. * MNT ZZ9000 Amiga Graphics and ARM Coprocessor SDK
  3. * Code example: "vector"
  4. *
  5. * Copyright (C) 2019, Lukas F. Hartmann <lukas@mntre.com>
  6. * MNT Research GmbH, Berlin
  7. * https://mntre.com
  8. *
  9. * More Info: https://mntre.com/zz9000
  10. *
  11. * SPDX-License-Identifier: GPL-3.0-or-later
  12. * GNU General Public License v3.0 or later
  13. *
  14. * https://spdx.org/licenses/GPL-3.0-or-later.html
  15. */
  16. /*
  17. Run it like this:
  18. zz9k load vector.bin
  19. zz9k run -320x240 !screen !width
  20. */
  21. #include <stdlib.h>
  22. #include <unistd.h>
  23. #include <math.h>
  24. #include "printf/printf.h"
  25. #include "zz9k_env.h"
  26. typedef struct Vec2 {
  27. float x;
  28. float y;
  29. } Vec2;
  30. typedef struct Vec3 {
  31. float x,y,z;
  32. } Vec3;
  33. typedef struct Tri3 {
  34. uint32_t color1;
  35. uint32_t color2;
  36. uint32_t color3;
  37. Vec3 a;
  38. Vec3 b;
  39. Vec3 c;
  40. } Tri3;
  41. static uint32_t* fb=0;
  42. static uint32_t fb_pitch=0;
  43. struct ZZ9K_ENV* _zz9k_env;
  44. void __aeabi_idiv0(int r) {
  45. while (1) {
  46. printf("__aeabi_idiv0()!\n");
  47. }
  48. }
  49. void __aeabi_ldiv0(int r) {
  50. while (1) {
  51. printf("__aeabi_idiv0()!\n");
  52. }
  53. }
  54. int errno_var = 0;
  55. int* __errno() {
  56. return &errno_var;
  57. }
  58. void _putchar(char c) {
  59. _zz9k_env->putchar(c);
  60. };
  61. void set_fb(uint32_t* fb_, uint32_t pitch) {
  62. fb=fb_;
  63. fb_pitch=pitch;
  64. }
  65. void horizline(uint16_t x1, uint16_t x2, uint16_t y, uint32_t color) {
  66. uint32_t* p=fb+y*fb_pitch;
  67. uint16_t tmp;
  68. if (x2>x1) {
  69. tmp=x1; x1=x2; x2=tmp;
  70. }
  71. while (x1>x2) {
  72. p[x1]=(p[x1]+color)/2;
  73. x1--;
  74. }
  75. }
  76. void horizline2(uint16_t x1, uint16_t x2, uint16_t y, uint32_t color1, uint32_t color2, uint32_t z) {
  77. uint32_t* p=fb+y*fb_pitch;
  78. uint16_t tmp;
  79. if (x2>x1) {
  80. tmp=x1; x1=x2; x2=tmp;
  81. }
  82. float b1=(color1&0xff0000)>>16;
  83. float g1=(color1&0xff00)>>8;
  84. float r1=color1&0xff;
  85. float b2=(color2&0xff0000)>>16;
  86. float g2=(color2&0xff00)>>8;
  87. float r2=color2&0xff;
  88. float d = x1-x2;
  89. float fb1 = (b2-b1)/d;
  90. float fg1 = (g2-g1)/d;
  91. float fr1 = (r2-r1)/d;
  92. while (x1>x2) {
  93. float zz = p[x1]>>24;
  94. if (zz<z) {
  95. p[x1]=((uint32_t)z<<24)|((uint32_t)b2<<16)|((uint32_t)g2<<8)|((uint32_t)r2);
  96. }
  97. x1--;
  98. b2+=fb1;
  99. g2+=fg1;
  100. r2+=fr1;
  101. }
  102. }
  103. void fill_triangle(Vec2 A, Vec2 B, Vec2 C, uint32_t color) {
  104. float dx1 = 0;
  105. float dx2 = 0;
  106. float dx3 = 0;
  107. // sort points by Y coord
  108. Vec2 tmp;
  109. if (A.y>B.y) { tmp=A; A=B; B=tmp; }
  110. if (B.y>C.y) {
  111. tmp=B; B=C; C=tmp;
  112. if (A.y>B.y) { tmp=A; A=B; B=tmp; }
  113. }
  114. //printf("triangle: %f,%f %f,%f %f,%f\n",A.x,A.y,B.x,B.y,C.x,C.y);
  115. if (B.y-A.y > 0) dx1=(B.x-A.x)/(B.y-A.y); else dx1=0;
  116. if (C.y-A.y > 0) dx2=(C.x-A.x)/(C.y-A.y); else dx2=0;
  117. if (C.y-B.y > 0) dx3=(C.x-B.x)/(C.y-B.y); else dx3=0;
  118. Vec2 S=A;
  119. Vec2 E=A;
  120. if(dx1 > dx2) {
  121. for(;S.y<=B.y;S.y++,E.y++,S.x+=dx2,E.x+=dx1)
  122. horizline(S.x,E.x,S.y,color);
  123. E=B;
  124. for(;S.y<=C.y;S.y++,E.y++,S.x+=dx2,E.x+=dx3)
  125. horizline(S.x,E.x,S.y,color);
  126. } else {
  127. for(;S.y<=B.y;S.y++,E.y++,S.x+=dx1,E.x+=dx2)
  128. horizline(S.x,E.x,S.y,color);
  129. S=B;
  130. for(;S.y<=C.y;S.y++,E.y++,S.x+=dx3,E.x+=dx2)
  131. horizline(S.x,E.x,S.y,color);
  132. }
  133. }
  134. void fill_triangle2(Vec2 A, Vec2 B, Vec2 C, uint32_t color1, uint32_t color2, uint32_t color3,float z) {
  135. float dx1 = 0;
  136. float dx2 = 0;
  137. float dx3 = 0;
  138. // sort points by Y coord
  139. Vec2 tmp;
  140. if (A.y>B.y) { tmp=A; A=B; B=tmp; }
  141. if (B.y>C.y) {
  142. tmp=B; B=C; C=tmp;
  143. if (A.y>B.y) { tmp=A; A=B; B=tmp; }
  144. }
  145. //printf("triangle: %f,%f %f,%f %f,%f\n",A.x,A.y,B.x,B.y,C.x,C.y);
  146. if (B.y-A.y > 0) dx1=(B.x-A.x)/(B.y-A.y); else dx1=0;
  147. if (C.y-A.y > 0) dx2=(C.x-A.x)/(C.y-A.y); else dx2=0;
  148. if (C.y-B.y > 0) dx3=(C.x-B.x)/(C.y-B.y); else dx3=0;
  149. Vec2 S=A;
  150. Vec2 E=A;
  151. if(dx1 > dx2) {
  152. for(;S.y<=B.y;S.y++,E.y++,S.x+=dx2,E.x+=dx1)
  153. horizline2(S.x,E.x,S.y,color1,color2,z);
  154. E=B;
  155. for(;S.y<=C.y;S.y++,E.y++,S.x+=dx2,E.x+=dx3)
  156. horizline2(S.x,E.x,S.y,color1,color2,z);
  157. } else {
  158. for(;S.y<=B.y;S.y++,E.y++,S.x+=dx1,E.x+=dx2)
  159. horizline2(S.x,E.x,S.y,color1,color2,z);
  160. S=B;
  161. for(;S.y<=C.y;S.y++,E.y++,S.x+=dx3,E.x+=dx2)
  162. horizline2(S.x,E.x,S.y,color1,color2,z);
  163. }
  164. }
  165. void fill_rect32(uint16_t rect_x1, uint16_t rect_y1, uint16_t rect_x2, uint16_t rect_y2, uint32_t rect_rgb) {
  166. for (uint16_t y=rect_y1; y<=rect_y2; y++) {
  167. uint32_t* p=fb+y*fb_pitch;
  168. for (uint16_t x=rect_x1; x<=rect_x2; x++) {
  169. p[x]=rect_rgb;
  170. }
  171. }
  172. }
  173. void copy_rect32(uint16_t rect_x1, uint16_t rect_y1, uint16_t rect_x2, uint16_t rect_y2, uint16_t rect_sx, uint16_t rect_sy) {
  174. int8_t ystep=1, xstep=1;
  175. uint16_t tmp;
  176. if (rect_sy < rect_y1) {
  177. uint16_t h = rect_y2-rect_y1;
  178. ystep=-1;
  179. tmp=rect_y2; rect_y2=rect_y1; rect_y1=tmp;
  180. rect_sy+=h;
  181. }
  182. if (rect_sx < rect_x1) {
  183. uint16_t w = rect_x2-rect_x1;
  184. xstep=-1;
  185. tmp=rect_x2; rect_x2=rect_x1; rect_x1=tmp;
  186. rect_sx+=w;
  187. }
  188. rect_y2+=ystep;
  189. rect_x2+=xstep;
  190. for (uint16_t sy=rect_sy, dy=rect_y1; dy!=rect_y2; sy+=ystep, dy+=ystep) {
  191. uint32_t* dp=(uint32_t*)(fb+dy*fb_pitch);
  192. uint32_t* sp=(uint32_t*)(fb+sy*fb_pitch);
  193. for (uint16_t sx=rect_sx, dx=rect_x1; dx!=rect_x2; sx+=xstep, dx+=xstep) {
  194. dp[dx]=sp[sx];
  195. }
  196. }
  197. }
  198. float rot_matrix[4][4];
  199. float matrix_out[4][1];
  200. float matrix_in[4][1];
  201. void multiply_matrix()
  202. {
  203. for(int i = 0; i < 4; i++) {
  204. for(int j = 0; j < 1; j++) {
  205. matrix_out[i][j] = 0;
  206. for(int k = 0; k < 4; k++) {
  207. matrix_out[i][j] += rot_matrix[i][k] * matrix_in[k][j];
  208. }
  209. }
  210. }
  211. }
  212. void init_rot_matrix(float angle, float u, float v, float w)
  213. {
  214. float L = (u*u + v * v + w * w);
  215. angle = angle * M_PI / 180.0; //converting to radian value
  216. float u2 = u * u;
  217. float v2 = v * v;
  218. float w2 = w * w;
  219. rot_matrix[0][0] = (u2 + (v2 + w2) * cos(angle)) / L;
  220. rot_matrix[0][1] = (u * v * (1 - cos(angle)) - w * sqrt(L) * sin(angle)) / L;
  221. rot_matrix[0][2] = (u * w * (1 - cos(angle)) + v * sqrt(L) * sin(angle)) / L;
  222. rot_matrix[0][3] = 0.0;
  223. rot_matrix[1][0] = (u * v * (1 - cos(angle)) + w * sqrt(L) * sin(angle)) / L;
  224. rot_matrix[1][1] = (v2 + (u2 + w2) * cos(angle)) / L;
  225. rot_matrix[1][2] = (v * w * (1 - cos(angle)) - u * sqrt(L) * sin(angle)) / L;
  226. rot_matrix[1][3] = 0.0;
  227. rot_matrix[2][0] = (u * w * (1 - cos(angle)) - v * sqrt(L) * sin(angle)) / L;
  228. rot_matrix[2][1] = (v * w * (1 - cos(angle)) + u * sqrt(L) * sin(angle)) / L;
  229. rot_matrix[2][2] = (w2 + (u2 + v2) * cos(angle)) / L;
  230. rot_matrix[2][3] = 0.0;
  231. rot_matrix[3][0] = 0.0;
  232. rot_matrix[3][1] = 0.0;
  233. rot_matrix[3][2] = 0.0;
  234. rot_matrix[3][3] = 1.0;
  235. }
  236. static int last_angle=0;
  237. void render_faces(float screen_x, float screen_y, float y_angle) {
  238. fill_rect32(screen_x-150,screen_y-100,screen_x+150,screen_y+100,0);
  239. init_rot_matrix(y_angle,1,1,0);
  240. // BGRA
  241. // front
  242. Tri3 triangles[] = {
  243. { 0x00000000, 0x0000ffff, 0x00ffffff, {-1,-1,-1}, { 1,-1,-1}, { 1, 1,-1}},
  244. //{ 0x00008888, {-1,-1,-1}, { 1, 1,-1}, {-1, 1,-1}},
  245. // back
  246. { 0x00000000, 0x00ffff00, 0x00ffffff, {-1,-1, 1}, { 1,-1, 1}, { 1, 1, 1}},
  247. //{ 0x00888800, {-1,-1, 1}, { 1, 1, 1}, {-1, 1, 1}},
  248. //
  249. { 0x00000000, 0x00ff00ff, 0x00ffffff, {-1,-1,-1}, {-1,-1, 1}, {-1, 1,-1}},
  250. //{ 0x00880088, {-1,-1, 1}, {-1, 1, 1}, {-1, 1,-1}},
  251. };
  252. float trans_z=2;
  253. float scale=64;
  254. matrix_in[3][0]=1;
  255. for (int i=0; i<3; i++) {
  256. Tri3 t = triangles[i];
  257. matrix_in[0][0]=t.a.x;
  258. matrix_in[1][0]=t.a.y;
  259. matrix_in[2][0]=t.a.z;
  260. multiply_matrix();
  261. float x=matrix_out[0][0], y=matrix_out[1][0], z=matrix_out[2][0];
  262. Vec2 a = {screen_x+scale*x/(trans_z+z), screen_y+scale*y/(trans_z+z)};
  263. matrix_in[0][0]=t.b.x;
  264. matrix_in[1][0]=t.b.y;
  265. matrix_in[2][0]=t.b.z;
  266. multiply_matrix();
  267. x=matrix_out[0][0], y=matrix_out[1][0], z=matrix_out[2][0];
  268. Vec2 b = {screen_x+scale*x/(trans_z+z), screen_y+scale*y/(trans_z+z)};
  269. matrix_in[0][0]=t.c.x;
  270. matrix_in[1][0]=t.c.y;
  271. matrix_in[2][0]=t.c.z;
  272. multiply_matrix();
  273. x=matrix_out[0][0], y=matrix_out[1][0], z=matrix_out[2][0];
  274. Vec2 c = {screen_x+scale*x/(trans_z+z), screen_y+scale*y/(trans_z+z)};
  275. fill_triangle2(a,b,c,t.color1,t.color2,t.color3,128-z);
  276. }
  277. copy_rect32(screen_x-150,screen_y-100-500,screen_x+150,screen_y+100-500, screen_x-150, screen_y-100);
  278. }
  279. int __attribute__ ((section (".binstart"))) main(struct ZZ9K_ENV* env) {
  280. _zz9k_env = env;
  281. if (!env) {
  282. return 1;
  283. }
  284. if (env->argc<2) {
  285. return 1;
  286. }
  287. // arg0: framebuffer pointer
  288. // arg1: screen width
  289. set_fb((uint32_t*)env->argv[0],env->argv[1]);
  290. fill_rect32(0,0,319,240-13,0);
  291. float angle = 0;
  292. while (1) {
  293. render_faces(env->argv[1]/2,env->argv[1]/3+500,angle);
  294. angle+=1.0;
  295. }
  296. return 0;
  297. }