The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
SDL_gpuShapes_GL_common.inl
Go to the documentation of this file.
1 /* This is an implementation file to be included after certain #defines have been set.
2 See a particular renderer's *.c file for specifics. */
3 
4 #ifndef DEGPERRAD
5 #define DEGPERRAD 57.2957795f
6 #endif
7 
8 #ifndef RADPERDEG
9 #define RADPERDEG 0.0174532925f
10 #endif
11 
12 
13 
14 
15 
16 
17 
18 // All shapes start this way for setup and so they can access the blit buffer properly
19 #define BEGIN_UNTEXTURED(function_name, shape, num_additional_vertices, num_additional_indices) \
20  GPU_CONTEXT_DATA* cdata; \
21  float* blit_buffer; \
22  unsigned short* index_buffer; \
23  int vert_index; \
24  int color_index; \
25  float r, g, b, a; \
26  unsigned short blit_buffer_starting_index; \
27  if(target == NULL) \
28  { \
29  GPU_PushErrorCode(function_name, GPU_ERROR_NULL_ARGUMENT, "target"); \
30  return; \
31  } \
32  if(renderer != target->renderer) \
33  { \
34  GPU_PushErrorCode(function_name, GPU_ERROR_USER_ERROR, "Mismatched renderer"); \
35  return; \
36  } \
37  \
38  makeContextCurrent(renderer, target); \
39  if(renderer->current_context_target == NULL) \
40  { \
41  GPU_PushErrorCode(function_name, GPU_ERROR_USER_ERROR, "NULL context"); \
42  return; \
43  } \
44  \
45  if(!bindFramebuffer(renderer, target)) \
46  { \
47  GPU_PushErrorCode(function_name, GPU_ERROR_BACKEND_ERROR, "Failed to bind framebuffer."); \
48  return; \
49  } \
50  \
51  prepareToRenderToTarget(renderer, target); \
52  prepareToRenderShapes(renderer, shape); \
53  \
54  cdata = (GPU_CONTEXT_DATA*)renderer->current_context_target->context->data; \
55  \
56  if(cdata->blit_buffer_num_vertices + (num_additional_vertices) >= cdata->blit_buffer_max_num_vertices) \
57  { \
58  if(!growBlitBuffer(cdata, cdata->blit_buffer_num_vertices + (num_additional_vertices))) \
59  renderer->FlushBlitBuffer(renderer); \
60  } \
61  if(cdata->index_buffer_num_vertices + (num_additional_indices) >= cdata->index_buffer_max_num_vertices) \
62  { \
63  if(!growIndexBuffer(cdata, cdata->index_buffer_num_vertices + (num_additional_indices))) \
64  renderer->FlushBlitBuffer(renderer); \
65  } \
66  \
67  blit_buffer = cdata->blit_buffer; \
68  index_buffer = cdata->index_buffer; \
69  \
70  vert_index = GPU_BLIT_BUFFER_VERTEX_OFFSET + cdata->blit_buffer_num_vertices*GPU_BLIT_BUFFER_FLOATS_PER_VERTEX; \
71  color_index = GPU_BLIT_BUFFER_COLOR_OFFSET + cdata->blit_buffer_num_vertices*GPU_BLIT_BUFFER_FLOATS_PER_VERTEX; \
72  \
73  if(target->use_color) \
74  { \
75  r = MIX_COLOR_COMPONENT_NORMALIZED_RESULT(target->color.r, color.r); \
76  g = MIX_COLOR_COMPONENT_NORMALIZED_RESULT(target->color.g, color.g); \
77  b = MIX_COLOR_COMPONENT_NORMALIZED_RESULT(target->color.b, color.b); \
78  a = MIX_COLOR_COMPONENT_NORMALIZED_RESULT(GET_ALPHA(target->color), GET_ALPHA(color)); \
79  } \
80  else \
81  { \
82  r = color.r/255.0f; \
83  g = color.g/255.0f; \
84  b = color.b/255.0f; \
85  a = GET_ALPHA(color)/255.0f; \
86  } \
87  blit_buffer_starting_index = cdata->blit_buffer_num_vertices; \
88  (void)blit_buffer_starting_index;
89 
90 
91 
92 
93 
94 static float SetLineThickness(GPU_Renderer* renderer, float thickness)
95 {
96  float old;
97 
98  if(renderer->current_context_target == NULL)
99  return 1.0f;
100 
102  if(old != thickness)
103  renderer->FlushBlitBuffer(renderer);
104 
105  renderer->current_context_target->context->line_thickness = thickness;
106  glLineWidth(thickness);
107  return old;
108 }
109 
110 static float GetLineThickness(GPU_Renderer* renderer)
111 {
112  return renderer->current_context_target->context->line_thickness;
113 }
114 
115 static void Pixel(GPU_Renderer* renderer, GPU_Target* target, float x, float y, SDL_Color color)
116 {
117  BEGIN_UNTEXTURED("GPU_Pixel", GL_POINTS, 1, 1);
118 
119  SET_UNTEXTURED_VERTEX(x, y, r, g, b, a);
120 }
121 
122 static void Line(GPU_Renderer* renderer, GPU_Target* target, float x1, float y1, float x2, float y2, SDL_Color color)
123 {
124  float thickness = renderer->GetLineThickness(renderer);
125 
126  float t = thickness/2;
127  float line_angle = atan2f(y2 - y1, x2 - x1);
128  float tc = t*cosf(line_angle);
129  float ts = t*sinf(line_angle);
130 
131  BEGIN_UNTEXTURED("GPU_Line", GL_TRIANGLES, 4, 6);
132 
133  SET_UNTEXTURED_VERTEX(x1 + ts, y1 - tc, r, g, b, a);
134  SET_UNTEXTURED_VERTEX(x1 - ts, y1 + tc, r, g, b, a);
135  SET_UNTEXTURED_VERTEX(x2 + ts, y2 - tc, r, g, b, a);
136 
139  SET_UNTEXTURED_VERTEX(x2 - ts, y2 + tc, r, g, b, a);
140 }
141 
142 // Arc() might call Circle()
143 static void Circle(GPU_Renderer* renderer, GPU_Target* target, float x, float y, float radius, SDL_Color color);
144 
145 static void Arc(GPU_Renderer* renderer, GPU_Target* target, float x, float y, float radius, float start_angle, float end_angle, SDL_Color color)
146 {
147  float t;
148  float dt;
149  float dx, dy;
150 
151  int numSegments;
152 
153  if(start_angle > end_angle)
154  {
155  float swapa = end_angle;
156  end_angle = start_angle;
157  start_angle = swapa;
158  }
159  if(start_angle == end_angle)
160  return;
161 
162  // Big angle
163  if(end_angle - start_angle >= 360)
164  {
165  Circle(renderer, target, x, y, radius, color);
166  return;
167  }
168 
169  // Shift together
170  while(start_angle < 0 && end_angle < 0)
171  {
172  start_angle += 360;
173  end_angle += 360;
174  }
175  while(start_angle > 360 && end_angle > 360)
176  {
177  start_angle -= 360;
178  end_angle -= 360;
179  }
180 
181 
182  t = start_angle;
183  dt = ((end_angle - start_angle)/360)*(1.25f/sqrtf(radius)) * DEGPERRAD; // s = rA, so dA = ds/r. ds of 1.25*sqrt(radius) is good, use A in degrees.
184 
185  numSegments = fabs(end_angle - start_angle)/dt;
186  if(numSegments == 0)
187  return;
188 
189  {
190  int i;
191  BEGIN_UNTEXTURED("GPU_Arc", GL_LINES, 1 + (numSegments - 1) + 1, 1 + (numSegments - 1) * 2 + 1);
192 
193  dx = radius*cos(t*RADPERDEG);
194  dy = radius*sin(t*RADPERDEG);
195  SET_UNTEXTURED_VERTEX(x + dx, y + dy, r, g, b, a); // first point
196  t += dt;
197 
198  for (i = 1; i < numSegments; i++)
199  {
200  dx = radius*cos(t*RADPERDEG);
201  dy = radius*sin(t*RADPERDEG);
202  SET_UNTEXTURED_VERTEX(x + dx, y + dy, r, g, b, a);
203  SET_INDEXED_VERTEX(i); // Double that vertex
204  t += dt;
205  }
206 
207  // Last point
208  dx = radius*cos(end_angle*RADPERDEG);
209  dy = radius*sin(end_angle*RADPERDEG);
210  SET_UNTEXTURED_VERTEX(x + dx, y + dy, r, g, b, a);
211  }
212 }
213 
214 // ArcFilled() might call CircleFilled()
215 static void CircleFilled(GPU_Renderer* renderer, GPU_Target* target, float x, float y, float radius, SDL_Color color);
216 
217 static void ArcFilled(GPU_Renderer* renderer, GPU_Target* target, float x, float y, float radius, float start_angle, float end_angle, SDL_Color color)
218 {
219  float t;
220  float dt;
221  float dx, dy;
222 
223  int numSegments;
224 
225  if(start_angle > end_angle)
226  {
227  float swapa = end_angle;
228  end_angle = start_angle;
229  start_angle = swapa;
230  }
231  if(start_angle == end_angle)
232  return;
233 
234  // Big angle
235  if(end_angle - start_angle >= 360)
236  {
237  CircleFilled(renderer, target, x, y, radius, color);
238  return;
239  }
240 
241  // Shift together
242  while(start_angle < 0 && end_angle < 0)
243  {
244  start_angle += 360;
245  end_angle += 360;
246  }
247  while(start_angle > 360 && end_angle > 360)
248  {
249  start_angle -= 360;
250  end_angle -= 360;
251  }
252 
253  t = start_angle;
254  dt = ((end_angle - start_angle)/360)*(1.25f/sqrtf(radius)) * DEGPERRAD; // s = rA, so dA = ds/r. ds of 1.25*sqrt(radius) is good, use A in degrees.
255 
256  numSegments = fabs(end_angle - start_angle)/dt;
257  if(numSegments == 0)
258  return;
259 
260  {
261  int i;
262  BEGIN_UNTEXTURED("GPU_ArcFilled", GL_TRIANGLES, 3 + (numSegments - 1) + 1, 3 + (numSegments - 1) * 3 + 3);
263 
264  // First triangle
265  SET_UNTEXTURED_VERTEX(x, y, r, g, b, a);
266  dx = radius*cos(t*RADPERDEG);
267  dy = radius*sin(t*RADPERDEG);
268  SET_UNTEXTURED_VERTEX(x + dx, y + dy, r, g, b, a); // first point
269  t += dt;
270  dx = radius*cos(t*RADPERDEG);
271  dy = radius*sin(t*RADPERDEG);
272  SET_UNTEXTURED_VERTEX(x + dx, y + dy, r, g, b, a); // new point
273  t += dt;
274 
275  for (i = 2; i < numSegments + 1; i++)
276  {
277  dx = radius*cos(t*RADPERDEG);
278  dy = radius*sin(t*RADPERDEG);
279  SET_INDEXED_VERTEX(0); // center
280  SET_INDEXED_VERTEX(i); // last point
281  SET_UNTEXTURED_VERTEX(x + dx, y + dy, r, g, b, a); // new point
282  t += dt;
283  }
284 
285  // Last triangle
286  dx = radius*cos(end_angle*RADPERDEG);
287  dy = radius*sin(end_angle*RADPERDEG);
288  SET_INDEXED_VERTEX(0); // center
289  SET_INDEXED_VERTEX(i); // last point
290  SET_UNTEXTURED_VERTEX(x + dx, y + dy, r, g, b, a); // new point
291  }
292 }
293 
294 static void Circle(GPU_Renderer* renderer, GPU_Target* target, float x, float y, float radius, SDL_Color color)
295 {
296  float t = 0;
297  float dt = (1.25f/sqrtf(radius)) * DEGPERRAD; // s = rA, so dA = ds/r. ds of 1.25*sqrt(radius) is good, use A in degrees.
298  float dx, dy;
299  int numSegments = 360/dt+1;
300  int i;
301 
302  BEGIN_UNTEXTURED("GPU_Circle", GL_LINES, 1 + (numSegments-1), 1 + (numSegments-1)*2 + 1);
303 
304  dx = radius;
305  dy = 0.0f;
306  SET_UNTEXTURED_VERTEX(x+dx, y+dy, r, g, b, a); // first point
307 
308  for(i = 1; i < numSegments; i++)
309  {
310  dx = radius*cos(t*RADPERDEG);
311  dy = radius*sin(t*RADPERDEG);
312  SET_UNTEXTURED_VERTEX(x+dx, y+dy, r, g, b, a);
313  SET_INDEXED_VERTEX(i); // Double that vertex
314  t += dt;
315  }
316 
317  SET_INDEXED_VERTEX(0); // back to the beginning
318 }
319 
320 static void CircleFilled(GPU_Renderer* renderer, GPU_Target* target, float x, float y, float radius, SDL_Color color)
321 {
322  float t = 0;
323  float dt = (1.25f/sqrtf(radius)) * DEGPERRAD; // s = rA, so dA = ds/r. ds of 1.25*sqrt(radius) is good, use A in degrees.
324  float dx, dy;
325 
326  int numSegments = 360/dt+1;
327  int i;
328 
329  BEGIN_UNTEXTURED("GPU_CircleFilled", GL_TRIANGLES, 3 + (numSegments-2), 3 + (numSegments-2)*3 + 3);
330 
331  // First triangle
332  SET_UNTEXTURED_VERTEX(x, y, r, g, b, a);
333  dx = radius;
334  dy = 0.0f;
335  SET_UNTEXTURED_VERTEX(x+dx, y+dy, r, g, b, a); // first point
336  t += dt;
337  dx = radius*cos(t*RADPERDEG);
338  dy = radius*sin(t*RADPERDEG);
339  SET_UNTEXTURED_VERTEX(x+dx, y+dy, r, g, b, a); // new point
340  t += dt;
341 
342  for(i = 2; i < numSegments; i++)
343  {
344  dx = radius*cos(t*RADPERDEG);
345  dy = radius*sin(t*RADPERDEG);
346  SET_INDEXED_VERTEX(0); // center
347  SET_INDEXED_VERTEX(i); // last point
348  SET_UNTEXTURED_VERTEX(x+dx, y+dy, r, g, b, a); // new point
349  t += dt;
350  }
351 
352  SET_INDEXED_VERTEX(0); // center
353  SET_INDEXED_VERTEX(i); // last point
354  SET_INDEXED_VERTEX(1); // first point
355 }
356 
357 static void Sector(GPU_Renderer* renderer, GPU_Target* target, float x, float y, float inner_radius, float outer_radius, float start_angle, float end_angle, SDL_Color color)
358 {
359  Uint8 circled;
360  float dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4;
361 
362  if(inner_radius < 0.0f)
363  inner_radius = 0.0f;
364  if(outer_radius < 0.0f)
365  outer_radius = 0.0f;
366 
367  if(inner_radius > outer_radius)
368  {
369  float s = inner_radius;
370  inner_radius = outer_radius;
371  outer_radius = s;
372  }
373 
374  if(start_angle > end_angle)
375  {
376  float swapa = end_angle;
377  end_angle = start_angle;
378  start_angle = swapa;
379  }
380  if(start_angle == end_angle)
381  return;
382 
383  if(inner_radius == outer_radius)
384  {
385  Arc(renderer, target, x, y, inner_radius, start_angle, end_angle, color);
386  return;
387  }
388 
389  circled = (end_angle - start_angle >= 360);
390  // Composited shape... But that means error codes may be confusing. :-/
391  Arc(renderer, target, x, y, inner_radius, start_angle, end_angle, color);
392 
393  if(!circled)
394  {
395  dx1 = inner_radius*cos(end_angle*RADPERDEG);
396  dy1 = inner_radius*sin(end_angle*RADPERDEG);
397  dx2 = outer_radius*cos(end_angle*RADPERDEG);
398  dy2 = outer_radius*sin(end_angle*RADPERDEG);
399  Line(renderer, target, x+dx1, y+dy1, x+dx2, y+dy2, color);
400  }
401 
402  Arc(renderer, target, x, y, outer_radius, start_angle, end_angle, color);
403 
404  if(!circled)
405  {
406  dx3 = inner_radius*cos(start_angle*RADPERDEG);
407  dy3 = inner_radius*sin(start_angle*RADPERDEG);
408  dx4 = outer_radius*cos(start_angle*RADPERDEG);
409  dy4 = outer_radius*sin(start_angle*RADPERDEG);
410  Line(renderer, target, x+dx3, y+dy3, x+dx4, y+dy4, color);
411  }
412 }
413 
414 static void SectorFilled(GPU_Renderer* renderer, GPU_Target* target, float x, float y, float inner_radius, float outer_radius, float start_angle, float end_angle, SDL_Color color)
415 {
416  float t;
417  float dt;
418  float dx, dy;
419 
420  int numSegments;
421 
422  if(inner_radius < 0.0f)
423  inner_radius = 0.0f;
424  if(outer_radius < 0.0f)
425  outer_radius = 0.0f;
426 
427  if(inner_radius > outer_radius)
428  {
429  float s = inner_radius;
430  inner_radius = outer_radius;
431  outer_radius = s;
432  }
433 
434  if(inner_radius == outer_radius)
435  {
436  Arc(renderer, target, x, y, inner_radius, start_angle, end_angle, color);
437  return;
438  }
439 
440 
441  if(start_angle > end_angle)
442  {
443  float swapa = end_angle;
444  end_angle = start_angle;
445  start_angle = swapa;
446  }
447  if(start_angle == end_angle)
448  return;
449 
450  if(end_angle - start_angle >= 360)
451  end_angle = start_angle + 360;
452 
453 
454  t = start_angle;
455  dt = ((end_angle - start_angle)/360)*(1.25f/sqrtf(outer_radius)) * DEGPERRAD; // s = rA, so dA = ds/r. ds of 1.25*sqrt(radius) is good, use A in degrees.
456 
457  numSegments = fabs(end_angle - start_angle)/dt;
458  if(numSegments == 0)
459  return;
460 
461  {
462  int i;
463  Uint8 use_inner;
464  BEGIN_UNTEXTURED("GPU_SectorFilled", GL_TRIANGLES, 3 + (numSegments - 1) + 1, 3 + (numSegments - 1) * 3 + 3);
465 
466  use_inner = 0; // Switches between the radii for the next point
467 
468  // First triangle
469  dx = inner_radius*cos(t*RADPERDEG);
470  dy = inner_radius*sin(t*RADPERDEG);
471  SET_UNTEXTURED_VERTEX(x + dx, y + dy, r, g, b, a);
472 
473  dx = outer_radius*cos(t*RADPERDEG);
474  dy = outer_radius*sin(t*RADPERDEG);
475  SET_UNTEXTURED_VERTEX(x + dx, y + dy, r, g, b, a);
476  t += dt;
477  dx = inner_radius*cos(t*RADPERDEG);
478  dy = inner_radius*sin(t*RADPERDEG);
479  SET_UNTEXTURED_VERTEX(x + dx, y + dy, r, g, b, a);
480  t += dt;
481 
482  for (i = 2; i < numSegments + 1; i++)
483  {
484  SET_INDEXED_VERTEX(i - 1);
486  if (use_inner)
487  {
488  dx = inner_radius*cos(t*RADPERDEG);
489  dy = inner_radius*sin(t*RADPERDEG);
490  }
491  else
492  {
493  dx = outer_radius*cos(t*RADPERDEG);
494  dy = outer_radius*sin(t*RADPERDEG);
495  }
496  SET_UNTEXTURED_VERTEX(x + dx, y + dy, r, g, b, a); // new point
497  t += dt;
498  use_inner = !use_inner;
499  }
500 
501  // Last quad
502  t = end_angle;
503  if (use_inner)
504  {
505  dx = inner_radius*cos(t*RADPERDEG);
506  dy = inner_radius*sin(t*RADPERDEG);
507  }
508  else
509  {
510  dx = outer_radius*cos(t*RADPERDEG);
511  dy = outer_radius*sin(t*RADPERDEG);
512  }
513  SET_INDEXED_VERTEX(i - 1);
515  SET_UNTEXTURED_VERTEX(x + dx, y + dy, r, g, b, a); // new point
516  use_inner = !use_inner;
517  i++;
518 
519  if (use_inner)
520  {
521  dx = inner_radius*cos(t*RADPERDEG);
522  dy = inner_radius*sin(t*RADPERDEG);
523  }
524  else
525  {
526  dx = outer_radius*cos(t*RADPERDEG);
527  dy = outer_radius*sin(t*RADPERDEG);
528  }
529  SET_INDEXED_VERTEX(i - 1);
531  SET_UNTEXTURED_VERTEX(x + dx, y + dy, r, g, b, a); // new point
532  }
533 }
534 
535 static void Tri(GPU_Renderer* renderer, GPU_Target* target, float x1, float y1, float x2, float y2, float x3, float y3, SDL_Color color)
536 {
537  BEGIN_UNTEXTURED("GPU_Tri", GL_LINES, 3, 6);
538 
539  SET_UNTEXTURED_VERTEX(x1, y1, r, g, b, a);
540  SET_UNTEXTURED_VERTEX(x2, y2, r, g, b, a);
541 
543  SET_UNTEXTURED_VERTEX(x3, y3, r, g, b, a);
544 
547 }
548 
549 static void TriFilled(GPU_Renderer* renderer, GPU_Target* target, float x1, float y1, float x2, float y2, float x3, float y3, SDL_Color color)
550 {
551  BEGIN_UNTEXTURED("GPU_TriFilled", GL_TRIANGLES, 3, 3);
552 
553  SET_UNTEXTURED_VERTEX(x1, y1, r, g, b, a);
554  SET_UNTEXTURED_VERTEX(x2, y2, r, g, b, a);
555  SET_UNTEXTURED_VERTEX(x3, y3, r, g, b, a);
556 }
557 
558 static void Rectangle(GPU_Renderer* renderer, GPU_Target* target, float x1, float y1, float x2, float y2, SDL_Color color)
559 {
560  if(y2 < y1)
561  {
562  float y = y1;
563  y1 = y2;
564  y2 = y;
565  }
566  if(x2 < x1)
567  {
568  float x = x1;
569  x1 = x2;
570  x2 = x;
571  }
572 
573  {
574  float thickness = renderer->GetLineThickness(renderer);
575 
576  float t = thickness / 2;
577 
578  // Thick lines via filled triangles
579 
580  BEGIN_UNTEXTURED("GPU_Rectangle", GL_TRIANGLES, 10, 24);
581 
582  // First triangle
583  SET_UNTEXTURED_VERTEX(x1 - t, y1 - t, r, g, b, a);
584  SET_UNTEXTURED_VERTEX(x1 + t, y1 + t, r, g, b, a);
585  SET_UNTEXTURED_VERTEX(x2 + t, y1 - t, r, g, b, a);
586 
589  SET_UNTEXTURED_VERTEX(x2 - t, y1 + t, r, g, b, a);
590 
593  SET_UNTEXTURED_VERTEX(x2 + t, y2 + t, r, g, b, a);
594 
597  SET_UNTEXTURED_VERTEX(x2 - t, y2 - t, r, g, b, a);
598 
601  SET_UNTEXTURED_VERTEX(x1 - t, y2 + t, r, g, b, a);
602 
605  SET_UNTEXTURED_VERTEX(x1 + t, y2 - t, r, g, b, a);
606 
609  SET_UNTEXTURED_VERTEX(x1 - t, y1 - t, r, g, b, a);
610 
613  SET_UNTEXTURED_VERTEX(x1 + t, y1 + t, r, g, b, a);
614  }
615 }
616 
617 static void RectangleFilled(GPU_Renderer* renderer, GPU_Target* target, float x1, float y1, float x2, float y2, SDL_Color color)
618 {
619  BEGIN_UNTEXTURED("GPU_RectangleFilled", GL_TRIANGLES, 4, 6);
620 
621  SET_UNTEXTURED_VERTEX(x1, y1, r, g, b, a);
622  SET_UNTEXTURED_VERTEX(x1, y2, r, g, b, a);
623  SET_UNTEXTURED_VERTEX(x2, y1, r, g, b, a);
624 
627  SET_UNTEXTURED_VERTEX(x2, y2, r, g, b, a);
628 }
629 
630 static void RectangleRound(GPU_Renderer* renderer, GPU_Target* target, float x1, float y1, float x2, float y2, float radius, SDL_Color color)
631 {
632  if(y2 < y1)
633  {
634  float temp = y2;
635  y2 = y1;
636  y1 = temp;
637  }
638  if(x2 < x1)
639  {
640  float temp = x2;
641  x2 = x1;
642  x1 = temp;
643  }
644 
645  if(radius > (x2-x1)/2)
646  radius = (x2-x1)/2;
647  if(radius > (y2-y1)/2)
648  radius = (y2 - y1) / 2;
649 
650  {
651  float tau = 2 * M_PI;
652 
653  int verts_per_corner = 7;
654  float corner_angle_increment = (tau / 4) / (verts_per_corner - 1); // 0, 15, 30, 45, 60, 75, 90
655  // Starting angle
656  float angle = tau*0.75f;
657  int last_index = 1;
658  int i;
659 
660  BEGIN_UNTEXTURED("GPU_RectangleRound", GL_LINES, 4 + 4 * (verts_per_corner - 1), 8 + 4 * (verts_per_corner - 1) * 2);
661 
662 
663  // First point
664  SET_UNTEXTURED_VERTEX(x2 - radius + cos(angle)*radius, y1 + radius + sin(angle)*radius, r, g, b, a);
665 
666  for (i = 1; i < verts_per_corner; i++)
667  {
668  SET_UNTEXTURED_VERTEX(x2 - radius + cos(angle)*radius, y1 + radius + sin(angle)*radius, r, g, b, a);
669  SET_INDEXED_VERTEX(last_index++);
670  angle += corner_angle_increment;
671  }
672 
673  SET_UNTEXTURED_VERTEX(x2 - radius + cos(angle)*radius, y2 - radius + sin(angle)*radius, r, g, b, a);
674  SET_INDEXED_VERTEX(last_index++);
675  for (i = 1; i < verts_per_corner; i++)
676  {
677  SET_UNTEXTURED_VERTEX(x2 - radius + cos(angle)*radius, y2 - radius + sin(angle)*radius, r, g, b, a);
678  SET_INDEXED_VERTEX(last_index++);
679  angle += corner_angle_increment;
680  }
681 
682  SET_UNTEXTURED_VERTEX(x1 + radius + cos(angle)*radius, y2 - radius + sin(angle)*radius, r, g, b, a);
683  SET_INDEXED_VERTEX(last_index++);
684  for (i = 1; i < verts_per_corner; i++)
685  {
686  SET_UNTEXTURED_VERTEX(x1 + radius + cos(angle)*radius, y2 - radius + sin(angle)*radius, r, g, b, a);
687  SET_INDEXED_VERTEX(last_index++);
688  angle += corner_angle_increment;
689  }
690 
691  SET_UNTEXTURED_VERTEX(x1 + radius + cos(angle)*radius, y1 + radius + sin(angle)*radius, r, g, b, a);
692  SET_INDEXED_VERTEX(last_index++);
693  for (i = 1; i < verts_per_corner; i++)
694  {
695  SET_UNTEXTURED_VERTEX(x1 + radius + cos(angle)*radius, y1 + radius + sin(angle)*radius, r, g, b, a);
696  SET_INDEXED_VERTEX(last_index++);
697  angle += corner_angle_increment;
698  }
699 
700  // Last point
702  }
703 }
704 
705 static void RectangleRoundFilled(GPU_Renderer* renderer, GPU_Target* target, float x1, float y1, float x2, float y2, float radius, SDL_Color color)
706 {
707  if(y2 < y1)
708  {
709  float temp = y2;
710  y2 = y1;
711  y1 = temp;
712  }
713  if(x2 < x1)
714  {
715  float temp = x2;
716  x2 = x1;
717  x1 = temp;
718  }
719 
720  if(radius > (x2-x1)/2)
721  radius = (x2-x1)/2;
722  if(radius > (y2-y1)/2)
723  radius = (y2 - y1) / 2;
724 
725  {
726  float tau = 2 * M_PI;
727 
728  int verts_per_corner = 7;
729  float corner_angle_increment = (tau / 4) / (verts_per_corner - 1); // 0, 15, 30, 45, 60, 75, 90
730 
731  // Starting angle
732  float angle = tau*0.75f;
733  int last_index = 2;
734  int i;
735 
736  BEGIN_UNTEXTURED("GPU_RectangleRoundFilled", GL_TRIANGLES, 6 + 4 * (verts_per_corner - 1) - 1, 15 + 4 * (verts_per_corner - 1) * 3 - 3);
737 
738 
739  // First triangle
740  SET_UNTEXTURED_VERTEX((x2 + x1) / 2, (y2 + y1) / 2, r, g, b, a); // Center
741  SET_UNTEXTURED_VERTEX(x2 - radius + cos(angle)*radius, y1 + radius + sin(angle)*radius, r, g, b, a);
742  angle += corner_angle_increment;
743  SET_UNTEXTURED_VERTEX(x2 - radius + cos(angle)*radius, y1 + radius + sin(angle)*radius, r, g, b, a);
744  angle += corner_angle_increment;
745 
746  for (i = 2; i < verts_per_corner; i++)
747  {
749  SET_INDEXED_VERTEX(last_index++);
750  SET_UNTEXTURED_VERTEX(x2 - radius + cos(angle)*radius, y1 + radius + sin(angle)*radius, r, g, b, a);
751  angle += corner_angle_increment;
752  }
753 
755  SET_INDEXED_VERTEX(last_index++);
756  SET_UNTEXTURED_VERTEX(x2 - radius + cos(angle)*radius, y2 - radius + sin(angle)*radius, r, g, b, a);
757  for (i = 1; i < verts_per_corner; i++)
758  {
760  SET_INDEXED_VERTEX(last_index++);
761  SET_UNTEXTURED_VERTEX(x2 - radius + cos(angle)*radius, y2 - radius + sin(angle)*radius, r, g, b, a);
762  angle += corner_angle_increment;
763  }
764 
766  SET_INDEXED_VERTEX(last_index++);
767  SET_UNTEXTURED_VERTEX(x1 + radius + cos(angle)*radius, y2 - radius + sin(angle)*radius, r, g, b, a);
768  for (i = 1; i < verts_per_corner; i++)
769  {
771  SET_INDEXED_VERTEX(last_index++);
772  SET_UNTEXTURED_VERTEX(x1 + radius + cos(angle)*radius, y2 - radius + sin(angle)*radius, r, g, b, a);
773  angle += corner_angle_increment;
774  }
775 
777  SET_INDEXED_VERTEX(last_index++);
778  SET_UNTEXTURED_VERTEX(x1 + radius + cos(angle)*radius, y1 + radius + sin(angle)*radius, r, g, b, a);
779  for (i = 1; i < verts_per_corner; i++)
780  {
782  SET_INDEXED_VERTEX(last_index++);
783  SET_UNTEXTURED_VERTEX(x1 + radius + cos(angle)*radius, y1 + radius + sin(angle)*radius, r, g, b, a);
784  angle += corner_angle_increment;
785  }
786 
787  // Last triangle
789  SET_INDEXED_VERTEX(last_index++);
791  }
792 }
793 
794 static void Polygon(GPU_Renderer* renderer, GPU_Target* target, unsigned int num_vertices, float* vertices, SDL_Color color)
795 {
796  if(num_vertices < 3)
797  return;
798 
799  {
800  int numSegments = 2 * num_vertices;
801  int last_index = 0;
802  int i;
803 
804  BEGIN_UNTEXTURED("GPU_Polygon", GL_LINES, num_vertices, numSegments);
805 
806  SET_UNTEXTURED_VERTEX(vertices[0], vertices[1], r, g, b, a);
807  for (i = 2; i < numSegments; i += 2)
808  {
809  SET_UNTEXTURED_VERTEX(vertices[i], vertices[i + 1], r, g, b, a);
810  last_index++;
811  SET_INDEXED_VERTEX(last_index); // Double the last one for the next line
812  }
814  }
815 }
816 
817 static void PolygonFilled(GPU_Renderer* renderer, GPU_Target* target, unsigned int num_vertices, float* vertices, SDL_Color color)
818 {
819  if(num_vertices < 3)
820  return;
821 
822  {
823  int numSegments = 2 * num_vertices;
824 
825  // Using a fan of triangles assumes that the polygon is convex
826  BEGIN_UNTEXTURED("GPU_PolygonFilled", GL_TRIANGLES, num_vertices, 3 + (num_vertices - 3) * 3);
827 
828  // First triangle
829  SET_UNTEXTURED_VERTEX(vertices[0], vertices[1], r, g, b, a);
830  SET_UNTEXTURED_VERTEX(vertices[2], vertices[3], r, g, b, a);
831  SET_UNTEXTURED_VERTEX(vertices[4], vertices[5], r, g, b, a);
832 
833  if (num_vertices > 3)
834  {
835  int last_index = 2;
836 
837  int i;
838  for (i = 6; i < numSegments; i += 2)
839  {
840  SET_INDEXED_VERTEX(0); // Start from the first vertex
841  SET_INDEXED_VERTEX(last_index); // Double the last one
842  SET_UNTEXTURED_VERTEX(vertices[i], vertices[i + 1], r, g, b, a);
843  last_index++;
844  }
845  }
846  }
847 }
848 
static void Circle(GPU_Renderer *renderer, GPU_Target *target, float x, float y, float radius, SDL_Color color)
static void Rectangle(GPU_Renderer *renderer, GPU_Target *target, float x1, float y1, float x2, float y2, SDL_Color color)
static void ArcFilled(GPU_Renderer *renderer, GPU_Target *target, float x, float y, float radius, float start_angle, float end_angle, SDL_Color color)
#define M_PI
#define GL_TRIANGLES
Definition: glew.h:303
static void Arc(GPU_Renderer *renderer, GPU_Target *target, float x, float y, float radius, float start_angle, float end_angle, SDL_Color color)
static float GetLineThickness(GPU_Renderer *renderer)
static void SectorFilled(GPU_Renderer *renderer, GPU_Target *target, float x, float y, float inner_radius, float outer_radius, float start_angle, float end_angle, SDL_Color color)
#define RADPERDEG
GLboolean GLboolean g
Definition: glew.h:7319
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1220
void(* FlushBlitBuffer)(GPU_Renderer *renderer)
Definition: SDL_gpu.h:629
#define BEGIN_UNTEXTURED(function_name, shape, num_additional_vertices, num_additional_indices)
GLdouble GLdouble t
Definition: glew.h:1366
GLAPI void GLAPIENTRY glLineWidth(GLfloat width)
static void RectangleRoundFilled(GPU_Renderer *renderer, GPU_Target *target, float x1, float y1, float x2, float y2, float radius, SDL_Color color)
GLdouble GLdouble GLdouble b
Definition: glew.h:6966
#define DEGPERRAD
static void Polygon(GPU_Renderer *renderer, GPU_Target *target, unsigned int num_vertices, float *vertices, SDL_Color color)
GPU_Target * current_context_target
Definition: SDL_gpu.h:494
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:7319
static void PolygonFilled(GPU_Renderer *renderer, GPU_Target *target, unsigned int num_vertices, float *vertices, SDL_Color color)
#define GL_POINTS
Definition: glew.h:292
static void Sector(GPU_Renderer *renderer, GPU_Target *target, float x, float y, float inner_radius, float outer_radius, float start_angle, float end_angle, SDL_Color color)
static float SetLineThickness(GPU_Renderer *renderer, float thickness)
GLuint color
Definition: glew.h:5801
static void CircleFilled(GPU_Renderer *renderer, GPU_Target *target, float x, float y, float radius, SDL_Color color)
static void RectangleFilled(GPU_Renderer *renderer, GPU_Target *target, float x1, float y1, float x2, float y2, SDL_Color color)
static void TriFilled(GPU_Renderer *renderer, GPU_Target *target, float x1, float y1, float x2, float y2, float x3, float y3, SDL_Color color)
size_t i
Definition: function.cpp:1057
GLint GLint GLint GLint GLint x
Definition: glew.h:1220
GLdouble GLdouble GLdouble r
Definition: glew.h:1374
GPU_Context * context
Definition: SDL_gpu.h:303
static void Tri(GPU_Renderer *renderer, GPU_Target *target, float x1, float y1, float x2, float y2, float x3, float y3, SDL_Color color)
const GLfloat * tc
Definition: glew.h:12749
static void Line(GPU_Renderer *renderer, GPU_Target *target, float x1, float y1, float x2, float y2, SDL_Color color)
static void RectangleRound(GPU_Renderer *renderer, GPU_Target *target, float x1, float y1, float x2, float y2, float radius, SDL_Color color)
static void Pixel(GPU_Renderer *renderer, GPU_Target *target, float x, float y, SDL_Color color)
GLdouble angle
Definition: glew.h:6979
#define GL_LINES
Definition: glew.h:297
#define SET_INDEXED_VERTEX(offset)
float line_thickness
Definition: SDL_gpu.h:266
GLdouble s
Definition: glew.h:1358
#define SET_UNTEXTURED_VERTEX(x, y, r, g, b, a)
GLenum target
Definition: glew.h:5190
float(* GetLineThickness)(GPU_Renderer *renderer)
Definition: SDL_gpu.h:743
GLclampf f
Definition: glew.h:3024