From 5361d498c33deeb1e1ad44aed24a53a4f9e97618 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 2 Jul 2023 17:27:38 +0200 Subject: [PATCH] WARNING: REDESIGN: `Vector2Angle()`<-->`Vector2LineAngle()` #2887 --- examples/others/raymath_vector_angle.c | 106 +++++++++++++++++++++++ examples/others/raymath_vector_angle.png | Bin 0 -> 16339 bytes src/raymath.h | 27 +++--- 3 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 examples/others/raymath_vector_angle.c create mode 100644 examples/others/raymath_vector_angle.png diff --git a/examples/others/raymath_vector_angle.c b/examples/others/raymath_vector_angle.c new file mode 100644 index 000000000..86cd91a93 --- /dev/null +++ b/examples/others/raymath_vector_angle.c @@ -0,0 +1,106 @@ +/******************************************************************************************* +* +* raylib [shapes] example - Vector Angle +* +* Example originally created with raylib 1.0, last time updated with raylib 4.2 +* +* 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) 2023 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include "raymath.h" + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [math] example - vector angle"); + + Vector2 v0 = { screenWidth/2, screenHeight/2 }; + Vector2 v1 = { 100.0f, 80.0f }; + Vector2 v2 = { 0 }; // Updated with mouse position + + float angle = 0.0f; // Angle in degrees + int angleMode = 0; // 0-Vector2Angle(), 1-Vector2LineAngle() + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + if (IsKeyPressed(KEY_SPACE)) angleMode = !angleMode; + + if (angleMode == 0) + { + // Calculate angle between two vectors, considering a common origin (v0) + v1 = Vector2Add(v0, (Vector2){ 100.0f, 80.0f }); + v2 = GetMousePosition(); + angle = Vector2Angle(Vector2Normalize(Vector2Subtract(v1, v0)), Vector2Normalize(Vector2Subtract(v2, v0)))*RAD2DEG; + } + else if (angleMode == 1) + { + // Calculate angle defined by a two vectors line, in reference to horizontal line + v1 = (Vector2){ screenWidth/2, screenHeight/2 }; + v2 = GetMousePosition(); + angle = Vector2LineAngle(v1, v2)*RAD2DEG; + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (angleMode == 0) DrawText("v0", v0.x, v0.y, 10, DARKGRAY); + DrawText("v1", v1.x, v1.y, 10, DARKGRAY); + DrawText("v2", v2.x, v2.y, 10, DARKGRAY); + + if (angleMode == 0) + { + DrawText("MODE: Angle between V1 and V2", 10, 10, 20, BLACK); + + DrawLineEx(v0, v1, 2.0f, BLACK); + DrawLineEx(v0, v2, 2.0f, RED); + + // TODO: Properly draw circle sector + DrawCircleSector(v0, 40.0f, Vector2LineAngle(v0, v1)*RAD2DEG, angle, 32, Fade(GREEN, 0.6f)); + } + else if (angleMode == 1) + { + DrawText("MODE: Angle formed by line V1 to V2", 10, 10, 20, BLACK); + + DrawLine(0, screenHeight/2, screenWidth, screenHeight/2, LIGHTGRAY); + DrawLineEx(v1, v2, 2.0f, RED); + + DrawCircleSector(v1, 40.0f, 90.0f, 180 - angle - 90, 32, Fade(GREEN, 0.6f)); + } + + DrawText("Press SPACE to change MODE", 460, 10, 20, DARKGRAY); + DrawText(TextFormat("ANGLE: %2.2f", angle), 10, 40, 20, LIME); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/others/raymath_vector_angle.png b/examples/others/raymath_vector_angle.png new file mode 100644 index 0000000000000000000000000000000000000000..29995e002f283e5bd9a1960085dc25da31d5e9eb GIT binary patch literal 16339 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 N8#8hAQNQ5m{{X8kT3rAD literal 0 HcmV?d00001 diff --git a/src/raymath.h b/src/raymath.h index 47728ff69..6a929cf6e 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -314,8 +314,19 @@ RMAPI float Vector2DistanceSqr(Vector2 v1, Vector2 v2) // NOTE: Angle is calculated from origin point (0, 0) RMAPI float Vector2Angle(Vector2 v1, Vector2 v2) { - float result = atan2f(v2.y - v1.y, v2.x - v1.x); + float result = 0.0f; + + float dot = v1.x*v2.x + v1.y*v2.y; // Dot product + float dotClamp = (dot < -1.0f)? -1.0f : dot; // Clamp + if (dotClamp > 1.0f) dotClamp = 1.0f; + result = acosf(dotClamp); + + // Alternative implementation, more costly + //float v1Length = sqrtf((v1.x*v1.x) + (v1.y*v1.y)); + //float v2Length = sqrtf((v2.x*v2.x) + (v2.y*v2.y)); + //float result = -acosf((v1.x*v2.x + v1.y*v2.y)/(v1Length*v2Length)); + return result; } @@ -325,18 +336,8 @@ RMAPI float Vector2Angle(Vector2 v1, Vector2 v2) RMAPI float Vector2LineAngle(Vector2 start, Vector2 end) { float result = 0.0f; - - float dot = start.x*end.x + start.y*end.y; // Dot product - - float dotClamp = (dot < -1.0f)? -1.0f : dot; // Clamp - if (dotClamp > 1.0f) dotClamp = 1.0f; - - result = acosf(dotClamp); - - // Alternative implementation, more costly - //float v1Length = sqrtf((start.x*start.x) + (start.y*start.y)); - //float v2Length = sqrtf((end.x*end.x) + (end.y*end.y)); - //float result = -acosf((start.x*end.x + start.y*end.y)/(v1Length*v2Length)); + + result = atan2f(end.y - start.y, end.x - start.x); return result; }