test.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. /**
  2. Some basic tests for small3dlib.
  3. author: Miloslav Ciz
  4. license: CC0 1.0
  5. */
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <math.h>
  9. #define S3L_PIXEL_FUNCTION pixelFunc
  10. #define S3L_RESOLUTION_X 64
  11. #define S3L_RESOLUTION_Y 40
  12. #define S3L_SORT 1
  13. #include "../small3dlib.h"
  14. #define TEST_BUFFER_W 16
  15. #define TEST_BUFFER_H 16
  16. const char expectedRender[S3L_RESOLUTION_X * S3L_RESOLUTION_Y + 1] =
  17. "...................54433221100.................................."
  18. "...................55443221100.................................."
  19. "...................6554432211..................................."
  20. "...................65544332....................................."
  21. "...................665544......................................."
  22. "..........AAA......7655........................................."
  23. "..........BAAACE...76..........................................."
  24. "..........CABAABDEG..........................................ddd"
  25. ".........DBABAAABCDFGH...............................eeeeeeeeddd"
  26. ".........DBABBAAABCDEGH.....................fffffffeeeeeeeeeeddd"
  27. ".........EDBACBAAABCDEFG............gggggffffffffffeeeeeeeeeeddd"
  28. "........FECBACCBBAAABDEG....hhhggggggggggffffffffffeeeeeeeeeeddd"
  29. "........GFDCBADCBBAihhhhhhhhhhggggggggggffffffffffeeeeeeeeeeeddd"
  30. "........HFECBADCCBBahhhhhhhhhhggggggggggffffffffffeeeeeeeeeeeddd"
  31. ".......IGFECBADDCCBaahhhhhhhhhggggggggggffffffffffeeeeeeeeeeeddd"
  32. "........HGEDCBAEDCCaaahhhhhhhhggggggggggfffffffffffeeeeeeeeeeddd"
  33. "........AGFDCBAEDDCaaaahhhhhhhgggggggggggffffffffffeeeeeeeeeeddd"
  34. "........BAFECBAEEDDaaaaahhhhhhhggggggggggffffffffffeeeeeeeeeeddd"
  35. "........BAAFDCBAFEEaaaaaahhhhhhggggggggggffffffffffeeeeeeeeeeddd"
  36. ".........BAAECBAFFEbaaaaahhhhhggggggggggffffffffffeeeeeeeeeeeddd"
  37. ".........CBAADCBAGFbbaaaaahhhhggggggggggffffffffffeeeeeeeeeeeddd"
  38. ".........CCBAACBAGFbbbaaaaahhhggggggggggfffffffffffeeeeeeeeeeddd"
  39. ".........DCBBAACAGGbbbbaaaaahhgggggggggggffffffffffeeeeeeeeeeddd"
  40. "..........DCCBAABAHbbbbbaaaaahhggggggggggffffffffffeeeeeeeeeeddd"
  41. "..........DDCBBAAAHbbbbbaaaaaahggggggggggffffffffffeeeeeeeeeeddd"
  42. "..........EDDCBBAAIcbbbbbaaaaaaggggggggggffffffffffeeeeeeeeeeddd"
  43. "..........EEDDCCBAHccbbbbbaaaaagggggggggffffffffffeeeeeeeeeeeddd"
  44. "...........FEDDCBGFcccbbbbbaaaaaggggggggfffffffffffeeeeeeeeeeddd"
  45. "...........FEEDCFEDccccbbbbbaaaaaggggggggffffffffffeeeeeeeeeeddd"
  46. "...........GFEEDEDCcccccbbbbbaaaaagggggggffffffffffeeeeeeeeeeddd"
  47. "...........GFFEDCBAcccccbbbbbaaaaaaggggggffffffffffeeeeeeeeeeddd"
  48. "............GFCBAACdcccccbbbbbaaaaaagggggffffffffffeeeeeeeeeeddd"
  49. "............HGBABAAddcccccbbbbbaaaaaggggffffffffffeeeeeeeeeeeddd"
  50. "............HAAA...dddcccccbbbbbaaaaagggfffffffffffeeeeeeeeeeddd"
  51. "...................ddddcccccbbbbbaaaaagggffffffffffeeeeeeeeeeddd"
  52. "...................dddddcccccbbbbbaaaaaggffffffffffeeeeeeeeeeddd"
  53. "...................dddddcccccbbbbbaaaaaagffffffffffeeeeeeeeeeddd"
  54. "...................edddddcccccbbbbbaaaaaaffffffffffeeeeeeeeeeddd"
  55. "...................eedddddcccccbbbbbaaaaaafffffffffeeeeeeeeeeddd"
  56. "...................eeedddddcccccbbbbbaaaaafffffffffeeeeeeeeeeddd";
  57. uint8_t testRaster[TEST_BUFFER_W * TEST_BUFFER_H];
  58. uint8_t testScreen[S3L_RESOLUTION_X * S3L_RESOLUTION_Y];
  59. uint8_t renderingMode = 0;
  60. void pixelFunc(S3L_PixelInfo *p)
  61. {
  62. if (renderingMode == 0)
  63. testRaster[p->y * TEST_BUFFER_W + p->x] += 1;
  64. else
  65. {
  66. char c = 'x';
  67. switch (p->modelIndex)
  68. {
  69. case 0: c = 'a'; break;
  70. case 1: c = 'A'; break;
  71. case 2: c = '0'; break;
  72. default: break;
  73. }
  74. c += ((p->barycentric[0] * 8) / S3L_FRACTIONS_PER_UNIT);
  75. testScreen[p->y * S3L_RESOLUTION_X + p->x] = c;
  76. }
  77. }
  78. int testTriangleRasterization(
  79. S3L_ScreenCoord x0,
  80. S3L_ScreenCoord y0,
  81. S3L_ScreenCoord x1,
  82. S3L_ScreenCoord y1,
  83. S3L_ScreenCoord x2,
  84. S3L_ScreenCoord y2,
  85. uint8_t *expectedPixels
  86. )
  87. {
  88. printf(" --- testing tringle rasterization [%d,%d] [%d,%d] [%d,%d] (|: expected, -: rasterized) ----\n",x0,y0,x1,y1,x2,y2);
  89. memset(testRaster,0,TEST_BUFFER_W * TEST_BUFFER_H);
  90. S3L_Vec4 p0, p1, p2;
  91. S3L_vec4Set(&p0,x0,y0,1000,0);
  92. S3L_vec4Set(&p1,x1,y1,1000,0);
  93. S3L_vec4Set(&p2,x2,y2,1000,0);
  94. S3L_drawTriangle(p0,p1,p2,0,0);
  95. printf(" 0123456789ABCDEF\n");
  96. uint16_t numErrors = 0;
  97. for (uint8_t y = 0; y < TEST_BUFFER_H; ++y)
  98. {
  99. printf(" %d",y);
  100. if (y < 10)
  101. printf(" ");
  102. for (uint8_t x = 0; x < TEST_BUFFER_W; ++x)
  103. {
  104. uint8_t expected = expectedPixels[y * TEST_BUFFER_W + x];
  105. uint8_t rasterized = testRaster[y * TEST_BUFFER_W + x];
  106. char c =
  107. expected ?
  108. (rasterized ? '+' : '|')
  109. :
  110. (rasterized ? '-' : ' ');
  111. if (c == '-' || c == '|')
  112. numErrors++;
  113. printf("%c",c);
  114. }
  115. printf("\n");
  116. }
  117. printf(" errors: %d\n\n",numErrors);
  118. return numErrors;
  119. }
  120. int testRasterization(void)
  121. {
  122. printf("\n=== TESTING RASTERIZATION ===\n");
  123. uint16_t numErrors = 0;
  124. uint8_t pixelsEmpty[TEST_BUFFER_W * TEST_BUFFER_H];
  125. memset(pixelsEmpty,0,TEST_BUFFER_W * TEST_BUFFER_H);
  126. numErrors += testTriangleRasterization(5,3, 3,3, 9,3, pixelsEmpty);
  127. numErrors += testTriangleRasterization(9,4, 9,0, 9,9, pixelsEmpty);
  128. numErrors += testTriangleRasterization(9,9, 6,6, 3,3, pixelsEmpty);
  129. numErrors += testTriangleRasterization(0,6, 3,3, 6,0, pixelsEmpty);
  130. numErrors += testTriangleRasterization(7,7, 7,7, 7,7, pixelsEmpty);
  131. uint8_t pixels1[TEST_BUFFER_W * TEST_BUFFER_H] =
  132. {
  133. // 0 1 2 3 4 5 6 7 8 9 A B C D E F
  134. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0
  135. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1
  136. 0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, // 2
  137. 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, // 3
  138. 0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0, // 4
  139. 0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0, // 5
  140. 0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, // 6
  141. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 7
  142. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 8
  143. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 9
  144. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A
  145. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B
  146. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // C
  147. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // D
  148. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // E
  149. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // F
  150. };
  151. numErrors += testTriangleRasterization(4,1, 1,6, 9,7, pixels1);
  152. uint8_t pixels2[TEST_BUFFER_W * TEST_BUFFER_H] =
  153. {
  154. // 0 1 2 3 4 5 6 7 8 9 A B C D E F
  155. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0
  156. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1
  157. 0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0, // 2
  158. 0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0, // 3
  159. 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, // 4
  160. 0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, // 5
  161. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 6
  162. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 7
  163. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 8
  164. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 9
  165. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A
  166. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B
  167. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // C
  168. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // D
  169. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // E
  170. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // F
  171. };
  172. numErrors += testTriangleRasterization(7,1, 1,2, 4,6, pixels2);
  173. uint8_t pixels3[TEST_BUFFER_W * TEST_BUFFER_H] =
  174. {
  175. // 0 1 2 3 4 5 6 7 8 9 A B C D E F
  176. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0
  177. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1
  178. 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, // 2
  179. 0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, // 3
  180. 0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0, // 4
  181. 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, // 5
  182. 0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, // 6
  183. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 7
  184. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 8
  185. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 9
  186. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A
  187. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B
  188. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // C
  189. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // D
  190. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // E
  191. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // F
  192. };
  193. numErrors += testTriangleRasterization(2,1, 1,3, 6,9, pixels3);
  194. uint8_t pixels4[TEST_BUFFER_W * TEST_BUFFER_H] =
  195. {
  196. // 0 1 2 3 4 5 6 7 8 9 A B C D E F
  197. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0
  198. 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1
  199. 0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, // 2
  200. 0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0, // 3
  201. 0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0, // 4
  202. 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, // 5
  203. 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, // 6
  204. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 7
  205. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 8
  206. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 9
  207. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A
  208. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B
  209. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // C
  210. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // D
  211. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // E
  212. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // F
  213. };
  214. numErrors += testTriangleRasterization(4,8, 4,2, 0,0, pixels4);
  215. uint8_t pixels5[TEST_BUFFER_W * TEST_BUFFER_H] =
  216. {
  217. // 0 1 2 3 4 5 6 7 8 9 A B C D E F
  218. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0
  219. 0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, // 1
  220. 0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0, // 2
  221. 0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0, // 3
  222. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 4
  223. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 5
  224. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 6
  225. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 7
  226. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 8
  227. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 9
  228. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A
  229. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B
  230. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // C
  231. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // D
  232. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // E
  233. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // F
  234. };
  235. numErrors += testTriangleRasterization(6,2, 2,4, 0,0, pixels5);
  236. uint8_t pixels6[TEST_BUFFER_W * TEST_BUFFER_H] =
  237. {
  238. // 0 1 2 3 4 5 6 7 8 9 A B C D E F
  239. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0
  240. 0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0, // 1
  241. 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0, // 2
  242. 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0, // 3
  243. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 4
  244. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 5
  245. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 6
  246. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 7
  247. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 8
  248. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 9
  249. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A
  250. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B
  251. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // C
  252. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // D
  253. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // E
  254. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // F
  255. };
  256. numErrors += testTriangleRasterization(0,2, 6,0, 4,4, pixels6);
  257. printf("cover test (each pixel should be covered exactly once):\n\n");
  258. S3L_ScreenCoord coords[] =
  259. {
  260. 0,0,
  261. 6,0,
  262. 13,0,
  263. 15,0,
  264. 14,1,
  265. 11,2,
  266. 3,3,
  267. 11,4,
  268. 14,5,
  269. 0,6,
  270. 6,6,
  271. 13,8,
  272. 8,9,
  273. 3,12,
  274. 9,12,
  275. 11,13,
  276. 9,14,
  277. 0,15,
  278. 15,15
  279. };
  280. memset(testRaster,0,TEST_BUFFER_W * TEST_BUFFER_H);
  281. #define dt(i1,i2,i3)\
  282. {\
  283. S3L_Vec4 p0, p1, p2;\
  284. S3L_vec4Set(&p0,coords[2*i1],coords[2*i1 + 1],1000,0);\
  285. S3L_vec4Set(&p1,coords[2*i2],coords[2*i2+1],1000,0);\
  286. S3L_vec4Set(&p2,coords[2*i3],coords[2*i3+1],1000,0);\
  287. S3L_drawTriangle(p0,p1,p2,0,0);\
  288. }
  289. dt(0,1,6) // 0
  290. dt(1,2,5) // 1
  291. dt(2,4,5) // 2
  292. dt(2,3,4) // 3
  293. dt(0,6,9) // 4
  294. dt(1,10,6) // 5
  295. dt(1,5,10) // 6
  296. dt(5,4,8) // 7
  297. dt(4,3,8) // 8
  298. dt(9,6,10) // 9
  299. dt(10,5,12) // 10
  300. dt(5,7,12) // 11
  301. dt(5,7,11) // 12
  302. dt(5,8,11) // 13
  303. dt(8,3,18) // 14
  304. dt(9,10,13) // 15
  305. dt(10,12,13) // 16
  306. dt(12,7,11) // 17
  307. dt(11,8,18) // 18
  308. dt(9,13,17) // 19
  309. dt(13,12,14) // 20
  310. dt(12,11,14) // 21
  311. dt(11,14,15) // 22
  312. dt(15,11,18) // 23
  313. dt(13,14,16) // 24
  314. dt(14,15,16) // 25
  315. dt(17,13,16) // 26
  316. dt(16,15,18) // 27
  317. dt(16,17,18) // 28
  318. // extra empty triangles
  319. dt(12,12,12);
  320. dt(9,10,10);
  321. dt(1,10,10);
  322. dt(9,6,1);
  323. dt(0,6,10);
  324. #undef dt
  325. uint16_t numErrors2 = 0;
  326. for (uint8_t y = 0; y < TEST_BUFFER_H - 1; ++y)
  327. { // ^ complete left and bottom aren't
  328. printf(" "); // supposed to be rasterized
  329. for (uint8_t x = 0; x < TEST_BUFFER_W - 1; ++x)
  330. {
  331. uint8_t count = testRaster[y * TEST_BUFFER_W + x];
  332. printf("%d",count);
  333. if (count != 1)
  334. numErrors2++;
  335. }
  336. printf("\n");
  337. }
  338. printf(" errors: %d\n",numErrors2);
  339. numErrors += numErrors2;
  340. printf("total rasterization errors: %d\n",numErrors);
  341. return numErrors;
  342. }
  343. static inline double absVal(double a)
  344. {
  345. return a >= 0.0 ? a : (-1 * a);
  346. }
  347. double vec3Len(S3L_Vec4 v)
  348. {
  349. return sqrt(
  350. ((double) v.x) * ((double) v.x) +
  351. ((double) v.y) * ((double) v.y) +
  352. ((double) v.z) * ((double) v.z));
  353. }
  354. int testGeneral(void)
  355. {
  356. printf("\n=== TESTING GENERAL ===\n");
  357. printf("testing vector normalization precision...\n");
  358. S3L_Unit m = 100 * S3L_FRACTIONS_PER_UNIT;
  359. S3L_Unit tolerance = 0.1 * S3L_FRACTIONS_PER_UNIT;
  360. uint32_t errors0 = 0;
  361. uint32_t errors1 = 0;
  362. for (S3L_Unit x = -1 * m; x < m; x += 3 * (absVal(x) / 64 + 1))
  363. for (S3L_Unit y = -1 * m; y < m; y += 3 * (absVal(y) / 32 + 1))
  364. for (S3L_Unit z = -1 * m; z < m; z += 5 * (absVal(z) / 64 + 1))
  365. {
  366. S3L_Vec4 v;
  367. S3L_vec4Set(&v,x,y,z,0);
  368. S3L_vec3NormalizeFast(&v);
  369. double l0 = vec3Len(v);
  370. double e0 = absVal(l0 - S3L_FRACTIONS_PER_UNIT);
  371. S3L_vec4Set(&v,x,y,z,0);
  372. S3L_vec3Normalize(&v);
  373. double l1 = vec3Len(v);
  374. double e1 = absVal(l1 - S3L_FRACTIONS_PER_UNIT);
  375. if (e0 > tolerance)
  376. errors0++;
  377. if (e1 > tolerance)
  378. {
  379. errors1++;
  380. printf("%f\n",l1);
  381. S3L_logVec4(v);
  382. }
  383. }
  384. printf("wrong normalization with unsafe function: %d\nwrong normalizations with safe function: %d\n",errors0,errors1);
  385. return errors1;
  386. }
  387. S3L_Unit cubeVertices[] = { S3L_CUBE_VERTICES(S3L_FRACTIONS_PER_UNIT) };
  388. S3L_Index cubeTriangles[] = { S3L_CUBE_TRIANGLES };
  389. S3L_Unit triangleVertices[] = { -512, 0, 512, 402, 0, 200, 0, 600, 0 };
  390. S3L_Index triangleTriangles[] = { 0, 1, 2 };
  391. S3L_Model3D cubeModel;
  392. S3L_Model3D triangleModel;
  393. S3L_Model3D models[4];
  394. S3L_Scene scene;
  395. int testRender(void)
  396. {
  397. printf("\n=== TESTING RENDER ===\n");
  398. memset(testScreen,'.',S3L_RESOLUTION_X * S3L_RESOLUTION_Y);
  399. S3L_model3DInit(cubeVertices,S3L_CUBE_VERTEX_COUNT,cubeTriangles,S3L_CUBE_TRIANGLE_COUNT,&cubeModel);
  400. S3L_model3DInit(triangleVertices,3,triangleTriangles,1,&triangleModel);
  401. models[0] = cubeModel;
  402. models[0].transform.translation.z -= S3L_FRACTIONS_PER_UNIT;
  403. models[1] = cubeModel;
  404. models[1].transform.translation.x -= S3L_FRACTIONS_PER_UNIT * 2;
  405. models[1].transform.translation.y = S3L_FRACTIONS_PER_UNIT / 2;
  406. models[1].transform.scale.y = S3L_FRACTIONS_PER_UNIT * 2;
  407. models[1].transform.rotation.x = 200;
  408. models[1].transform.rotation.y = 100;
  409. models[2] = triangleModel;
  410. models[2].transform.translation.x = -1000;
  411. models[2].transform.translation.y = 1000;
  412. models[3] = triangleModel;
  413. models[3].transform.translation.x = -1500;
  414. models[3].transform.translation.y = 1200;
  415. models[3].transform.rotation.x = S3L_FRACTIONS_PER_UNIT / 2; // turn away, test BF culling
  416. S3L_sceneInit(models,4,&scene);
  417. scene.camera.transform.translation.z = -2 * S3L_FRACTIONS_PER_UNIT;
  418. scene.camera.transform.translation.y = S3L_FRACTIONS_PER_UNIT / 3;
  419. scene.camera.transform.rotation.y = 30;
  420. renderingMode = 1;
  421. S3L_newFrame();
  422. S3L_drawScene(scene);
  423. int errors = 0;
  424. for (uint32_t i = 0; i < (S3L_RESOLUTION_X * S3L_RESOLUTION_Y); ++i)
  425. {
  426. if ((i % S3L_RESOLUTION_X) == 0)
  427. printf(" \n");
  428. printf("%c",testScreen[i]);
  429. if (testScreen[i] != expectedRender[i])
  430. errors += 1;
  431. }
  432. return errors;
  433. }
  434. int main(void)
  435. {
  436. printf("testing small3dlib\n\n");
  437. S3L_Mat4 m, m2;
  438. S3L_Vec4 v;
  439. S3L_mat4Init(&m);
  440. S3L_logMat4(m);
  441. S3L_vec4Init(&v);
  442. S3L_logVec4(v);
  443. S3L_vec4Xmat4(&v,&m);
  444. S3L_logVec4(v);
  445. S3L_makeTranslationMat(100,200,300,&m2);
  446. S3L_logMat4(m2);
  447. S3L_mat4Xmat4(&m,&m2);
  448. S3L_logMat4(m);
  449. uint32_t totalErrors = 0;
  450. totalErrors += testGeneral();
  451. totalErrors += testRasterization();
  452. totalErrors += testRender();
  453. printf("\n\n===== DONE =====\ntotal errors: %d\n",totalErrors);
  454. return 0;
  455. }