github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/rshapes.c (about)

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