rshapes.c updated

This commit is contained in:
JupiterRider 2024-11-23 16:57:42 +01:00
parent 37fd299f2a
commit 4738b1467e

View file

@ -79,8 +79,8 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Global Variables Definition // Global Variables Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (white pixel loaded by rlgl) static Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (white pixel loaded by rlgl)
Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing static Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module specific Functions Declaration // Module specific Functions Declaration
@ -126,7 +126,7 @@ Rectangle GetShapesTextureRectangle(void)
// Draw a pixel // Draw a pixel
void DrawPixel(int posX, int posY, Color color) void DrawPixel(int posX, int posY, Color color)
{ {
DrawPixelV((Vector2){ (float)posX, (float)posY }, color); DrawPixelV((Vector2){ (float)posX, (float)posY }, color);
} }
// Draw a pixel (Vector version) // Draw a pixel (Vector version)
@ -178,9 +178,8 @@ void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color colo
{ {
rlBegin(RL_LINES); rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
// WARNING: Adding 0.5f offset to "center" point on selected pixel rlVertex2f((float)startPosX, (float)startPosY);
rlVertex2f((float)startPosX + 0.5f, (float)startPosY + 0.5f); rlVertex2f((float)endPosX, (float)endPosY);
rlVertex2f((float)endPosX + 0.5f, (float)endPosY + 0.5f);
rlEnd(); rlEnd();
} }
@ -189,14 +188,13 @@ void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
{ {
rlBegin(RL_LINES); rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
// WARNING: Adding 0.5f offset to "center" point on selected pixel rlVertex2f(startPos.x, startPos.y);
rlVertex2f(startPos.x + 0.5f, startPos.y + 0.5f); rlVertex2f(endPos.x, endPos.y);
rlVertex2f(endPos.x + 0.5f, endPos.y + 0.5f);
rlEnd(); rlEnd();
} }
// Draw lines sequuence (using gl lines) // Draw lines sequuence (using gl lines)
void DrawLineStrip(Vector2 *points, int pointCount, Color color) void DrawLineStrip(const Vector2 *points, int pointCount, Color color)
{ {
if (pointCount < 2) return; // Security check if (pointCount < 2) return; // Security check
@ -339,7 +337,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
} }
// NOTE: In case number of segments is odd, we add one last piece to the cake // NOTE: In case number of segments is odd, we add one last piece to the cake
if (((unsigned int)segments%2) == 1) if ((((unsigned int)segments)%2) == 1)
{ {
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
@ -432,17 +430,16 @@ void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float
} }
// Draw a gradient-filled circle // Draw a gradient-filled circle
// NOTE: Gradient goes from center (color1) to border (color2) void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer)
void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
{ {
rlBegin(RL_TRIANGLES); rlBegin(RL_TRIANGLES);
for (int i = 0; i < 360; i += 10) for (int i = 0; i < 360; i += 10)
{ {
rlColor4ub(color1.r, color1.g, color1.b, color1.a); rlColor4ub(inner.r, inner.g, inner.b, inner.a);
rlVertex2f((float)centerX, (float)centerY); rlVertex2f((float)centerX, (float)centerY);
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlColor4ub(outer.r, outer.g, outer.b, outer.a);
rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radius, (float)centerY + sinf(DEG2RAD*(i + 10))*radius); rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radius, (float)centerY + sinf(DEG2RAD*(i + 10))*radius);
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlColor4ub(outer.r, outer.g, outer.b, outer.a);
rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radius, (float)centerY + sinf(DEG2RAD*i)*radius); rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radius, (float)centerY + sinf(DEG2RAD*i)*radius);
} }
rlEnd(); rlEnd();
@ -763,22 +760,19 @@ void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color
} }
// Draw a vertical-gradient-filled rectangle // Draw a vertical-gradient-filled rectangle
// NOTE: Gradient goes from bottom (color1) to top (color2) void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom)
void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2)
{ {
DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color2, color2, color1); DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, top, bottom, bottom, top);
} }
// Draw a horizontal-gradient-filled rectangle // Draw a horizontal-gradient-filled rectangle
// NOTE: Gradient goes from bottom (color1) to top (color2) void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right)
void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2)
{ {
DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color1, color2, color2); DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, left, left, right, right);
} }
// Draw a gradient-filled rectangle // Draw a gradient-filled rectangle
// NOTE: Colors refer to corners, starting at top-lef corner and counter-clockwise void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color topRight, Color bottomRight)
void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4)
{ {
rlSetTexture(GetShapesTexture().id); rlSetTexture(GetShapesTexture().id);
Rectangle shapeRect = GetShapesTextureRectangle(); Rectangle shapeRect = GetShapesTextureRectangle();
@ -787,19 +781,19 @@ void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3,
rlNormal3f(0.0f, 0.0f, 1.0f); rlNormal3f(0.0f, 0.0f, 1.0f);
// NOTE: Default raylib font character 95 is a white square // NOTE: Default raylib font character 95 is a white square
rlColor4ub(col1.r, col1.g, col1.b, col1.a); rlColor4ub(topLeft.r, topLeft.g, topLeft.b, topLeft.a);
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
rlVertex2f(rec.x, rec.y); rlVertex2f(rec.x, rec.y);
rlColor4ub(col2.r, col2.g, col2.b, col2.a); rlColor4ub(bottomLeft.r, bottomLeft.g, bottomLeft.b, bottomLeft.a);
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
rlVertex2f(rec.x, rec.y + rec.height); rlVertex2f(rec.x, rec.y + rec.height);
rlColor4ub(col3.r, col3.g, col3.b, col3.a); rlColor4ub(topRight.r, topRight.g, topRight.b, topRight.a);
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
rlVertex2f(rec.x + rec.width, rec.y + rec.height); rlVertex2f(rec.x + rec.width, rec.y + rec.height);
rlColor4ub(col4.r, col4.g, col4.b, col4.a); rlColor4ub(bottomRight.r, bottomRight.g, bottomRight.b, bottomRight.a);
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
rlVertex2f(rec.x + rec.width, rec.y); rlVertex2f(rec.x + rec.width, rec.y);
rlEnd(); rlEnd();
@ -813,6 +807,30 @@ void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3,
// but it solves another issue: https://github.com/raysan5/raylib/issues/3884 // but it solves another issue: https://github.com/raysan5/raylib/issues/3884
void DrawRectangleLines(int posX, int posY, int width, int height, Color color) void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
{ {
Matrix mat = rlGetMatrixModelview();
float zoomFactor = 0.5f/mat.m0;
rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2f((float)posX - zoomFactor, (float)posY);
rlVertex2f((float)posX + (float)width + zoomFactor, (float)posY);
rlVertex2f((float)posX + (float)width, (float)posY - zoomFactor);
rlVertex2f((float)posX + (float)width, (float)posY + (float)height + zoomFactor);
rlVertex2f((float)posX + (float)width + zoomFactor, (float)posY + (float)height);
rlVertex2f((float)posX - zoomFactor, (float)posY + (float)height);
rlVertex2f((float)posX, (float)posY + (float)height + zoomFactor);
rlVertex2f((float)posX, (float)posY - zoomFactor);
rlEnd();
/*
// Previous implementation, it has issues... but it does not require view matrix...
#if defined(SUPPORT_QUADS_DRAW_MODE)
DrawRectangle(posX, posY, width, 1, color);
DrawRectangle(posX + width - 1, posY + 1, 1, height - 2, color);
DrawRectangle(posX, posY + height - 1, width, 1, color);
DrawRectangle(posX, posY + 1, 1, height - 2, color);
#else
rlBegin(RL_LINES); rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2f((float)posX, (float)posY); rlVertex2f((float)posX, (float)posY);
@ -827,6 +845,8 @@ void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
rlVertex2f((float)posX + 1, (float)posY + (float)height); rlVertex2f((float)posX + 1, (float)posY + (float)height);
rlVertex2f((float)posX + 1, (float)posY + 1); rlVertex2f((float)posX + 1, (float)posY + 1);
rlEnd(); rlEnd();
//#endif
*/
} }
// Draw rectangle outline with extended parameters // Draw rectangle outline with extended parameters
@ -834,8 +854,8 @@ void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color)
{ {
if ((lineThick > rec.width) || (lineThick > rec.height)) if ((lineThick > rec.width) || (lineThick > rec.height))
{ {
if (rec.width > rec.height) lineThick = rec.height/2; if (rec.width >= rec.height) lineThick = rec.height/2;
else if (rec.width < rec.height) lineThick = rec.width/2; else if (rec.width <= rec.height) lineThick = rec.width/2;
} }
// When rec = { x, y, 8.0f, 6.0f } and lineThick = 2, the following // When rec = { x, y, 8.0f, 6.0f } and lineThick = 2, the following
@ -1385,7 +1405,7 @@ void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
// Draw a triangle fan defined by points // Draw a triangle fan defined by points
// NOTE: First vertex provided is the center, shared by all triangles // NOTE: First vertex provided is the center, shared by all triangles
// By default, following vertex should be provided in counter-clockwise order // By default, following vertex should be provided in counter-clockwise order
void DrawTriangleFan(Vector2 *points, int pointCount, Color color) void DrawTriangleFan(const Vector2 *points, int pointCount, Color color)
{ {
if (pointCount >= 3) if (pointCount >= 3)
{ {
@ -1416,7 +1436,7 @@ void DrawTriangleFan(Vector2 *points, int pointCount, Color color)
// Draw a triangle strip defined by points // Draw a triangle strip defined by points
// NOTE: Every new vertex connects with previous two // NOTE: Every new vertex connects with previous two
void DrawTriangleStrip(Vector2 *points, int pointCount, Color color) void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color)
{ {
if (pointCount >= 3) if (pointCount >= 3)
{ {
@ -1570,7 +1590,7 @@ void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, fl
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw spline: linear, minimum 2 points // Draw spline: linear, minimum 2 points
void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color) void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color)
{ {
if (pointCount < 2) return; if (pointCount < 2) return;
@ -1656,7 +1676,7 @@ void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color)
prevNormal = normal; prevNormal = normal;
} }
#else // !SUPPORT_SPLINE_MITTERS #else // !SUPPORT_SPLINE_MITERS
Vector2 delta = { 0 }; Vector2 delta = { 0 };
float length = 0.0f; float length = 0.0f;
@ -1687,7 +1707,7 @@ void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color)
} }
// Draw spline: B-Spline, minimum 4 points // Draw spline: B-Spline, minimum 4 points
void DrawSplineBasis(Vector2 *points, int pointCount, float thick, Color color) void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color)
{ {
if (pointCount < 4) return; if (pointCount < 4) return;
@ -1759,11 +1779,12 @@ void DrawSplineBasis(Vector2 *points, int pointCount, float thick, Color color)
DrawTriangleStrip(vertices, 2*SPLINE_SEGMENT_DIVISIONS + 2, color); DrawTriangleStrip(vertices, 2*SPLINE_SEGMENT_DIVISIONS + 2, color);
} }
DrawCircleV(currentPoint, thick/2.0f, color); // Draw end line circle-cap // Cap circle drawing at the end of every segment
DrawCircleV(currentPoint, thick/2.0f, color);
} }
// Draw spline: Catmull-Rom, minimum 4 points // Draw spline: Catmull-Rom, minimum 4 points
void DrawSplineCatmullRom(Vector2 *points, int pointCount, float thick, Color color) void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color)
{ {
if (pointCount < 4) return; if (pointCount < 4) return;
@ -1825,28 +1846,31 @@ void DrawSplineCatmullRom(Vector2 *points, int pointCount, float thick, Color co
DrawTriangleStrip(vertices, 2*SPLINE_SEGMENT_DIVISIONS + 2, color); DrawTriangleStrip(vertices, 2*SPLINE_SEGMENT_DIVISIONS + 2, color);
} }
DrawCircleV(currentPoint, thick/2.0f, color); // Draw end line circle-cap // Cap circle drawing at the end of every segment
DrawCircleV(currentPoint, thick/2.0f, color);
} }
// Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...] // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]
void DrawSplineBezierQuadratic(Vector2 *points, int pointCount, float thick, Color color) void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color)
{ {
if (pointCount < 3) return; if (pointCount >= 3)
for (int i = 0; i < pointCount - 2; i++)
{ {
DrawSplineSegmentBezierQuadratic(points[i], points[i + 1], points[i + 2], thick, color); for (int i = 0; i < pointCount - 2; i += 2) DrawSplineSegmentBezierQuadratic(points[i], points[i + 1], points[i + 2], thick, color);
// Cap circle drawing at the end of every segment
//for (int i = 2; i < pointCount - 2; i += 2) DrawCircleV(points[i], thick/2.0f, color);
} }
} }
// Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...] // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]
void DrawSplineBezierCubic(Vector2 *points, int pointCount, float thick, Color color) void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color)
{ {
if (pointCount < 4) return; if (pointCount >= 4)
for (int i = 0; i < pointCount - 3; i++)
{ {
DrawSplineSegmentBezierCubic(points[i], points[i + 1], points[i + 2], points[i + 3], thick, color); for (int i = 0; i < pointCount - 3; i += 3) DrawSplineSegmentBezierCubic(points[i], points[i + 1], points[i + 2], points[i + 3], thick, color);
// Cap circle drawing at the end of every segment
//for (int i = 3; i < pointCount - 3; i += 3) DrawCircleV(points[i], thick/2.0f, color);
} }
} }
@ -2170,7 +2194,9 @@ bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius)
{ {
bool collision = false; bool collision = false;
collision = CheckCollisionCircles(point, 0, center, radius); float distanceSquared = (point.x - center.x)*(point.x - center.x) + (point.y - center.y)*(point.y - center.y);
if (distanceSquared <= radius*radius) collision = true;
return collision; return collision;
} }
@ -2195,7 +2221,7 @@ bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2
// Check if point is within a polygon described by array of vertices // Check if point is within a polygon described by array of vertices
// NOTE: Based on http://jeffreythompson.org/collision-detection/poly-point.php // NOTE: Based on http://jeffreythompson.org/collision-detection/poly-point.php
bool CheckCollisionPointPoly(Vector2 point, Vector2 *points, int pointCount) bool CheckCollisionPointPoly(Vector2 point, const Vector2 *points, int pointCount)
{ {
bool inside = false; bool inside = false;
@ -2233,9 +2259,10 @@ bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, floa
float dx = center2.x - center1.x; // X distance between centers float dx = center2.x - center1.x; // X distance between centers
float dy = center2.y - center1.y; // Y distance between centers float dy = center2.y - center1.y; // Y distance between centers
float distance = sqrtf(dx*dx + dy*dy); // Distance between centers float distanceSquared = dx*dx + dy*dy; // Distance between centers squared
float radiusSum = radius1 + radius2;
if (distance <= (radius1 + radius2)) collision = true; collision = (distanceSquared <= (radiusSum*radiusSum));
return collision; return collision;
} }
@ -2315,6 +2342,30 @@ bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshol
return collision; return collision;
} }
// Check if circle collides with a line created betweeen two points [p1] and [p2]
RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2)
{
float dx = p1.x - p2.x;
float dy = p1.y - p2.y;
if ((fabsf(dx) + fabsf(dy)) <= FLT_EPSILON)
{
return CheckCollisionCircles(p1, 0, center, radius);
}
float lengthSQ = ((dx*dx) + (dy*dy));
float dotProduct = (((center.x - p1.x)*(p2.x - p1.x)) + ((center.y - p1.y)*(p2.y - p1.y)))/(lengthSQ);
if (dotProduct > 1.0f) dotProduct = 1.0f;
else if (dotProduct < 0.0f) dotProduct = 0.0f;
float dx2 = (p1.x - (dotProduct*(dx))) - center.x;
float dy2 = (p1.y - (dotProduct*(dy))) - center.y;
float distanceSQ = ((dx2*dx2) + (dy2*dy2));
return (distanceSQ <= radius*radius);
}
// Get collision rectangle for two rectangles collision // Get collision rectangle for two rectangles collision
Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2) Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
{ {