From d053b9afa0a6f1d2c991f336db22397bb581742d Mon Sep 17 00:00:00 2001 From: RobinsAviary Date: Thu, 13 Nov 2025 17:45:15 -0500 Subject: [PATCH] [examples] Added: `shapes_rlgl_triangle` example --- examples/shapes/shapes_rlgl_triangle.c | 190 +++++++++++++++++++++++ examples/shapes/shapes_rlgl_triangle.png | Bin 0 -> 22402 bytes 2 files changed, 190 insertions(+) create mode 100644 examples/shapes/shapes_rlgl_triangle.c create mode 100644 examples/shapes/shapes_rlgl_triangle.png diff --git a/examples/shapes/shapes_rlgl_triangle.c b/examples/shapes/shapes_rlgl_triangle.c new file mode 100644 index 000000000..7cda0c97d --- /dev/null +++ b/examples/shapes/shapes_rlgl_triangle.c @@ -0,0 +1,190 @@ +/******************************************************************************************* +* +* raylib [shapes] example - rlgl beginner triangle +* +* Example complexity rating: [★★☆☆] 2/4 +* +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev +* +* Example contributed by Robin (@RobinsAviary) 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) 2025-2025 Robin (@RobinsAviary) +* +********************************************************************************************/ + +#include "raylib.h" +#include "rlgl.h" +#include "raymath.h" + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - rlgl beginner triangle"); + + // Starting postions and rendered triangle positions + Vector2 startingPositions[] = {{ 400.0f, 150.0f }, { 300.0f, 300.0f }, { 500.0f, 300.0f }}; + Vector2 trianglePositions[] = { startingPositions[0], startingPositions[1], startingPositions[2] }; + + // Currently selected vertex, -1 means none + int triangleIndex = -1; + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // Reset index on release + if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) + { + triangleIndex = -1; + } + + // If the user has selected a vertex, offset it by the mouse's delta this frame + if (triangleIndex != -1) + { + Vector2 *position = &trianglePositions[triangleIndex]; + + Vector2 mouseDelta = GetMouseDelta(); + position->x += mouseDelta.x; + position->y += mouseDelta.y; + } + + // Enable/disable backface culling (2-sided triangles, slower to render) + if (IsKeyPressed(KEY_LEFT)) + { + rlEnableBackfaceCulling(); + } + + if (IsKeyPressed(KEY_RIGHT)) + { + rlDisableBackfaceCulling(); + } + + // Reset triangle vertices to starting positions and reset backface culling + if (IsKeyPressed(KEY_R)) + { + trianglePositions[0] = startingPositions[0]; + trianglePositions[1] = startingPositions[1]; + trianglePositions[2] = startingPositions[2]; + + rlEnableBackfaceCulling(); + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (IsKeyDown(KEY_SPACE)) + { + // Draw triangle with lines + rlBegin(RL_LINES); + // Three lines, six points + + // Define color for next vertex + rlColor4ub(255, 0, 0, 255); + // Define vertex + rlVertex2f(trianglePositions[0].x, trianglePositions[0].y); + rlColor4ub(0, 255, 0, 255); + rlVertex2f(trianglePositions[1].x, trianglePositions[1].y); + + rlColor4ub(0, 255, 0, 255); + rlVertex2f(trianglePositions[1].x, trianglePositions[1].y); + rlColor4ub(0, 0, 255, 255); + rlVertex2f(trianglePositions[2].x, trianglePositions[2].y); + + rlColor4ub(0, 0, 255, 255); + rlVertex2f(trianglePositions[2].x, trianglePositions[2].y); + rlColor4ub(255, 0, 0, 255); + rlVertex2f(trianglePositions[0].x, trianglePositions[0].y); + rlEnd(); + } + else + { + // Draw triangle as a triangle + rlBegin(RL_TRIANGLES); + // One triangle, three points + // Define color for next vertex + rlColor4ub(255, 0, 0, 255); + // Define vertex + rlVertex2f(trianglePositions[0].x, trianglePositions[0].y); + rlColor4ub(0, 255, 0, 255); + rlVertex2f(trianglePositions[1].x, trianglePositions[1].y); + rlColor4ub(0, 0, 255, 255); + rlVertex2f(trianglePositions[2].x, trianglePositions[2].y); + rlEnd(); + } + + // Render the vertex handles, reacting to mouse movement/input + for (unsigned int i = 0; i < 3; i++) + { + Vector2 position = trianglePositions[i]; + + float size = 4.0f; + + Vector2 mousePosition = GetMousePosition(); + + // If the cursor is within the handle circle + if (Vector2Distance(mousePosition, position) < size) + { + float fillAlpha = 0.0f; + if (triangleIndex == -1) + { + fillAlpha = 0.5f; + } + + // If handle selected/clicked + if (i == triangleIndex) + { + fillAlpha = 1.0f; + } + + // If clicked, set selected index to handle index + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) + { + triangleIndex = i; + } + + // If visible, draw DARKGRAY circle with varying alpha. + if (fillAlpha > 0.0f) + { + Color fillColor = ColorAlpha(DARKGRAY, fillAlpha); + + DrawCircleV(position, size, fillColor); + } + } + + // Draw handle outline + DrawCircleLinesV(position, size, BLACK); + } + + // Draw controls + DrawText("space for lines\nleft for backface culling\nright for no backface culling\nclick and drag points\nr to reset", 10, 10, 20, DARKGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/shapes/shapes_rlgl_triangle.png b/examples/shapes/shapes_rlgl_triangle.png new file mode 100644 index 0000000000000000000000000000000000000000..9fec558ff1e337157e488886e18238018cf4907c GIT binary patch literal 22402 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 literal 0 HcmV?d00001