| 
				
				
					
						
					
				
				
				 | 
			
			 | 
			
			@ -2,145 +2,219 @@ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			* | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			*   raylib [textures] example - Draw a texture along a segmented curve | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			* | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			*   Example originally created with raylib 4.5 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			*   Example originally created with raylib 4.5-dev | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			* | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			*   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) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			*   Copyright (c) 2022 Jeffery Myers and Ramon Santamaria (@raysan5) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			* | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			********************************************************************************************/ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#include "raylib.h" | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#include "raymath.h" | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#include "rlgl.h" | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			Texture RoadTexture = { 0 }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#include <math.h>           // Required for: powf() | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			#include <stdlib.h>         // Required for: NULL | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			//---------------------------------------------------------------------------------- | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			// Global Variables Definition | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			//---------------------------------------------------------------------------------- | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static Texture texRoad = { 0 }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static bool showCurve = false; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static float curveWidth = 50; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static int curveSegments = 24; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static Vector2 curveStartPosition = { 0 }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static Vector2 curveStartPositionTangent = { 0 }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static Vector2 curveEndPosition = { 0 }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static Vector2 curveEndPositionTangent = { 0 }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static Vector2 *curveSelectedPoint = NULL; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			//---------------------------------------------------------------------------------- | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			// Module Functions Declaration | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			//---------------------------------------------------------------------------------- | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static void UpdateOptions(void); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static void UpdateCurve(void); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static void DrawCurve(void); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static void DrawTexturedCurve(void); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			bool ShowCurve = false; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			//------------------------------------------------------------------------------------ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			// Program main entry point | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			//------------------------------------------------------------------------------------ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			int main() | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			{ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    // Initialization | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    //-------------------------------------------------------------------------------------- | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    const int screenWidth = 800; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    const int screenHeight = 450; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				SetConfigFlags(FLAG_VSYNC_HINT | FLAG_MSAA_4X_HINT); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				InitWindow(screenWidth, screenHeight, "raylib [textures] examples - textured curve"); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// Load the road texture | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				texRoad = LoadTexture("resources/road.png"); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    SetTextureFilter(texRoad, TEXTURE_FILTER_BILINEAR); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// Setup the curve | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				curveStartPosition = (Vector2){ 80, 100 }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				curveStartPositionTangent = (Vector2){ 100, 300 }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				curveEndPosition = (Vector2){ 700, 350 }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				curveEndPositionTangent = (Vector2){ 600, 100 }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    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 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			        //---------------------------------------------------------------------------------- | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					UpdateCurve(); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					UpdateOptions(); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			float Width = 50; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			int Segments = 24; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			        //---------------------------------------------------------------------------------- | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			Vector2 SP = { 0 }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			Vector2 SPTangent = { 0 }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			        // Draw | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			        //---------------------------------------------------------------------------------- | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			        BeginDrawing(); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			Vector2 EP = { 0 }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			Vector2 EPTangent = { 0 }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			            ClearBackground(RAYWHITE); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			Vector2* Selected = NULL; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			            DrawTexturedCurve(); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			            DrawCurve(); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			         | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			            DrawText("Drag points to move curve, press SPACE to show/hide base curve", 10, 10, 10, DARKGRAY); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			            DrawText(TextFormat("Curve width: %2.0f (Use + and - to adjust)", curveWidth), 10, 30, 10, DARKGRAY); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			            DrawText(TextFormat("Curve segments: %d (Use LEFT and RIGHT to adjust)", curveSegments), 10, 50, 10, DARKGRAY); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			             | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					EndDrawing(); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			        //---------------------------------------------------------------------------------- | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    } | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			void DrawCurve() | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    // De-Initialization | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    //-------------------------------------------------------------------------------------- | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				UnloadTexture(texRoad); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			     | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    CloseWindow();              // Close window and OpenGL context | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    //-------------------------------------------------------------------------------------- | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    return 0; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			//---------------------------------------------------------------------------------- | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			// Module Functions Definition | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			//---------------------------------------------------------------------------------- | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static void DrawCurve(void) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			{ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (ShowCurve) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					DrawLineBezierCubic(SP, EP, SPTangent, EPTangent, 2, BLUE); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (showCurve) DrawLineBezierCubic(curveStartPosition, curveEndPosition, curveStartPositionTangent, curveEndPositionTangent, 2, BLUE); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// draw the various control points and highlight where the mouse is | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				DrawLineV(SP, SPTangent, SKYBLUE); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				DrawLineV(EP, EPTangent, PURPLE); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// Draw the various control points and highlight where the mouse is | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				DrawLineV(curveStartPosition, curveStartPositionTangent, SKYBLUE); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				DrawLineV(curveEndPosition, curveEndPositionTangent, PURPLE); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				Vector2 mouse = GetMousePosition(); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (CheckCollisionPointCircle(mouse, SP, 6)) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					DrawCircleV(SP, 7, YELLOW); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				DrawCircleV(SP, 5, RED); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (CheckCollisionPointCircle(mouse, curveStartPosition, 6)) DrawCircleV(curveStartPosition, 7, YELLOW); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				DrawCircleV(curveStartPosition, 5, RED); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (CheckCollisionPointCircle(mouse, SPTangent, 6)) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					DrawCircleV(SPTangent, 7, YELLOW); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				DrawCircleV(SPTangent, 5, MAROON); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (CheckCollisionPointCircle(mouse, curveStartPositionTangent, 6)) DrawCircleV(curveStartPositionTangent, 7, YELLOW); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				DrawCircleV(curveStartPositionTangent, 5, MAROON); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (CheckCollisionPointCircle(mouse, EP, 6)) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					DrawCircleV(EP, 7, YELLOW); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				DrawCircleV(EP, 5, GREEN); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (CheckCollisionPointCircle(mouse, curveEndPosition, 6)) DrawCircleV(curveEndPosition, 7, YELLOW); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				DrawCircleV(curveEndPosition, 5, GREEN); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (CheckCollisionPointCircle(mouse, EPTangent, 6)) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					DrawCircleV(EPTangent, 7, YELLOW); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				DrawCircleV(EPTangent, 5, DARKGREEN); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (CheckCollisionPointCircle(mouse, curveEndPositionTangent, 6)) DrawCircleV(curveEndPositionTangent, 7, YELLOW); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				DrawCircleV(curveEndPositionTangent, 5, DARKGREEN); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			t">void EditCurve() | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			">static void UpdateCurve(void) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			{ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// k">if the mouse is not down, we are not editing the curve so clear the selection | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// n">If the mouse is not down, we are not editing the curve so clear the selection | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (!IsMouseButtonDown(MOUSE_LEFT_BUTTON)) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				{ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					Selected = NULL; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					curveSelectedPoint = NULL; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					return; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// k">if a point was selected, move it | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (Selected) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// n">If a point was selected, move it | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (curveSelectedPoint) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				{ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					*Selected = Vector2Add(*Selected, GetMouseDelta()); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					*curveSelectedPoint = Vector2Add(*curveSelectedPoint, GetMouseDelta()); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					return; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// the mouse is down, and nothing was selected, so see if anything was picked | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// 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; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (CheckCollisionPointCircle(mouse, curveStartPosition, 6)) curveSelectedPoint = &curveStartPosition; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				else if (CheckCollisionPointCircle(mouse, curveStartPositionTangent, 6)) curveSelectedPoint = &curveStartPositionTangent; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				else if (CheckCollisionPointCircle(mouse, curveEndPosition, 6)) curveSelectedPoint = &curveEndPosition; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				else if (CheckCollisionPointCircle(mouse, curveEndPositionTangent, 6)) curveSelectedPoint = &curveEndPositionTangent; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			void DrawTexturedCurve() | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static void DrawTexturedCurve(void) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			{ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				const float step = 1.0f / Segments; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				const float step = 1.0f/curveSegments; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				Vector2 previous = SP; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				Vector2 previous = curveStartPosition; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				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 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// 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++) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				for (int i = 1; i <= curveSegments; i++) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				{ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					// segment the curve | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					t = step * 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 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; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					// Compute the endpoint for this segment | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					current.y = a*curveStartPosition.y + b*curveStartPositionTangent.y + c*curveEndPositionTangent.y + d*curveEndPosition.y; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					current.x = a*curveStartPosition.x + b*curveStartPositionTangent.x + c*curveEndPositionTangent.x + d*curveEndPosition.x; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					// vector from previous to current | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					// Vector from previous to current | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					Vector2 delta = { current.x - previous.x, current.y - previous.y }; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					// the right hand normal to the delta vector | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					// 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) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					// 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 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					// 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)); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					// Extend out the normals from the previous and current points to get the quad for this segment | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					Vector2 prevPosNormal = Vector2Add(previous, Vector2Scale(previousTangent, curveWidth)); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					Vector2 prevNegNormal = Vector2Add(previous, Vector2Scale(previousTangent, -curveWidth)); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					Vector2 currentPosNormal = Vector2Add(current, Vector2Scale(normal, Width)); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					Vector2 currentNegNormal = Vector2Add(current, Vector2Scale(normal, -Width)); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					Vector2 currentPosNormal = Vector2Add(current, Vector2Scale(normal, curveWidth)); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					Vector2 currentNegNormal = Vector2Add(current, Vector2Scale(normal, -curveWidth)); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					// draw the segment as a quad | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					rlSetTexture(RoadTexture.id); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					// Draw the segment as a quad | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					rlSetTexture(texRoad.id); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					rlBegin(RL_QUADS); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					rlColor4ub(255,255,255,255); | 
			
		
		
	
	
		
			
				| 
				
				
				
					
						
					
				
				 | 
			
			 | 
			
			@ -160,82 +234,26 @@ void DrawTexturedCurve() | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					rlEnd(); | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					// the current step is the start of the next step | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					// The current step is the start of the next step | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					previous = current; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					previousTangent = normal; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					previousV = v; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			void UpdateOptions() | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			static void UpdateOptions(void) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			{ | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (IsKeyPressed(KEY_SPACE)) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					ShowCurve = !ShowCurve; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// width | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (IsKeyPressed(KEY_EQUAL)) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					Width += 2; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (IsKeyPressed(KEY_MINUS)) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					Width -= 2; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (Width < 2) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					Width = 2; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (IsKeyPressed(KEY_SPACE)) showCurve = !showCurve; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// segments | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// Update with | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (IsKeyPressed(KEY_EQUAL)) curveWidth += 2; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (IsKeyPressed(KEY_MINUS)) curveWidth -= 2; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (IsKeyPressed(KEY_LEFT_BRACKET)) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					Segments -= 2; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (curveWidth < 2) curveWidth = 2; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (IsKeyPressed(KEY_RIGHT_BRACKET)) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					Segments += 2; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				// Update segments | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (IsKeyPressed(KEY_LEFT)) curveSegments -= 2; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (IsKeyPressed(KEY_RIGHT)) curveSegments += 2; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (Segments < 2) | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
					Segments = 2; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
				if (curveSegments < 2) curveSegments = 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; | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			} | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			
 | 
			
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
			    |