Add DrawSplineSegmentLinearVar

This commit is contained in:
Henry Wilder 2025-03-04 12:02:39 -05:00
parent 35e4300422
commit 6f89aa57ab
3 changed files with 109 additions and 6 deletions

View File

@ -35,6 +35,7 @@ typedef enum {
SPLINE_BASIS, // B-Spline SPLINE_BASIS, // B-Spline
SPLINE_CATMULLROM, // Catmull-Rom SPLINE_CATMULLROM, // Catmull-Rom
SPLINE_BEZIER, // Cubic Bezier SPLINE_BEZIER, // Cubic Bezier
SPLINE_LINEAR_VAR, // Linear, variable thickness
SPLINE_BEZIER_VAR // Cubic Bezier, variable thickness SPLINE_BEZIER_VAR // Cubic Bezier, variable thickness
} SplineType; } SplineType;
@ -79,7 +80,8 @@ int main(void)
// Spline config variables // Spline config variables
float splineThickness = 8.0f; float splineThickness = 8.0f;
int splineTypeActive = SPLINE_BEZIER_VAR; // 0-Linear, 1-BSpline, 2-CatmullRom, 3-Bezier, 4-BezierVar int splineTypeActive = SPLINE_LINEAR_VAR; // 0-Linear, 1-BSpline, 2-CatmullRom, 3-Bezier, 4-LinearVar, 5-BezierVar
// TODO: Change the default back to SPLINE_LINEAR when finished testing
bool splineTypeEditMode = false; bool splineTypeEditMode = false;
bool splineHelpersActive = true; bool splineHelpersActive = true;
@ -155,6 +157,7 @@ int main(void)
else if (IsKeyPressed(KEY_THREE)) splineTypeActive = 2; else if (IsKeyPressed(KEY_THREE)) splineTypeActive = 2;
else if (IsKeyPressed(KEY_FOUR)) splineTypeActive = 3; else if (IsKeyPressed(KEY_FOUR)) splineTypeActive = 3;
else if (IsKeyPressed(KEY_FIVE)) splineTypeActive = 4; else if (IsKeyPressed(KEY_FIVE)) splineTypeActive = 4;
else if (IsKeyPressed(KEY_SIX)) splineTypeActive = 5;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -218,6 +221,21 @@ int main(void)
} }
*/ */
} }
else if (splineTypeActive == SPLINE_LINEAR_VAR)
{
float thicks[] = {
0.0f,
splineThickness,
splineThickness,
0.0f,
};
// Draw spline: variable-width linear
for (int i = 0; i < pointCount - 1; ++i)
{
DrawSplineSegmentLinearVar(points[i], points[i+1], thicks, 4, RED);
}
}
else if (splineTypeActive == SPLINE_BEZIER_VAR) else if (splineTypeActive == SPLINE_BEZIER_VAR)
{ {
float thicks[] = { float thicks[] = {
@ -238,7 +256,7 @@ int main(void)
pointsInterleaved[3*(pointCount - 1)] = points[pointCount - 1]; pointsInterleaved[3*(pointCount - 1)] = points[pointCount - 1];
// Draw spline: cubic-bezier (with control points) // Draw spline: variable-width cubic-bezier (with control points)
for (int i = 0; i < pointCount - 1; ++i) for (int i = 0; i < pointCount - 1; ++i)
{ {
DrawSplineSegmentBezierCubicVar(points[i], control[i].start, control[i].end, points[i+1], thicks, 4, RED); DrawSplineSegmentBezierCubicVar(points[i], control[i].start, control[i].end, points[i+1], thicks, 4, RED);
@ -272,6 +290,7 @@ int main(void)
{ {
DrawCircleLinesV(points[i], (focusedPoint == i)? 12.0f : 8.0f, (focusedPoint == i)? BLUE: DARKBLUE); DrawCircleLinesV(points[i], (focusedPoint == i)? 12.0f : 8.0f, (focusedPoint == i)? BLUE: DARKBLUE);
if ((splineTypeActive != SPLINE_LINEAR) && if ((splineTypeActive != SPLINE_LINEAR) &&
(splineTypeActive != SPLINE_LINEAR_VAR) &&
(splineTypeActive != SPLINE_BEZIER) && (splineTypeActive != SPLINE_BEZIER) &&
(splineTypeActive != SPLINE_BEZIER_VAR) && (splineTypeActive != SPLINE_BEZIER_VAR) &&
(i < pointCount - 1)) DrawLineV(points[i], points[i + 1], GRAY); (i < pointCount - 1)) DrawLineV(points[i], points[i + 1], GRAY);
@ -292,7 +311,7 @@ int main(void)
GuiUnlock(); GuiUnlock();
GuiLabel((Rectangle){ 12, 10, 140, 24 }, "Spline type:"); GuiLabel((Rectangle){ 12, 10, 140, 24 }, "Spline type:");
if (GuiDropdownBox((Rectangle){ 12, 8 + 24, 140, 28 }, "LINEAR;BSPLINE;CATMULLROM;BEZIER;BEZIER VARIABLE", &splineTypeActive, splineTypeEditMode)) splineTypeEditMode = !splineTypeEditMode; if (GuiDropdownBox((Rectangle){ 12, 8 + 24, 140, 28 }, "LINEAR;BSPLINE;CATMULLROM;BEZIER;LINEAR VARIABLE;BEZIER VARIABLE", &splineTypeActive, splineTypeEditMode)) splineTypeEditMode = !splineTypeEditMode;
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -1298,6 +1298,7 @@ RLAPI void DrawSplineSegmentBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4
RLAPI void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: Catmull-Rom, 4 points RLAPI void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: Catmull-Rom, 4 points
RLAPI void DrawSplineSegmentBezierQuadratic(Vector2 p1, Vector2 c2, Vector2 p3, float thick, Color color); // Draw spline segment: Quadratic Bezier, 2 points, 1 control point RLAPI void DrawSplineSegmentBezierQuadratic(Vector2 p1, Vector2 c2, Vector2 p3, float thick, Color color); // Draw spline segment: Quadratic Bezier, 2 points, 1 control point
RLAPI void DrawSplineSegmentBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float thick, Color color); // Draw spline segment: Cubic Bezier, 2 points, 2 control points RLAPI void DrawSplineSegmentBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float thick, Color color); // Draw spline segment: Cubic Bezier, 2 points, 2 control points
RLAPI void DrawSplineSegmentLinearVar(Vector2 p1, Vector2 p2, const float* thicks, int thickCount, Color color); // Draw spline segment with variable thickness: Linear Bezier, 2 points
RLAPI void DrawSplineSegmentBezierCubicVar(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, const float* thicks, int thickCount, Color color); // Draw spline segment with variable thickness: Cubic Bezier, 2 points, 2 control points RLAPI void DrawSplineSegmentBezierCubicVar(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, const float* thicks, int thickCount, Color color); // Draw spline segment with variable thickness: Cubic Bezier, 2 points, 2 control points
// Spline segment point evaluation functions, for a given t [0.0f .. 1.0f] // Spline segment point evaluation functions, for a given t [0.0f .. 1.0f]

View File

@ -2107,6 +2107,89 @@ void DrawSplineSegmentBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4
DrawTriangleStrip(points, 2*SPLINE_SEGMENT_DIVISIONS + 2, color); DrawTriangleStrip(points, 2*SPLINE_SEGMENT_DIVISIONS + 2, color);
} }
// Draw spline segment with variable thickness: Linear, 2 points
void DrawSplineSegmentLinearVar(Vector2 p1, Vector2 p2, const float* thicks, int thickCount, Color color)
{
if (thickCount >= 4)
{
const float step = 1.0f/SPLINE_SEGMENT_DIVISIONS;
Vector2 previous[2] = { 0 };
Vector2 current[2] = { 0 };
float t = 0.0f;
// Linear velocity does not change across the curve
Vector2 tangent = { 0 };
tangent.x = p2.x - p1.x;
tangent.y = p2.y - p1.y;
float speedSqr = tangent.x*tangent.x + tangent.y*tangent.y;
if (speedSqr > 0)
{
float speedInv = 1.0f/sqrtf(speedSqr);
tangent.x *= speedInv;
tangent.y *= speedInv;
rlBegin(RL_TRIANGLES);
rlColor4ub(color.r, color.g, color.b, color.a);
for (int i = 0; i <= SPLINE_SEGMENT_DIVISIONS; i++)
{
t = step*(float)i;
Vector2 point = { 0 };
point.x = p1.x*(1.0f - t) + p2.x*t;
point.y = p1.y*(1.0f - t) + p2.y*t;
// TODO: Doesn't seem to be working properly for more than 3 distinct values
float thick;
{
float tMajor = t*(float)thickCount;
int tIndex = (int)tMajor;
float tMinor = tMajor - (float)tIndex;
tIndex *= 3;
if (tIndex >= thickCount - 3)
{
tIndex = thickCount - 4;
tMinor = 1.0f;
}
float a = powf(1.0f - t, 3);
float b = 3.0f*powf(1.0f - t, 2)*t;
float c = 3.0f*(1.0f - t)*t*t;
float d = t*t*t;
thick = a*thicks[tIndex] + b*thicks[tIndex + 1] + c*thicks[tIndex + 2] + d*thicks[tIndex + 3];
}
current[0].x = point.x + thick*tangent.y;
current[0].y = point.y - thick*tangent.x;
current[1].x = point.x - thick*tangent.y;
current[1].y = point.y + thick*tangent.x;
if (i > 0)
{
rlVertex2f(current[0].x, current[0].y);
rlVertex2f(previous[0].x, previous[0].y);
rlVertex2f(previous[1].x, previous[1].y);
rlVertex2f(current[1].x, current[1].y);
rlVertex2f(current[0].x, current[0].y);
rlVertex2f(previous[1].x, previous[1].y);
}
previous[0] = current[0];
previous[1] = current[1];
}
rlEnd();
}
}
}
// Draw spline segment with variable thickness: Cubic Bezier, 2 points, 2 control points // Draw spline segment with variable thickness: Cubic Bezier, 2 points, 2 control points
void DrawSplineSegmentBezierCubicVar(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, const float* thicks, int thickCount, Color color) void DrawSplineSegmentBezierCubicVar(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, const float* thicks, int thickCount, Color color)
{ {
@ -2138,8 +2221,8 @@ void DrawSplineSegmentBezierCubicVar(Vector2 p1, Vector2 c2, Vector2 c3, Vector2
float speedSqr = (tangent.x*tangent.x + tangent.y*tangent.y); float speedSqr = (tangent.x*tangent.x + tangent.y*tangent.y);
if (speedSqr == 0) continue; if (speedSqr == 0) continue;
float speedInv = 1.0f/sqrtf(speedSqr); float speedInv = 1.0f/sqrtf(speedSqr);
tangent.x = tangent.x*speedInv; tangent.x *= speedInv;
tangent.y = tangent.y*speedInv; tangent.y *= speedInv;
Vector2 point = { 0 }; Vector2 point = { 0 };
{ {
@ -2178,7 +2261,7 @@ void DrawSplineSegmentBezierCubicVar(Vector2 p1, Vector2 c2, Vector2 c3, Vector2
current[1].x = point.x - thick*tangent.y; current[1].x = point.x - thick*tangent.y;
current[1].y = point.y + thick*tangent.x; current[1].y = point.y + thick*tangent.x;
if (i > 0) if (i > 0) // TODO: `previous` may be unassigned in i=1 if i=0 had a `speedSqr` of 0
{ {
rlVertex2f(current[0].x, current[0].y); rlVertex2f(current[0].x, current[0].y);
rlVertex2f(previous[0].x, previous[0].y); rlVertex2f(previous[0].x, previous[0].y);