minesweeper

A minewseeper implementation to play around with Hare and Raylib
git clone https://git.tronto.net/minesweeper
Download | Log | Files | Refs | README | LICENSE

rshapes.c (92430B)


      1 /**********************************************************************************************
      2 *
      3 *   rshapes - Basic functions to draw 2d shapes and check collisions
      4 *
      5 *   ADDITIONAL NOTES:
      6 *       Shapes can be draw using 3 types of primitives: LINES, TRIANGLES and QUADS.
      7 *       Some functions implement two drawing options: TRIANGLES and QUADS, by default TRIANGLES
      8 *       are used but QUADS implementation can be selected with SUPPORT_QUADS_DRAW_MODE define
      9 *
     10 *       Some functions define texture coordinates (rlTexCoord2f()) for the shapes and use a
     11 *       user-provided texture with SetShapesTexture(), the pourpouse of this implementation
     12 *       is allowing to reduce draw calls when combined with a texture-atlas.
     13 *
     14 *       By default, raylib sets the default texture and rectangle at InitWindow()[rcore] to one
     15 *       white character of default font [rtext], this way, raylib text and shapes can be draw with
     16 *       a single draw call and it also allows users to configure it the same way with their own fonts.
     17 *
     18 *   CONFIGURATION:
     19 *       #define SUPPORT_MODULE_RSHAPES
     20 *           rshapes module is included in the build
     21 *
     22 *       #define SUPPORT_QUADS_DRAW_MODE
     23 *           Use QUADS instead of TRIANGLES for drawing when possible. Lines-based shapes still use LINES
     24 *
     25 *
     26 *   LICENSE: zlib/libpng
     27 *
     28 *   Copyright (c) 2013-2024 Ramon Santamaria (@raysan5)
     29 *
     30 *   This software is provided "as-is", without any express or implied warranty. In no event
     31 *   will the authors be held liable for any damages arising from the use of this software.
     32 *
     33 *   Permission is granted to anyone to use this software for any purpose, including commercial
     34 *   applications, and to alter it and redistribute it freely, subject to the following restrictions:
     35 *
     36 *     1. The origin of this software must not be misrepresented; you must not claim that you
     37 *     wrote the original software. If you use this software in a product, an acknowledgment
     38 *     in the product documentation would be appreciated but is not required.
     39 *
     40 *     2. Altered source versions must be plainly marked as such, and must not be misrepresented
     41 *     as being the original software.
     42 *
     43 *     3. This notice may not be removed or altered from any source distribution.
     44 *
     45 **********************************************************************************************/
     46 
     47 #include "raylib.h"     // Declares module functions
     48 
     49 // Check if config flags have been externally provided on compilation line
     50 #if !defined(EXTERNAL_CONFIG_FLAGS)
     51     #include "config.h"         // Defines module configuration flags
     52 #endif
     53 
     54 #if defined(SUPPORT_MODULE_RSHAPES)
     55 
     56 #include "rlgl.h"       // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
     57 
     58 #include <math.h>       // Required for: sinf(), asinf(), cosf(), acosf(), sqrtf(), fabsf()
     59 #include <float.h>      // Required for: FLT_EPSILON
     60 #include <stdlib.h>     // Required for: RL_FREE
     61 
     62 //----------------------------------------------------------------------------------
     63 // Defines and Macros
     64 //----------------------------------------------------------------------------------
     65 // Error rate to calculate how many segments we need to draw a smooth circle,
     66 // taken from https://stackoverflow.com/a/2244088
     67 #ifndef SMOOTH_CIRCLE_ERROR_RATE
     68     #define SMOOTH_CIRCLE_ERROR_RATE    0.5f      // Circle error rate
     69 #endif
     70 #ifndef SPLINE_SEGMENT_DIVISIONS
     71     #define SPLINE_SEGMENT_DIVISIONS      24      // Spline segment divisions
     72 #endif
     73 
     74 //----------------------------------------------------------------------------------
     75 // Types and Structures Definition
     76 //----------------------------------------------------------------------------------
     77 // Not here...
     78 
     79 //----------------------------------------------------------------------------------
     80 // Global Variables Definition
     81 //----------------------------------------------------------------------------------
     82 static Texture2D texShapes = { 1, 1, 1, 1, 7 };                // Texture used on shapes drawing (white pixel loaded by rlgl)
     83 static Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f };    // Texture source rectangle used on shapes drawing
     84 
     85 //----------------------------------------------------------------------------------
     86 // Module specific Functions Declaration
     87 //----------------------------------------------------------------------------------
     88 static float EaseCubicInOut(float t, float b, float c, float d);    // Cubic easing
     89 
     90 //----------------------------------------------------------------------------------
     91 // Module Functions Definition
     92 //----------------------------------------------------------------------------------
     93 
     94 // Set texture and rectangle to be used on shapes drawing
     95 // NOTE: It can be useful when using basic shapes and one single font,
     96 // defining a font char white rectangle would allow drawing everything in a single draw call
     97 void SetShapesTexture(Texture2D texture, Rectangle source)
     98 {
     99     // Reset texture to default pixel if required
    100     // WARNING: Shapes texture should be probably better validated,
    101     // it can break the rendering of all shapes if misused
    102     if ((texture.id == 0) || (source.width == 0) || (source.height == 0))
    103     {
    104         texShapes = (Texture2D){ 1, 1, 1, 1, 7 };
    105         texShapesRec = (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f };
    106     }
    107     else
    108     {
    109         texShapes = texture;
    110         texShapesRec = source;
    111     }
    112 }
    113 
    114 // Get texture that is used for shapes drawing
    115 Texture2D GetShapesTexture(void)
    116 {
    117     return texShapes;
    118 }
    119 
    120 // Get texture source rectangle that is used for shapes drawing
    121 Rectangle GetShapesTextureRectangle(void)
    122 {
    123     return texShapesRec;
    124 }
    125 
    126 // Draw a pixel
    127 void DrawPixel(int posX, int posY, Color color)
    128 {
    129     DrawPixelV((Vector2){ (float)posX, (float)posY }, color);
    130 }
    131 
    132 // Draw a pixel (Vector version)
    133 void DrawPixelV(Vector2 position, Color color)
    134 {
    135 #if defined(SUPPORT_QUADS_DRAW_MODE)
    136     rlSetTexture(GetShapesTexture().id);
    137     Rectangle shapeRect = GetShapesTextureRectangle();
    138 
    139     rlBegin(RL_QUADS);
    140 
    141         rlNormal3f(0.0f, 0.0f, 1.0f);
    142         rlColor4ub(color.r, color.g, color.b, color.a);
    143 
    144         rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
    145         rlVertex2f(position.x, position.y);
    146 
    147         rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    148         rlVertex2f(position.x, position.y + 1);
    149 
    150         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    151         rlVertex2f(position.x + 1, position.y + 1);
    152 
    153         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
    154         rlVertex2f(position.x + 1, position.y);
    155 
    156     rlEnd();
    157 
    158     rlSetTexture(0);
    159 #else
    160     rlBegin(RL_TRIANGLES);
    161 
    162         rlColor4ub(color.r, color.g, color.b, color.a);
    163 
    164         rlVertex2f(position.x, position.y);
    165         rlVertex2f(position.x, position.y + 1);
    166         rlVertex2f(position.x + 1, position.y);
    167 
    168         rlVertex2f(position.x + 1, position.y);
    169         rlVertex2f(position.x, position.y + 1);
    170         rlVertex2f(position.x + 1, position.y + 1);
    171 
    172     rlEnd();
    173 #endif
    174 }
    175 
    176 // Draw a line (using gl lines)
    177 void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color)
    178 {
    179     rlBegin(RL_LINES);
    180         rlColor4ub(color.r, color.g, color.b, color.a);
    181         rlVertex2f((float)startPosX, (float)startPosY);
    182         rlVertex2f((float)endPosX, (float)endPosY);
    183     rlEnd();
    184 }
    185 
    186 // Draw a line (using gl lines)
    187 void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
    188 {
    189     rlBegin(RL_LINES);
    190         rlColor4ub(color.r, color.g, color.b, color.a);
    191         rlVertex2f(startPos.x, startPos.y);
    192         rlVertex2f(endPos.x, endPos.y);
    193     rlEnd();
    194 }
    195 
    196 // Draw lines sequuence (using gl lines)
    197 void DrawLineStrip(const Vector2 *points, int pointCount, Color color)
    198 {
    199     if (pointCount < 2) return; // Security check
    200 
    201     rlBegin(RL_LINES);
    202         rlColor4ub(color.r, color.g, color.b, color.a);
    203 
    204         for (int i = 0; i < pointCount - 1; i++)
    205         {
    206             rlVertex2f(points[i].x, points[i].y);
    207             rlVertex2f(points[i + 1].x, points[i + 1].y);
    208         }
    209     rlEnd();
    210 }
    211 
    212 // Draw line using cubic-bezier spline, in-out interpolation, no control points
    213 void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color)
    214 {
    215     Vector2 previous = startPos;
    216     Vector2 current = { 0 };
    217 
    218     Vector2 points[2*SPLINE_SEGMENT_DIVISIONS + 2] = { 0 };
    219 
    220     for (int i = 1; i <= SPLINE_SEGMENT_DIVISIONS; i++)
    221     {
    222         // Cubic easing in-out
    223         // NOTE: Easing is calculated only for y position value
    224         current.y = EaseCubicInOut((float)i, startPos.y, endPos.y - startPos.y, (float)SPLINE_SEGMENT_DIVISIONS);
    225         current.x = previous.x + (endPos.x - startPos.x)/(float)SPLINE_SEGMENT_DIVISIONS;
    226 
    227         float dy = current.y - previous.y;
    228         float dx = current.x - previous.x;
    229         float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
    230 
    231         if (i == 1)
    232         {
    233             points[0].x = previous.x + dy*size;
    234             points[0].y = previous.y - dx*size;
    235             points[1].x = previous.x - dy*size;
    236             points[1].y = previous.y + dx*size;
    237         }
    238 
    239         points[2*i + 1].x = current.x - dy*size;
    240         points[2*i + 1].y = current.y + dx*size;
    241         points[2*i].x = current.x + dy*size;
    242         points[2*i].y = current.y - dx*size;
    243 
    244         previous = current;
    245     }
    246 
    247     DrawTriangleStrip(points, 2*SPLINE_SEGMENT_DIVISIONS + 2, color);
    248 }
    249 
    250 // Draw a line defining thickness
    251 void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color)
    252 {
    253     Vector2 delta = { endPos.x - startPos.x, endPos.y - startPos.y };
    254     float length = sqrtf(delta.x*delta.x + delta.y*delta.y);
    255 
    256     if ((length > 0) && (thick > 0))
    257     {
    258         float scale = thick/(2*length);
    259 
    260         Vector2 radius = { -scale*delta.y, scale*delta.x };
    261         Vector2 strip[4] = {
    262             { startPos.x - radius.x, startPos.y - radius.y },
    263             { startPos.x + radius.x, startPos.y + radius.y },
    264             { endPos.x - radius.x, endPos.y - radius.y },
    265             { endPos.x + radius.x, endPos.y + radius.y }
    266         };
    267 
    268         DrawTriangleStrip(strip, 4, color);
    269     }
    270 }
    271 
    272 // Draw a color-filled circle
    273 void DrawCircle(int centerX, int centerY, float radius, Color color)
    274 {
    275     DrawCircleV((Vector2){ (float)centerX, (float)centerY }, radius, color);
    276 }
    277 
    278 // Draw a color-filled circle (Vector version)
    279 // NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
    280 void DrawCircleV(Vector2 center, float radius, Color color)
    281 {
    282     DrawCircleSector(center, radius, 0, 360, 36, color);
    283 }
    284 
    285 // Draw a piece of a circle
    286 void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
    287 {
    288     if (radius <= 0.0f) radius = 0.1f;  // Avoid div by zero
    289 
    290     // Function expects (endAngle > startAngle)
    291     if (endAngle < startAngle)
    292     {
    293         // Swap values
    294         float tmp = startAngle;
    295         startAngle = endAngle;
    296         endAngle = tmp;
    297     }
    298 
    299     int minSegments = (int)ceilf((endAngle - startAngle)/90);
    300 
    301     if (segments < minSegments)
    302     {
    303         // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
    304         float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
    305         segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
    306 
    307         if (segments <= 0) segments = minSegments;
    308     }
    309 
    310     float stepLength = (endAngle - startAngle)/(float)segments;
    311     float angle = startAngle;
    312 
    313 #if defined(SUPPORT_QUADS_DRAW_MODE)
    314     rlSetTexture(GetShapesTexture().id);
    315     Rectangle shapeRect = GetShapesTextureRectangle();
    316 
    317     rlBegin(RL_QUADS);
    318 
    319         // NOTE: Every QUAD actually represents two segments
    320         for (int i = 0; i < segments/2; i++)
    321         {
    322             rlColor4ub(color.r, color.g, color.b, color.a);
    323 
    324             rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
    325             rlVertex2f(center.x, center.y);
    326 
    327             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
    328             rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength*2.0f))*radius, center.y + sinf(DEG2RAD*(angle + stepLength*2.0f))*radius);
    329 
    330             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    331             rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
    332 
    333             rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    334             rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
    335 
    336             angle += (stepLength*2.0f);
    337         }
    338 
    339         // NOTE: In case number of segments is odd, we add one last piece to the cake
    340         if ((((unsigned int)segments)%2) == 1)
    341         {
    342             rlColor4ub(color.r, color.g, color.b, color.a);
    343 
    344             rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
    345             rlVertex2f(center.x, center.y);
    346 
    347             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    348             rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
    349 
    350             rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    351             rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
    352 
    353             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
    354             rlVertex2f(center.x, center.y);
    355         }
    356 
    357     rlEnd();
    358 
    359     rlSetTexture(0);
    360 #else
    361     rlBegin(RL_TRIANGLES);
    362         for (int i = 0; i < segments; i++)
    363         {
    364             rlColor4ub(color.r, color.g, color.b, color.a);
    365 
    366             rlVertex2f(center.x, center.y);
    367             rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
    368             rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
    369 
    370             angle += stepLength;
    371         }
    372     rlEnd();
    373 #endif
    374 }
    375 
    376 // Draw a piece of a circle outlines
    377 void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
    378 {
    379     if (radius <= 0.0f) radius = 0.1f;  // Avoid div by zero issue
    380 
    381     // Function expects (endAngle > startAngle)
    382     if (endAngle < startAngle)
    383     {
    384         // Swap values
    385         float tmp = startAngle;
    386         startAngle = endAngle;
    387         endAngle = tmp;
    388     }
    389 
    390     int minSegments = (int)ceilf((endAngle - startAngle)/90);
    391 
    392     if (segments < minSegments)
    393     {
    394         // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
    395         float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
    396         segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
    397 
    398         if (segments <= 0) segments = minSegments;
    399     }
    400 
    401     float stepLength = (endAngle - startAngle)/(float)segments;
    402     float angle = startAngle;
    403     bool showCapLines = true;
    404 
    405     rlBegin(RL_LINES);
    406         if (showCapLines)
    407         {
    408             rlColor4ub(color.r, color.g, color.b, color.a);
    409             rlVertex2f(center.x, center.y);
    410             rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
    411         }
    412 
    413         for (int i = 0; i < segments; i++)
    414         {
    415             rlColor4ub(color.r, color.g, color.b, color.a);
    416 
    417             rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
    418             rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
    419 
    420             angle += stepLength;
    421         }
    422 
    423         if (showCapLines)
    424         {
    425             rlColor4ub(color.r, color.g, color.b, color.a);
    426             rlVertex2f(center.x, center.y);
    427             rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
    428         }
    429     rlEnd();
    430 }
    431 
    432 // Draw a gradient-filled circle
    433 void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer)
    434 {
    435     rlBegin(RL_TRIANGLES);
    436         for (int i = 0; i < 360; i += 10)
    437         {
    438             rlColor4ub(inner.r, inner.g, inner.b, inner.a);
    439             rlVertex2f((float)centerX, (float)centerY);
    440             rlColor4ub(outer.r, outer.g, outer.b, outer.a);
    441             rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radius, (float)centerY + sinf(DEG2RAD*(i + 10))*radius);
    442             rlColor4ub(outer.r, outer.g, outer.b, outer.a);
    443             rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radius, (float)centerY + sinf(DEG2RAD*i)*radius);
    444         }
    445     rlEnd();
    446 }
    447 
    448 // Draw circle outline
    449 void DrawCircleLines(int centerX, int centerY, float radius, Color color)
    450 {
    451     DrawCircleLinesV((Vector2){ (float)centerX, (float)centerY }, radius, color);
    452 }
    453 
    454 // Draw circle outline (Vector version)
    455 void DrawCircleLinesV(Vector2 center, float radius, Color color)
    456 {
    457     rlBegin(RL_LINES);
    458         rlColor4ub(color.r, color.g, color.b, color.a);
    459 
    460         // NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
    461         for (int i = 0; i < 360; i += 10)
    462         {
    463             rlVertex2f(center.x + cosf(DEG2RAD*i)*radius, center.y + sinf(DEG2RAD*i)*radius);
    464             rlVertex2f(center.x + cosf(DEG2RAD*(i + 10))*radius, center.y + sinf(DEG2RAD*(i + 10))*radius);
    465         }
    466     rlEnd();
    467 }
    468 
    469 // Draw ellipse
    470 void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color)
    471 {
    472     rlBegin(RL_TRIANGLES);
    473         for (int i = 0; i < 360; i += 10)
    474         {
    475             rlColor4ub(color.r, color.g, color.b, color.a);
    476             rlVertex2f((float)centerX, (float)centerY);
    477             rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radiusH, (float)centerY + sinf(DEG2RAD*(i + 10))*radiusV);
    478             rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radiusH, (float)centerY + sinf(DEG2RAD*i)*radiusV);
    479         }
    480     rlEnd();
    481 }
    482 
    483 // Draw ellipse outline
    484 void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color)
    485 {
    486     rlBegin(RL_LINES);
    487         for (int i = 0; i < 360; i += 10)
    488         {
    489             rlColor4ub(color.r, color.g, color.b, color.a);
    490             rlVertex2f(centerX + cosf(DEG2RAD*(i + 10))*radiusH, centerY + sinf(DEG2RAD*(i + 10))*radiusV);
    491             rlVertex2f(centerX + cosf(DEG2RAD*i)*radiusH, centerY + sinf(DEG2RAD*i)*radiusV);
    492         }
    493     rlEnd();
    494 }
    495 
    496 // Draw ring
    497 void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color)
    498 {
    499     if (startAngle == endAngle) return;
    500 
    501     // Function expects (outerRadius > innerRadius)
    502     if (outerRadius < innerRadius)
    503     {
    504         float tmp = outerRadius;
    505         outerRadius = innerRadius;
    506         innerRadius = tmp;
    507 
    508         if (outerRadius <= 0.0f) outerRadius = 0.1f;
    509     }
    510 
    511     // Function expects (endAngle > startAngle)
    512     if (endAngle < startAngle)
    513     {
    514         // Swap values
    515         float tmp = startAngle;
    516         startAngle = endAngle;
    517         endAngle = tmp;
    518     }
    519 
    520     int minSegments = (int)ceilf((endAngle - startAngle)/90);
    521 
    522     if (segments < minSegments)
    523     {
    524         // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
    525         float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/outerRadius, 2) - 1);
    526         segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
    527 
    528         if (segments <= 0) segments = minSegments;
    529     }
    530 
    531     // Not a ring
    532     if (innerRadius <= 0.0f)
    533     {
    534         DrawCircleSector(center, outerRadius, startAngle, endAngle, segments, color);
    535         return;
    536     }
    537 
    538     float stepLength = (endAngle - startAngle)/(float)segments;
    539     float angle = startAngle;
    540 
    541 #if defined(SUPPORT_QUADS_DRAW_MODE)
    542     rlSetTexture(GetShapesTexture().id);
    543     Rectangle shapeRect = GetShapesTextureRectangle();
    544 
    545     rlBegin(RL_QUADS);
    546         for (int i = 0; i < segments; i++)
    547         {
    548             rlColor4ub(color.r, color.g, color.b, color.a);
    549 
    550             rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    551             rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
    552 
    553             rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
    554             rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
    555 
    556             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
    557             rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
    558 
    559             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    560             rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
    561 
    562             angle += stepLength;
    563         }
    564     rlEnd();
    565 
    566     rlSetTexture(0);
    567 #else
    568     rlBegin(RL_TRIANGLES);
    569         for (int i = 0; i < segments; i++)
    570         {
    571             rlColor4ub(color.r, color.g, color.b, color.a);
    572 
    573             rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
    574             rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
    575             rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
    576 
    577             rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
    578             rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
    579             rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
    580 
    581             angle += stepLength;
    582         }
    583     rlEnd();
    584 #endif
    585 }
    586 
    587 // Draw ring outline
    588 void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color)
    589 {
    590     if (startAngle == endAngle) return;
    591 
    592     // Function expects (outerRadius > innerRadius)
    593     if (outerRadius < innerRadius)
    594     {
    595         float tmp = outerRadius;
    596         outerRadius = innerRadius;
    597         innerRadius = tmp;
    598 
    599         if (outerRadius <= 0.0f) outerRadius = 0.1f;
    600     }
    601 
    602     // Function expects (endAngle > startAngle)
    603     if (endAngle < startAngle)
    604     {
    605         // Swap values
    606         float tmp = startAngle;
    607         startAngle = endAngle;
    608         endAngle = tmp;
    609     }
    610 
    611     int minSegments = (int)ceilf((endAngle - startAngle)/90);
    612 
    613     if (segments < minSegments)
    614     {
    615         // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
    616         float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/outerRadius, 2) - 1);
    617         segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
    618 
    619         if (segments <= 0) segments = minSegments;
    620     }
    621 
    622     if (innerRadius <= 0.0f)
    623     {
    624         DrawCircleSectorLines(center, outerRadius, startAngle, endAngle, segments, color);
    625         return;
    626     }
    627 
    628     float stepLength = (endAngle - startAngle)/(float)segments;
    629     float angle = startAngle;
    630     bool showCapLines = true;
    631 
    632     rlBegin(RL_LINES);
    633         if (showCapLines)
    634         {
    635             rlColor4ub(color.r, color.g, color.b, color.a);
    636             rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
    637             rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
    638         }
    639 
    640         for (int i = 0; i < segments; i++)
    641         {
    642             rlColor4ub(color.r, color.g, color.b, color.a);
    643 
    644             rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
    645             rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
    646 
    647             rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
    648             rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
    649 
    650             angle += stepLength;
    651         }
    652 
    653         if (showCapLines)
    654         {
    655             rlColor4ub(color.r, color.g, color.b, color.a);
    656             rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
    657             rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
    658         }
    659     rlEnd();
    660 }
    661 
    662 // Draw a color-filled rectangle
    663 void DrawRectangle(int posX, int posY, int width, int height, Color color)
    664 {
    665     DrawRectangleV((Vector2){ (float)posX, (float)posY }, (Vector2){ (float)width, (float)height }, color);
    666 }
    667 
    668 // Draw a color-filled rectangle (Vector version)
    669 // NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
    670 void DrawRectangleV(Vector2 position, Vector2 size, Color color)
    671 {
    672     DrawRectanglePro((Rectangle){ position.x, position.y, size.x, size.y }, (Vector2){ 0.0f, 0.0f }, 0.0f, color);
    673 }
    674 
    675 // Draw a color-filled rectangle
    676 void DrawRectangleRec(Rectangle rec, Color color)
    677 {
    678     DrawRectanglePro(rec, (Vector2){ 0.0f, 0.0f }, 0.0f, color);
    679 }
    680 
    681 // Draw a color-filled rectangle with pro parameters
    682 void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color)
    683 {
    684     Vector2 topLeft = { 0 };
    685     Vector2 topRight = { 0 };
    686     Vector2 bottomLeft = { 0 };
    687     Vector2 bottomRight = { 0 };
    688 
    689     // Only calculate rotation if needed
    690     if (rotation == 0.0f)
    691     {
    692         float x = rec.x - origin.x;
    693         float y = rec.y - origin.y;
    694         topLeft = (Vector2){ x, y };
    695         topRight = (Vector2){ x + rec.width, y };
    696         bottomLeft = (Vector2){ x, y + rec.height };
    697         bottomRight = (Vector2){ x + rec.width, y + rec.height };
    698     }
    699     else
    700     {
    701         float sinRotation = sinf(rotation*DEG2RAD);
    702         float cosRotation = cosf(rotation*DEG2RAD);
    703         float x = rec.x;
    704         float y = rec.y;
    705         float dx = -origin.x;
    706         float dy = -origin.y;
    707 
    708         topLeft.x = x + dx*cosRotation - dy*sinRotation;
    709         topLeft.y = y + dx*sinRotation + dy*cosRotation;
    710 
    711         topRight.x = x + (dx + rec.width)*cosRotation - dy*sinRotation;
    712         topRight.y = y + (dx + rec.width)*sinRotation + dy*cosRotation;
    713 
    714         bottomLeft.x = x + dx*cosRotation - (dy + rec.height)*sinRotation;
    715         bottomLeft.y = y + dx*sinRotation + (dy + rec.height)*cosRotation;
    716 
    717         bottomRight.x = x + (dx + rec.width)*cosRotation - (dy + rec.height)*sinRotation;
    718         bottomRight.y = y + (dx + rec.width)*sinRotation + (dy + rec.height)*cosRotation;
    719     }
    720 
    721 #if defined(SUPPORT_QUADS_DRAW_MODE)
    722     rlSetTexture(GetShapesTexture().id);
    723     Rectangle shapeRect = GetShapesTextureRectangle();
    724 
    725     rlBegin(RL_QUADS);
    726 
    727         rlNormal3f(0.0f, 0.0f, 1.0f);
    728         rlColor4ub(color.r, color.g, color.b, color.a);
    729 
    730         rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
    731         rlVertex2f(topLeft.x, topLeft.y);
    732 
    733         rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    734         rlVertex2f(bottomLeft.x, bottomLeft.y);
    735 
    736         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    737         rlVertex2f(bottomRight.x, bottomRight.y);
    738 
    739         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
    740         rlVertex2f(topRight.x, topRight.y);
    741 
    742     rlEnd();
    743 
    744     rlSetTexture(0);
    745 #else
    746     rlBegin(RL_TRIANGLES);
    747 
    748         rlColor4ub(color.r, color.g, color.b, color.a);
    749 
    750         rlVertex2f(topLeft.x, topLeft.y);
    751         rlVertex2f(bottomLeft.x, bottomLeft.y);
    752         rlVertex2f(topRight.x, topRight.y);
    753 
    754         rlVertex2f(topRight.x, topRight.y);
    755         rlVertex2f(bottomLeft.x, bottomLeft.y);
    756         rlVertex2f(bottomRight.x, bottomRight.y);
    757 
    758     rlEnd();
    759 #endif
    760 }
    761 
    762 // Draw a vertical-gradient-filled rectangle
    763 void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom)
    764 {
    765     DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, top, bottom, bottom, top);
    766 }
    767 
    768 // Draw a horizontal-gradient-filled rectangle
    769 void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right)
    770 {
    771     DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, left, left, right, right);
    772 }
    773 
    774 // Draw a gradient-filled rectangle
    775 void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight)
    776 {
    777     rlSetTexture(GetShapesTexture().id);
    778     Rectangle shapeRect = GetShapesTextureRectangle();
    779 
    780     rlBegin(RL_QUADS);
    781         rlNormal3f(0.0f, 0.0f, 1.0f);
    782 
    783         // NOTE: Default raylib font character 95 is a white square
    784         rlColor4ub(topLeft.r, topLeft.g, topLeft.b, topLeft.a);
    785         rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
    786         rlVertex2f(rec.x, rec.y);
    787 
    788         rlColor4ub(bottomLeft.r, bottomLeft.g, bottomLeft.b, bottomLeft.a);
    789         rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    790         rlVertex2f(rec.x, rec.y + rec.height);
    791 
    792         rlColor4ub(topRight.r, topRight.g, topRight.b, topRight.a);
    793         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    794         rlVertex2f(rec.x + rec.width, rec.y + rec.height);
    795 
    796         rlColor4ub(bottomRight.r, bottomRight.g, bottomRight.b, bottomRight.a);
    797         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
    798         rlVertex2f(rec.x + rec.width, rec.y);
    799     rlEnd();
    800 
    801     rlSetTexture(0);
    802 }
    803 
    804 // Draw rectangle outline
    805 // WARNING: All Draw*Lines() functions use RL_LINES for drawing,
    806 // it implies flushing the current batch and changing draw mode to RL_LINES
    807 // but it solves another issue: https://github.com/raysan5/raylib/issues/3884
    808 void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
    809 {
    810     Matrix mat = rlGetMatrixModelview();
    811     float zoomFactor = 0.5f/mat.m0;
    812     rlBegin(RL_LINES);
    813         rlColor4ub(color.r, color.g, color.b, color.a);
    814         rlVertex2f((float)posX - zoomFactor, (float)posY);
    815         rlVertex2f((float)posX + (float)width + zoomFactor, (float)posY);
    816 
    817         rlVertex2f((float)posX + (float)width, (float)posY - zoomFactor);
    818         rlVertex2f((float)posX + (float)width, (float)posY + (float)height + zoomFactor);
    819 
    820         rlVertex2f((float)posX + (float)width + zoomFactor, (float)posY + (float)height);
    821         rlVertex2f((float)posX - zoomFactor, (float)posY + (float)height);
    822 
    823         rlVertex2f((float)posX, (float)posY + (float)height + zoomFactor);
    824         rlVertex2f((float)posX, (float)posY - zoomFactor);
    825     rlEnd();
    826 /*
    827 // Previous implementation, it has issues... but it does not require view matrix...
    828 #if defined(SUPPORT_QUADS_DRAW_MODE)
    829     DrawRectangle(posX, posY, width, 1, color);
    830     DrawRectangle(posX + width - 1, posY + 1, 1, height - 2, color);
    831     DrawRectangle(posX, posY + height - 1, width, 1, color);
    832     DrawRectangle(posX, posY + 1, 1, height - 2, color);
    833 #else
    834     rlBegin(RL_LINES);
    835         rlColor4ub(color.r, color.g, color.b, color.a);
    836         rlVertex2f((float)posX, (float)posY);
    837         rlVertex2f((float)posX + (float)width, (float)posY + 1);
    838 
    839         rlVertex2f((float)posX + (float)width, (float)posY + 1);
    840         rlVertex2f((float)posX + (float)width, (float)posY + (float)height);
    841 
    842         rlVertex2f((float)posX + (float)width, (float)posY + (float)height);
    843         rlVertex2f((float)posX + 1, (float)posY + (float)height);
    844 
    845         rlVertex2f((float)posX + 1, (float)posY + (float)height);
    846         rlVertex2f((float)posX + 1, (float)posY + 1);
    847     rlEnd();
    848 //#endif
    849 */
    850 }
    851 
    852 // Draw rectangle outline with extended parameters
    853 void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color)
    854 {
    855     if ((lineThick > rec.width) || (lineThick > rec.height))
    856     {
    857         if (rec.width >= rec.height) lineThick = rec.height/2;
    858         else if (rec.width <= rec.height) lineThick = rec.width/2;
    859     }
    860 
    861     // When rec = { x, y, 8.0f, 6.0f } and lineThick = 2, the following
    862     // four rectangles are drawn ([T]op, [B]ottom, [L]eft, [R]ight):
    863     //
    864     //   TTTTTTTT
    865     //   TTTTTTTT
    866     //   LL    RR
    867     //   LL    RR
    868     //   BBBBBBBB
    869     //   BBBBBBBB
    870     //
    871 
    872     Rectangle top = { rec.x, rec.y, rec.width, lineThick };
    873     Rectangle bottom = { rec.x, rec.y - lineThick + rec.height, rec.width, lineThick };
    874     Rectangle left = { rec.x, rec.y + lineThick, lineThick, rec.height - lineThick*2.0f };
    875     Rectangle right = { rec.x - lineThick + rec.width, rec.y + lineThick, lineThick, rec.height - lineThick*2.0f };
    876 
    877     DrawRectangleRec(top, color);
    878     DrawRectangleRec(bottom, color);
    879     DrawRectangleRec(left, color);
    880     DrawRectangleRec(right, color);
    881 }
    882 
    883 // Draw rectangle with rounded edges
    884 void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color)
    885 {
    886     // Not a rounded rectangle
    887     if ((roundness <= 0.0f) || (rec.width < 1) || (rec.height < 1 ))
    888     {
    889         DrawRectangleRec(rec, color);
    890         return;
    891     }
    892 
    893     if (roundness >= 1.0f) roundness = 1.0f;
    894 
    895     // Calculate corner radius
    896     float radius = (rec.width > rec.height)? (rec.height*roundness)/2 : (rec.width*roundness)/2;
    897     if (radius <= 0.0f) return;
    898 
    899     // Calculate number of segments to use for the corners
    900     if (segments < 4)
    901     {
    902         // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
    903         float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
    904         segments = (int)(ceilf(2*PI/th)/4.0f);
    905         if (segments <= 0) segments = 4;
    906     }
    907 
    908     float stepLength = 90.0f/(float)segments;
    909 
    910     /*
    911     Quick sketch to make sense of all of this,
    912     there are 9 parts to draw, also mark the 12 points we'll use
    913 
    914           P0____________________P1
    915           /|                    |\
    916          /1|          2         |3\
    917      P7 /__|____________________|__\ P2
    918        |   |P8                P9|   |
    919        | 8 |          9         | 4 |
    920        | __|____________________|__ |
    921      P6 \  |P11              P10|  / P3
    922          \7|          6         |5/
    923           \|____________________|/
    924           P5                    P4
    925     */
    926     // Coordinates of the 12 points that define the rounded rect
    927     const Vector2 point[12] = {
    928         {(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
    929         {rec.x + rec.width, (float)(rec.y + rec.height) - radius}, {(float)(rec.x + rec.width) - radius, rec.y + rec.height},           // P3, P4
    930         {(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
    931         {(float)rec.x + radius, (float)rec.y + radius}, {(float)(rec.x + rec.width) - radius, (float)rec.y + radius},                   // P8, P9
    932         {(float)(rec.x + rec.width) - radius, (float)(rec.y + rec.height) - radius}, {(float)rec.x + radius, (float)(rec.y + rec.height) - radius} // P10, P11
    933     };
    934 
    935     const Vector2 centers[4] = { point[8], point[9], point[10], point[11] };
    936     const float angles[4] = { 180.0f, 270.0f, 0.0f, 90.0f };
    937 
    938 #if defined(SUPPORT_QUADS_DRAW_MODE)
    939     rlSetTexture(GetShapesTexture().id);
    940     Rectangle shapeRect = GetShapesTextureRectangle();
    941 
    942     rlBegin(RL_QUADS);
    943         // Draw all the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner
    944         for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
    945         {
    946             float angle = angles[k];
    947             const Vector2 center = centers[k];
    948 
    949             // NOTE: Every QUAD actually represents two segments
    950             for (int i = 0; i < segments/2; i++)
    951             {
    952                 rlColor4ub(color.r, color.g, color.b, color.a);
    953                 rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
    954                 rlVertex2f(center.x, center.y);
    955 
    956                 rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
    957                 rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength*2))*radius, center.y + sinf(DEG2RAD*(angle + stepLength*2))*radius);
    958 
    959                 rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    960                 rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
    961 
    962                 rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    963                 rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
    964 
    965                 angle += (stepLength*2);
    966             }
    967 
    968             // NOTE: In case number of segments is odd, we add one last piece to the cake
    969             if (segments%2)
    970             {
    971                 rlColor4ub(color.r, color.g, color.b, color.a);
    972                 rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
    973                 rlVertex2f(center.x, center.y);
    974 
    975                 rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    976                 rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
    977 
    978                 rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    979                 rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
    980 
    981                 rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
    982                 rlVertex2f(center.x, center.y);
    983             }
    984         }
    985 
    986         // [2] Upper Rectangle
    987         rlColor4ub(color.r, color.g, color.b, color.a);
    988         rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
    989         rlVertex2f(point[0].x, point[0].y);
    990         rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    991         rlVertex2f(point[8].x, point[8].y);
    992         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
    993         rlVertex2f(point[9].x, point[9].y);
    994         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
    995         rlVertex2f(point[1].x, point[1].y);
    996 
    997         // [4] Right Rectangle
    998         rlColor4ub(color.r, color.g, color.b, color.a);
    999         rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
   1000         rlVertex2f(point[2].x, point[2].y);
   1001         rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1002         rlVertex2f(point[9].x, point[9].y);
   1003         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1004         rlVertex2f(point[10].x, point[10].y);
   1005         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
   1006         rlVertex2f(point[3].x, point[3].y);
   1007 
   1008         // [6] Bottom Rectangle
   1009         rlColor4ub(color.r, color.g, color.b, color.a);
   1010         rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
   1011         rlVertex2f(point[11].x, point[11].y);
   1012         rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1013         rlVertex2f(point[5].x, point[5].y);
   1014         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1015         rlVertex2f(point[4].x, point[4].y);
   1016         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
   1017         rlVertex2f(point[10].x, point[10].y);
   1018 
   1019         // [8] Left Rectangle
   1020         rlColor4ub(color.r, color.g, color.b, color.a);
   1021         rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
   1022         rlVertex2f(point[7].x, point[7].y);
   1023         rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1024         rlVertex2f(point[6].x, point[6].y);
   1025         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1026         rlVertex2f(point[11].x, point[11].y);
   1027         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
   1028         rlVertex2f(point[8].x, point[8].y);
   1029 
   1030         // [9] Middle Rectangle
   1031         rlColor4ub(color.r, color.g, color.b, color.a);
   1032         rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
   1033         rlVertex2f(point[8].x, point[8].y);
   1034         rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1035         rlVertex2f(point[11].x, point[11].y);
   1036         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1037         rlVertex2f(point[10].x, point[10].y);
   1038         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
   1039         rlVertex2f(point[9].x, point[9].y);
   1040 
   1041     rlEnd();
   1042     rlSetTexture(0);
   1043 #else
   1044     rlBegin(RL_TRIANGLES);
   1045 
   1046         // Draw all of the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner
   1047         for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
   1048         {
   1049             float angle = angles[k];
   1050             const Vector2 center = centers[k];
   1051             for (int i = 0; i < segments; i++)
   1052             {
   1053                 rlColor4ub(color.r, color.g, color.b, color.a);
   1054                 rlVertex2f(center.x, center.y);
   1055                 rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
   1056                 rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
   1057                 angle += stepLength;
   1058             }
   1059         }
   1060 
   1061         // [2] Upper Rectangle
   1062         rlColor4ub(color.r, color.g, color.b, color.a);
   1063         rlVertex2f(point[0].x, point[0].y);
   1064         rlVertex2f(point[8].x, point[8].y);
   1065         rlVertex2f(point[9].x, point[9].y);
   1066         rlVertex2f(point[1].x, point[1].y);
   1067         rlVertex2f(point[0].x, point[0].y);
   1068         rlVertex2f(point[9].x, point[9].y);
   1069 
   1070         // [4] Right Rectangle
   1071         rlColor4ub(color.r, color.g, color.b, color.a);
   1072         rlVertex2f(point[9].x, point[9].y);
   1073         rlVertex2f(point[10].x, point[10].y);
   1074         rlVertex2f(point[3].x, point[3].y);
   1075         rlVertex2f(point[2].x, point[2].y);
   1076         rlVertex2f(point[9].x, point[9].y);
   1077         rlVertex2f(point[3].x, point[3].y);
   1078 
   1079         // [6] Bottom Rectangle
   1080         rlColor4ub(color.r, color.g, color.b, color.a);
   1081         rlVertex2f(point[11].x, point[11].y);
   1082         rlVertex2f(point[5].x, point[5].y);
   1083         rlVertex2f(point[4].x, point[4].y);
   1084         rlVertex2f(point[10].x, point[10].y);
   1085         rlVertex2f(point[11].x, point[11].y);
   1086         rlVertex2f(point[4].x, point[4].y);
   1087 
   1088         // [8] Left Rectangle
   1089         rlColor4ub(color.r, color.g, color.b, color.a);
   1090         rlVertex2f(point[7].x, point[7].y);
   1091         rlVertex2f(point[6].x, point[6].y);
   1092         rlVertex2f(point[11].x, point[11].y);
   1093         rlVertex2f(point[8].x, point[8].y);
   1094         rlVertex2f(point[7].x, point[7].y);
   1095         rlVertex2f(point[11].x, point[11].y);
   1096 
   1097         // [9] Middle Rectangle
   1098         rlColor4ub(color.r, color.g, color.b, color.a);
   1099         rlVertex2f(point[8].x, point[8].y);
   1100         rlVertex2f(point[11].x, point[11].y);
   1101         rlVertex2f(point[10].x, point[10].y);
   1102         rlVertex2f(point[9].x, point[9].y);
   1103         rlVertex2f(point[8].x, point[8].y);
   1104         rlVertex2f(point[10].x, point[10].y);
   1105     rlEnd();
   1106 #endif
   1107 }
   1108 
   1109 // Draw rectangle with rounded edges
   1110 // TODO: This function should be refactored to use RL_LINES, for consistency with other Draw*Lines()
   1111 void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color)
   1112 {
   1113     DrawRectangleRoundedLinesEx(rec, roundness, segments, 1.0f, color);
   1114 }
   1115 
   1116 // Draw rectangle with rounded edges outline
   1117 void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float lineThick, Color color)
   1118 {
   1119     if (lineThick < 0) lineThick = 0;
   1120 
   1121     // Not a rounded rectangle
   1122     if (roundness <= 0.0f)
   1123     {
   1124         DrawRectangleLinesEx((Rectangle){rec.x-lineThick, rec.y-lineThick, rec.width+2*lineThick, rec.height+2*lineThick}, lineThick, color);
   1125         return;
   1126     }
   1127 
   1128     if (roundness >= 1.0f) roundness = 1.0f;
   1129 
   1130     // Calculate corner radius
   1131     float radius = (rec.width > rec.height)? (rec.height*roundness)/2 : (rec.width*roundness)/2;
   1132     if (radius <= 0.0f) return;
   1133 
   1134     // Calculate number of segments to use for the corners
   1135     if (segments < 4)
   1136     {
   1137         // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
   1138         float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
   1139         segments = (int)(ceilf(2*PI/th)/2.0f);
   1140         if (segments <= 0) segments = 4;
   1141     }
   1142 
   1143     float stepLength = 90.0f/(float)segments;
   1144     const float outerRadius = radius + lineThick, innerRadius = radius;
   1145 
   1146     /*
   1147     Quick sketch to make sense of all of this,
   1148     marks the 16 + 4(corner centers P16-19) points we'll use
   1149 
   1150            P0 ================== P1
   1151           // P8                P9 \\
   1152          //                        \\
   1153      P7 // P15                  P10 \\ P2
   1154        ||   *P16             P17*    ||
   1155        ||                            ||
   1156        || P14                   P11  ||
   1157      P6 \\  *P19             P18*   // P3
   1158          \\                        //
   1159           \\ P13              P12 //
   1160            P5 ================== P4
   1161     */
   1162     const Vector2 point[16] = {
   1163         {(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
   1164         {rec.x + rec.width + lineThick, (float)(rec.y + rec.height) - innerRadius}, {(float)(rec.x + rec.width) - innerRadius, rec.y + rec.height + lineThick}, // P3, P4
   1165         {(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
   1166         {(float)rec.x + innerRadius, rec.y}, {(float)(rec.x + rec.width) - innerRadius, rec.y}, // P8, P9
   1167         { rec.x + rec.width, (float)rec.y + innerRadius }, {rec.x + rec.width, (float)(rec.y + rec.height) - innerRadius}, // P10, P11
   1168         {(float)(rec.x + rec.width) - innerRadius, rec.y + rec.height}, {(float)rec.x + innerRadius, rec.y + rec.height}, // P12, P13
   1169         { rec.x, (float)(rec.y + rec.height) - innerRadius}, {rec.x, (float)rec.y + innerRadius} // P14, P15
   1170     };
   1171 
   1172     const Vector2 centers[4] = {
   1173         {(float)rec.x + innerRadius, (float)rec.y + innerRadius}, {(float)(rec.x + rec.width) - innerRadius, (float)rec.y + innerRadius}, // P16, P17
   1174         {(float)(rec.x + rec.width) - innerRadius, (float)(rec.y + rec.height) - innerRadius}, {(float)rec.x + innerRadius, (float)(rec.y + rec.height) - innerRadius} // P18, P19
   1175     };
   1176 
   1177     const float angles[4] = { 180.0f, 270.0f, 0.0f, 90.0f };
   1178 
   1179     if (lineThick > 1)
   1180     {
   1181 #if defined(SUPPORT_QUADS_DRAW_MODE)
   1182         rlSetTexture(GetShapesTexture().id);
   1183         Rectangle shapeRect = GetShapesTextureRectangle();
   1184 
   1185         rlBegin(RL_QUADS);
   1186 
   1187             // Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
   1188             for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
   1189             {
   1190                 float angle = angles[k];
   1191                 const Vector2 center = centers[k];
   1192                 for (int i = 0; i < segments; i++)
   1193                 {
   1194                     rlColor4ub(color.r, color.g, color.b, color.a);
   1195 
   1196                     rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
   1197                     rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
   1198 
   1199                     rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
   1200                     rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
   1201 
   1202                     rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1203                     rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
   1204 
   1205                     rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1206                     rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
   1207 
   1208                     angle += stepLength;
   1209                 }
   1210             }
   1211 
   1212             // Upper rectangle
   1213             rlColor4ub(color.r, color.g, color.b, color.a);
   1214             rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
   1215             rlVertex2f(point[0].x, point[0].y);
   1216             rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1217             rlVertex2f(point[8].x, point[8].y);
   1218             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1219             rlVertex2f(point[9].x, point[9].y);
   1220             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
   1221             rlVertex2f(point[1].x, point[1].y);
   1222 
   1223             // Right rectangle
   1224             rlColor4ub(color.r, color.g, color.b, color.a);
   1225             rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
   1226             rlVertex2f(point[2].x, point[2].y);
   1227             rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1228             rlVertex2f(point[10].x, point[10].y);
   1229             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1230             rlVertex2f(point[11].x, point[11].y);
   1231             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
   1232             rlVertex2f(point[3].x, point[3].y);
   1233 
   1234             // Lower rectangle
   1235             rlColor4ub(color.r, color.g, color.b, color.a);
   1236             rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
   1237             rlVertex2f(point[13].x, point[13].y);
   1238             rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1239             rlVertex2f(point[5].x, point[5].y);
   1240             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1241             rlVertex2f(point[4].x, point[4].y);
   1242             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
   1243             rlVertex2f(point[12].x, point[12].y);
   1244 
   1245             // Left rectangle
   1246             rlColor4ub(color.r, color.g, color.b, color.a);
   1247             rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
   1248             rlVertex2f(point[15].x, point[15].y);
   1249             rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1250             rlVertex2f(point[7].x, point[7].y);
   1251             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1252             rlVertex2f(point[6].x, point[6].y);
   1253             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
   1254             rlVertex2f(point[14].x, point[14].y);
   1255 
   1256         rlEnd();
   1257         rlSetTexture(0);
   1258 #else
   1259         rlBegin(RL_TRIANGLES);
   1260 
   1261             // Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
   1262             for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
   1263             {
   1264                 float angle = angles[k];
   1265                 const Vector2 center = centers[k];
   1266 
   1267                 for (int i = 0; i < segments; i++)
   1268                 {
   1269                     rlColor4ub(color.r, color.g, color.b, color.a);
   1270 
   1271                     rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
   1272                     rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
   1273                     rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
   1274 
   1275                     rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
   1276                     rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
   1277                     rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
   1278 
   1279                     angle += stepLength;
   1280                 }
   1281             }
   1282 
   1283             // Upper rectangle
   1284             rlColor4ub(color.r, color.g, color.b, color.a);
   1285             rlVertex2f(point[0].x, point[0].y);
   1286             rlVertex2f(point[8].x, point[8].y);
   1287             rlVertex2f(point[9].x, point[9].y);
   1288             rlVertex2f(point[1].x, point[1].y);
   1289             rlVertex2f(point[0].x, point[0].y);
   1290             rlVertex2f(point[9].x, point[9].y);
   1291 
   1292             // Right rectangle
   1293             rlColor4ub(color.r, color.g, color.b, color.a);
   1294             rlVertex2f(point[10].x, point[10].y);
   1295             rlVertex2f(point[11].x, point[11].y);
   1296             rlVertex2f(point[3].x, point[3].y);
   1297             rlVertex2f(point[2].x, point[2].y);
   1298             rlVertex2f(point[10].x, point[10].y);
   1299             rlVertex2f(point[3].x, point[3].y);
   1300 
   1301             // Lower rectangle
   1302             rlColor4ub(color.r, color.g, color.b, color.a);
   1303             rlVertex2f(point[13].x, point[13].y);
   1304             rlVertex2f(point[5].x, point[5].y);
   1305             rlVertex2f(point[4].x, point[4].y);
   1306             rlVertex2f(point[12].x, point[12].y);
   1307             rlVertex2f(point[13].x, point[13].y);
   1308             rlVertex2f(point[4].x, point[4].y);
   1309 
   1310             // Left rectangle
   1311             rlColor4ub(color.r, color.g, color.b, color.a);
   1312             rlVertex2f(point[7].x, point[7].y);
   1313             rlVertex2f(point[6].x, point[6].y);
   1314             rlVertex2f(point[14].x, point[14].y);
   1315             rlVertex2f(point[15].x, point[15].y);
   1316             rlVertex2f(point[7].x, point[7].y);
   1317             rlVertex2f(point[14].x, point[14].y);
   1318         rlEnd();
   1319 #endif
   1320     }
   1321     else
   1322     {
   1323         // Use LINES to draw the outline
   1324         rlBegin(RL_LINES);
   1325 
   1326             // Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
   1327             for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
   1328             {
   1329                 float angle = angles[k];
   1330                 const Vector2 center = centers[k];
   1331 
   1332                 for (int i = 0; i < segments; i++)
   1333                 {
   1334                     rlColor4ub(color.r, color.g, color.b, color.a);
   1335                     rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
   1336                     rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
   1337                     angle += stepLength;
   1338                 }
   1339             }
   1340 
   1341             // And now the remaining 4 lines
   1342             for (int i = 0; i < 8; i += 2)
   1343             {
   1344                 rlColor4ub(color.r, color.g, color.b, color.a);
   1345                 rlVertex2f(point[i].x, point[i].y);
   1346                 rlVertex2f(point[i + 1].x, point[i + 1].y);
   1347             }
   1348 
   1349         rlEnd();
   1350     }
   1351 }
   1352 
   1353 // Draw a triangle
   1354 // NOTE: Vertex must be provided in counter-clockwise order
   1355 void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
   1356 {
   1357 #if defined(SUPPORT_QUADS_DRAW_MODE)
   1358     rlSetTexture(GetShapesTexture().id);
   1359     Rectangle shapeRect = GetShapesTextureRectangle();
   1360 
   1361     rlBegin(RL_QUADS);
   1362         rlColor4ub(color.r, color.g, color.b, color.a);
   1363 
   1364         rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
   1365         rlVertex2f(v1.x, v1.y);
   1366 
   1367         rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1368         rlVertex2f(v2.x, v2.y);
   1369 
   1370         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1371         rlVertex2f(v2.x, v2.y);
   1372 
   1373         rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
   1374         rlVertex2f(v3.x, v3.y);
   1375     rlEnd();
   1376 
   1377     rlSetTexture(0);
   1378 #else
   1379     rlBegin(RL_TRIANGLES);
   1380         rlColor4ub(color.r, color.g, color.b, color.a);
   1381         rlVertex2f(v1.x, v1.y);
   1382         rlVertex2f(v2.x, v2.y);
   1383         rlVertex2f(v3.x, v3.y);
   1384     rlEnd();
   1385 #endif
   1386 }
   1387 
   1388 // Draw a triangle using lines
   1389 // NOTE: Vertex must be provided in counter-clockwise order
   1390 void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
   1391 {
   1392     rlBegin(RL_LINES);
   1393         rlColor4ub(color.r, color.g, color.b, color.a);
   1394         rlVertex2f(v1.x, v1.y);
   1395         rlVertex2f(v2.x, v2.y);
   1396 
   1397         rlVertex2f(v2.x, v2.y);
   1398         rlVertex2f(v3.x, v3.y);
   1399 
   1400         rlVertex2f(v3.x, v3.y);
   1401         rlVertex2f(v1.x, v1.y);
   1402     rlEnd();
   1403 }
   1404 
   1405 // Draw a triangle fan defined by points
   1406 // NOTE: First vertex provided is the center, shared by all triangles
   1407 // By default, following vertex should be provided in counter-clockwise order
   1408 void DrawTriangleFan(const Vector2 *points, int pointCount, Color color)
   1409 {
   1410     if (pointCount >= 3)
   1411     {
   1412         rlSetTexture(GetShapesTexture().id);
   1413         Rectangle shapeRect = GetShapesTextureRectangle();
   1414 
   1415         rlBegin(RL_QUADS);
   1416             rlColor4ub(color.r, color.g, color.b, color.a);
   1417 
   1418             for (int i = 1; i < pointCount - 1; i++)
   1419             {
   1420                 rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
   1421                 rlVertex2f(points[0].x, points[0].y);
   1422 
   1423                 rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1424                 rlVertex2f(points[i].x, points[i].y);
   1425 
   1426                 rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1427                 rlVertex2f(points[i + 1].x, points[i + 1].y);
   1428 
   1429                 rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
   1430                 rlVertex2f(points[i + 1].x, points[i + 1].y);
   1431             }
   1432         rlEnd();
   1433         rlSetTexture(0);
   1434     }
   1435 }
   1436 
   1437 // Draw a triangle strip defined by points
   1438 // NOTE: Every new vertex connects with previous two
   1439 void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color)
   1440 {
   1441     if (pointCount >= 3)
   1442     {
   1443         rlBegin(RL_TRIANGLES);
   1444             rlColor4ub(color.r, color.g, color.b, color.a);
   1445 
   1446             for (int i = 2; i < pointCount; i++)
   1447             {
   1448                 if ((i%2) == 0)
   1449                 {
   1450                     rlVertex2f(points[i].x, points[i].y);
   1451                     rlVertex2f(points[i - 2].x, points[i - 2].y);
   1452                     rlVertex2f(points[i - 1].x, points[i - 1].y);
   1453                 }
   1454                 else
   1455                 {
   1456                     rlVertex2f(points[i].x, points[i].y);
   1457                     rlVertex2f(points[i - 1].x, points[i - 1].y);
   1458                     rlVertex2f(points[i - 2].x, points[i - 2].y);
   1459                 }
   1460             }
   1461         rlEnd();
   1462     }
   1463 }
   1464 
   1465 // Draw a regular polygon of n sides (Vector version)
   1466 void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color)
   1467 {
   1468     if (sides < 3) sides = 3;
   1469     float centralAngle = rotation*DEG2RAD;
   1470     float angleStep = 360.0f/(float)sides*DEG2RAD;
   1471 
   1472 #if defined(SUPPORT_QUADS_DRAW_MODE)
   1473     rlSetTexture(GetShapesTexture().id);
   1474     Rectangle shapeRect = GetShapesTextureRectangle();
   1475 
   1476     rlBegin(RL_QUADS);
   1477         for (int i = 0; i < sides; i++)
   1478         {
   1479             rlColor4ub(color.r, color.g, color.b, color.a);
   1480             float nextAngle = centralAngle + angleStep;
   1481 
   1482             rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
   1483             rlVertex2f(center.x, center.y);
   1484 
   1485             rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1486             rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
   1487 
   1488             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
   1489             rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
   1490 
   1491             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1492             rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
   1493 
   1494             centralAngle = nextAngle;
   1495         }
   1496     rlEnd();
   1497     rlSetTexture(0);
   1498 #else
   1499     rlBegin(RL_TRIANGLES);
   1500         for (int i = 0; i < sides; i++)
   1501         {
   1502             rlColor4ub(color.r, color.g, color.b, color.a);
   1503 
   1504             rlVertex2f(center.x, center.y);
   1505             rlVertex2f(center.x + cosf(centralAngle + angleStep)*radius, center.y + sinf(centralAngle + angleStep)*radius);
   1506             rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
   1507 
   1508             centralAngle += angleStep;
   1509         }
   1510     rlEnd();
   1511 #endif
   1512 }
   1513 
   1514 // Draw a polygon outline of n sides
   1515 void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color)
   1516 {
   1517     if (sides < 3) sides = 3;
   1518     float centralAngle = rotation*DEG2RAD;
   1519     float angleStep = 360.0f/(float)sides*DEG2RAD;
   1520 
   1521     rlBegin(RL_LINES);
   1522         for (int i = 0; i < sides; i++)
   1523         {
   1524             rlColor4ub(color.r, color.g, color.b, color.a);
   1525 
   1526             rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
   1527             rlVertex2f(center.x + cosf(centralAngle + angleStep)*radius, center.y + sinf(centralAngle + angleStep)*radius);
   1528 
   1529             centralAngle += angleStep;
   1530         }
   1531     rlEnd();
   1532 }
   1533 
   1534 void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color)
   1535 {
   1536     if (sides < 3) sides = 3;
   1537     float centralAngle = rotation*DEG2RAD;
   1538     float exteriorAngle = 360.0f/(float)sides*DEG2RAD;
   1539     float innerRadius = radius - (lineThick*cosf(DEG2RAD*exteriorAngle/2.0f));
   1540 
   1541 #if defined(SUPPORT_QUADS_DRAW_MODE)
   1542     rlSetTexture(GetShapesTexture().id);
   1543     Rectangle shapeRect = GetShapesTextureRectangle();
   1544 
   1545     rlBegin(RL_QUADS);
   1546         for (int i = 0; i < sides; i++)
   1547         {
   1548             rlColor4ub(color.r, color.g, color.b, color.a);
   1549             float nextAngle = centralAngle + exteriorAngle;
   1550 
   1551             rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1552             rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
   1553 
   1554             rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
   1555             rlVertex2f(center.x + cosf(centralAngle)*innerRadius, center.y + sinf(centralAngle)*innerRadius);
   1556 
   1557             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
   1558             rlVertex2f(center.x + cosf(nextAngle)*innerRadius, center.y + sinf(nextAngle)*innerRadius);
   1559 
   1560             rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
   1561             rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
   1562 
   1563             centralAngle = nextAngle;
   1564         }
   1565     rlEnd();
   1566     rlSetTexture(0);
   1567 #else
   1568     rlBegin(RL_TRIANGLES);
   1569         for (int i = 0; i < sides; i++)
   1570         {
   1571             rlColor4ub(color.r, color.g, color.b, color.a);
   1572             float nextAngle = centralAngle + exteriorAngle;
   1573 
   1574             rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
   1575             rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
   1576             rlVertex2f(center.x + cosf(centralAngle)*innerRadius, center.y + sinf(centralAngle)*innerRadius);
   1577 
   1578             rlVertex2f(center.x + cosf(centralAngle)*innerRadius, center.y + sinf(centralAngle)*innerRadius);
   1579             rlVertex2f(center.x + cosf(nextAngle)*innerRadius, center.y + sinf(nextAngle)*innerRadius);
   1580             rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
   1581 
   1582             centralAngle = nextAngle;
   1583         }
   1584     rlEnd();
   1585 #endif
   1586 }
   1587 
   1588 //----------------------------------------------------------------------------------
   1589 // Module Functions Definition - Splines functions
   1590 //----------------------------------------------------------------------------------
   1591 
   1592 // Draw spline: linear, minimum 2 points
   1593 void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color)
   1594 {
   1595     if (pointCount < 2) return;
   1596 
   1597 #if defined(SUPPORT_SPLINE_MITERS)
   1598     Vector2 prevNormal = (Vector2){-(points[1].y - points[0].y), (points[1].x - points[0].x)};
   1599     float prevLength = sqrtf(prevNormal.x*prevNormal.x + prevNormal.y*prevNormal.y);
   1600 
   1601     if (prevLength > 0.0f)
   1602     {
   1603         prevNormal.x /= prevLength;
   1604         prevNormal.y /= prevLength;
   1605     }
   1606     else
   1607     {
   1608         prevNormal.x = 0.0f;
   1609         prevNormal.y = 0.0f;
   1610     }
   1611 
   1612     Vector2 prevRadius = { 0.5f*thick*prevNormal.x, 0.5f*thick*prevNormal.y };
   1613 
   1614     for (int i = 0; i < pointCount - 1; i++)
   1615     {
   1616         Vector2 normal = { 0 };
   1617 
   1618         if (i < pointCount - 2)
   1619         {
   1620             normal = (Vector2){-(points[i + 2].y - points[i + 1].y), (points[i + 2].x - points[i + 1].x)};
   1621             float normalLength = sqrtf(normal.x*normal.x + normal.y*normal.y);
   1622 
   1623             if (normalLength > 0.0f)
   1624             {
   1625                 normal.x /= normalLength;
   1626                 normal.y /= normalLength;
   1627             }
   1628             else
   1629             {
   1630                 normal.x = 0.0f;
   1631                 normal.y = 0.0f;
   1632             }
   1633         }
   1634         else
   1635         {
   1636             normal = prevNormal;
   1637         }
   1638 
   1639         Vector2 radius = { prevNormal.x + normal.x, prevNormal.y + normal.y };
   1640         float radiusLength = sqrtf(radius.x*radius.x + radius.y*radius.y);
   1641 
   1642         if (radiusLength > 0.0f)
   1643         {
   1644             radius.x /= radiusLength;
   1645             radius.y /= radiusLength;
   1646         }
   1647         else
   1648         {
   1649             radius.x = 0.0f;
   1650             radius.y = 0.0f;
   1651         }
   1652 
   1653         float cosTheta = radius.x*normal.x + radius.y*normal.y;
   1654 
   1655         if (cosTheta != 0.0f)
   1656         {
   1657             radius.x *= (thick*0.5f/cosTheta);
   1658             radius.y *= (thick*0.5f/cosTheta);
   1659         }
   1660         else
   1661         {
   1662             radius.x = 0.0f;
   1663             radius.y = 0.0f;
   1664         }
   1665 
   1666         Vector2 strip[4] = {
   1667             { points[i].x - prevRadius.x, points[i].y - prevRadius.y },
   1668             { points[i].x + prevRadius.x, points[i].y + prevRadius.y },
   1669             { points[i + 1].x - radius.x, points[i + 1].y - radius.y },
   1670             { points[i + 1].x + radius.x, points[i + 1].y + radius.y }
   1671         };
   1672 
   1673         DrawTriangleStrip(strip, 4, color);
   1674 
   1675         prevRadius = radius;
   1676         prevNormal = normal;
   1677     }
   1678 
   1679 #else   // !SUPPORT_SPLINE_MITERS
   1680 
   1681     Vector2 delta = { 0 };
   1682     float length = 0.0f;
   1683     float scale = 0.0f;
   1684 
   1685     for (int i = 0; i < pointCount - 1; i++)
   1686     {
   1687         delta = (Vector2){ points[i + 1].x - points[i].x, points[i + 1].y - points[i].y };
   1688         length = sqrtf(delta.x*delta.x + delta.y*delta.y);
   1689 
   1690         if (length > 0) scale = thick/(2*length);
   1691 
   1692         Vector2 radius = { -scale*delta.y, scale*delta.x };
   1693         Vector2 strip[4] = {
   1694             { points[i].x - radius.x, points[i].y - radius.y },
   1695             { points[i].x + radius.x, points[i].y + radius.y },
   1696             { points[i + 1].x - radius.x, points[i + 1].y - radius.y },
   1697             { points[i + 1].x + radius.x, points[i + 1].y + radius.y }
   1698         };
   1699 
   1700         DrawTriangleStrip(strip, 4, color);
   1701     }
   1702 #endif
   1703 
   1704 #if defined(SUPPORT_SPLINE_SEGMENT_CAPS)
   1705     // TODO: Add spline segment rounded caps at the begin/end of the spline
   1706 #endif
   1707 }
   1708 
   1709 // Draw spline: B-Spline, minimum 4 points
   1710 void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color)
   1711 {
   1712     if (pointCount < 4) return;
   1713 
   1714     float a[4] = { 0 };
   1715     float b[4] = { 0 };
   1716     float dy = 0.0f;
   1717     float dx = 0.0f;
   1718     float size = 0.0f;
   1719 
   1720     Vector2 currentPoint = { 0 };
   1721     Vector2 nextPoint = { 0 };
   1722     Vector2 vertices[2*SPLINE_SEGMENT_DIVISIONS + 2] = { 0 };
   1723 
   1724     for (int i = 0; i < (pointCount - 3); i++)
   1725     {
   1726         float t = 0.0f;
   1727         Vector2 p1 = points[i], p2 = points[i + 1], p3 = points[i + 2], p4 = points[i + 3];
   1728 
   1729         a[0] = (-p1.x + 3.0f*p2.x - 3.0f*p3.x + p4.x)/6.0f;
   1730         a[1] = (3.0f*p1.x - 6.0f*p2.x + 3.0f*p3.x)/6.0f;
   1731         a[2] = (-3.0f*p1.x + 3.0f*p3.x)/6.0f;
   1732         a[3] = (p1.x + 4.0f*p2.x + p3.x)/6.0f;
   1733 
   1734         b[0] = (-p1.y + 3.0f*p2.y - 3.0f*p3.y + p4.y)/6.0f;
   1735         b[1] = (3.0f*p1.y - 6.0f*p2.y + 3.0f*p3.y)/6.0f;
   1736         b[2] = (-3.0f*p1.y + 3.0f*p3.y)/6.0f;
   1737         b[3] = (p1.y + 4.0f*p2.y + p3.y)/6.0f;
   1738 
   1739         currentPoint.x = a[3];
   1740         currentPoint.y = b[3];
   1741 
   1742         if (i == 0) DrawCircleV(currentPoint, thick/2.0f, color);   // Draw init line circle-cap
   1743 
   1744         if (i > 0)
   1745         {
   1746             vertices[0].x = currentPoint.x + dy*size;
   1747             vertices[0].y = currentPoint.y - dx*size;
   1748             vertices[1].x = currentPoint.x - dy*size;
   1749             vertices[1].y = currentPoint.y + dx*size;
   1750         }
   1751 
   1752         for (int j = 1; j <= SPLINE_SEGMENT_DIVISIONS; j++)
   1753         {
   1754             t = ((float)j)/((float)SPLINE_SEGMENT_DIVISIONS);
   1755 
   1756             nextPoint.x = a[3] + t*(a[2] + t*(a[1] + t*a[0]));
   1757             nextPoint.y = b[3] + t*(b[2] + t*(b[1] + t*b[0]));
   1758 
   1759             dy = nextPoint.y - currentPoint.y;
   1760             dx = nextPoint.x - currentPoint.x;
   1761             size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
   1762 
   1763             if ((i == 0) && (j == 1))
   1764             {
   1765                 vertices[0].x = currentPoint.x + dy*size;
   1766                 vertices[0].y = currentPoint.y - dx*size;
   1767                 vertices[1].x = currentPoint.x - dy*size;
   1768                 vertices[1].y = currentPoint.y + dx*size;
   1769             }
   1770 
   1771             vertices[2*j + 1].x = nextPoint.x - dy*size;
   1772             vertices[2*j + 1].y = nextPoint.y + dx*size;
   1773             vertices[2*j].x = nextPoint.x + dy*size;
   1774             vertices[2*j].y = nextPoint.y - dx*size;
   1775 
   1776             currentPoint = nextPoint;
   1777         }
   1778 
   1779         DrawTriangleStrip(vertices, 2*SPLINE_SEGMENT_DIVISIONS + 2, color);
   1780     }
   1781 
   1782     // Cap circle drawing at the end of every segment
   1783     DrawCircleV(currentPoint, thick/2.0f, color);
   1784 }
   1785 
   1786 // Draw spline: Catmull-Rom, minimum 4 points
   1787 void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color)
   1788 {
   1789     if (pointCount < 4) return;
   1790 
   1791     float dy = 0.0f;
   1792     float dx = 0.0f;
   1793     float size = 0.0f;
   1794 
   1795     Vector2 currentPoint = points[1];
   1796     Vector2 nextPoint = { 0 };
   1797     Vector2 vertices[2*SPLINE_SEGMENT_DIVISIONS + 2] = { 0 };
   1798 
   1799     DrawCircleV(currentPoint, thick/2.0f, color);   // Draw init line circle-cap
   1800 
   1801     for (int i = 0; i < (pointCount - 3); i++)
   1802     {
   1803         float t = 0.0f;
   1804         Vector2 p1 = points[i], p2 = points[i + 1], p3 = points[i + 2], p4 = points[i + 3];
   1805 
   1806         if (i > 0)
   1807         {
   1808             vertices[0].x = currentPoint.x + dy*size;
   1809             vertices[0].y = currentPoint.y - dx*size;
   1810             vertices[1].x = currentPoint.x - dy*size;
   1811             vertices[1].y = currentPoint.y + dx*size;
   1812         }
   1813 
   1814         for (int j = 1; j <= SPLINE_SEGMENT_DIVISIONS; j++)
   1815         {
   1816             t = ((float)j)/((float)SPLINE_SEGMENT_DIVISIONS);
   1817 
   1818             float q0 = (-1.0f*t*t*t) + (2.0f*t*t) + (-1.0f*t);
   1819             float q1 = (3.0f*t*t*t) + (-5.0f*t*t) + 2.0f;
   1820             float q2 = (-3.0f*t*t*t) + (4.0f*t*t) + t;
   1821             float q3 = t*t*t - t*t;
   1822 
   1823             nextPoint.x = 0.5f*((p1.x*q0) + (p2.x*q1) + (p3.x*q2) + (p4.x*q3));
   1824             nextPoint.y = 0.5f*((p1.y*q0) + (p2.y*q1) + (p3.y*q2) + (p4.y*q3));
   1825 
   1826             dy = nextPoint.y - currentPoint.y;
   1827             dx = nextPoint.x - currentPoint.x;
   1828             size = (0.5f*thick)/sqrtf(dx*dx + dy*dy);
   1829 
   1830             if ((i == 0) && (j == 1))
   1831             {
   1832                 vertices[0].x = currentPoint.x + dy*size;
   1833                 vertices[0].y = currentPoint.y - dx*size;
   1834                 vertices[1].x = currentPoint.x - dy*size;
   1835                 vertices[1].y = currentPoint.y + dx*size;
   1836             }
   1837 
   1838             vertices[2*j + 1].x = nextPoint.x - dy*size;
   1839             vertices[2*j + 1].y = nextPoint.y + dx*size;
   1840             vertices[2*j].x = nextPoint.x + dy*size;
   1841             vertices[2*j].y = nextPoint.y - dx*size;
   1842 
   1843             currentPoint = nextPoint;
   1844         }
   1845 
   1846         DrawTriangleStrip(vertices, 2*SPLINE_SEGMENT_DIVISIONS + 2, color);
   1847     }
   1848 
   1849     // Cap circle drawing at the end of every segment
   1850     DrawCircleV(currentPoint, thick/2.0f, color);
   1851 }
   1852 
   1853 // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]
   1854 void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color)
   1855 {
   1856     if (pointCount >= 3)
   1857     {
   1858         for (int i = 0; i < pointCount - 2; i += 2) DrawSplineSegmentBezierQuadratic(points[i], points[i + 1], points[i + 2], thick, color);
   1859 
   1860         // Cap circle drawing at the end of every segment
   1861         //for (int i = 2; i < pointCount - 2; i += 2) DrawCircleV(points[i], thick/2.0f, color);
   1862     }
   1863 }
   1864 
   1865 // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]
   1866 void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color)
   1867 {
   1868     if (pointCount >= 4)
   1869     {
   1870         for (int i = 0; i < pointCount - 3; i += 3) DrawSplineSegmentBezierCubic(points[i], points[i + 1], points[i + 2], points[i + 3], thick, color);
   1871 
   1872         // Cap circle drawing at the end of every segment
   1873         //for (int i = 3; i < pointCount - 3; i += 3) DrawCircleV(points[i], thick/2.0f, color);
   1874     }
   1875 }
   1876 
   1877 // Draw spline segment: Linear, 2 points
   1878 void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color)
   1879 {
   1880     // NOTE: For the linear spline we don't use subdivisions, just a single quad
   1881 
   1882     Vector2 delta = { p2.x - p1.x, p2.y - p1.y };
   1883     float length = sqrtf(delta.x*delta.x + delta.y*delta.y);
   1884 
   1885     if ((length > 0) && (thick > 0))
   1886     {
   1887         float scale = thick/(2*length);
   1888 
   1889         Vector2 radius = { -scale*delta.y, scale*delta.x };
   1890         Vector2 strip[4] = {
   1891             { p1.x - radius.x, p1.y - radius.y },
   1892             { p1.x + radius.x, p1.y + radius.y },
   1893             { p2.x - radius.x, p2.y - radius.y },
   1894             { p2.x + radius.x, p2.y + radius.y }
   1895         };
   1896 
   1897         DrawTriangleStrip(strip, 4, color);
   1898     }
   1899 }
   1900 
   1901 // Draw spline segment: B-Spline, 4 points
   1902 void DrawSplineSegmentBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color)
   1903 {
   1904     const float step = 1.0f/SPLINE_SEGMENT_DIVISIONS;
   1905 
   1906     Vector2 currentPoint = { 0 };
   1907     Vector2 nextPoint = { 0 };
   1908     float t = 0.0f;
   1909 
   1910     Vector2 points[2*SPLINE_SEGMENT_DIVISIONS + 2] = { 0 };
   1911 
   1912     float a[4] = { 0 };
   1913     float b[4] = { 0 };
   1914 
   1915     a[0] = (-p1.x + 3*p2.x - 3*p3.x + p4.x)/6.0f;
   1916     a[1] = (3*p1.x - 6*p2.x + 3*p3.x)/6.0f;
   1917     a[2] = (-3*p1.x + 3*p3.x)/6.0f;
   1918     a[3] = (p1.x + 4*p2.x + p3.x)/6.0f;
   1919 
   1920     b[0] = (-p1.y + 3*p2.y - 3*p3.y + p4.y)/6.0f;
   1921     b[1] = (3*p1.y - 6*p2.y + 3*p3.y)/6.0f;
   1922     b[2] = (-3*p1.y + 3*p3.y)/6.0f;
   1923     b[3] = (p1.y + 4*p2.y + p3.y)/6.0f;
   1924 
   1925     currentPoint.x = a[3];
   1926     currentPoint.y = b[3];
   1927 
   1928     for (int i = 0; i <= SPLINE_SEGMENT_DIVISIONS; i++)
   1929     {
   1930         t = step*(float)i;
   1931 
   1932         nextPoint.x = a[3] + t*(a[2] + t*(a[1] + t*a[0]));
   1933         nextPoint.y = b[3] + t*(b[2] + t*(b[1] + t*b[0]));
   1934 
   1935         float dy = nextPoint.y - currentPoint.y;
   1936         float dx = nextPoint.x - currentPoint.x;
   1937         float size = (0.5f*thick)/sqrtf(dx*dx + dy*dy);
   1938 
   1939         if (i == 1)
   1940         {
   1941             points[0].x = currentPoint.x + dy*size;
   1942             points[0].y = currentPoint.y - dx*size;
   1943             points[1].x = currentPoint.x - dy*size;
   1944             points[1].y = currentPoint.y + dx*size;
   1945         }
   1946 
   1947         points[2*i + 1].x = nextPoint.x - dy*size;
   1948         points[2*i + 1].y = nextPoint.y + dx*size;
   1949         points[2*i].x = nextPoint.x + dy*size;
   1950         points[2*i].y = nextPoint.y - dx*size;
   1951 
   1952         currentPoint = nextPoint;
   1953     }
   1954 
   1955     DrawTriangleStrip(points, 2*SPLINE_SEGMENT_DIVISIONS+2, color);
   1956 }
   1957 
   1958 // Draw spline segment: Catmull-Rom, 4 points
   1959 void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color)
   1960 {
   1961     const float step = 1.0f/SPLINE_SEGMENT_DIVISIONS;
   1962 
   1963     Vector2 currentPoint = p1;
   1964     Vector2 nextPoint = { 0 };
   1965     float t = 0.0f;
   1966 
   1967     Vector2 points[2*SPLINE_SEGMENT_DIVISIONS + 2] = { 0 };
   1968 
   1969     for (int i = 0; i <= SPLINE_SEGMENT_DIVISIONS; i++)
   1970     {
   1971         t = step*(float)i;
   1972 
   1973         float q0 = (-1*t*t*t) + (2*t*t) + (-1*t);
   1974         float q1 = (3*t*t*t) + (-5*t*t) + 2;
   1975         float q2 = (-3*t*t*t) + (4*t*t) + t;
   1976         float q3 = t*t*t - t*t;
   1977 
   1978         nextPoint.x = 0.5f*((p1.x*q0) + (p2.x*q1) + (p3.x*q2) + (p4.x*q3));
   1979         nextPoint.y = 0.5f*((p1.y*q0) + (p2.y*q1) + (p3.y*q2) + (p4.y*q3));
   1980 
   1981         float dy = nextPoint.y - currentPoint.y;
   1982         float dx = nextPoint.x - currentPoint.x;
   1983         float size = (0.5f*thick)/sqrtf(dx*dx + dy*dy);
   1984 
   1985         if (i == 1)
   1986         {
   1987             points[0].x = currentPoint.x + dy*size;
   1988             points[0].y = currentPoint.y - dx*size;
   1989             points[1].x = currentPoint.x - dy*size;
   1990             points[1].y = currentPoint.y + dx*size;
   1991         }
   1992 
   1993         points[2*i + 1].x = nextPoint.x - dy*size;
   1994         points[2*i + 1].y = nextPoint.y + dx*size;
   1995         points[2*i].x = nextPoint.x + dy*size;
   1996         points[2*i].y = nextPoint.y - dx*size;
   1997 
   1998         currentPoint = nextPoint;
   1999     }
   2000 
   2001     DrawTriangleStrip(points, 2*SPLINE_SEGMENT_DIVISIONS + 2, color);
   2002 }
   2003 
   2004 // Draw spline segment: Quadratic Bezier, 2 points, 1 control point
   2005 void DrawSplineSegmentBezierQuadratic(Vector2 p1, Vector2 c2, Vector2 p3, float thick, Color color)
   2006 {
   2007     const float step = 1.0f/SPLINE_SEGMENT_DIVISIONS;
   2008 
   2009     Vector2 previous = p1;
   2010     Vector2 current = { 0 };
   2011     float t = 0.0f;
   2012 
   2013     Vector2 points[2*SPLINE_SEGMENT_DIVISIONS + 2] = { 0 };
   2014 
   2015     for (int i = 1; i <= SPLINE_SEGMENT_DIVISIONS; i++)
   2016     {
   2017         t = step*(float)i;
   2018 
   2019         float a = powf(1.0f - t, 2);
   2020         float b = 2.0f*(1.0f - t)*t;
   2021         float c = powf(t, 2);
   2022 
   2023         // NOTE: The easing functions aren't suitable here because they don't take a control point
   2024         current.y = a*p1.y + b*c2.y + c*p3.y;
   2025         current.x = a*p1.x + b*c2.x + c*p3.x;
   2026 
   2027         float dy = current.y - previous.y;
   2028         float dx = current.x - previous.x;
   2029         float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
   2030 
   2031         if (i == 1)
   2032         {
   2033             points[0].x = previous.x + dy*size;
   2034             points[0].y = previous.y - dx*size;
   2035             points[1].x = previous.x - dy*size;
   2036             points[1].y = previous.y + dx*size;
   2037         }
   2038 
   2039         points[2*i + 1].x = current.x - dy*size;
   2040         points[2*i + 1].y = current.y + dx*size;
   2041         points[2*i].x = current.x + dy*size;
   2042         points[2*i].y = current.y - dx*size;
   2043 
   2044         previous = current;
   2045     }
   2046 
   2047     DrawTriangleStrip(points, 2*SPLINE_SEGMENT_DIVISIONS + 2, color);
   2048 }
   2049 
   2050 // Draw spline segment: Cubic Bezier, 2 points, 2 control points
   2051 void DrawSplineSegmentBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float thick, Color color)
   2052 {
   2053     const float step = 1.0f/SPLINE_SEGMENT_DIVISIONS;
   2054 
   2055     Vector2 previous = p1;
   2056     Vector2 current = { 0 };
   2057     float t = 0.0f;
   2058 
   2059     Vector2 points[2*SPLINE_SEGMENT_DIVISIONS + 2] = { 0 };
   2060 
   2061     for (int i = 1; i <= SPLINE_SEGMENT_DIVISIONS; i++)
   2062     {
   2063         t = step*(float)i;
   2064 
   2065         float a = powf(1.0f - t, 3);
   2066         float b = 3.0f*powf(1.0f - t, 2)*t;
   2067         float c = 3.0f*(1.0f - t)*powf(t, 2);
   2068         float d = powf(t, 3);
   2069 
   2070         current.y = a*p1.y + b*c2.y + c*c3.y + d*p4.y;
   2071         current.x = a*p1.x + b*c2.x + c*c3.x + d*p4.x;
   2072 
   2073         float dy = current.y - previous.y;
   2074         float dx = current.x - previous.x;
   2075         float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
   2076 
   2077         if (i == 1)
   2078         {
   2079             points[0].x = previous.x + dy*size;
   2080             points[0].y = previous.y - dx*size;
   2081             points[1].x = previous.x - dy*size;
   2082             points[1].y = previous.y + dx*size;
   2083         }
   2084 
   2085         points[2*i + 1].x = current.x - dy*size;
   2086         points[2*i + 1].y = current.y + dx*size;
   2087         points[2*i].x = current.x + dy*size;
   2088         points[2*i].y = current.y - dx*size;
   2089 
   2090         previous = current;
   2091     }
   2092 
   2093     DrawTriangleStrip(points, 2*SPLINE_SEGMENT_DIVISIONS + 2, color);
   2094 }
   2095 
   2096 // Get spline point for a given t [0.0f .. 1.0f], Linear
   2097 Vector2 GetSplinePointLinear(Vector2 startPos, Vector2 endPos, float t)
   2098 {
   2099     Vector2 point = { 0 };
   2100 
   2101     point.x = startPos.x*(1.0f - t) + endPos.x*t;
   2102     point.y = startPos.y*(1.0f - t) + endPos.y*t;
   2103 
   2104     return point;
   2105 }
   2106 
   2107 // Get spline point for a given t [0.0f .. 1.0f], B-Spline
   2108 Vector2 GetSplinePointBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t)
   2109 {
   2110     Vector2 point = { 0 };
   2111 
   2112     float a[4] = { 0 };
   2113     float b[4] = { 0 };
   2114 
   2115     a[0] = (-p1.x + 3*p2.x - 3*p3.x + p4.x)/6.0f;
   2116     a[1] = (3*p1.x - 6*p2.x + 3*p3.x)/6.0f;
   2117     a[2] = (-3*p1.x + 3*p3.x)/6.0f;
   2118     a[3] = (p1.x + 4*p2.x + p3.x)/6.0f;
   2119 
   2120     b[0] = (-p1.y + 3*p2.y - 3*p3.y + p4.y)/6.0f;
   2121     b[1] = (3*p1.y - 6*p2.y + 3*p3.y)/6.0f;
   2122     b[2] = (-3*p1.y + 3*p3.y)/6.0f;
   2123     b[3] = (p1.y + 4*p2.y + p3.y)/6.0f;
   2124 
   2125     point.x = a[3] + t*(a[2] + t*(a[1] + t*a[0]));
   2126     point.y = b[3] + t*(b[2] + t*(b[1] + t*b[0]));
   2127 
   2128     return point;
   2129 }
   2130 
   2131 // Get spline point for a given t [0.0f .. 1.0f], Catmull-Rom
   2132 Vector2 GetSplinePointCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t)
   2133 {
   2134     Vector2 point = { 0 };
   2135 
   2136     float q0 = (-1*t*t*t) + (2*t*t) + (-1*t);
   2137     float q1 = (3*t*t*t) + (-5*t*t) + 2;
   2138     float q2 = (-3*t*t*t) + (4*t*t) + t;
   2139     float q3 = t*t*t - t*t;
   2140 
   2141     point.x = 0.5f*((p1.x*q0) + (p2.x*q1) + (p3.x*q2) + (p4.x*q3));
   2142     point.y = 0.5f*((p1.y*q0) + (p2.y*q1) + (p3.y*q2) + (p4.y*q3));
   2143 
   2144     return point;
   2145 }
   2146 
   2147 // Get spline point for a given t [0.0f .. 1.0f], Quadratic Bezier
   2148 Vector2 GetSplinePointBezierQuad(Vector2 startPos, Vector2 controlPos, Vector2 endPos, float t)
   2149 {
   2150     Vector2 point = { 0 };
   2151 
   2152     float a = powf(1.0f - t, 2);
   2153     float b = 2.0f*(1.0f - t)*t;
   2154     float c = powf(t, 2);
   2155 
   2156     point.y = a*startPos.y + b*controlPos.y + c*endPos.y;
   2157     point.x = a*startPos.x + b*controlPos.x + c*endPos.x;
   2158 
   2159     return point;
   2160 }
   2161 
   2162 // Get spline point for a given t [0.0f .. 1.0f], Cubic Bezier
   2163 Vector2 GetSplinePointBezierCubic(Vector2 startPos, Vector2 startControlPos, Vector2 endControlPos, Vector2 endPos, float t)
   2164 {
   2165     Vector2 point = { 0 };
   2166 
   2167     float a = powf(1.0f - t, 3);
   2168     float b = 3.0f*powf(1.0f - t, 2)*t;
   2169     float c = 3.0f*(1.0f - t)*powf(t, 2);
   2170     float d = powf(t, 3);
   2171 
   2172     point.y = a*startPos.y + b*startControlPos.y + c*endControlPos.y + d*endPos.y;
   2173     point.x = a*startPos.x + b*startControlPos.x + c*endControlPos.x + d*endPos.x;
   2174 
   2175     return point;
   2176 }
   2177 
   2178 //----------------------------------------------------------------------------------
   2179 // Module Functions Definition - Collision Detection functions
   2180 //----------------------------------------------------------------------------------
   2181 
   2182 // Check if point is inside rectangle
   2183 bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
   2184 {
   2185     bool collision = false;
   2186 
   2187     if ((point.x >= rec.x) && (point.x < (rec.x + rec.width)) && (point.y >= rec.y) && (point.y < (rec.y + rec.height))) collision = true;
   2188 
   2189     return collision;
   2190 }
   2191 
   2192 // Check if point is inside circle
   2193 bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius)
   2194 {
   2195     bool collision = false;
   2196 
   2197     float distanceSquared = (point.x - center.x)*(point.x - center.x) + (point.y - center.y)*(point.y - center.y);
   2198 
   2199     if (distanceSquared <= radius*radius) collision = true;
   2200 
   2201     return collision;
   2202 }
   2203 
   2204 // Check if point is inside a triangle defined by three points (p1, p2, p3)
   2205 bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3)
   2206 {
   2207     bool collision = false;
   2208 
   2209     float alpha = ((p2.y - p3.y)*(point.x - p3.x) + (p3.x - p2.x)*(point.y - p3.y)) /
   2210                   ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
   2211 
   2212     float beta = ((p3.y - p1.y)*(point.x - p3.x) + (p1.x - p3.x)*(point.y - p3.y)) /
   2213                  ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
   2214 
   2215     float gamma = 1.0f - alpha - beta;
   2216 
   2217     if ((alpha > 0) && (beta > 0) && (gamma > 0)) collision = true;
   2218 
   2219     return collision;
   2220 }
   2221 
   2222 // Check if point is within a polygon described by array of vertices
   2223 // NOTE: Based on http://jeffreythompson.org/collision-detection/poly-point.php
   2224 bool CheckCollisionPointPoly(Vector2 point, const Vector2 *points, int pointCount)
   2225 {
   2226     bool inside = false;
   2227 
   2228     if (pointCount > 2)
   2229     {
   2230         for (int i = 0, j = pointCount - 1; i < pointCount; j = i++)
   2231         {
   2232             if ((points[i].y > point.y) != (points[j].y > point.y) &&
   2233                 (point.x < (points[j].x - points[i].x)*(point.y - points[i].y)/(points[j].y - points[i].y) + points[i].x))
   2234             {
   2235                 inside = !inside;
   2236             }
   2237         }
   2238     }
   2239 
   2240     return inside;
   2241 }
   2242 
   2243 // Check collision between two rectangles
   2244 bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2)
   2245 {
   2246     bool collision = false;
   2247 
   2248     if ((rec1.x < (rec2.x + rec2.width) && (rec1.x + rec1.width) > rec2.x) &&
   2249         (rec1.y < (rec2.y + rec2.height) && (rec1.y + rec1.height) > rec2.y)) collision = true;
   2250 
   2251     return collision;
   2252 }
   2253 
   2254 // Check collision between two circles
   2255 bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2)
   2256 {
   2257     bool collision = false;
   2258 
   2259     float dx = center2.x - center1.x;      // X distance between centers
   2260     float dy = center2.y - center1.y;      // Y distance between centers
   2261 
   2262     float distanceSquared = dx*dx + dy*dy; // Distance between centers squared
   2263     float radiusSum = radius1 + radius2;
   2264 
   2265     collision = (distanceSquared <= (radiusSum*radiusSum));
   2266 
   2267     return collision;
   2268 }
   2269 
   2270 // Check collision between circle and rectangle
   2271 // NOTE: Reviewed version to take into account corner limit case
   2272 bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
   2273 {
   2274     bool collision = false;
   2275 
   2276     float recCenterX = rec.x + rec.width/2.0f;
   2277     float recCenterY = rec.y + rec.height/2.0f;
   2278 
   2279     float dx = fabsf(center.x - recCenterX);
   2280     float dy = fabsf(center.y - recCenterY);
   2281 
   2282     if (dx > (rec.width/2.0f + radius)) { return false; }
   2283     if (dy > (rec.height/2.0f + radius)) { return false; }
   2284 
   2285     if (dx <= (rec.width/2.0f)) { return true; }
   2286     if (dy <= (rec.height/2.0f)) { return true; }
   2287 
   2288     float cornerDistanceSq = (dx - rec.width/2.0f)*(dx - rec.width/2.0f) +
   2289                              (dy - rec.height/2.0f)*(dy - rec.height/2.0f);
   2290 
   2291     collision = (cornerDistanceSq <= (radius*radius));
   2292 
   2293     return collision;
   2294 }
   2295 
   2296 // Check the collision between two lines defined by two points each, returns collision point by reference
   2297 bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2, Vector2 *collisionPoint)
   2298 {
   2299     bool collision = false;
   2300 
   2301     float div = (endPos2.y - startPos2.y)*(endPos1.x - startPos1.x) - (endPos2.x - startPos2.x)*(endPos1.y - startPos1.y);
   2302 
   2303     if (fabsf(div) >= FLT_EPSILON)
   2304     {
   2305         collision = true;
   2306 
   2307         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;
   2308         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;
   2309 
   2310         if (((fabsf(startPos1.x - endPos1.x) > FLT_EPSILON) && (xi < fminf(startPos1.x, endPos1.x) || (xi > fmaxf(startPos1.x, endPos1.x)))) ||
   2311             ((fabsf(startPos2.x - endPos2.x) > FLT_EPSILON) && (xi < fminf(startPos2.x, endPos2.x) || (xi > fmaxf(startPos2.x, endPos2.x)))) ||
   2312             ((fabsf(startPos1.y - endPos1.y) > FLT_EPSILON) && (yi < fminf(startPos1.y, endPos1.y) || (yi > fmaxf(startPos1.y, endPos1.y)))) ||
   2313             ((fabsf(startPos2.y - endPos2.y) > FLT_EPSILON) && (yi < fminf(startPos2.y, endPos2.y) || (yi > fmaxf(startPos2.y, endPos2.y))))) collision = false;
   2314 
   2315         if (collision && (collisionPoint != 0))
   2316         {
   2317             collisionPoint->x = xi;
   2318             collisionPoint->y = yi;
   2319         }
   2320     }
   2321 
   2322     return collision;
   2323 }
   2324 
   2325 // Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]
   2326 bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshold)
   2327 {
   2328     bool collision = false;
   2329 
   2330     float dxc = point.x - p1.x;
   2331     float dyc = point.y - p1.y;
   2332     float dxl = p2.x - p1.x;
   2333     float dyl = p2.y - p1.y;
   2334     float cross = dxc*dyl - dyc*dxl;
   2335 
   2336     if (fabsf(cross) < (threshold*fmaxf(fabsf(dxl), fabsf(dyl))))
   2337     {
   2338         if (fabsf(dxl) >= fabsf(dyl)) collision = (dxl > 0)? ((p1.x <= point.x) && (point.x <= p2.x)) : ((p2.x <= point.x) && (point.x <= p1.x));
   2339         else collision = (dyl > 0)? ((p1.y <= point.y) && (point.y <= p2.y)) : ((p2.y <= point.y) && (point.y <= p1.y));
   2340     }
   2341 
   2342     return collision;
   2343 }
   2344 
   2345 // Check if circle collides with a line created betweeen two points [p1] and [p2]
   2346 RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2)
   2347 {
   2348     float dx = p1.x - p2.x;
   2349     float dy = p1.y - p2.y;
   2350 
   2351     if ((fabsf(dx) + fabsf(dy)) <= FLT_EPSILON)
   2352     {
   2353         return CheckCollisionCircles(p1, 0, center, radius);
   2354     }
   2355 
   2356     float lengthSQ = ((dx*dx) + (dy*dy));
   2357     float dotProduct = (((center.x - p1.x)*(p2.x - p1.x)) + ((center.y - p1.y)*(p2.y - p1.y)))/(lengthSQ);
   2358 
   2359     if (dotProduct > 1.0f) dotProduct = 1.0f;
   2360     else if (dotProduct < 0.0f) dotProduct = 0.0f;
   2361 
   2362     float dx2 = (p1.x - (dotProduct*(dx))) - center.x;
   2363     float dy2 = (p1.y - (dotProduct*(dy))) - center.y;
   2364     float distanceSQ = ((dx2*dx2) + (dy2*dy2));
   2365 
   2366     return (distanceSQ <= radius*radius);
   2367 }
   2368 
   2369 // Get collision rectangle for two rectangles collision
   2370 Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
   2371 {
   2372     Rectangle overlap = { 0 };
   2373 
   2374     float left = (rec1.x > rec2.x)? rec1.x : rec2.x;
   2375     float right1 = rec1.x + rec1.width;
   2376     float right2 = rec2.x + rec2.width;
   2377     float right = (right1 < right2)? right1 : right2;
   2378     float top = (rec1.y > rec2.y)? rec1.y : rec2.y;
   2379     float bottom1 = rec1.y + rec1.height;
   2380     float bottom2 = rec2.y + rec2.height;
   2381     float bottom = (bottom1 < bottom2)? bottom1 : bottom2;
   2382 
   2383     if ((left < right) && (top < bottom))
   2384     {
   2385         overlap.x = left;
   2386         overlap.y = top;
   2387         overlap.width = right - left;
   2388         overlap.height = bottom - top;
   2389     }
   2390 
   2391     return overlap;
   2392 }
   2393 
   2394 //----------------------------------------------------------------------------------
   2395 // Module specific Functions Definition
   2396 //----------------------------------------------------------------------------------
   2397 
   2398 // Cubic easing in-out
   2399 // NOTE: Used by DrawLineBezier() only
   2400 static float EaseCubicInOut(float t, float b, float c, float d)
   2401 {
   2402     float result = 0.0f;
   2403 
   2404     if ((t /= 0.5f*d) < 1) result = 0.5f*c*t*t*t + b;
   2405     else
   2406     {
   2407         t -= 2;
   2408         result = 0.5f*c*(t*t*t + 2.0f) + b;
   2409     }
   2410 
   2411     return result;
   2412 }
   2413 
   2414 #endif      // SUPPORT_MODULE_RSHAPES