]> git.sesse.net Git - pistorm/blob - raylib_pi4_test/shapes.c
Add Meson build files.
[pistorm] / raylib_pi4_test / shapes.c
1 /**********************************************************************************************
2 *
3 *   raylib.shapes - Basic functions to draw 2d Shapes and check collisions
4 *
5 *   CONFIGURATION:
6 *
7 *   #define SUPPORT_QUADS_DRAW_MODE
8 *       Use QUADS instead of TRIANGLES for drawing when possible.
9 *       Some lines-based shapes could still use lines
10 *
11 *   LICENSE: zlib/libpng
12 *
13 *   Copyright (c) 2013-2021 Ramon Santamaria (@raysan5)
14 *
15 *   This software is provided "as-is", without any express or implied warranty. In no event
16 *   will the authors be held liable for any damages arising from the use of this software.
17 *
18 *   Permission is granted to anyone to use this software for any purpose, including commercial
19 *   applications, and to alter it and redistribute it freely, subject to the following restrictions:
20 *
21 *     1. The origin of this software must not be misrepresented; you must not claim that you
22 *     wrote the original software. If you use this software in a product, an acknowledgment
23 *     in the product documentation would be appreciated but is not required.
24 *
25 *     2. Altered source versions must be plainly marked as such, and must not be misrepresented
26 *     as being the original software.
27 *
28 *     3. This notice may not be removed or altered from any source distribution.
29 *
30 **********************************************************************************************/
31
32 #include "raylib.h"     // Declares module functions
33
34 // Check if config flags have been externally provided on compilation line
35 #if !defined(EXTERNAL_CONFIG_FLAGS)
36     #include "config.h"         // Defines module configuration flags
37 #endif
38
39 #include "rlgl.h"       // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
40
41 #include <math.h>       // Required for: sinf(), asinf(), cosf(), acosf(), sqrtf(), fabsf()
42
43 //----------------------------------------------------------------------------------
44 // Defines and Macros
45 //----------------------------------------------------------------------------------
46
47 // Error rate to calculate how many segments we need to draw a smooth circle,
48 // taken from https://stackoverflow.com/a/2244088
49 #ifndef SMOOTH_CIRCLE_ERROR_RATE
50     #define SMOOTH_CIRCLE_ERROR_RATE  0.5f
51 #endif
52
53 //----------------------------------------------------------------------------------
54 // Types and Structures Definition
55 //----------------------------------------------------------------------------------
56 // Not here...
57
58 //----------------------------------------------------------------------------------
59 // Global Variables Definition
60 //----------------------------------------------------------------------------------
61 Texture2D texShapes = { 1, 1, 1, 1, 7 };        // Texture used on shapes drawing (usually a white pixel)
62 Rectangle texShapesRec = { 0, 0, 1, 1 };        // Texture source rectangle used on shapes drawing
63
64 //----------------------------------------------------------------------------------
65 // Module specific Functions Declaration
66 //----------------------------------------------------------------------------------
67 static float EaseCubicInOut(float t, float b, float c, float d);    // Cubic easing
68
69 //----------------------------------------------------------------------------------
70 // Module Functions Definition
71 //----------------------------------------------------------------------------------
72
73 // Set texture and rectangle to be used on shapes drawing
74 // NOTE: It can be useful when using basic shapes and one single font,
75 // defining a font char white rectangle would allow drawing everything in a single draw call
76 void SetShapesTexture(Texture2D texture, Rectangle source)
77 {
78     texShapes = texture;
79     texShapesRec = source;
80 }
81
82 // Draw a pixel
83 void DrawPixel(int posX, int posY, Color color)
84 {
85     rlBegin(RL_LINES);
86         rlColor4ub(color.r, color.g, color.b, color.a);
87         rlVertex2i(posX, posY);
88         rlVertex2i(posX + 1, posY + 1);
89     rlEnd();
90 }
91
92 // Draw a pixel (Vector version)
93 void DrawPixelV(Vector2 position, Color color)
94 {
95     rlBegin(RL_LINES);
96         rlColor4ub(color.r, color.g, color.b, color.a);
97         rlVertex2f(position.x, position.y);
98         rlVertex2f(position.x + 1.0f, position.y + 1.0f);
99     rlEnd();
100 }
101
102 // Draw a line
103 void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color)
104 {
105     rlBegin(RL_LINES);
106         rlColor4ub(color.r, color.g, color.b, color.a);
107         rlVertex2i(startPosX, startPosY);
108         rlVertex2i(endPosX, endPosY);
109     rlEnd();
110 }
111
112 // Draw a line  (Vector version)
113 void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
114 {
115     rlBegin(RL_LINES);
116         rlColor4ub(color.r, color.g, color.b, color.a);
117         rlVertex2f(startPos.x, startPos.y);
118         rlVertex2f(endPos.x, endPos.y);
119     rlEnd();
120 }
121
122 // Draw a line defining thickness
123 void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color)
124 {
125     Vector2 delta = {endPos.x-startPos.x, endPos.y-startPos.y};
126     float   length = sqrtf(delta.x*delta.x + delta.y*delta.y);
127
128     if (length > 0  &&  thick > 0)
129     {
130         float   scale = thick/(2*length);
131         Vector2 radius = {-scale*delta.y, scale*delta.x};
132         Vector2 strip[] = {{startPos.x-radius.x, startPos.y-radius.y}, {startPos.x+radius.x, startPos.y+radius.y},
133                            {endPos.x-radius.x, endPos.y-radius.y}, {endPos.x+radius.x, endPos.y+radius.y}};
134
135         DrawTriangleStrip(strip, 4, color);
136     }
137 }
138
139 // Draw line using cubic-bezier curves in-out
140 void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color)
141 {
142 #ifndef BEZIER_LINE_DIVISIONS
143     #define BEZIER_LINE_DIVISIONS         24   // Bezier line divisions
144 #endif
145
146     Vector2 previous = startPos;
147     Vector2 current;
148
149     for (int i = 1; i <= BEZIER_LINE_DIVISIONS; i++)
150     {
151         // Cubic easing in-out
152         // NOTE: Easing is calculated only for y position value
153         current.y = EaseCubicInOut((float)i, startPos.y, endPos.y - startPos.y, (float)BEZIER_LINE_DIVISIONS);
154         current.x = previous.x + (endPos.x - startPos.x)/ (float)BEZIER_LINE_DIVISIONS;
155
156         DrawLineEx(previous, current, thick, color);
157
158         previous = current;
159     }
160 }
161
162 // Draw line using quadratic bezier curves with a control point
163 void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color)
164 {
165     const float step = 1.0f/BEZIER_LINE_DIVISIONS;
166
167     Vector2 previous = startPos;
168     Vector2 current = { 0 };
169     float t = 0.0f;
170
171     for (int i = 0; i <= BEZIER_LINE_DIVISIONS; i++)
172     {
173         t = step*i;
174         float a = powf(1 - t, 2);
175         float b = 2*(1 - t)*t;
176         float c = powf(t, 2);
177
178         // NOTE: The easing functions aren't suitable here because they don't take a control point
179         current.y = a*startPos.y + b*controlPos.y + c*endPos.y;
180         current.x = a*startPos.x + b*controlPos.x + c*endPos.x;
181
182         DrawLineEx(previous, current, thick, color);
183
184         previous = current;
185     }
186 }
187
188 // Draw lines sequence
189 void DrawLineStrip(Vector2 *points, int pointsCount, Color color)
190 {
191     if (pointsCount >= 2)
192     {
193         rlCheckRenderBatchLimit(pointsCount);
194
195         rlBegin(RL_LINES);
196             rlColor4ub(color.r, color.g, color.b, color.a);
197
198             for (int i = 0; i < pointsCount - 1; i++)
199             {
200                 rlVertex2f(points[i].x, points[i].y);
201                 rlVertex2f(points[i + 1].x, points[i + 1].y);
202             }
203         rlEnd();
204     }
205 }
206
207 // Draw a color-filled circle
208 void DrawCircle(int centerX, int centerY, float radius, Color color)
209 {
210     DrawCircleV((Vector2){ (float)centerX, (float)centerY }, radius, color);
211 }
212
213 // Draw a piece of a circle
214 void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
215 {
216     if (radius <= 0.0f) radius = 0.1f;  // Avoid div by zero
217
218     // Function expects (endAngle > startAngle)
219     if (endAngle < startAngle)
220     {
221         // Swap values
222         float tmp = startAngle;
223         startAngle = endAngle;
224         endAngle = tmp;
225     }
226
227     int minSegments = (int)ceilf((endAngle - startAngle)/90);
228
229     if (segments < minSegments)
230     {
231         // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
232         float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
233         segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
234
235         if (segments <= 0) segments = minSegments;
236     }
237
238     float stepLength = (endAngle - startAngle)/(float)segments;
239     float angle = startAngle;
240
241 #if defined(SUPPORT_QUADS_DRAW_MODE)
242     rlCheckRenderBatchLimit(4*segments/2);
243
244     rlSetTexture(texShapes.id);
245
246     rlBegin(RL_QUADS);
247         // NOTE: Every QUAD actually represents two segments
248         for (int i = 0; i < segments/2; i++)
249         {
250             rlColor4ub(color.r, color.g, color.b, color.a);
251
252             rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
253             rlVertex2f(center.x, center.y);
254
255             rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
256             rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
257
258             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
259             rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
260
261             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
262             rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength*2))*radius, center.y + cosf(DEG2RAD*(angle + stepLength*2))*radius);
263
264             angle += (stepLength*2);
265         }
266
267         // NOTE: In case number of segments is odd, we add one last piece to the cake
268         if (segments%2)
269         {
270             rlColor4ub(color.r, color.g, color.b, color.a);
271
272             rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
273             rlVertex2f(center.x, center.y);
274
275             rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
276             rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
277
278             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
279             rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
280
281             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
282             rlVertex2f(center.x, center.y);
283         }
284     rlEnd();
285
286     rlSetTexture(0);
287 #else
288     rlCheckRenderBatchLimit(3*segments);
289
290     rlBegin(RL_TRIANGLES);
291         for (int i = 0; i < segments; i++)
292         {
293             rlColor4ub(color.r, color.g, color.b, color.a);
294
295             rlVertex2f(center.x, center.y);
296             rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
297             rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
298
299             angle += stepLength;
300         }
301     rlEnd();
302 #endif
303 }
304
305 void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
306 {
307     if (radius <= 0.0f) radius = 0.1f;  // Avoid div by zero issue
308
309     // Function expects (endAngle > startAngle)
310     if (endAngle < startAngle)
311     {
312         // Swap values
313         float tmp = startAngle;
314         startAngle = endAngle;
315         endAngle = tmp;
316     }
317
318     int minSegments = (int)ceilf((endAngle - startAngle)/90);
319
320     if (segments < minSegments)
321     {
322         // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
323         float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
324         segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
325
326         if (segments <= 0) segments = minSegments;
327     }
328
329     float stepLength = (endAngle - startAngle)/(float)segments;
330     float angle = startAngle;
331
332     // Hide the cap lines when the circle is full
333     bool showCapLines = true;
334     int limit = 2*(segments + 2);
335     if ((int)(endAngle - startAngle)%360 == 0) { limit = 2*segments; showCapLines = false; }
336
337     rlCheckRenderBatchLimit(limit);
338
339     rlBegin(RL_LINES);
340         if (showCapLines)
341         {
342             rlColor4ub(color.r, color.g, color.b, color.a);
343             rlVertex2f(center.x, center.y);
344             rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
345         }
346
347         for (int i = 0; i < segments; i++)
348         {
349             rlColor4ub(color.r, color.g, color.b, color.a);
350
351             rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
352             rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
353
354             angle += stepLength;
355         }
356
357         if (showCapLines)
358         {
359             rlColor4ub(color.r, color.g, color.b, color.a);
360             rlVertex2f(center.x, center.y);
361             rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
362         }
363     rlEnd();
364 }
365
366 // Draw a gradient-filled circle
367 // NOTE: Gradient goes from center (color1) to border (color2)
368 void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
369 {
370     rlCheckRenderBatchLimit(3*36);
371
372     rlBegin(RL_TRIANGLES);
373         for (int i = 0; i < 360; i += 10)
374         {
375             rlColor4ub(color1.r, color1.g, color1.b, color1.a);
376             rlVertex2f((float)centerX, (float)centerY);
377             rlColor4ub(color2.r, color2.g, color2.b, color2.a);
378             rlVertex2f((float)centerX + sinf(DEG2RAD*i)*radius, (float)centerY + cosf(DEG2RAD*i)*radius);
379             rlColor4ub(color2.r, color2.g, color2.b, color2.a);
380             rlVertex2f((float)centerX + sinf(DEG2RAD*(i + 10))*radius, (float)centerY + cosf(DEG2RAD*(i + 10))*radius);
381         }
382     rlEnd();
383 }
384
385 // Draw a color-filled circle (Vector version)
386 // NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
387 void DrawCircleV(Vector2 center, float radius, Color color)
388 {
389     DrawCircleSector(center, radius, 0, 360, 36, color);
390 }
391
392 // Draw circle outline
393 void DrawCircleLines(int centerX, int centerY, float radius, Color color)
394 {
395     rlCheckRenderBatchLimit(2*36);
396
397     rlBegin(RL_LINES);
398         rlColor4ub(color.r, color.g, color.b, color.a);
399
400         // NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
401         for (int i = 0; i < 360; i += 10)
402         {
403             rlVertex2f(centerX + sinf(DEG2RAD*i)*radius, centerY + cosf(DEG2RAD*i)*radius);
404             rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radius, centerY + cosf(DEG2RAD*(i + 10))*radius);
405         }
406     rlEnd();
407 }
408
409 // Draw ellipse
410 void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color)
411 {
412     rlCheckRenderBatchLimit(3*36);
413
414     rlBegin(RL_TRIANGLES);
415         for (int i = 0; i < 360; i += 10)
416         {
417             rlColor4ub(color.r, color.g, color.b, color.a);
418             rlVertex2f((float)centerX, (float)centerY);
419             rlVertex2f((float)centerX + sinf(DEG2RAD*i)*radiusH, (float)centerY + cosf(DEG2RAD*i)*radiusV);
420             rlVertex2f((float)centerX + sinf(DEG2RAD*(i + 10))*radiusH, (float)centerY + cosf(DEG2RAD*(i + 10))*radiusV);
421         }
422     rlEnd();
423 }
424
425 // Draw ellipse outline
426 void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color)
427 {
428     rlCheckRenderBatchLimit(2*36);
429
430     rlBegin(RL_LINES);
431         for (int i = 0; i < 360; i += 10)
432         {
433             rlColor4ub(color.r, color.g, color.b, color.a);
434             rlVertex2f(centerX + sinf(DEG2RAD*i)*radiusH, centerY + cosf(DEG2RAD*i)*radiusV);
435             rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radiusH, centerY + cosf(DEG2RAD*(i + 10))*radiusV);
436         }
437     rlEnd();
438 }
439
440 void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color)
441 {
442     if (startAngle == endAngle) return;
443
444     // Function expects (outerRadius > innerRadius)
445     if (outerRadius < innerRadius)
446     {
447         float tmp = outerRadius;
448         outerRadius = innerRadius;
449         innerRadius = tmp;
450
451         if (outerRadius <= 0.0f) outerRadius = 0.1f;
452     }
453
454     // Function expects (endAngle > startAngle)
455     if (endAngle < startAngle)
456     {
457         // Swap values
458         float tmp = startAngle;
459         startAngle = endAngle;
460         endAngle = tmp;
461     }
462
463     int minSegments = (int)ceilf((endAngle - startAngle)/90);
464
465     if (segments < minSegments)
466     {
467         // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
468         float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/outerRadius, 2) - 1);
469         segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
470
471         if (segments <= 0) segments = minSegments;
472     }
473
474     // Not a ring
475     if (innerRadius <= 0.0f)
476     {
477         DrawCircleSector(center, outerRadius, startAngle, endAngle, segments, color);
478         return;
479     }
480
481     float stepLength = (endAngle - startAngle)/(float)segments;
482     float angle = startAngle;
483
484 #if defined(SUPPORT_QUADS_DRAW_MODE)
485     rlCheckRenderBatchLimit(4*segments);
486
487     rlSetTexture(texShapes.id);
488
489     rlBegin(RL_QUADS);
490         for (int i = 0; i < segments; i++)
491         {
492             rlColor4ub(color.r, color.g, color.b, color.a);
493
494             rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
495             rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
496
497             rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
498             rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
499
500             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
501             rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
502
503             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
504             rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
505
506             angle += stepLength;
507         }
508     rlEnd();
509
510     rlSetTexture(0);
511 #else
512     rlCheckRenderBatchLimit(6*segments);
513
514     rlBegin(RL_TRIANGLES);
515         for (int i = 0; i < segments; i++)
516         {
517             rlColor4ub(color.r, color.g, color.b, color.a);
518
519             rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
520             rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
521             rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
522
523             rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
524             rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
525             rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
526
527             angle += stepLength;
528         }
529     rlEnd();
530 #endif
531 }
532
533 void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color)
534 {
535     if (startAngle == endAngle) return;
536
537     // Function expects (outerRadius > innerRadius)
538     if (outerRadius < innerRadius)
539     {
540         float tmp = outerRadius;
541         outerRadius = innerRadius;
542         innerRadius = tmp;
543
544         if (outerRadius <= 0.0f) outerRadius = 0.1f;
545     }
546
547     // Function expects (endAngle > startAngle)
548     if (endAngle < startAngle)
549     {
550         // Swap values
551         float tmp = startAngle;
552         startAngle = endAngle;
553         endAngle = tmp;
554     }
555
556     int minSegments = (int)ceilf((endAngle - startAngle)/90);
557
558     if (segments < minSegments)
559     {
560         // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
561         float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/outerRadius, 2) - 1);
562         segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
563
564         if (segments <= 0) segments = minSegments;
565     }
566
567     if (innerRadius <= 0.0f)
568     {
569         DrawCircleSectorLines(center, outerRadius, startAngle, endAngle, segments, color);
570         return;
571     }
572
573     float stepLength = (endAngle - startAngle)/(float)segments;
574     float angle = startAngle;
575
576     bool showCapLines = true;
577     int limit = 4*(segments + 1);
578     if ((int)(endAngle - startAngle)%360 == 0) { limit = 4*segments; showCapLines = false; }
579
580     rlCheckRenderBatchLimit(limit);
581
582     rlBegin(RL_LINES);
583         if (showCapLines)
584         {
585             rlColor4ub(color.r, color.g, color.b, color.a);
586             rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
587             rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
588         }
589
590         for (int i = 0; i < segments; i++)
591         {
592             rlColor4ub(color.r, color.g, color.b, color.a);
593
594             rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
595             rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
596
597             rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
598             rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
599
600             angle += stepLength;
601         }
602
603         if (showCapLines)
604         {
605             rlColor4ub(color.r, color.g, color.b, color.a);
606             rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
607             rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
608         }
609     rlEnd();
610 }
611
612 // Draw a color-filled rectangle
613 void DrawRectangle(int posX, int posY, int width, int height, Color color)
614 {
615     DrawRectangleV((Vector2){ (float)posX, (float)posY }, (Vector2){ (float)width, (float)height }, color);
616 }
617
618 // Draw a color-filled rectangle (Vector version)
619 // NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
620 void DrawRectangleV(Vector2 position, Vector2 size, Color color)
621 {
622     DrawRectanglePro((Rectangle){ position.x, position.y, size.x, size.y }, (Vector2){ 0.0f, 0.0f }, 0.0f, color);
623 }
624
625 // Draw a color-filled rectangle
626 void DrawRectangleRec(Rectangle rec, Color color)
627 {
628     DrawRectanglePro(rec, (Vector2){ 0.0f, 0.0f }, 0.0f, color);
629 }
630
631 // Draw a color-filled rectangle with pro parameters
632 void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color)
633 {
634     rlCheckRenderBatchLimit(4);
635
636     Vector2 topLeft = { 0 };
637     Vector2 topRight = { 0 };
638     Vector2 bottomLeft = { 0 };
639     Vector2 bottomRight = { 0 };
640
641     // Only calculate rotation if needed
642     if (rotation == 0.0f)
643     {
644         float x = rec.x - origin.x;
645         float y = rec.y - origin.y;
646         topLeft = (Vector2){ x, y };
647         topRight = (Vector2){ x + rec.width, y };
648         bottomLeft = (Vector2){ x, y + rec.height };
649         bottomRight = (Vector2){ x + rec.width, y + rec.height };
650     }
651     else
652     {
653         float sinRotation = sinf(rotation*DEG2RAD);
654         float cosRotation = cosf(rotation*DEG2RAD);
655         float x = rec.x;
656         float y = rec.y;
657         float dx = -origin.x;
658         float dy = -origin.y;
659
660         topLeft.x = x + dx*cosRotation - dy*sinRotation;
661         topLeft.y = y + dx*sinRotation + dy*cosRotation;
662
663         topRight.x = x + (dx + rec.width)*cosRotation - dy*sinRotation;
664         topRight.y = y + (dx + rec.width)*sinRotation + dy*cosRotation;
665
666         bottomLeft.x = x + dx*cosRotation - (dy + rec.height)*sinRotation;
667         bottomLeft.y = y + dx*sinRotation + (dy + rec.height)*cosRotation;
668
669         bottomRight.x = x + (dx + rec.width)*cosRotation - (dy + rec.height)*sinRotation;
670         bottomRight.y = y + (dx + rec.width)*sinRotation + (dy + rec.height)*cosRotation;
671     }
672
673     rlSetTexture(texShapes.id);
674     rlBegin(RL_QUADS);
675
676         rlNormal3f(0.0f, 0.0f, 1.0f);
677         rlColor4ub(color.r, color.g, color.b, color.a);
678
679         rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
680         rlVertex2f(topLeft.x, topLeft.y);
681
682         rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
683         rlVertex2f(bottomLeft.x, bottomLeft.y);
684
685         rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
686         rlVertex2f(bottomRight.x, bottomRight.y);
687
688         rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
689         rlVertex2f(topRight.x, topRight.y);
690
691     rlEnd();
692     rlSetTexture(0);
693 }
694
695 // Draw a vertical-gradient-filled rectangle
696 // NOTE: Gradient goes from bottom (color1) to top (color2)
697 void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2)
698 {
699     DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color2, color2, color1);
700 }
701
702 // Draw a horizontal-gradient-filled rectangle
703 // NOTE: Gradient goes from bottom (color1) to top (color2)
704 void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2)
705 {
706     DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color1, color2, color2);
707 }
708
709 // Draw a gradient-filled rectangle
710 // NOTE: Colors refer to corners, starting at top-lef corner and counter-clockwise
711 void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4)
712 {
713     rlSetTexture(texShapes.id);
714
715     rlPushMatrix();
716         rlBegin(RL_QUADS);
717             rlNormal3f(0.0f, 0.0f, 1.0f);
718
719             // NOTE: Default raylib font character 95 is a white square
720             rlColor4ub(col1.r, col1.g, col1.b, col1.a);
721             rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
722             rlVertex2f(rec.x, rec.y);
723
724             rlColor4ub(col2.r, col2.g, col2.b, col2.a);
725             rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
726             rlVertex2f(rec.x, rec.y + rec.height);
727
728             rlColor4ub(col3.r, col3.g, col3.b, col3.a);
729             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
730             rlVertex2f(rec.x + rec.width, rec.y + rec.height);
731
732             rlColor4ub(col4.r, col4.g, col4.b, col4.a);
733             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
734             rlVertex2f(rec.x + rec.width, rec.y);
735         rlEnd();
736     rlPopMatrix();
737
738     rlSetTexture(0);
739 }
740
741 // Draw rectangle outline
742 // NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
743 void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
744 {
745 #if defined(SUPPORT_QUADS_DRAW_MODE)
746     DrawRectangle(posX, posY, width, 1, color);
747     DrawRectangle(posX + width - 1, posY + 1, 1, height - 2, color);
748     DrawRectangle(posX, posY + height - 1, width, 1, color);
749     DrawRectangle(posX, posY + 1, 1, height - 2, color);
750 #else
751     rlBegin(RL_LINES);
752         rlColor4ub(color.r, color.g, color.b, color.a);
753         rlVertex2i(posX + 1, posY + 1);
754         rlVertex2i(posX + width, posY + 1);
755
756         rlVertex2i(posX + width, posY + 1);
757         rlVertex2i(posX + width, posY + height);
758
759         rlVertex2i(posX + width, posY + height);
760         rlVertex2i(posX + 1, posY + height);
761
762         rlVertex2i(posX + 1, posY + height);
763         rlVertex2i(posX + 1, posY + 1);
764     rlEnd();
765 #endif
766 }
767
768 // Draw rectangle outline with extended parameters
769 void DrawRectangleLinesEx(Rectangle rec, int lineThick, Color color)
770 {
771     if ((lineThick > rec.width) || (lineThick > rec.height))
772     {
773         if (rec.width > rec.height) lineThick = (int)rec.height/2;
774         else if (rec.width < rec.height) lineThick = (int)rec.width/2;
775     }
776
777     // When rec = { x, y, 8.0f, 6.0f } and lineThick = 2, the following
778     // four rectangles are drawn ([T]op, [B]ottom, [L]eft, [R]ight):
779     //
780     //   TTTTTTTT
781     //   TTTTTTTT
782     //   LL    RR
783     //   LL    RR
784     //   BBBBBBBB
785     //   BBBBBBBB
786     //
787     float thick = (float)lineThick;
788     Rectangle top = { rec.x, rec.y, rec.width, thick };
789     Rectangle bottom = { rec.x, rec.y - thick + rec.height, rec.width, thick };
790     Rectangle left = { rec.x, rec.y + thick, thick, rec.height - thick*2.0f };
791     Rectangle right = { rec.x - thick + rec.width, rec.y + thick, thick, rec.height - thick*2.0f };
792
793     DrawRectangleRec(top, color);
794     DrawRectangleRec(bottom, color);
795     DrawRectangleRec(left, color);
796     DrawRectangleRec(right, color);
797 }
798
799 // Draw rectangle with rounded edges
800 void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color)
801 {
802     // Not a rounded rectangle
803     if ((roundness <= 0.0f) || (rec.width < 1) || (rec.height < 1 ))
804     {
805         DrawRectangleRec(rec, color);
806         return;
807     }
808
809     if (roundness >= 1.0f) roundness = 1.0f;
810
811     // Calculate corner radius
812     float radius = (rec.width > rec.height)? (rec.height*roundness)/2 : (rec.width*roundness)/2;
813     if (radius <= 0.0f) return;
814
815     // Calculate number of segments to use for the corners
816     if (segments < 4)
817     {
818         // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
819         float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
820         segments = (int)(ceilf(2*PI/th)/4.0f);
821         if (segments <= 0) segments = 4;
822     }
823
824     float stepLength = 90.0f/(float)segments;
825
826     /*
827     Quick sketch to make sense of all of this,
828     there are 9 parts to draw, also mark the 12 points we'll use
829
830           P0____________________P1
831           /|                    |\
832          /1|          2         |3\
833      P7 /__|____________________|__\ P2
834        |   |P8                P9|   |
835        | 8 |          9         | 4 |
836        | __|____________________|__ |
837      P6 \  |P11              P10|  / P3
838          \7|          6         |5/
839           \|____________________|/
840           P5                    P4
841     */
842     // Coordinates of the 12 points that define the rounded rect
843     const Vector2 point[12] = {
844         {(float)rec.x + radius, rec.y}, {(float)(rec.x + rec.width) - radius, rec.y}, { rec.x + rec.width, (float)rec.y + radius },     // PO, P1, P2
845         {rec.x + rec.width, (float)(rec.y + rec.height) - radius}, {(float)(rec.x + rec.width) - radius, rec.y + rec.height},           // P3, P4
846         {(float)rec.x + radius, rec.y + rec.height}, { rec.x, (float)(rec.y + rec.height) - radius}, {rec.x, (float)rec.y + radius},    // P5, P6, P7
847         {(float)rec.x + radius, (float)rec.y + radius}, {(float)(rec.x + rec.width) - radius, (float)rec.y + radius},                   // P8, P9
848         {(float)(rec.x + rec.width) - radius, (float)(rec.y + rec.height) - radius}, {(float)rec.x + radius, (float)(rec.y + rec.height) - radius} // P10, P11
849     };
850
851     const Vector2 centers[4] = { point[8], point[9], point[10], point[11] };
852     const float angles[4] = { 180.0f, 90.0f, 0.0f, 270.0f };
853
854 #if defined(SUPPORT_QUADS_DRAW_MODE)
855     rlCheckRenderBatchLimit(16*segments/2 + 5*4);
856
857     rlSetTexture(texShapes.id);
858
859     rlBegin(RL_QUADS);
860         // Draw all of the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner
861         for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
862         {
863             float angle = angles[k];
864             const Vector2 center = centers[k];
865
866             // NOTE: Every QUAD actually represents two segments
867             for (int i = 0; i < segments/2; i++)
868             {
869                 rlColor4ub(color.r, color.g, color.b, color.a);
870                 rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
871                 rlVertex2f(center.x, center.y);
872                 rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
873                 rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
874                 rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
875                 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
876                 rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
877                 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength*2))*radius, center.y + cosf(DEG2RAD*(angle + stepLength*2))*radius);
878                 angle += (stepLength*2);
879             }
880
881             // NOTE: In case number of segments is odd, we add one last piece to the cake
882             if (segments%2)
883             {
884                 rlColor4ub(color.r, color.g, color.b, color.a);
885                 rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
886                 rlVertex2f(center.x, center.y);
887                 rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
888                 rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
889                 rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
890                 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
891                 rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
892                 rlVertex2f(center.x, center.y);
893             }
894         }
895
896         // [2] Upper Rectangle
897         rlColor4ub(color.r, color.g, color.b, color.a);
898         rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
899         rlVertex2f(point[0].x, point[0].y);
900         rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
901         rlVertex2f(point[8].x, point[8].y);
902         rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
903         rlVertex2f(point[9].x, point[9].y);
904         rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
905         rlVertex2f(point[1].x, point[1].y);
906
907         // [4] Right Rectangle
908         rlColor4ub(color.r, color.g, color.b, color.a);
909         rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
910         rlVertex2f(point[2].x, point[2].y);
911         rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
912         rlVertex2f(point[9].x, point[9].y);
913         rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
914         rlVertex2f(point[10].x, point[10].y);
915         rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
916         rlVertex2f(point[3].x, point[3].y);
917
918         // [6] Bottom Rectangle
919         rlColor4ub(color.r, color.g, color.b, color.a);
920         rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
921         rlVertex2f(point[11].x, point[11].y);
922         rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
923         rlVertex2f(point[5].x, point[5].y);
924         rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
925         rlVertex2f(point[4].x, point[4].y);
926         rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
927         rlVertex2f(point[10].x, point[10].y);
928
929         // [8] Left Rectangle
930         rlColor4ub(color.r, color.g, color.b, color.a);
931         rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
932         rlVertex2f(point[7].x, point[7].y);
933         rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
934         rlVertex2f(point[6].x, point[6].y);
935         rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
936         rlVertex2f(point[11].x, point[11].y);
937         rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
938         rlVertex2f(point[8].x, point[8].y);
939
940         // [9] Middle Rectangle
941         rlColor4ub(color.r, color.g, color.b, color.a);
942         rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
943         rlVertex2f(point[8].x, point[8].y);
944         rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
945         rlVertex2f(point[11].x, point[11].y);
946         rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
947         rlVertex2f(point[10].x, point[10].y);
948         rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
949         rlVertex2f(point[9].x, point[9].y);
950
951     rlEnd();
952     rlSetTexture(0);
953 #else
954     rlCheckRenderBatchLimit(12*segments + 5*6); // 4 corners with 3 vertices per segment + 5 rectangles with 6 vertices each
955
956     rlBegin(RL_TRIANGLES);
957
958         // Draw all of the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner
959         for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
960         {
961             float angle = angles[k];
962             const Vector2 center = centers[k];
963             for (int i = 0; i < segments; i++)
964             {
965                 rlColor4ub(color.r, color.g, color.b, color.a);
966                 rlVertex2f(center.x, center.y);
967                 rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
968                 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
969                 angle += stepLength;
970             }
971         }
972
973         // [2] Upper Rectangle
974         rlColor4ub(color.r, color.g, color.b, color.a);
975         rlVertex2f(point[0].x, point[0].y);
976         rlVertex2f(point[8].x, point[8].y);
977         rlVertex2f(point[9].x, point[9].y);
978         rlVertex2f(point[1].x, point[1].y);
979         rlVertex2f(point[0].x, point[0].y);
980         rlVertex2f(point[9].x, point[9].y);
981
982         // [4] Right Rectangle
983         rlColor4ub(color.r, color.g, color.b, color.a);
984         rlVertex2f(point[9].x, point[9].y);
985         rlVertex2f(point[10].x, point[10].y);
986         rlVertex2f(point[3].x, point[3].y);
987         rlVertex2f(point[2].x, point[2].y);
988         rlVertex2f(point[9].x, point[9].y);
989         rlVertex2f(point[3].x, point[3].y);
990
991         // [6] Bottom Rectangle
992         rlColor4ub(color.r, color.g, color.b, color.a);
993         rlVertex2f(point[11].x, point[11].y);
994         rlVertex2f(point[5].x, point[5].y);
995         rlVertex2f(point[4].x, point[4].y);
996         rlVertex2f(point[10].x, point[10].y);
997         rlVertex2f(point[11].x, point[11].y);
998         rlVertex2f(point[4].x, point[4].y);
999
1000         // [8] Left Rectangle
1001         rlColor4ub(color.r, color.g, color.b, color.a);
1002         rlVertex2f(point[7].x, point[7].y);
1003         rlVertex2f(point[6].x, point[6].y);
1004         rlVertex2f(point[11].x, point[11].y);
1005         rlVertex2f(point[8].x, point[8].y);
1006         rlVertex2f(point[7].x, point[7].y);
1007         rlVertex2f(point[11].x, point[11].y);
1008
1009         // [9] Middle Rectangle
1010         rlColor4ub(color.r, color.g, color.b, color.a);
1011         rlVertex2f(point[8].x, point[8].y);
1012         rlVertex2f(point[11].x, point[11].y);
1013         rlVertex2f(point[10].x, point[10].y);
1014         rlVertex2f(point[9].x, point[9].y);
1015         rlVertex2f(point[8].x, point[8].y);
1016         rlVertex2f(point[10].x, point[10].y);
1017     rlEnd();
1018 #endif
1019 }
1020
1021 // Draw rectangle with rounded edges outline
1022 void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, int lineThick, Color color)
1023 {
1024     if (lineThick < 0) lineThick = 0;
1025
1026     // Not a rounded rectangle
1027     if (roundness <= 0.0f)
1028     {
1029         DrawRectangleLinesEx((Rectangle){rec.x-lineThick, rec.y-lineThick, rec.width+2*lineThick, rec.height+2*lineThick}, lineThick, color);
1030         return;
1031     }
1032
1033     if (roundness >= 1.0f) roundness = 1.0f;
1034
1035     // Calculate corner radius
1036     float radius = (rec.width > rec.height)? (rec.height*roundness)/2 : (rec.width*roundness)/2;
1037     if (radius <= 0.0f) return;
1038
1039     // Calculate number of segments to use for the corners
1040     if (segments < 4)
1041     {
1042         // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
1043         float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
1044         segments = (int)(ceilf(2*PI/th)/2.0f);
1045         if (segments <= 0) segments = 4;
1046     }
1047
1048     float stepLength = 90.0f/(float)segments;
1049     const float outerRadius = radius + (float)lineThick, innerRadius = radius;
1050
1051     /*
1052     Quick sketch to make sense of all of this,
1053     marks the 16 + 4(corner centers P16-19) points we'll use
1054
1055            P0 ================== P1
1056           // P8                P9 \\
1057          //                        \\
1058      P7 // P15                  P10 \\ P2
1059        ||   *P16             P17*    ||
1060        ||                            ||
1061        || P14                   P11  ||
1062      P6 \\  *P19             P18*   // P3
1063          \\                        //
1064           \\ P13              P12 //
1065            P5 ================== P4
1066     */
1067     const Vector2 point[16] = {
1068         {(float)rec.x + innerRadius, rec.y - lineThick}, {(float)(rec.x + rec.width) - innerRadius, rec.y - lineThick}, { rec.x + rec.width + lineThick, (float)rec.y + innerRadius }, // PO, P1, P2
1069         {rec.x + rec.width + lineThick, (float)(rec.y + rec.height) - innerRadius}, {(float)(rec.x + rec.width) - innerRadius, rec.y + rec.height + lineThick}, // P3, P4
1070         {(float)rec.x + innerRadius, rec.y + rec.height + lineThick}, { rec.x - lineThick, (float)(rec.y + rec.height) - innerRadius}, {rec.x - lineThick, (float)rec.y + innerRadius}, // P5, P6, P7
1071         {(float)rec.x + innerRadius, rec.y}, {(float)(rec.x + rec.width) - innerRadius, rec.y}, // P8, P9
1072         { rec.x + rec.width, (float)rec.y + innerRadius }, {rec.x + rec.width, (float)(rec.y + rec.height) - innerRadius}, // P10, P11
1073         {(float)(rec.x + rec.width) - innerRadius, rec.y + rec.height}, {(float)rec.x + innerRadius, rec.y + rec.height}, // P12, P13
1074         { rec.x, (float)(rec.y + rec.height) - innerRadius}, {rec.x, (float)rec.y + innerRadius} // P14, P15
1075     };
1076
1077     const Vector2 centers[4] = {
1078         {(float)rec.x + innerRadius, (float)rec.y + innerRadius}, {(float)(rec.x + rec.width) - innerRadius, (float)rec.y + innerRadius}, // P16, P17
1079         {(float)(rec.x + rec.width) - innerRadius, (float)(rec.y + rec.height) - innerRadius}, {(float)rec.x + innerRadius, (float)(rec.y + rec.height) - innerRadius} // P18, P19
1080     };
1081
1082     const float angles[4] = { 180.0f, 90.0f, 0.0f, 270.0f };
1083
1084     if (lineThick > 1)
1085     {
1086 #if defined(SUPPORT_QUADS_DRAW_MODE)
1087         rlCheckRenderBatchLimit(4*4*segments + 4*4); // 4 corners with 4 vertices for each segment + 4 rectangles with 4 vertices each
1088
1089         rlSetTexture(texShapes.id);
1090
1091         rlBegin(RL_QUADS);
1092
1093             // Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
1094             for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
1095             {
1096                 float angle = angles[k];
1097                 const Vector2 center = centers[k];
1098                 for (int i = 0; i < segments; i++)
1099                 {
1100                     rlColor4ub(color.r, color.g, color.b, color.a);
1101                     rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
1102                     rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
1103                     rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1104                     rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
1105                     rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1106                     rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
1107                     rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
1108                     rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
1109
1110                     angle += stepLength;
1111                 }
1112             }
1113
1114             // Upper rectangle
1115             rlColor4ub(color.r, color.g, color.b, color.a);
1116             rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
1117             rlVertex2f(point[0].x, point[0].y);
1118             rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1119             rlVertex2f(point[8].x, point[8].y);
1120             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1121             rlVertex2f(point[9].x, point[9].y);
1122             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
1123             rlVertex2f(point[1].x, point[1].y);
1124
1125             // Right rectangle
1126             rlColor4ub(color.r, color.g, color.b, color.a);
1127             rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
1128             rlVertex2f(point[2].x, point[2].y);
1129             rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1130             rlVertex2f(point[10].x, point[10].y);
1131             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1132             rlVertex2f(point[11].x, point[11].y);
1133             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
1134             rlVertex2f(point[3].x, point[3].y);
1135
1136             // Lower rectangle
1137             rlColor4ub(color.r, color.g, color.b, color.a);
1138             rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
1139             rlVertex2f(point[13].x, point[13].y);
1140             rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1141             rlVertex2f(point[5].x, point[5].y);
1142             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1143             rlVertex2f(point[4].x, point[4].y);
1144             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
1145             rlVertex2f(point[12].x, point[12].y);
1146
1147             // Left rectangle
1148             rlColor4ub(color.r, color.g, color.b, color.a);
1149             rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
1150             rlVertex2f(point[15].x, point[15].y);
1151             rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1152             rlVertex2f(point[7].x, point[7].y);
1153             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1154             rlVertex2f(point[6].x, point[6].y);
1155             rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
1156             rlVertex2f(point[14].x, point[14].y);
1157
1158         rlEnd();
1159         rlSetTexture(0);
1160 #else
1161         rlCheckRenderBatchLimit(4*6*segments + 4*6); // 4 corners with 6(2*3) vertices for each segment + 4 rectangles with 6 vertices each
1162
1163         rlBegin(RL_TRIANGLES);
1164
1165             // Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
1166             for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
1167             {
1168                 float angle = angles[k];
1169                 const Vector2 center = centers[k];
1170
1171                 for (int i = 0; i < segments; i++)
1172                 {
1173                     rlColor4ub(color.r, color.g, color.b, color.a);
1174
1175                     rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
1176                     rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
1177                     rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
1178
1179                     rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
1180                     rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
1181                     rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
1182
1183                     angle += stepLength;
1184                 }
1185             }
1186
1187             // Upper rectangle
1188             rlColor4ub(color.r, color.g, color.b, color.a);
1189             rlVertex2f(point[0].x, point[0].y);
1190             rlVertex2f(point[8].x, point[8].y);
1191             rlVertex2f(point[9].x, point[9].y);
1192             rlVertex2f(point[1].x, point[1].y);
1193             rlVertex2f(point[0].x, point[0].y);
1194             rlVertex2f(point[9].x, point[9].y);
1195
1196             // Right rectangle
1197             rlColor4ub(color.r, color.g, color.b, color.a);
1198             rlVertex2f(point[10].x, point[10].y);
1199             rlVertex2f(point[11].x, point[11].y);
1200             rlVertex2f(point[3].x, point[3].y);
1201             rlVertex2f(point[2].x, point[2].y);
1202             rlVertex2f(point[10].x, point[10].y);
1203             rlVertex2f(point[3].x, point[3].y);
1204
1205             // Lower rectangle
1206             rlColor4ub(color.r, color.g, color.b, color.a);
1207             rlVertex2f(point[13].x, point[13].y);
1208             rlVertex2f(point[5].x, point[5].y);
1209             rlVertex2f(point[4].x, point[4].y);
1210             rlVertex2f(point[12].x, point[12].y);
1211             rlVertex2f(point[13].x, point[13].y);
1212             rlVertex2f(point[4].x, point[4].y);
1213
1214             // Left rectangle
1215             rlColor4ub(color.r, color.g, color.b, color.a);
1216             rlVertex2f(point[7].x, point[7].y);
1217             rlVertex2f(point[6].x, point[6].y);
1218             rlVertex2f(point[14].x, point[14].y);
1219             rlVertex2f(point[15].x, point[15].y);
1220             rlVertex2f(point[7].x, point[7].y);
1221             rlVertex2f(point[14].x, point[14].y);
1222         rlEnd();
1223 #endif
1224     }
1225     else
1226     {
1227         // Use LINES to draw the outline
1228         rlCheckRenderBatchLimit(8*segments + 4*2); // 4 corners with 2 vertices for each segment + 4 rectangles with 2 vertices each
1229
1230         rlBegin(RL_LINES);
1231
1232             // Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
1233             for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
1234             {
1235                 float angle = angles[k];
1236                 const Vector2 center = centers[k];
1237
1238                 for (int i = 0; i < segments; i++)
1239                 {
1240                     rlColor4ub(color.r, color.g, color.b, color.a);
1241                     rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
1242                     rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
1243                     angle += stepLength;
1244                 }
1245             }
1246
1247             // And now the remaining 4 lines
1248             for (int i = 0; i < 8; i += 2)
1249             {
1250                 rlColor4ub(color.r, color.g, color.b, color.a);
1251                 rlVertex2f(point[i].x, point[i].y);
1252                 rlVertex2f(point[i + 1].x, point[i + 1].y);
1253             }
1254
1255         rlEnd();
1256     }
1257 }
1258
1259 // Draw a triangle
1260 // NOTE: Vertex must be provided in counter-clockwise order
1261 void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
1262 {
1263     rlCheckRenderBatchLimit(4);
1264
1265 #if defined(SUPPORT_QUADS_DRAW_MODE)
1266     rlSetTexture(texShapes.id);
1267
1268     rlBegin(RL_QUADS);
1269         rlColor4ub(color.r, color.g, color.b, color.a);
1270
1271         rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
1272         rlVertex2f(v1.x, v1.y);
1273
1274         rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1275         rlVertex2f(v2.x, v2.y);
1276
1277         rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1278         rlVertex2f(v2.x, v2.y);
1279
1280         rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
1281         rlVertex2f(v3.x, v3.y);
1282     rlEnd();
1283
1284     rlSetTexture(0);
1285 #else
1286     rlBegin(RL_TRIANGLES);
1287         rlColor4ub(color.r, color.g, color.b, color.a);
1288         rlVertex2f(v1.x, v1.y);
1289         rlVertex2f(v2.x, v2.y);
1290         rlVertex2f(v3.x, v3.y);
1291     rlEnd();
1292 #endif
1293 }
1294
1295 // Draw a triangle using lines
1296 // NOTE: Vertex must be provided in counter-clockwise order
1297 void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
1298 {
1299     rlCheckRenderBatchLimit(6);
1300
1301     rlBegin(RL_LINES);
1302         rlColor4ub(color.r, color.g, color.b, color.a);
1303         rlVertex2f(v1.x, v1.y);
1304         rlVertex2f(v2.x, v2.y);
1305
1306         rlVertex2f(v2.x, v2.y);
1307         rlVertex2f(v3.x, v3.y);
1308
1309         rlVertex2f(v3.x, v3.y);
1310         rlVertex2f(v1.x, v1.y);
1311     rlEnd();
1312 }
1313
1314 // Draw a triangle fan defined by points
1315 // NOTE: First vertex provided is the center, shared by all triangles
1316 // By default, following vertex should be provided in counter-clockwise order
1317 void DrawTriangleFan(Vector2 *points, int pointsCount, Color color)
1318 {
1319     if (pointsCount >= 3)
1320     {
1321         rlCheckRenderBatchLimit((pointsCount - 2)*4);
1322
1323         rlSetTexture(texShapes.id);
1324         rlBegin(RL_QUADS);
1325             rlColor4ub(color.r, color.g, color.b, color.a);
1326
1327             for (int i = 1; i < pointsCount - 1; i++)
1328             {
1329                 rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
1330                 rlVertex2f(points[0].x, points[0].y);
1331
1332                 rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1333                 rlVertex2f(points[i].x, points[i].y);
1334
1335                 rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1336                 rlVertex2f(points[i + 1].x, points[i + 1].y);
1337
1338                 rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
1339                 rlVertex2f(points[i + 1].x, points[i + 1].y);
1340             }
1341         rlEnd();
1342         rlSetTexture(0);
1343     }
1344 }
1345
1346 // Draw a triangle strip defined by points
1347 // NOTE: Every new vertex connects with previous two
1348 void DrawTriangleStrip(Vector2 *points, int pointsCount, Color color)
1349 {
1350     if (pointsCount >= 3)
1351     {
1352         rlCheckRenderBatchLimit(3*(pointsCount - 2));
1353
1354         rlBegin(RL_TRIANGLES);
1355             rlColor4ub(color.r, color.g, color.b, color.a);
1356
1357             for (int i = 2; i < pointsCount; i++)
1358             {
1359                 if ((i%2) == 0)
1360                 {
1361                     rlVertex2f(points[i].x, points[i].y);
1362                     rlVertex2f(points[i - 2].x, points[i - 2].y);
1363                     rlVertex2f(points[i - 1].x, points[i - 1].y);
1364                 }
1365                 else
1366                 {
1367                     rlVertex2f(points[i].x, points[i].y);
1368                     rlVertex2f(points[i - 1].x, points[i - 1].y);
1369                     rlVertex2f(points[i - 2].x, points[i - 2].y);
1370                 }
1371             }
1372         rlEnd();
1373     }
1374 }
1375
1376 // Draw a regular polygon of n sides (Vector version)
1377 void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color)
1378 {
1379     if (sides < 3) sides = 3;
1380     float centralAngle = 0.0f;
1381
1382     rlCheckRenderBatchLimit(4*(360/sides));
1383
1384     rlPushMatrix();
1385         rlTranslatef(center.x, center.y, 0.0f);
1386         rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
1387
1388 #if defined(SUPPORT_QUADS_DRAW_MODE)
1389         rlSetTexture(texShapes.id);
1390
1391         rlBegin(RL_QUADS);
1392             for (int i = 0; i < sides; i++)
1393             {
1394                 rlColor4ub(color.r, color.g, color.b, color.a);
1395
1396                 rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
1397                 rlVertex2f(0, 0);
1398
1399                 rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1400                 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1401
1402                 rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
1403                 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1404
1405                 centralAngle += 360.0f/(float)sides;
1406                 rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
1407                 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1408             }
1409         rlEnd();
1410         rlSetTexture(0);
1411 #else
1412         rlBegin(RL_TRIANGLES);
1413             for (int i = 0; i < sides; i++)
1414             {
1415                 rlColor4ub(color.r, color.g, color.b, color.a);
1416
1417                 rlVertex2f(0, 0);
1418                 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1419
1420                 centralAngle += 360.0f/(float)sides;
1421                 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1422             }
1423         rlEnd();
1424 #endif
1425     rlPopMatrix();
1426 }
1427
1428 // Draw a polygon outline of n sides
1429 void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color)
1430 {
1431     if (sides < 3) sides = 3;
1432     float centralAngle = 0.0f;
1433
1434     rlCheckRenderBatchLimit(3*(360/sides));
1435
1436     rlPushMatrix();
1437         rlTranslatef(center.x, center.y, 0.0f);
1438         rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
1439
1440         rlBegin(RL_LINES);
1441             for (int i = 0; i < sides; i++)
1442             {
1443                 rlColor4ub(color.r, color.g, color.b, color.a);
1444
1445                 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1446                 centralAngle += 360.0f/(float)sides;
1447                 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1448             }
1449         rlEnd();
1450     rlPopMatrix();
1451 }
1452
1453 //----------------------------------------------------------------------------------
1454 // Module Functions Definition - Collision Detection functions
1455 //----------------------------------------------------------------------------------
1456
1457 // Check if point is inside rectangle
1458 bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
1459 {
1460     bool collision = false;
1461
1462     if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) && (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true;
1463
1464     return collision;
1465 }
1466
1467 // Check if point is inside circle
1468 bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius)
1469 {
1470     return CheckCollisionCircles(point, 0, center, radius);
1471 }
1472
1473 // Check if point is inside a triangle defined by three points (p1, p2, p3)
1474 bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3)
1475 {
1476     bool collision = false;
1477
1478     float alpha = ((p2.y - p3.y)*(point.x - p3.x) + (p3.x - p2.x)*(point.y - p3.y)) /
1479                   ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
1480
1481     float beta = ((p3.y - p1.y)*(point.x - p3.x) + (p1.x - p3.x)*(point.y - p3.y)) /
1482                  ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
1483
1484     float gamma = 1.0f - alpha - beta;
1485
1486     if ((alpha > 0) && (beta > 0) && (gamma > 0)) collision = true;
1487
1488     return collision;
1489 }
1490
1491 // Check collision between two rectangles
1492 bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2)
1493 {
1494     bool collision = false;
1495
1496     if ((rec1.x < (rec2.x + rec2.width) && (rec1.x + rec1.width) > rec2.x) &&
1497         (rec1.y < (rec2.y + rec2.height) && (rec1.y + rec1.height) > rec2.y)) collision = true;
1498
1499     return collision;
1500 }
1501
1502 // Check collision between two circles
1503 bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2)
1504 {
1505     bool collision = false;
1506
1507     float dx = center2.x - center1.x;      // X distance between centers
1508     float dy = center2.y - center1.y;      // Y distance between centers
1509
1510     float distance = sqrtf(dx*dx + dy*dy); // Distance between centers
1511
1512     if (distance <= (radius1 + radius2)) collision = true;
1513
1514     return collision;
1515 }
1516
1517 // Check collision between circle and rectangle
1518 // NOTE: Reviewed version to take into account corner limit case
1519 bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
1520 {
1521     int recCenterX = (int)(rec.x + rec.width/2.0f);
1522     int recCenterY = (int)(rec.y + rec.height/2.0f);
1523
1524     float dx = fabsf(center.x - (float)recCenterX);
1525     float dy = fabsf(center.y - (float)recCenterY);
1526
1527     if (dx > (rec.width/2.0f + radius)) { return false; }
1528     if (dy > (rec.height/2.0f + radius)) { return false; }
1529
1530     if (dx <= (rec.width/2.0f)) { return true; }
1531     if (dy <= (rec.height/2.0f)) { return true; }
1532
1533     float cornerDistanceSq = (dx - rec.width/2.0f)*(dx - rec.width/2.0f) +
1534                              (dy - rec.height/2.0f)*(dy - rec.height/2.0f);
1535
1536     return (cornerDistanceSq <= (radius*radius));
1537 }
1538
1539 // Check the collision between two lines defined by two points each, returns collision point by reference
1540 bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2, Vector2 *collisionPoint)
1541 {
1542     const float div = (endPos2.y - startPos2.y)*(endPos1.x - startPos1.x) - (endPos2.x - startPos2.x)*(endPos1.y - startPos1.y);
1543
1544     if (div == 0.0f) return false;      // WARNING: This check could not work due to float precision rounding issues...
1545
1546     const float xi = ((startPos2.x - endPos2.x)*(startPos1.x*endPos1.y - startPos1.y*endPos1.x) - (startPos1.x - endPos1.x)*(startPos2.x*endPos2.y - startPos2.y*endPos2.x))/div;
1547     const float yi = ((startPos2.y - endPos2.y)*(startPos1.x*endPos1.y - startPos1.y*endPos1.x) - (startPos1.y - endPos1.y)*(startPos2.x*endPos2.y - startPos2.y*endPos2.x))/div;
1548
1549     if (xi < fminf(startPos1.x, endPos1.x) || xi > fmaxf(startPos1.x, endPos1.x)) return false;
1550     if (xi < fminf(startPos2.x, endPos2.x) || xi > fmaxf(startPos2.x, endPos2.x)) return false;
1551     if (yi < fminf(startPos1.y, endPos1.y) || yi > fmaxf(startPos1.y, endPos1.y)) return false;
1552     if (yi < fminf(startPos2.y, endPos2.y) || yi > fmaxf(startPos2.y, endPos2.y)) return false;
1553
1554     if (collisionPoint != 0)
1555     {
1556         collisionPoint->x = xi;
1557         collisionPoint->y = yi;
1558     }
1559
1560     return true;
1561 }
1562
1563 // Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]
1564 bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshold)
1565 {
1566     bool collision = false;
1567     float dxc = point.x - p1.x;
1568     float dyc = point.y - p1.y;
1569     float dxl = p2.x - p1.x;
1570     float dyl = p2.y - p1.y;
1571     float cross = dxc*dyl - dyc*dxl;
1572
1573     if (fabsf(cross) < (threshold*fmaxf(fabsf(dxl), fabsf(dyl))))
1574     {
1575         if (fabsf(dxl) >= fabsf(dyl)) collision = (dxl > 0)? ((p1.x <= point.x) && (point.x <= p2.x)) : ((p2.x <= point.x) && (point.x <= p1.x));
1576         else collision = (dyl > 0)? ((p1.y <= point.y) && (point.y <= p2.y)) : ((p2.y <= point.y) && (point.y <= p1.y));
1577     }
1578         
1579     return collision;
1580 }
1581
1582 // Get collision rectangle for two rectangles collision
1583 Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
1584 {
1585     Rectangle rec = { 0, 0, 0, 0 };
1586
1587     if (CheckCollisionRecs(rec1, rec2))
1588     {
1589         float dxx = fabsf(rec1.x - rec2.x);
1590         float dyy = fabsf(rec1.y - rec2.y);
1591
1592         if (rec1.x <= rec2.x)
1593         {
1594             if (rec1.y <= rec2.y)
1595             {
1596                 rec.x = rec2.x;
1597                 rec.y = rec2.y;
1598                 rec.width = rec1.width - dxx;
1599                 rec.height = rec1.height - dyy;
1600             }
1601             else
1602             {
1603                 rec.x = rec2.x;
1604                 rec.y = rec1.y;
1605                 rec.width = rec1.width - dxx;
1606                 rec.height = rec2.height - dyy;
1607             }
1608         }
1609         else
1610         {
1611             if (rec1.y <= rec2.y)
1612             {
1613                 rec.x = rec1.x;
1614                 rec.y = rec2.y;
1615                 rec.width = rec2.width - dxx;
1616                 rec.height = rec1.height - dyy;
1617             }
1618             else
1619             {
1620                 rec.x = rec1.x;
1621                 rec.y = rec1.y;
1622                 rec.width = rec2.width - dxx;
1623                 rec.height = rec2.height - dyy;
1624             }
1625         }
1626
1627         if (rec1.width > rec2.width)
1628         {
1629             if (rec.width >= rec2.width) rec.width = rec2.width;
1630         }
1631         else
1632         {
1633             if (rec.width >= rec1.width) rec.width = rec1.width;
1634         }
1635
1636         if (rec1.height > rec2.height)
1637         {
1638             if (rec.height >= rec2.height) rec.height = rec2.height;
1639         }
1640         else
1641         {
1642            if (rec.height >= rec1.height) rec.height = rec1.height;
1643         }
1644     }
1645
1646     return rec;
1647 }
1648
1649 //----------------------------------------------------------------------------------
1650 // Module specific Functions Definition
1651 //----------------------------------------------------------------------------------
1652
1653 // Cubic easing in-out
1654 // NOTE: Required for DrawLineBezier()
1655 static float EaseCubicInOut(float t, float b, float c, float d)
1656 {
1657     if ((t /= 0.5f*d) < 1) return 0.5f*c*t*t*t + b;
1658
1659     t -= 2;
1660
1661     return 0.5f*c*(t*t*t + 2.0f) + b;
1662 }