Ensure DrawSplineSegmentBezierCubicVar renders somewhat correctly
This commit is contained in:
parent
6120df6a87
commit
efa7ef12e6
13
CHANGELOG
13
CHANGELOG
|
|
@ -179,6 +179,19 @@ WIP: Last update with commit from 02-Nov-2024
|
||||||
[rshapes] REVIEWED: `CheckCollisionCircleRec()` (#3584) by @ubkp
|
[rshapes] REVIEWED: `CheckCollisionCircleRec()` (#3584) by @ubkp
|
||||||
[rshapes] REVIEWED: Add more detail to function comment (#4344) by @Jeffery Myers
|
[rshapes] REVIEWED: Add more detail to function comment (#4344) by @Jeffery Myers
|
||||||
[rshapes] REVIEWED: Functions that draw point arrays take them as const (#4051) by @Jeffery Myers
|
[rshapes] REVIEWED: Functions that draw point arrays take them as const (#4051) by @Jeffery Myers
|
||||||
|
[rshapes] ADDED: `DrawSplineSegmentBezierCubicVar()` (#TBD) by @AmityWilder
|
||||||
|
[rshapes] ADDED: `GetSplineVelocityLinear()` (#TBD) by @AmityWilder
|
||||||
|
[rshapes] ADDED: `GetSplineVelocityBezierQuad()` (#TBD) by @AmityWilder
|
||||||
|
[rshapes] ADDED: `GetSplineVelocityBezierCubic()` (#TBD) by @AmityWilder
|
||||||
|
[rshapes] ADDED: `GetSplineAccelerationBezierQuad()` (#TBD) by @AmityWilder
|
||||||
|
[rshapes] ADDED: `GetSplineAccelerationBezierCubic()` (#TBD) by @AmityWilder
|
||||||
|
[rshapes] ADDED: `GetSplineJoltBezierCubic()` (#TBD) by @AmityWilder
|
||||||
|
[rshapes] ADDED: `GetSplineBoundsBezierLinear()` (#TBD) by @AmityWilder
|
||||||
|
[rshapes] ADDED: `GetSplineBoundsBezierQuad()` (#TBD) by @AmityWilder
|
||||||
|
[rshapes] ADDED: `GetSplineBoundsBezierCubic()` (#TBD) by @AmityWilder
|
||||||
|
[rshapes] ADDED: `GetSplineCurvatureBezierCubic()` (#TBD) by @AmityWilder
|
||||||
|
[rshapes] ADDED: `GetSplineNearestTLinear()` (#TBD) by @AmityWilder
|
||||||
|
[rshapes] ADDED: Example of `DrawSplineSegmentBezierCubicVar` in splines drawing example (#TBD) by @AmityWilder
|
||||||
[rtextures] ADDED: `ColorIsEqual()` by @Ray
|
[rtextures] ADDED: `ColorIsEqual()` by @Ray
|
||||||
[rtextures] ADDED: `ColorLerp()`, to mix 2 colors together (#4310) by @SusgUY446
|
[rtextures] ADDED: `ColorLerp()`, to mix 2 colors together (#4310) by @SusgUY446
|
||||||
[rtextures] ADDED: `LoadImageAnimFromMemory()` (#3681) by @IoIxD
|
[rtextures] ADDED: `LoadImageAnimFromMemory()` (#3681) by @IoIxD
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,8 @@ typedef enum {
|
||||||
SPLINE_LINEAR = 0, // Linear
|
SPLINE_LINEAR = 0, // Linear
|
||||||
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_BEZIER_VAR // Cubic Bezier, variable thickness
|
||||||
} SplineType;
|
} SplineType;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
@ -78,7 +79,7 @@ int main(void)
|
||||||
|
|
||||||
// Spline config variables
|
// Spline config variables
|
||||||
float splineThickness = 8.0f;
|
float splineThickness = 8.0f;
|
||||||
int splineTypeActive = SPLINE_LINEAR; // 0-Linear, 1-BSpline, 2-CatmullRom, 3-Bezier
|
int splineTypeActive = SPLINE_BEZIER_VAR; // 0-Linear, 1-BSpline, 2-CatmullRom, 3-Bezier, 4-BezierVar
|
||||||
bool splineTypeEditMode = false;
|
bool splineTypeEditMode = false;
|
||||||
bool splineHelpersActive = true;
|
bool splineHelpersActive = true;
|
||||||
|
|
||||||
|
|
@ -120,7 +121,7 @@ int main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cubic Bezier spline control points logic
|
// Cubic Bezier spline control points logic
|
||||||
if ((splineTypeActive == SPLINE_BEZIER) && (focusedPoint == -1))
|
if (((splineTypeActive == SPLINE_BEZIER) || (splineTypeActive == SPLINE_BEZIER_VAR)) && (focusedPoint == -1))
|
||||||
{
|
{
|
||||||
// Spline control point focus and selection logic
|
// Spline control point focus and selection logic
|
||||||
for (int i = 0; i < pointCount - 1; i++)
|
for (int i = 0; i < pointCount - 1; i++)
|
||||||
|
|
@ -153,6 +154,7 @@ int main(void)
|
||||||
else if (IsKeyPressed(KEY_TWO)) splineTypeActive = 1;
|
else if (IsKeyPressed(KEY_TWO)) splineTypeActive = 1;
|
||||||
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;
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
|
|
@ -215,7 +217,36 @@ int main(void)
|
||||||
DrawSplineSegmentBezierCubic(pointsInterleaved[i], pointsInterleaved[i + 1], pointsInterleaved[i + 2], pointsInterleaved[i + 3], splineThickness, MAROON);
|
DrawSplineSegmentBezierCubic(pointsInterleaved[i], pointsInterleaved[i + 1], pointsInterleaved[i + 2], pointsInterleaved[i + 3], splineThickness, MAROON);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
}
|
||||||
|
else if (splineTypeActive == SPLINE_BEZIER_VAR)
|
||||||
|
{
|
||||||
|
float thicks[] = {
|
||||||
|
0.0f,
|
||||||
|
splineThickness,
|
||||||
|
splineThickness,
|
||||||
|
0.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
// NOTE: Cubic-bezier spline requires the 2 control points of each segnment to be
|
||||||
|
// provided interleaved with the start and end point of every segment
|
||||||
|
for (int i = 0; i < (pointCount - 1); i++)
|
||||||
|
{
|
||||||
|
pointsInterleaved[3*i] = points[i];
|
||||||
|
pointsInterleaved[3*i + 1] = control[i].start;
|
||||||
|
pointsInterleaved[3*i + 2] = control[i].end;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointsInterleaved[3*(pointCount - 1)] = points[pointCount - 1];
|
||||||
|
|
||||||
|
// Draw spline: cubic-bezier (with control points)
|
||||||
|
for (int i = 0; i < pointCount - 1; ++i)
|
||||||
|
{
|
||||||
|
DrawSplineSegmentBezierCubicVar(points[i], control[i].start, control[i].end, points[i+1], thicks, 4, RED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((splineTypeActive == SPLINE_BEZIER) || (splineTypeActive == SPLINE_BEZIER_VAR))
|
||||||
|
{
|
||||||
// Draw spline control points
|
// Draw spline control points
|
||||||
for (int i = 0; i < pointCount - 1; i++)
|
for (int i = 0; i < pointCount - 1; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -242,6 +273,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_BEZIER) &&
|
(splineTypeActive != SPLINE_BEZIER) &&
|
||||||
|
(splineTypeActive != SPLINE_BEZIER_VAR) &&
|
||||||
(i < pointCount - 1)) DrawLineV(points[i], points[i + 1], GRAY);
|
(i < pointCount - 1)) DrawLineV(points[i], points[i + 1], GRAY);
|
||||||
|
|
||||||
DrawText(TextFormat("[%.0f, %.0f]", points[i].x, points[i].y), (int)points[i].x, (int)points[i].y + 10, 10, BLACK);
|
DrawText(TextFormat("[%.0f, %.0f]", points[i].x, points[i].y), (int)points[i].x, (int)points[i].y + 10, 10, BLACK);
|
||||||
|
|
@ -260,7 +292,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", &splineTypeActive, splineTypeEditMode)) splineTypeEditMode = !splineTypeEditMode;
|
if (GuiDropdownBox((Rectangle){ 12, 8 + 24, 140, 28 }, "LINEAR;BSPLINE;CATMULLROM;BEZIER;BEZIER VARIABLE", &splineTypeActive, splineTypeEditMode)) splineTypeEditMode = !splineTypeEditMode;
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -1298,7 +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 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, 1 or more thickness
|
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]
|
||||||
RLAPI Vector2 GetSplinePointLinear(Vector2 startPos, Vector2 endPos, float t); // Get (evaluate) spline point: Linear
|
RLAPI Vector2 GetSplinePointLinear(Vector2 startPos, Vector2 endPos, float t); // Get (evaluate) spline point: Linear
|
||||||
|
|
|
||||||
|
|
@ -2107,63 +2107,93 @@ 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: Cubic Bezier, 2 points, 2 control points, 1 or more thickness
|
// 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)
|
||||||
{
|
{
|
||||||
if (thickCount >= 1)
|
if (thickCount >= 4)
|
||||||
{
|
{
|
||||||
|
rlBegin(RL_TRIANGLES);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
const float step = 1.0f/SPLINE_SEGMENT_DIVISIONS;
|
const float step = 1.0f/SPLINE_SEGMENT_DIVISIONS;
|
||||||
|
|
||||||
Vector2 previous = p1;
|
Vector2 previous[2] = { 0 };
|
||||||
Vector2 current = { 0 };
|
Vector2 current[2] = { 0 };
|
||||||
float t = 0.0f;
|
float t = 0.0f;
|
||||||
|
|
||||||
Vector2 points[2*SPLINE_SEGMENT_DIVISIONS + 2] = { 0 };
|
for (int i = 0; i <= SPLINE_SEGMENT_DIVISIONS; i++)
|
||||||
|
|
||||||
for (int i = 1; i <= SPLINE_SEGMENT_DIVISIONS; i++)
|
|
||||||
{
|
{
|
||||||
t = step*(float)i;
|
t = step*(float)i;
|
||||||
|
|
||||||
float thick;
|
Vector2 tangent = { 0 };
|
||||||
if (thickCount > 1) {
|
{
|
||||||
float tMajor = t*(float)thickCount;
|
float a = 3.0f*powf(1.0f - t, 2);
|
||||||
int tIndex = (int)tMajor;
|
float b = 6.0f*(1.0f - t)*t;
|
||||||
if (tIndex >= thickCount) tIndex = thickCount - 1;
|
float c = 3.0f*t*t;
|
||||||
float tMinor = tMajor - (float)tIndex;
|
|
||||||
thick = thicks[tIndex];
|
tangent.x = a*(c2.x - p1.x) + b*(c3.x - c2.x) + c*(p4.x - c3.x);
|
||||||
} else {
|
tangent.y = a*(c2.y - p1.y) + b*(c3.y - c2.y) + c*(p4.y - c3.y);
|
||||||
thick = thicks[0]; // constant thickness
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float speedSqr = (tangent.x*tangent.x + tangent.y*tangent.y);
|
||||||
|
if (speedSqr == 0) continue;
|
||||||
|
float speedInv = 1.0f/sqrtf(speedSqr);
|
||||||
|
tangent.x = tangent.x*speedInv;
|
||||||
|
tangent.y = tangent.y*speedInv;
|
||||||
|
|
||||||
|
Vector2 point = { 0 };
|
||||||
|
{
|
||||||
float a = powf(1.0f - t, 3);
|
float a = powf(1.0f - t, 3);
|
||||||
float b = 3.0f*powf(1.0f - t, 2)*t;
|
float b = 3.0f*powf(1.0f - t, 2)*t;
|
||||||
float c = 3.0f*(1.0f - t)*powf(t, 2);
|
float c = 3.0f*(1.0f - t)*powf(t, 2);
|
||||||
float d = powf(t, 3);
|
float d = powf(t, 3);
|
||||||
|
|
||||||
current.y = a*p1.y + b*c2.y + c*c3.y + d*p4.y;
|
point.y = a*p1.y + b*c2.y + c*c3.y + d*p4.y;
|
||||||
current.x = a*p1.x + b*c2.x + c*c3.x + d*p4.x;
|
point.x = a*p1.x + b*c2.x + c*c3.x + d*p4.x;
|
||||||
|
}
|
||||||
|
|
||||||
float dy = current.y - previous.y;
|
// TODO: Doesn't seem to be working properly for more than 3 distinct values
|
||||||
float dx = current.x - previous.x;
|
float thick;
|
||||||
float size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
|
|
||||||
|
|
||||||
if (i == 1)
|
|
||||||
{
|
{
|
||||||
points[0].x = previous.x + dy*size;
|
float tMajor = t*(float)thickCount;
|
||||||
points[0].y = previous.y - dx*size;
|
int tIndex = (int)tMajor;
|
||||||
points[1].x = previous.x - dy*size;
|
float tMinor = tMajor - (float)tIndex;
|
||||||
points[1].y = previous.y + dx*size;
|
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];
|
||||||
}
|
}
|
||||||
|
|
||||||
points[2*i + 1].x = current.x - dy*size;
|
current[0].x = point.x + thick*tangent.y;
|
||||||
points[2*i + 1].y = current.y + dx*size;
|
current[0].y = point.y - thick*tangent.x;
|
||||||
points[2*i].x = current.x + dy*size;
|
|
||||||
points[2*i].y = current.y - dx*size;
|
|
||||||
|
|
||||||
previous = current;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawTriangleStrip(points, 2*SPLINE_SEGMENT_DIVISIONS + 2, color);
|
previous[0] = current[0];
|
||||||
|
previous[1] = current[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
rlEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2576,7 +2606,7 @@ float GetSplineCurvatureBezierCubic(Vector2 startPos, Vector2 startControlPos, V
|
||||||
acceleration.x = a*(endControlPos.x - 2.0f*startControlPos.x + startPos.x) + b*(endPos.x - 2.0f*endControlPos.x + startControlPos.x);
|
acceleration.x = a*(endControlPos.x - 2.0f*startControlPos.x + startPos.x) + b*(endPos.x - 2.0f*endControlPos.x + startControlPos.x);
|
||||||
acceleration.y = a*(endControlPos.y - 2.0f*startControlPos.y + startPos.y) + b*(endPos.y - 2.0f*endControlPos.y + startControlPos.y);
|
acceleration.y = a*(endControlPos.y - 2.0f*startControlPos.y + startPos.y) + b*(endPos.y - 2.0f*endControlPos.y + startControlPos.y);
|
||||||
|
|
||||||
float curvature = (velocity.x*acceleration.y - velocity.y*acceleration.x)/powf(sqrtf(velocity.x*velocity.x + velocity.y*velocity.y), 3);
|
curvature = (velocity.x*acceleration.y - velocity.y*acceleration.x)/powf(sqrtf(velocity.x*velocity.x + velocity.y*velocity.y), 3);
|
||||||
|
|
||||||
return curvature;
|
return curvature;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user