sokol_shape_test.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. //------------------------------------------------------------------------------
  2. // sokol-shape-test.c
  3. //------------------------------------------------------------------------------
  4. #include "sokol_gfx.h"
  5. #define SOKOL_SHAPE_IMPL
  6. #include "sokol_shape.h"
  7. #include "utest.h"
  8. #define T(b) EXPECT_TRUE(b)
  9. #define TFLT(f0,f1,epsilon) {T(fabs((f0)-(f1))<=(epsilon));}
  10. UTEST(sokol_shape, color4f) {
  11. T(sshape_color_4f(1.0f, 0.0f, 0.0f, 0.0f) == 0x000000FF);
  12. T(sshape_color_4f(0.0f, 1.0f, 0.0f, 0.0f) == 0x0000FF00);
  13. T(sshape_color_4f(0.0f, 0.0f, 1.0f, 0.0f) == 0x00FF0000);
  14. T(sshape_color_4f(0.0f, 0.0f, 0.0f, 1.0f) == 0xFF000000);
  15. }
  16. UTEST(sokol_shape, color3f) {
  17. T(sshape_color_3f(1.0f, 0.0f, 0.0f) == 0xFF0000FF);
  18. T(sshape_color_3f(0.0f, 1.0f, 0.0f) == 0xFF00FF00);
  19. T(sshape_color_3f(0.0f, 0.0f, 1.0f) == 0xFFFF0000);
  20. }
  21. UTEST(sokol_shape, color4b) {
  22. T(sshape_color_4b(255, 0, 0, 0) == 0x000000FF);
  23. T(sshape_color_4b(0, 255, 0, 0) == 0x0000FF00);
  24. T(sshape_color_4b(0, 0, 255, 0) == 0x00FF0000);
  25. T(sshape_color_4b(0, 0, 0, 255) == 0xFF000000);
  26. }
  27. UTEST(sokol_shape, color3b) {
  28. T(sshape_color_3b(255, 0, 0) == 0xFF0000FF);
  29. T(sshape_color_3b(0, 255, 0) == 0xFF00FF00);
  30. T(sshape_color_3b(0, 0, 255) == 0xFFFF0000);
  31. }
  32. UTEST(sokol_shape, mat4) {
  33. float values[16] = {
  34. 1.0f, 2.0f, 3.0f, 4.0f,
  35. 5.0f, 6.0f, 7.0f, 8.0f,
  36. 9.0f, 10.0f, 11.0f, 12.0f,
  37. 13.0f, 14.0f, 15.0f, 16.0f
  38. };
  39. sshape_mat4_t m = sshape_mat4(values);
  40. T(m.m[0][0] == 1.0f);
  41. T(m.m[0][1] == 2.0f);
  42. T(m.m[0][2] == 3.0f);
  43. T(m.m[0][3] == 4.0f);
  44. T(m.m[1][0] == 5.0f);
  45. T(m.m[1][1] == 6.0f);
  46. T(m.m[1][2] == 7.0f);
  47. T(m.m[1][3] == 8.0f);
  48. T(m.m[2][0] == 9.0f);
  49. T(m.m[2][1] == 10.0f);
  50. T(m.m[2][2] == 11.0f);
  51. T(m.m[2][3] == 12.0f);
  52. T(m.m[3][0] == 13.0f);
  53. T(m.m[3][1] == 14.0f);
  54. T(m.m[3][2] == 15.0f);
  55. T(m.m[3][3] == 16.0f);
  56. }
  57. UTEST(sokol_shape, mat4_transpose) {
  58. float values[16] = {
  59. 1.0f, 2.0f, 3.0f, 4.0f,
  60. 5.0f, 6.0f, 7.0f, 8.0f,
  61. 9.0f, 10.0f, 11.0f, 12.0f,
  62. 13.0f, 14.0f, 15.0f, 16.0f
  63. };
  64. sshape_mat4_t m = sshape_mat4_transpose(values);
  65. T(m.m[0][0] == 1.0f);
  66. T(m.m[1][0] == 2.0f);
  67. T(m.m[2][0] == 3.0f);
  68. T(m.m[3][0] == 4.0f);
  69. T(m.m[0][1] == 5.0f);
  70. T(m.m[1][1] == 6.0f);
  71. T(m.m[2][1] == 7.0f);
  72. T(m.m[3][1] == 8.0f);
  73. T(m.m[0][2] == 9.0f);
  74. T(m.m[1][2] == 10.0f);
  75. T(m.m[2][2] == 11.0f);
  76. T(m.m[3][2] == 12.0f);
  77. T(m.m[0][3] == 13.0f);
  78. T(m.m[1][3] == 14.0f);
  79. T(m.m[2][3] == 15.0f);
  80. T(m.m[3][3] == 16.0f);
  81. }
  82. UTEST(sokol_shape, plane_buffer_sizes) {
  83. sshape_sizes_t res;
  84. res = sshape_plane_sizes(1);
  85. T(4 == res.vertices.num);
  86. T(6 == res.indices.num);
  87. T(res.vertices.num * sizeof(sshape_vertex_t) == res.vertices.size);
  88. T(res.indices.num * sizeof(uint16_t) == res.indices.size);
  89. res = sshape_plane_sizes(2);
  90. T(9 == res.vertices.num);
  91. T(24 == res.indices.num);
  92. T(res.vertices.num * sizeof(sshape_vertex_t) == res.vertices.size);
  93. T(res.indices.num * sizeof(uint16_t) == res.indices.size);
  94. }
  95. UTEST(sokol_shape, box_buffer_sizes) {
  96. sshape_sizes_t res;
  97. res = sshape_box_sizes(1);
  98. T(24 == res.vertices.num);
  99. T(36 == res.indices.num);
  100. T(res.vertices.num * sizeof(sshape_vertex_t) == res.vertices.size);
  101. T(res.indices.num * sizeof(uint16_t) == res.indices.size);
  102. res = sshape_box_sizes(2);
  103. T(54 == res.vertices.num);
  104. T(144 == res.indices.num);
  105. T(res.vertices.num * sizeof(sshape_vertex_t) == res.vertices.size);
  106. T(res.indices.num * sizeof(uint16_t) == res.indices.size);
  107. }
  108. UTEST(sokol_shape, sphere_buffer_sizes) {
  109. sshape_sizes_t res;
  110. res = sshape_sphere_sizes(3, 2);
  111. T(12 == res.vertices.num);
  112. T(18 == res.indices.num);
  113. T(res.vertices.num * sizeof(sshape_vertex_t) == res.vertices.size);
  114. T(res.indices.num * sizeof(uint16_t) == res.indices.size);
  115. res = sshape_sphere_sizes(36, 12);
  116. T(481 == res.vertices.num);
  117. T(2376 == res.indices.num);
  118. T(res.vertices.num * sizeof(sshape_vertex_t) == res.vertices.size);
  119. T(res.indices.num * sizeof(uint16_t) == res.indices.size);
  120. }
  121. UTEST(sokol_shape, cylinder_buffer_sizes) {
  122. sshape_sizes_t res;
  123. res = sshape_cylinder_sizes(3, 1);
  124. T(24 == res.vertices.num);
  125. T(36 == res.indices.num);
  126. T(res.vertices.num * sizeof(sshape_vertex_t) == res.vertices.size);
  127. T(res.indices.num * sizeof(uint16_t) == res.indices.size);
  128. res = sshape_cylinder_sizes(5, 2);
  129. T(42 == res.vertices.num);
  130. T(90 == res.indices.num);
  131. T(res.vertices.num * sizeof(sshape_vertex_t) == res.vertices.size);
  132. T(res.indices.num * sizeof(uint16_t) == res.indices.size);
  133. }
  134. UTEST(sokol_shape, torus_buffer_sizes) {
  135. sshape_sizes_t res;
  136. res = sshape_torus_sizes(3, 3);
  137. T(16 == res.vertices.num);
  138. T(54 == res.indices.num);
  139. T(res.vertices.num * sizeof(sshape_vertex_t) == res.vertices.size);
  140. T(res.indices.num * sizeof(uint16_t) == res.indices.size);
  141. res = sshape_torus_sizes(4, 5);
  142. T(30 == res.vertices.num);
  143. T(120 == res.indices.num);
  144. T(res.vertices.num * sizeof(sshape_vertex_t) == res.vertices.size);
  145. T(res.indices.num * sizeof(uint16_t) == res.indices.size);
  146. }
  147. UTEST(sokol_shape, buffer_layout_desc) {
  148. const sg_vertex_buffer_layout_state l_state = sshape_vertex_buffer_layout_state();
  149. T(sizeof(sshape_vertex_t) == l_state.stride);
  150. T(0 == l_state.step_func);
  151. T(0 == l_state.step_rate);
  152. }
  153. UTEST(sokol_shape, attr_descs) {
  154. {
  155. const sg_vertex_attr_state a_state = sshape_position_vertex_attr_state();
  156. T(offsetof(sshape_vertex_t, x) == a_state.offset);
  157. T(SG_VERTEXFORMAT_FLOAT3 == a_state.format);
  158. T(0 == a_state.buffer_index);
  159. }
  160. {
  161. const sg_vertex_attr_state a_state = sshape_normal_vertex_attr_state();
  162. T(offsetof(sshape_vertex_t, normal) == a_state.offset);
  163. T(SG_VERTEXFORMAT_BYTE4N == a_state.format);
  164. T(0 == a_state.buffer_index);
  165. }
  166. {
  167. const sg_vertex_attr_state a_state = sshape_texcoord_vertex_attr_state();
  168. T(offsetof(sshape_vertex_t, u) == a_state.offset);
  169. T(SG_VERTEXFORMAT_USHORT2N == a_state.format);
  170. T(0 == a_state.buffer_index);
  171. }
  172. {
  173. const sg_vertex_attr_state a_state = sshape_color_vertex_attr_state();
  174. T(offsetof(sshape_vertex_t, color) == a_state.offset);
  175. T(SG_VERTEXFORMAT_UBYTE4N == a_state.format);
  176. T(0 == a_state.buffer_index);
  177. }
  178. }
  179. UTEST(sokol_shape, buffer_descs_elm_range) {
  180. sshape_vertex_t vx[128] = { 0 };
  181. uint16_t ix[128] = { 0 };
  182. sshape_buffer_t buf = {
  183. .vertices.buffer = SSHAPE_RANGE(vx),
  184. .indices.buffer = SSHAPE_RANGE(ix),
  185. };
  186. // build a box...
  187. {
  188. buf = sshape_build_box(&buf, &(sshape_box_t) {0});
  189. const sg_buffer_desc vbuf_desc = sshape_vertex_buffer_desc(&buf);
  190. const sg_buffer_desc ibuf_desc = sshape_index_buffer_desc(&buf);
  191. const sshape_element_range_t elm_range = sshape_element_range(&buf);
  192. T(vbuf_desc.size == 0);
  193. T(vbuf_desc.type == SG_BUFFERTYPE_VERTEXBUFFER);
  194. T(vbuf_desc.usage == SG_USAGE_IMMUTABLE);
  195. T(vbuf_desc.data.ptr == vx);
  196. T(vbuf_desc.data.size == 24 * sizeof(sshape_vertex_t));
  197. T(ibuf_desc.size == 0);
  198. T(ibuf_desc.type == SG_BUFFERTYPE_INDEXBUFFER);
  199. T(ibuf_desc.usage == SG_USAGE_IMMUTABLE);
  200. T(ibuf_desc.data.ptr == ix);
  201. T(ibuf_desc.data.size == 36 * sizeof(uint16_t));
  202. T(elm_range.base_element == 0);
  203. T(elm_range.num_elements == 36);
  204. }
  205. // append a plane...
  206. {
  207. buf = sshape_build_plane(&buf, &(sshape_plane_t) {0});
  208. const sg_buffer_desc vbuf_desc = sshape_vertex_buffer_desc(&buf);
  209. const sg_buffer_desc ibuf_desc = sshape_index_buffer_desc(&buf);
  210. const sshape_element_range_t elm_range = sshape_element_range(&buf);
  211. T(vbuf_desc.size == 0);
  212. T(vbuf_desc.type == SG_BUFFERTYPE_VERTEXBUFFER);
  213. T(vbuf_desc.usage == SG_USAGE_IMMUTABLE);
  214. T(vbuf_desc.data.ptr == vx);
  215. T(vbuf_desc.data.size == 28 * sizeof(sshape_vertex_t));
  216. T(ibuf_desc.size == 0);
  217. T(ibuf_desc.type == SG_BUFFERTYPE_INDEXBUFFER);
  218. T(ibuf_desc.usage == SG_USAGE_IMMUTABLE);
  219. T(ibuf_desc.data.ptr == ix);
  220. T(ibuf_desc.data.size == 42 * sizeof(uint16_t));
  221. T(elm_range.base_element == 36);
  222. T(elm_range.num_elements == 6);
  223. }
  224. }
  225. UTEST(sokol_shape, build_plane_defaults) {
  226. sshape_vertex_t vx[64] = { 0 };
  227. uint16_t ix[64] = { 0 };
  228. sshape_buffer_t buf = {
  229. .vertices.buffer = SSHAPE_RANGE(vx),
  230. .indices.buffer = SSHAPE_RANGE(ix),
  231. };
  232. buf = sshape_build_plane(&buf, &(sshape_plane_t) { 0 });
  233. T(buf.valid);
  234. T(0 == buf.vertices.shape_offset);
  235. T(4 * sizeof(sshape_vertex_t) == buf.vertices.data_size);
  236. T(0 == buf.indices.shape_offset);
  237. T(6 * sizeof(uint16_t) == buf.indices.data_size);
  238. for (int i = 0; i < 4; i++) {
  239. T(vx[i].color == 0xFFFFFFFF);
  240. }
  241. T(ix[0] == 0);
  242. T(ix[1] == 1);
  243. T(ix[2] == 3);
  244. T(ix[3] == 0);
  245. T(ix[4] == 3);
  246. T(ix[5] == 2);
  247. }
  248. UTEST(sokol_shape, build_plane_validate) {
  249. sshape_vertex_t vx[64] = { 0 };
  250. uint16_t ix[64] = { 0 };
  251. const sshape_plane_t params = { 0 };
  252. // vertex buffer too small
  253. {
  254. sshape_buffer_t buf = {
  255. .vertices.buffer = { .ptr = vx, .size = 3 * sizeof(sshape_vertex_t) },
  256. .indices.buffer = SSHAPE_RANGE(ix),
  257. };
  258. T(!sshape_build_plane(&buf, &params).valid);
  259. }
  260. // index buffer too small
  261. {
  262. sshape_buffer_t buf = {
  263. .vertices.buffer = SSHAPE_RANGE(vx),
  264. .indices.buffer = { .ptr = ix, .size = 5 * sizeof(uint16_t) }
  265. };
  266. T(!sshape_build_plane(&buf, &params).valid);
  267. }
  268. // just the right size
  269. {
  270. sshape_buffer_t buf = {
  271. .vertices.buffer = { .ptr = vx, .size = 4 * sizeof(sshape_vertex_t) },
  272. .indices.buffer = { .ptr = ix, .size = 6 * sizeof(uint16_t) }
  273. };
  274. T(sshape_build_plane(&buf, &params).valid);
  275. }
  276. // too small for two planes
  277. {
  278. sshape_buffer_t buf = {
  279. .vertices.buffer = { .ptr = vx, .size = 5 * sizeof(sshape_vertex_t) },
  280. .indices.buffer = { .ptr = ix, .size = 7 * sizeof(uint16_t) }
  281. };
  282. buf = sshape_build_plane(&buf, &params);
  283. T(buf.valid);
  284. buf = sshape_build_plane(&buf, &params);
  285. T(!buf.valid);
  286. }
  287. // just the right size for two planes
  288. {
  289. sshape_buffer_t buf = {
  290. .vertices.buffer = { .ptr = vx, .size = 8 * sizeof(sshape_vertex_t) },
  291. .indices.buffer = { .ptr = ix, .size = 12 * sizeof(uint16_t) }
  292. };
  293. buf = sshape_build_plane(&buf, &params);
  294. T(buf.valid);
  295. T(buf.vertices.shape_offset == 0);
  296. T(buf.vertices.data_size == 4 * sizeof(sshape_vertex_t));
  297. T(buf.indices.shape_offset == 0);
  298. T(buf.indices.data_size == 6 * sizeof(uint16_t));
  299. buf = sshape_build_plane(&buf, &params);
  300. T(buf.valid);
  301. T(buf.vertices.shape_offset == 4 * sizeof(sshape_vertex_t));
  302. T(buf.vertices.data_size == 8 * sizeof(sshape_vertex_t));
  303. T(buf.indices.shape_offset == 6 * sizeof(uint16_t));
  304. T(buf.indices.data_size == 12 * sizeof(uint16_t));
  305. }
  306. }
  307. UTEST(sokol_shape, build_box_defaults) {
  308. sshape_vertex_t vx[128] = { 0 };
  309. uint16_t ix[128] = { 0 };
  310. sshape_buffer_t buf = {
  311. .vertices.buffer = SSHAPE_RANGE(vx),
  312. .indices.buffer = SSHAPE_RANGE(ix),
  313. };
  314. buf = sshape_build_box(&buf, &(sshape_box_t) { .color = 0xFF0000FF });
  315. T(buf.valid);
  316. T(buf.vertices.buffer.ptr == vx);
  317. T(buf.vertices.buffer.size == sizeof(vx));
  318. T(buf.indices.buffer.ptr == ix);
  319. T(buf.indices.buffer.size == sizeof(ix));
  320. T(buf.vertices.shape_offset == 0);
  321. T(buf.vertices.data_size == 24 * sizeof(sshape_vertex_t));
  322. T(buf.indices.shape_offset == 0);
  323. T(buf.indices.data_size == 36 * sizeof(uint16_t));
  324. }
  325. UTEST(sokol_shape, build_sphere_defaults) {
  326. sshape_vertex_t vx[128] = { 0 };
  327. uint16_t ix[128] = { 0 };
  328. sshape_buffer_t buf = {
  329. .vertices.buffer = SSHAPE_RANGE(vx),
  330. .indices.buffer = SSHAPE_RANGE(ix),
  331. };
  332. buf = sshape_build_sphere(&buf, &(sshape_sphere_t) { .color = 0xFF0000FF });
  333. T(buf.valid);
  334. T(buf.vertices.buffer.ptr == vx);
  335. T(buf.vertices.buffer.size == sizeof(vx));
  336. T(buf.indices.buffer.ptr == ix);
  337. T(buf.indices.buffer.size == sizeof(ix));
  338. T(buf.vertices.shape_offset == 0);
  339. T(buf.vertices.data_size == 30 * sizeof(sshape_vertex_t));
  340. T(buf.indices.shape_offset == 0);
  341. T(buf.indices.data_size == 90 * sizeof(uint16_t));
  342. }
  343. UTEST(sokol_shape, build_cylinder_defaults) {
  344. sshape_vertex_t vx[128] = { 0 };
  345. uint16_t ix[128] = { 0 };
  346. sshape_buffer_t buf = {
  347. .vertices.buffer = SSHAPE_RANGE(vx),
  348. .indices.buffer = SSHAPE_RANGE(ix)
  349. };
  350. buf = sshape_build_cylinder(&buf, &(sshape_cylinder_t) { .color = 0xFF0000FF });
  351. T(buf.valid);
  352. T(buf.vertices.buffer.ptr == vx);
  353. T(buf.vertices.buffer.size == sizeof(vx));
  354. T(buf.indices.buffer.ptr == ix);
  355. T(buf.indices.buffer.size == sizeof(ix));
  356. T(buf.vertices.shape_offset == 0);
  357. T(buf.vertices.data_size == 36 * sizeof(sshape_vertex_t));
  358. T(buf.indices.shape_offset == 0);
  359. T(buf.indices.data_size == 60 * sizeof(uint16_t));
  360. }
  361. UTEST(sokol_shape, build_torus_defaults) {
  362. sshape_vertex_t vx[128] = { 0 };
  363. uint16_t ix[256] = { 0 };
  364. sshape_buffer_t buf = {
  365. .vertices.buffer = SSHAPE_RANGE(vx),
  366. .indices.buffer = SSHAPE_RANGE(ix),
  367. };
  368. buf = sshape_build_torus(&buf, &(sshape_torus_t) { .color = 0xFF0000FF });
  369. T(buf.valid);
  370. T(buf.vertices.buffer.ptr == vx);
  371. T(buf.vertices.buffer.size == sizeof(vx));
  372. T(buf.indices.buffer.ptr == ix);
  373. T(buf.indices.buffer.size == sizeof(ix));
  374. T(buf.vertices.shape_offset == 0);
  375. T(buf.vertices.data_size == 36 * sizeof(sshape_vertex_t));
  376. T(buf.indices.shape_offset == 0);
  377. T(buf.indices.data_size == 150 * sizeof(uint16_t));
  378. }