SDL2_wip.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. /*
  2. SDL2_wip.c: Some basic geometric primatives written using SDL2's
  3. RenderGeometry function
  4. Inspired by the work by:
  5. Copyright (C) 2012-2014 Andreas Schiffler
  6. Additions for BBC BASIC (C) 2016-2020 Richard Russell
  7. This software is provided 'as-is', without any express or implied
  8. warranty. In no event will the authors be held liable for any damages
  9. arising from the use of this software.
  10. Permission is granted to anyone to use this software for any purpose,
  11. including commercial applications, and to alter it and redistribute it
  12. freely, subject to the following restrictions:
  13. 1. The origin of this software must not be misrepresented; you must not
  14. claim that you wrote the original software. If you use this software
  15. in a product, an acknowledgment in the product documentation would be
  16. appreciated but is not required.
  17. 2. Altered source versions must be plainly marked as such, and must not be
  18. misrepresented as being the original software.
  19. 3. This notice may not be removed or altered from any source
  20. distribution.
  21. Andreas Schiffler -- aschiffler at ferzkopp dot net
  22. Richard Russell -- richard at rtrussell dot co dot uk
  23. Avon -- avon61002 at g mail dot com
  24. */
  25. #include "SDL2_wip.h"
  26. #include <math.h>
  27. #include <stdio.h>
  28. #define CAP_BUTT 0
  29. #define CAP_SQUARE 1
  30. #define CAP_ROUND 2
  31. #define JOIN_MITER 0
  32. #define JOIN_BEVEL 1
  33. #define JOIN_ROUND 2
  34. int
  35. point (SDL_Renderer *renderer, float x, float y, Uint8 r, Uint8 g, Uint8 b,
  36. Uint8 a)
  37. {
  38. int result = 0;
  39. if (a != 255)
  40. {
  41. result |= SDL_SetRenderDrawBlendMode (renderer, SDL_BLENDMODE_BLEND);
  42. }
  43. result |= SDL_SetRenderDrawColor (renderer, r, g, b, a);
  44. result |= SDL_RenderDrawPointF (renderer, x, y);
  45. return 0;
  46. }
  47. int
  48. points (SDL_Renderer *renderer, float *vx, float *vy, Sint16 num_points,
  49. Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  50. {
  51. SDL_FPoint *points = (SDL_FPoint *)malloc (sizeof (SDL_FPoint) * num_points);
  52. if (points == NULL)
  53. {
  54. return -1;
  55. }
  56. for (int i = 0; i < num_points; i++)
  57. {
  58. points[i].x = vx[i];
  59. points[i].y = vy[i];
  60. }
  61. int result = 0;
  62. if (a != 255)
  63. {
  64. result |= SDL_SetRenderDrawBlendMode (renderer, SDL_BLENDMODE_BLEND);
  65. }
  66. result |= SDL_SetRenderDrawColor (renderer, r, g, b, a);
  67. result |= SDL_RenderDrawPointsF (renderer, points, num_points);
  68. free (points);
  69. return result;
  70. }
  71. int
  72. pointsFromVertices (SDL_Renderer *renderer, SDL_Vertex *v, Sint16 num_vertices)
  73. {
  74. int result = 0;
  75. for (int i = 0; i < num_vertices; i++)
  76. {
  77. SDL_FPoint p = v[i].position;
  78. SDL_Color c = v[i].color;
  79. result |= SDL_SetRenderDrawColor (renderer, c.r, c.g, c.b, c.a);
  80. result |= SDL_RenderDrawPointF (renderer, p.x, p.y);
  81. }
  82. return result;
  83. }
  84. int
  85. lineRaw (SDL_Renderer *renderer, float x1, float y1, float x2, float y2,
  86. Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  87. {
  88. int result = 0;
  89. if (a != 255)
  90. {
  91. result |= SDL_SetRenderDrawBlendMode (renderer, SDL_BLENDMODE_BLEND);
  92. }
  93. result |= SDL_SetRenderDrawColor (renderer, r, g, b, a);
  94. result |= SDL_RenderDrawLineF (renderer, x1, y1, x2, y2);
  95. return result;
  96. }
  97. int
  98. linesRaw (SDL_Renderer *renderer, float *vx, float *vy, Sint16 num_points)
  99. {
  100. /* TODO */
  101. if (num_points % 2 != 0)
  102. {
  103. return 1;
  104. }
  105. return -1;
  106. }
  107. int
  108. rectRaw (SDL_Renderer *renderer, float x1, float y1, float x2, float y2,
  109. Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  110. {
  111. SDL_FRect rect;
  112. rect.x = x1;
  113. rect.y = y1;
  114. rect.w = x2 - x1;
  115. rect.h = y2 - y1;
  116. int result = 0;
  117. if (a != 255)
  118. {
  119. result |= SDL_SetRenderDrawBlendMode (renderer, SDL_BLENDMODE_BLEND);
  120. }
  121. result |= SDL_SetRenderDrawColor (renderer, r, g, b, a);
  122. result |= SDL_RenderDrawRectF (renderer, &rect);
  123. return result;
  124. }
  125. int
  126. rectsRaw (SDL_Renderer *renderer, float *vx, float *vy, Sint16 num_points)
  127. {
  128. /* TODO */
  129. if (num_points % 2 != 0)
  130. {
  131. return 1;
  132. }
  133. return -1;
  134. }
  135. int
  136. filledRectRaw (SDL_Renderer *renderer, float x1, float y1, float x2, float y2,
  137. Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  138. {
  139. SDL_FRect rect;
  140. rect.x = x1;
  141. rect.y = y1;
  142. rect.w = x2 - x1;
  143. rect.h = y2 - y1;
  144. int result = 0;
  145. if (a != 255)
  146. {
  147. result |= SDL_SetRenderDrawBlendMode (renderer, SDL_BLENDMODE_BLEND);
  148. }
  149. result |= SDL_SetRenderDrawColor (renderer, r, g, b, a);
  150. result |= SDL_RenderFillRectF (renderer, &rect);
  151. return result;
  152. }
  153. int
  154. filledRectsRaw (SDL_Renderer *renderer, float *vx, float *vy, Sint16 num_points,
  155. Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  156. {
  157. /* TODO */
  158. if (num_points % 2 != 0)
  159. {
  160. return 1;
  161. }
  162. return -1;
  163. }
  164. // Abstracted Shape Functions
  165. int
  166. hLine (SDL_Renderer *renderer, float x1, float y, float x2, float thickness,
  167. Uint8 cap_type, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  168. {
  169. /* TODO error checking */
  170. int result = 0;
  171. result |= filledRectRaw (renderer, x1, y - thickness, x2, y + thickness, r, g,
  172. b, a);
  173. return result;
  174. }
  175. int
  176. vLine (SDL_Renderer *renderer, float x, float y1, float y2, float thickness,
  177. Uint8 cap_type, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  178. {
  179. /* TODO error checking */
  180. int result = 0;
  181. result |= filledRectRaw (renderer, x - thickness, y1, x + thickness, y2, r, g,
  182. b, a);
  183. return result;
  184. }
  185. // Tessellated Line Segment with 2 triangles with option segment caps
  186. // Reference:
  187. // https://web.archive.org/web/20190614093605/https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader
  188. int
  189. line (SDL_Renderer *renderer, float x1, float y1, float x2, float y2,
  190. float thickness, Uint8 cap_type, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
  191. {
  192. /* TODO input check and check for hLine and vLine */
  193. // TODO handle caps
  194. float half_thick = thickness / 2.0;
  195. float dx = x2 - x1;
  196. float dy = y2 - y1;
  197. float mag = sqrt ((dx * dx) + (dy * dy));
  198. float nx_normalized = -dy / mag;
  199. float ny_normalized = dx / mag;
  200. float p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y;
  201. float nx = half_thick * nx_normalized;
  202. float ny = half_thick * ny_normalized;
  203. p1x = x1 - nx;
  204. p1y = y1 - ny;
  205. p2x = x1 + nx;
  206. p2y = y1 + ny;
  207. p3x = x2 + nx;
  208. p3y = y2 + ny;
  209. p4x = x2 - nx;
  210. p4y = y2 - ny;
  211. const SDL_Vertex quadVerticies[4]
  212. = { { { p1x, p1y }, { r, g, b, a }, { 0.f, 0.f } },
  213. { { p2x, p2y }, { r, g, b, a }, { 0.f, 0.f } },
  214. { { p3x, p3y }, { r, g, b, a }, { 0.f, 0.f } },
  215. { { p4x, p4y }, { r, g, b, a }, { 0.f, 0.f } } };
  216. const int tmp_indicies[6] = { 0, 1, 2, 0, 3, 2 };
  217. int result = 0;
  218. result |= SDL_SetRenderDrawBlendMode (renderer, SDL_BLENDMODE_BLEND);
  219. result
  220. |= SDL_RenderGeometry (renderer, NULL, quadVerticies, 4, tmp_indicies, 6);
  221. return result;
  222. }
  223. // Finds the normal vector of point (x1,y1)
  224. // given line x1y1 -> x2y2 and a thickness
  225. SDL_FPoint
  226. _thickNormal (float x1, float y1, float x2, float y2, float thickness)
  227. {
  228. float half_thick = thickness / 2.0;
  229. float dx1 = x2 - x1;
  230. float dy1 = y2 - y1;
  231. float mag1 = sqrt ((dx1 * dx1) + (dy1 * dy1));
  232. float nx_normalized = -dy1 / mag1;
  233. float ny_normalized = dx1 / mag1;
  234. float nx = nx_normalized * half_thick;
  235. float ny = ny_normalized * half_thick;
  236. SDL_FPoint result = { nx, ny };
  237. return result;
  238. }
  239. // Generates Miter points for a given point (x2,y2),
  240. // based on two control points: (x1,y1) & (x3,y3)
  241. // Reference Diagram:
  242. // https://www.codeproject.com/Articles/226569/Drawing-polylines-by-tessellation
  243. // wrt the diagram, we are generating points m and -m
  244. SDL_FPoint
  245. _polylineGen (float x1, float y1, float x2, float y2, float x3, float y3,
  246. float thickness, Uint8 joint_type)
  247. {
  248. // TODO handle joint types and start/end caps
  249. float half_thick = thickness / 2.0;
  250. float dx1 = x2 - x1;
  251. float dy1 = y2 - y1;
  252. float mag1 = sqrt ((dx1 * dx1) + (dy1 * dy1));
  253. float nx_normalized = -dy1 / mag1;
  254. float ny_normalized = dx1 / mag1;
  255. float dx2 = x3 - x2;
  256. float dy2 = y3 - y2;
  257. float mag2 = sqrt ((dx2 * dx2) + (dy2 * dy2));
  258. float tx = (dx2 / mag2) + (dx1 / mag1);
  259. float ty = (dy2 / mag2) + (dy1 / mag1);
  260. float t_mag = sqrt ((tx * tx) + (ty * ty));
  261. float tx_normalized = tx / t_mag;
  262. float ty_normalized = ty / t_mag;
  263. float mx_normalized = -ty_normalized;
  264. float my_normalized = tx_normalized;
  265. float m_mag
  266. = half_thick
  267. / ((mx_normalized * nx_normalized) + (my_normalized * ny_normalized));
  268. float mx = m_mag * mx_normalized;
  269. float my = m_mag * my_normalized;
  270. // finding angle between two lines to determine where to put join
  271. float det = ((-dx1 * dy2) - (-dx2 * dy1));
  272. float dot = ((-dx1 * dx2) + (-dy1 * dy2));
  273. float theta = atan2 (det, dot);
  274. SDL_FPoint m = { mx, my };
  275. return m;
  276. }
  277. // Tessellated Polyline
  278. int
  279. polyline (SDL_Renderer *renderer, float *vx, float *vy, Sint16 num_points,
  280. float thickness, Uint8 joint_type, Uint8 cap_type, Uint8 r, Uint8 g,
  281. Uint8 b, Uint8 a)
  282. {
  283. /* TODO */
  284. if (num_points < 3)
  285. {
  286. return 1;
  287. }
  288. if (joint_type == 0)
  289. {
  290. int num_vertices = 2 * num_points;
  291. SDL_Vertex *vertices
  292. = (SDL_Vertex *)malloc (sizeof (SDL_Vertex) * num_vertices);
  293. if (vertices == NULL)
  294. return -1;
  295. int num_indices = 6 * (num_points - 1);
  296. int *indices = (int *)malloc (sizeof (int) * num_indices);
  297. if (indices == NULL)
  298. return -1;
  299. SDL_FPoint n_prime = _thickNormal (vx[0], vy[0], vx[1], vy[1], thickness);
  300. SDL_FPoint n = { vx[0] + n_prime.x, vy[0] + n_prime.y };
  301. SDL_FPoint minus_n = { vx[0] - n_prime.x, vy[0] - n_prime.y };
  302. SDL_Vertex nv = { n, { 255, g, b, a }, { 0.f, 0.f } };
  303. SDL_Vertex minus_nv = { minus_n, { r, 255, b, a }, { 0.f, 0.f } };
  304. vertices[0] = nv;
  305. vertices[1] = minus_nv;
  306. for (int i = 0; i < num_points - 2; i++)
  307. {
  308. SDL_FPoint m_prime
  309. = _polylineGen (vx[i], vy[i], vx[i + 1], vy[i + 1], vx[i + 2],
  310. vy[i + 2], thickness, 0);
  311. SDL_FPoint m = { vx[i + 1] + m_prime.x, vy[i + 1] + m_prime.y };
  312. SDL_FPoint minus_m = { vx[i + 1] - m_prime.x, vy[i + 1] - m_prime.y };
  313. SDL_Vertex mv = { m, { r, g, 255, a }, { 0.f, 0.f } };
  314. SDL_Vertex minus_mv = { minus_m, { 255, 255, b, a }, { 0.f, 0.f } };
  315. vertices[2 * (i + 1)] = mv;
  316. vertices[2 * (i + 1) + 1] = minus_mv;
  317. int start_ind = 6 * i;
  318. int start_vert = 2 * i;
  319. indices[start_ind] = start_vert;
  320. indices[start_ind + 1] = start_vert + 1;
  321. indices[start_ind + 2] = start_vert + 3;
  322. indices[start_ind + 3] = start_vert;
  323. indices[start_ind + 4] = start_vert + 2;
  324. indices[start_ind + 5] = start_vert + 3;
  325. }
  326. Sint16 end = num_points - 1;
  327. SDL_FPoint end_n_prime = _thickNormal (vx[end - 1], vy[end - 1], vx[end],
  328. vy[end], thickness);
  329. SDL_FPoint end_n = { vx[end] + end_n_prime.x, vy[end] + end_n_prime.y };
  330. SDL_FPoint end_minus_n
  331. = { vx[end] - end_n_prime.x, vy[end] - end_n_prime.y };
  332. SDL_Vertex end_nv = { end_n, { 255, g, b, a }, { 0.f, 0.f } };
  333. SDL_Vertex end_minus_nv = { end_minus_n, { r, 255, b, a }, { 0.f, 0.f } };
  334. vertices[num_vertices - 2] = end_nv;
  335. vertices[num_vertices - 1] = end_minus_nv;
  336. int ind_end = (6 * (num_points - 1)) - 6;
  337. indices[ind_end] = num_vertices - 4;
  338. indices[ind_end + 1] = num_vertices - 3;
  339. indices[ind_end + 2] = num_vertices - 1;
  340. indices[ind_end + 3] = num_vertices - 4;
  341. indices[ind_end + 4] = num_vertices - 2;
  342. indices[ind_end + 5] = num_vertices - 1;
  343. if (SDL_RenderGeometry (renderer, NULL, vertices, num_vertices, indices,
  344. num_indices))
  345. {
  346. printf ("yikes");
  347. }
  348. free (vertices);
  349. free (indices);
  350. }
  351. return -1;
  352. }
  353. // Tessellated Polyline that automatically closes the last point to the first
  354. int
  355. closedPolyline (SDL_Renderer *renderer, float *vx, float *vy, Sint16 num_points,
  356. float thickness, Uint8 joint_type, Uint8 r, Uint8 g, Uint8 b,
  357. Uint8 a)
  358. {
  359. /* TODO */
  360. if (num_points < 3)
  361. {
  362. return 1;
  363. }
  364. if (joint_type == 0)
  365. {
  366. int num_vertices = 2 * num_points;
  367. SDL_Vertex *vertices
  368. = (SDL_Vertex *)malloc (sizeof (SDL_Vertex) * num_vertices);
  369. if (vertices == NULL)
  370. return -1;
  371. int num_indices = 6 * num_points;
  372. int *indices = (int *)malloc (sizeof (int) * num_indices);
  373. if (indices == NULL)
  374. return -1;
  375. Sint16 end = num_points - 1;
  376. SDL_FPoint n_prime = _polylineGen (vx[end], vy[end], vx[0], vy[0], vx[1],
  377. vy[1], thickness, joint_type);
  378. SDL_FPoint n = { vx[0] + n_prime.x, vy[0] + n_prime.y };
  379. SDL_FPoint minus_n = { vx[0] - n_prime.x, vy[0] - n_prime.y };
  380. SDL_Vertex nv = { n, { r, g, b, a }, { 0.f, 0.f } };
  381. SDL_Vertex minus_nv = { minus_n, { r, g, b, a }, { 0.f, 0.f } };
  382. vertices[0] = nv;
  383. vertices[1] = minus_nv;
  384. for (int i = 0; i < num_points - 2; i++)
  385. {
  386. SDL_FPoint m_prime
  387. = _polylineGen (vx[i], vy[i], vx[i + 1], vy[i + 1], vx[i + 2],
  388. vy[i + 2], thickness, 0);
  389. SDL_FPoint m = { vx[i + 1] + m_prime.x, vy[i + 1] + m_prime.y };
  390. SDL_FPoint minus_m = { vx[i + 1] - m_prime.x, vy[i + 1] - m_prime.y };
  391. SDL_Vertex mv = { m, { r, g, b, a }, { 0.f, 0.f } };
  392. SDL_Vertex minus_mv = { minus_m, { r, g, b, a }, { 0.f, 0.f } };
  393. vertices[2 * (i + 1)] = mv;
  394. vertices[2 * (i + 1) + 1] = minus_mv;
  395. int start_ind = 6 * i;
  396. int start_vert = 2 * i;
  397. indices[start_ind] = start_vert;
  398. indices[start_ind + 1] = start_vert + 1;
  399. indices[start_ind + 2] = start_vert + 3;
  400. indices[start_ind + 3] = start_vert;
  401. indices[start_ind + 4] = start_vert + 2;
  402. indices[start_ind + 5] = start_vert + 3;
  403. }
  404. SDL_FPoint end_n_prime
  405. = _polylineGen (vx[end - 1], vy[end - 1], vx[end], vy[end], vx[0],
  406. vy[0], thickness, joint_type);
  407. SDL_FPoint end_n = { vx[end] + end_n_prime.x, vy[end] + end_n_prime.y };
  408. SDL_FPoint end_minus_n
  409. = { vx[end] - end_n_prime.x, vy[end] - end_n_prime.y };
  410. SDL_Vertex end_nv = { end_n, { r, g, b, a }, { 0.f, 0.f } };
  411. SDL_Vertex end_minus_nv = { end_minus_n, { r, g, b, a }, { 0.f, 0.f } };
  412. vertices[num_vertices - 2] = end_nv;
  413. vertices[num_vertices - 1] = end_minus_nv;
  414. int ind_end = (6 * (num_points - 1)) - 6;
  415. indices[ind_end] = num_vertices - 4;
  416. indices[ind_end + 1] = num_vertices - 3;
  417. indices[ind_end + 2] = num_vertices - 1;
  418. indices[ind_end + 3] = num_vertices - 4;
  419. indices[ind_end + 4] = num_vertices - 2;
  420. indices[ind_end + 5] = num_vertices - 1;
  421. ind_end = num_indices - 6;
  422. indices[ind_end] = num_vertices - 2;
  423. indices[ind_end + 1] = num_vertices - 1;
  424. indices[ind_end + 2] = 0;
  425. indices[ind_end + 3] = num_vertices - 1;
  426. indices[ind_end + 4] = 0;
  427. indices[ind_end + 5] = 1;
  428. if (SDL_RenderGeometry (renderer, NULL, vertices, num_vertices, indices,
  429. num_indices))
  430. {
  431. printf ("yikes");
  432. }
  433. free (vertices);
  434. free (indices);
  435. }
  436. return -1;
  437. }
  438. // Axis-Aligned Rect
  439. int
  440. aaRect (SDL_Renderer *renderer, float x1, float y1, float x2, float y2,
  441. float stroke_thickness, Uint8 joint_type, Uint8 stroke_r,
  442. Uint8 stroke_g, Uint8 stroke_b, Uint8 stroke_a, Uint8 filled,
  443. Uint8 fill_r, Uint8 fill_g, Uint8 fill_b, Uint8 fill_a)
  444. {
  445. /* TODO handle fancy joints */
  446. float w = x2 - x1;
  447. float h = y2 - y1;
  448. float ht = stroke_thickness / 2;
  449. if (filled)
  450. {
  451. filledRectRaw (renderer, x1, y1, x2, y2, fill_r, fill_g, fill_b, fill_a);
  452. }
  453. if (stroke_thickness != 0)
  454. {
  455. if (joint_type == 0)
  456. {
  457. filledRectRaw (renderer, x1 - ht, y1 - ht, x2 + ht, y1 + ht, stroke_r,
  458. stroke_g, stroke_b, stroke_a);
  459. filledRectRaw (renderer, x2 - ht, y1 + ht, x2 + ht, y2 - ht, stroke_r,
  460. stroke_g, stroke_b, stroke_a);
  461. filledRectRaw (renderer, x1 - ht, y2 - ht, x2 + ht, y2 + ht, stroke_r,
  462. stroke_g, stroke_b, stroke_a);
  463. filledRectRaw (renderer, x1 - ht, y1 + ht, x1 + ht, y2 - ht, stroke_r,
  464. stroke_g, stroke_b, stroke_a);
  465. }
  466. if (joint_type == 1)
  467. {
  468. // TODO
  469. }
  470. if (joint_type == 2)
  471. {
  472. // TODO
  473. }
  474. }
  475. return 0;
  476. }
  477. int
  478. _renderFanPolygon (SDL_Renderer *renderer, float cx, float cy, float *vx,
  479. float *vy, Sint16 num_points, Uint8 r, Uint8 g, Uint8 b,
  480. Uint8 a)
  481. {
  482. /* TODO */
  483. if (num_points < 3)
  484. return -1;
  485. int num_vertices = num_points + 1;
  486. SDL_Vertex *vertices
  487. = (SDL_Vertex *)malloc (sizeof (SDL_Vertex) * num_vertices);
  488. if (vertices == NULL)
  489. return -1;
  490. SDL_Vertex v0 = { { cx, cy }, { r, g, b, a }, { 0.f, 0.f } };
  491. SDL_Vertex v1 = { { vx[0], vy[0] }, { r, g, b, a }, { 0.f, 0.f } };
  492. vertices[0] = v0;
  493. vertices[1] = v1;
  494. int num_indices = 3 * (num_points - 1);
  495. int *indices = (int *)malloc (sizeof (int) * num_indices);
  496. if (indices == NULL)
  497. return -1;
  498. for (int i = 1; i < num_points; i++)
  499. {
  500. SDL_Vertex vi = { { vx[i], vy[i] }, { r, g, b, a }, { 0.f, 0.f } };
  501. vertices[i + 1] = vi;
  502. int start_ind = 3 * (i - 1);
  503. indices[start_ind] = 0;
  504. indices[start_ind + 1] = i;
  505. indices[start_ind + 2] = i + 1;
  506. }
  507. SDL_RenderGeometry (renderer, NULL, vertices, num_vertices, indices,
  508. num_indices);
  509. return 0;
  510. }
  511. int
  512. _renderClosedFanPolygon (SDL_Renderer *renderer, float cx, float cy, float *vx,
  513. float *vy, Sint16 num_points, Uint8 r, Uint8 g,
  514. Uint8 b, Uint8 a)
  515. {
  516. /* TODO */
  517. if (num_points < 3)
  518. return -1;
  519. int num_vertices = num_points + 1;
  520. SDL_Vertex *vertices
  521. = (SDL_Vertex *)malloc (sizeof (SDL_Vertex) * num_vertices);
  522. if (vertices == NULL)
  523. return -1;
  524. SDL_Vertex v0 = { { cx, cy }, { r, g, b, a }, { 0.f, 0.f } };
  525. SDL_Vertex v1 = { { vx[0], vy[0] }, { r, g, b, a }, { 0.f, 0.f } };
  526. vertices[0] = v0;
  527. vertices[1] = v1;
  528. int num_indices = 3 * num_points;
  529. int *indices = (int *)malloc (sizeof (int) * num_indices);
  530. if (indices == NULL)
  531. return -1;
  532. for (int i = 1; i < num_points; i++)
  533. {
  534. SDL_Vertex vi = { { vx[i], vy[i] }, { r, g, b, a }, { 0.f, 0.f } };
  535. vertices[i + 1] = vi;
  536. int start_ind = 3 * (i - 1);
  537. indices[start_ind] = 0;
  538. indices[start_ind + 1] = i;
  539. indices[start_ind + 2] = i + 1;
  540. }
  541. int end_ind = 3 * (num_points - 1);
  542. indices[end_ind] = 0;
  543. indices[end_ind + 1] = num_points;
  544. indices[end_ind + 2] = 1;
  545. SDL_RenderGeometry (renderer, NULL, vertices, num_vertices, indices,
  546. num_indices);
  547. return 0;
  548. }
  549. int
  550. regularPolygon (SDL_Renderer *renderer, float cx, float cy, float rad,
  551. Sint16 num_sides, float stroke_thickness, Uint8 joint_type,
  552. Uint8 stroke_r, Uint8 stroke_g, Uint8 stroke_b, Uint8 stroke_a,
  553. Uint8 filled, Uint8 fill_r, Uint8 fill_g, Uint8 fill_b,
  554. Uint8 fill_a)
  555. {
  556. /* TODO error checking */
  557. float *vx = (float *)malloc (sizeof (float) * num_sides);
  558. float *vy = (float *)malloc (sizeof (float) * num_sides);
  559. for (int i = 0; i < num_sides; i++)
  560. {
  561. vx[i] = (rad * cos ((2 * M_PI / num_sides) * i)) + cx;
  562. vy[i] = rad * sin ((2 * M_PI / num_sides) * i) + cy;
  563. }
  564. if (filled)
  565. {
  566. _renderClosedFanPolygon (renderer, cx, cy, vx, vy, num_sides, fill_r,
  567. fill_g, fill_b, fill_a);
  568. }
  569. if (stroke_thickness)
  570. {
  571. closedPolyline (renderer, vx, vy, num_sides, stroke_thickness, 0,
  572. stroke_r, stroke_g, stroke_b, stroke_a);
  573. }
  574. free (vx);
  575. free (vy);
  576. return -1;
  577. }
  578. // Convex Polygon rendered using Fan Triangulation
  579. // Reference: https://en.wikipedia.org/wiki/Fan_triangulation
  580. int
  581. convexPolygon (SDL_Renderer *renderer, float *vx, float *vy, Sint16 num_points,
  582. float stroke_thickness, Uint8 joint_type, Uint8 stroke_r,
  583. Uint8 stroke_g, Uint8 stroke_b, Uint8 stroke_a, Uint8 filled,
  584. Uint8 fill_r, Uint8 fill_g, Uint8 fill_b, Uint8 fill_a)
  585. {
  586. /* TODO */
  587. return -1;
  588. }