diff options
| author | Jeffery Myers <[email protected]> | 2022-12-03 13:55:05 -0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-12-03 22:55:05 +0100 |
| commit | 57dd345dc3ac95332d656a06ac110237699e3726 (patch) | |
| tree | 912e293b8c5e44ab24b572a68f96ace8a55138d1 /examples/textures | |
| parent | 5b5dff3f9e33ee53b18c92e94cc98c13d19c29c5 (diff) | |
| download | raylib-57dd345dc3ac95332d656a06ac110237699e3726.tar.gz raylib-57dd345dc3ac95332d656a06ac110237699e3726.zip | |
Add a textured curve example (#2821)
Diffstat (limited to 'examples/textures')
| -rw-r--r-- | examples/textures/resources/roadTexture_01.png | bin | 0 -> 1006 bytes | |||
| -rw-r--r-- | examples/textures/textures_textured_curve.c | 241 | ||||
| -rw-r--r-- | examples/textures/textures_textured_curve.png | bin | 0 -> 21036 bytes |
3 files changed, 241 insertions, 0 deletions
diff --git a/examples/textures/resources/roadTexture_01.png b/examples/textures/resources/roadTexture_01.png Binary files differnew file mode 100644 index 00000000..082f4cd2 --- /dev/null +++ b/examples/textures/resources/roadTexture_01.png diff --git a/examples/textures/textures_textured_curve.c b/examples/textures/textures_textured_curve.c new file mode 100644 index 00000000..1407f738 --- /dev/null +++ b/examples/textures/textures_textured_curve.c @@ -0,0 +1,241 @@ +/******************************************************************************************* +* +* raylib [textures] example - Draw a texture along a segmented curve +* +* Example originally created with raylib 4.5 +* +* Example contributed by Jeffery Myers and reviewed by Ramon Santamaria (@raysan5) +* +* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software +* +* Copyright (c) 2019-2022 Jeffery Myers and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + + +#include "raylib.h" +#include "raymath.h" +#include "rlgl.h" + +Texture RoadTexture = { 0 }; + +bool ShowCurve = false; + +float Width = 50; +int Segments = 24; + +Vector2 SP = { 0 }; +Vector2 SPTangent = { 0 }; + +Vector2 EP = { 0 }; +Vector2 EPTangent = { 0 }; + +Vector2* Selected = NULL; + +void DrawCurve() +{ + if (ShowCurve) + DrawLineBezierCubic(SP, EP, SPTangent, EPTangent, 2, BLUE); + + // draw the various control points and highlight where the mouse is + DrawLineV(SP, SPTangent, SKYBLUE); + DrawLineV(EP, EPTangent, PURPLE); + Vector2 mouse = GetMousePosition(); + + if (CheckCollisionPointCircle(mouse, SP, 6)) + DrawCircleV(SP, 7, YELLOW); + DrawCircleV(SP, 5, RED); + + if (CheckCollisionPointCircle(mouse, SPTangent, 6)) + DrawCircleV(SPTangent, 7, YELLOW); + DrawCircleV(SPTangent, 5, MAROON); + + if (CheckCollisionPointCircle(mouse, EP, 6)) + DrawCircleV(EP, 7, YELLOW); + DrawCircleV(EP, 5, GREEN); + + if (CheckCollisionPointCircle(mouse, EPTangent, 6)) + DrawCircleV(EPTangent, 7, YELLOW); + DrawCircleV(EPTangent, 5, DARKGREEN); +} + +void EditCurve() +{ + // if the mouse is not down, we are not editing the curve so clear the selection + if (!IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + Selected = NULL; + return; + } + + // if a point was selected, move it + if (Selected) + { + *Selected = Vector2Add(*Selected, GetMouseDelta()); + return; + } + + // the mouse is down, and nothing was selected, so see if anything was picked + Vector2 mouse = GetMousePosition(); + + if (CheckCollisionPointCircle(mouse, SP, 6)) + Selected = &SP; + else if (CheckCollisionPointCircle(mouse, SPTangent, 6)) + Selected = &SPTangent; + else if (CheckCollisionPointCircle(mouse, EP, 6)) + Selected = &EP; + else if (CheckCollisionPointCircle(mouse, EPTangent, 6)) + Selected = &EPTangent; +} + +void DrawTexturedCurve() +{ + const float step = 1.0f / Segments; + + Vector2 previous = SP; + Vector2 previousTangent = { 0 }; + float previousV = 0; + + // we can't compute a tangent for the first point, so we need to reuse the tangent from the first segment + bool tangentSet = false; + + Vector2 current = { 0 }; + float t = 0.0f; + + for (int i = 1; i <= Segments; i++) + { + // segment the curve + t = step * i; + float a = powf(1 - t, 3); + float b = 3 * powf(1 - t, 2) * t; + float c = 3 * (1 - t) * powf(t, 2); + float d = powf(t, 3); + + // compute the endpoint for this segment + current.y = a * SP.y + b * SPTangent.y + c * EPTangent.y + d * EP.y; + current.x = a * SP.x + b * SPTangent.x + c * EPTangent.x + d * EP.x; + + // vector from previous to current + Vector2 delta = { current.x - previous.x, current.y - previous.y }; + + // the right hand normal to the delta vector + Vector2 normal = Vector2Normalize((Vector2){ -delta.y, delta.x }); + + // the v texture coordinate of the segment (add up the length of all the segments so far) + float v = previousV + Vector2Length(delta); + + // make sure the start point has a normal + if (!tangentSet) + { + previousTangent = normal; + tangentSet = true; + } + + // extend out the normals from the previous and current points to get the quad for this segment + Vector2 prevPosNormal = Vector2Add(previous, Vector2Scale(previousTangent, Width)); + Vector2 prevNegNormal = Vector2Add(previous, Vector2Scale(previousTangent, -Width)); + + Vector2 currentPosNormal = Vector2Add(current, Vector2Scale(normal, Width)); + Vector2 currentNegNormal = Vector2Add(current, Vector2Scale(normal, -Width)); + + // draw the segment as a quad + rlSetTexture(RoadTexture.id); + rlBegin(RL_QUADS); + + rlColor4ub(255,255,255,255); + rlNormal3f(0.0f, 0.0f, 1.0f); + + rlTexCoord2f(0, previousV); + rlVertex2f(prevNegNormal.x, prevNegNormal.y); + + rlTexCoord2f(1, previousV); + rlVertex2f(prevPosNormal.x, prevPosNormal.y); + + rlTexCoord2f(1, v); + rlVertex2f(currentPosNormal.x, currentPosNormal.y); + + rlTexCoord2f(0, v); + rlVertex2f(currentNegNormal.x, currentNegNormal.y); + + rlEnd(); + + // the current step is the start of the next step + previous = current; + previousTangent = normal; + previousV = v; + } +} + +void UpdateOptions() +{ + if (IsKeyPressed(KEY_SPACE)) + ShowCurve = !ShowCurve; + + // width + if (IsKeyPressed(KEY_EQUAL)) + Width += 2; + + if (IsKeyPressed(KEY_MINUS)) + Width -= 2; + + if (Width < 2) + Width = 2; + + // segments + + if (IsKeyPressed(KEY_LEFT_BRACKET)) + Segments -= 2; + + if (IsKeyPressed(KEY_RIGHT_BRACKET)) + Segments += 2; + + if (Segments < 2) + Segments = 2; +} + +int main () +{ + // set up the window + SetConfigFlags(FLAG_VSYNC_HINT); + InitWindow(1280, 800, "raylib [textures] examples - textured curve"); + SetTargetFPS(144); + + // load the road texture + RoadTexture = LoadTexture("resources/roadTexture_01.png"); + + // setup the curve + SP = (Vector2){ 80, 400 }; + SPTangent = (Vector2){ 600, 100 }; + + EP = (Vector2){ 1200, 400 }; + EPTangent = (Vector2){ 600, 700 }; + + // game loop + while (!WindowShouldClose()) + { + EditCurve(); + UpdateOptions(); + + BeginDrawing(); + + ClearBackground(BLACK); + + DrawTexturedCurve(); + DrawCurve(); + + DrawText("Drag points to move curve, press space to show/hide base curve", 10, 0, 20, WHITE); + DrawText(TextFormat("Width %2.0f + and - to adjust", Width), 10, 20, 20, WHITE); + DrawText(TextFormat("Segments %d [ and ] to adjust", Segments), 10, 40, 20, WHITE); + DrawFPS(10, 60); + + EndDrawing(); + } + + // cleanup + UnloadTexture(RoadTexture); + CloseWindow(); + return 0; +} + +
\ No newline at end of file diff --git a/examples/textures/textures_textured_curve.png b/examples/textures/textures_textured_curve.png Binary files differnew file mode 100644 index 00000000..1f45e8d2 --- /dev/null +++ b/examples/textures/textures_textured_curve.png |
