Prechádzať zdrojové kódy

Merge remote-tracking branch 'refs/remotes/raysan5/develop' into develop

victorfisac 9 rokov pred
rodič
commit
d728494099

+ 59 - 26
examples/makefile → examples/Makefile

@@ -79,31 +79,65 @@ endif
 
 # define any directories containing required header files
 ifeq ($(PLATFORM),PLATFORM_RPI)
-    INCLUDES = -I. -I../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
-else
-    INCLUDES = -I. -I../src
-# external libraries headers
-# GLFW3
-    INCLUDES += -I../external/glfw3/include
-# GLEW - Not required any more, replaced by GLAD
-    #INCLUDES += -I../external/glew/include
-# OpenAL Soft
-    INCLUDES += -I../external/openal_soft/include
+    INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        INCLUDES = -I. -I../src -I/usr/local/include/raylib/
+    else
+        INCLUDES = -I. -I../../src -IC:/raylib/raylib/src
+        # external libraries headers
+        # GLFW3
+            INCLUDES += -I../../external/glfw3/include
+        # GLEW - Not required any more, replaced by GLAD
+            #INCLUDES += -I../external/glew/include
+        # OpenAL Soft
+            INCLUDES += -I../../external/openal_soft/include
+    endif
 endif
 
 # define library paths containing required libs
 ifeq ($(PLATFORM),PLATFORM_RPI)
-    LFLAGS = -L. -L../src -L/opt/vc/lib
-else
-    LFLAGS = -L. -L../src
-# external libraries to link with
-# GLFW3
-    LFLAGS += -L../external/glfw3/lib/$(LIBPATH)
-    ifneq ($(PLATFORM_OS),OSX)
-    # OpenAL Soft
-    	LFLAGS += -L../external/openal_soft/lib/$(LIBPATH)
-	# GLEW - Not required any more, replaced by GLAD
-    	#LFLAGS += -L../external/glew/lib/$(LIBPATH)
+    LFLAGS = -L. -L../../src -L/opt/vc/lib
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        LFLAGS = -L. -L../../src
+    else
+        LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+        # external libraries to link with
+        # GLFW3
+            LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+        ifneq ($(PLATFORM_OS),OSX)
+        # OpenAL Soft
+            LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+        # GLEW: Not used, replaced by GLAD
+            #LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+        endif
+    endif
+endif
+
+# define library paths containing required libs
+ifeq ($(PLATFORM),PLATFORM_RPI)
+    LFLAGS = -L. -L../../src -L/opt/vc/lib
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        LFLAGS = -L. -L../../src
+    else
+        LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+        # external libraries to link with
+        # GLFW3
+        LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+        ifneq ($(PLATFORM_OS),OSX)
+        # OpenAL Soft
+            LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+        # GLEW
+            LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+        endif
     endif
 endif
 
@@ -114,9 +148,8 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
         # libraries for Debian GNU/Linux desktop compiling
         # requires the following packages:
         # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
-        LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lm -pthread
-	# on XWindow could require also below libraries, just uncomment
-	#LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+        LIBS = -lraylib -lglfw3 -lGL -lopenal -lm -pthread -ldl -lX11 \
+               -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
     else
     ifeq ($(PLATFORM_OS),OSX)
         # libraries for OS X 10.9 desktop compiling
@@ -202,9 +235,9 @@ EXAMPLES = \
     fix_dylib \
 
 
-# typing 'make' will invoke the first target entry in the file,
+# typing 'make' will invoke the default target entry called 'all',
 # in this case, the 'default' target entry is raylib
-default: examples
+all: examples
 
 # compile all examples
 examples: $(EXAMPLES)

+ 71 - 0
examples/core_2d_camera.c

@@ -0,0 +1,71 @@
+/*******************************************************************************************
+*
+*   raylib [core] example - 2d camera
+*
+*   This example has been created using raylib 1.5 (www.raylib.com)
+*   raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+*   Copyright (c) 2016 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+int main()
+{
+    // Initialization
+    //--------------------------------------------------------------------------------------
+    int screenWidth = 800;
+    int screenHeight = 450;
+
+    InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera");
+    
+    Camera2D camera;
+    
+    camera.position = (Vector2){ 0, 0 };
+    camera.origin = (Vector2){ 100, 100 };
+    camera.rotation = 0.0f;
+    camera.zoom = 1.0f;
+    
+    SetTargetFPS(60);
+    //--------------------------------------------------------------------------------------
+
+    // Main game loop
+    while (!WindowShouldClose())    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        if (IsKeyDown(KEY_RIGHT)) camera.position.x--;
+        else if (IsKeyDown(KEY_LEFT)) camera.position.x++;
+        else if (IsKeyDown(KEY_UP)) camera.position.y++;
+        else if (IsKeyDown(KEY_DOWN)) camera.position.y--;
+        
+        if (IsKeyDown(KEY_R)) camera.rotation--;
+        else if (IsKeyDown(KEY_F)) camera.rotation++;
+        
+        if (IsKeyDown(KEY_W)) camera.zoom += 0.005f;
+        if (IsKeyDown(KEY_S)) camera.zoom -= 0.005f;
+        //----------------------------------------------------------------------------------
+
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawingEx(camera);
+
+            ClearBackground(RAYWHITE);
+
+            DrawText("2D CAMERA TEST", 20, 20, 20, GRAY);
+            
+            DrawRectangle(0, 300, screenWidth, 50, GRAY);
+            DrawRectangle(400, 250, 40, 40, RED);
+
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------   
+    CloseWindow();        // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+}

+ 2 - 1
examples/core_3d_camera_first_person.c

@@ -23,7 +23,7 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera first person");
     
     // Define the camera to look into our 3d world (position, target, up vector)
-    Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }};
+    Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 60.0f };
 
     // Generates some random columns
     float heights[MAX_COLUMNS];
@@ -40,6 +40,7 @@ int main()
     Vector3 playerPosition = { 4.0f, 2.0f, 4.0f };       // Define player position
     
     SetCameraMode(CAMERA_FIRST_PERSON);         // Set a first person camera mode
+    SetCameraFovy(camera.fovy);                 // Set internal camera field-of-view Y
 
     SetTargetFPS(60);                           // Set our game to run at 60 frames-per-second
     //--------------------------------------------------------------------------------------

+ 2 - 0
examples/core_3d_camera_free.c

@@ -25,12 +25,14 @@ int main()
     camera.position = (Vector3){ 0.0f, 10.0f, 10.0f };  // Camera position
     camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };      // Camera looking at point
     camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };          // Camera up vector (rotation towards target)
+    camera.fovy = 45.0f;                                // Camera field-of-view Y
     
     Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
     
     SetCameraMode(CAMERA_FREE);         // Set a free camera mode
     SetCameraPosition(camera.position); // Set internal camera position to match our camera position
     SetCameraTarget(camera.target);     // Set internal camera target to match our camera target
+    SetCameraFovy(camera.fovy);         // Set internal camera field-of-view Y
 
     SetTargetFPS(60);                   // Set our game to run at 60 frames-per-second
     //--------------------------------------------------------------------------------------

+ 1 - 0
examples/core_3d_mode.c

@@ -25,6 +25,7 @@ int main()
     camera.position = (Vector3){ 0.0f, 10.0f, 10.0f };  // Camera position
     camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };      // Camera looking at point
     camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };          // Camera up vector (rotation towards target)
+    camera.fovy = 45.0f;                                // Camera field-of-view Y
 
     Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
 

+ 4 - 2
examples/core_3d_picking.c

@@ -25,6 +25,7 @@ int main()
     camera.position = (Vector3){ 0.0f, 10.0f, 10.0f };  // Camera position
     camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };      // Camera looking at point
     camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };          // Camera up vector (rotation towards target)
+    camera.fovy = 45.0f;                                // Camera field-of-view Y
 
     Vector3 cubePosition = { 0.0f, 1.0f, 0.0f };
     Vector3 cubeSize = { 2.0f, 2.0f, 2.0f };
@@ -35,6 +36,7 @@ int main()
     
     SetCameraMode(CAMERA_FREE);         // Set a free camera mode
     SetCameraPosition(camera.position); // Set internal camera position to match our camera position
+    SetCameraFovy(camera.fovy);         // Set internal camera field-of-view Y
 
     SetTargetFPS(60);                   // Set our game to run at 60 frames-per-second
     //--------------------------------------------------------------------------------------
@@ -53,8 +55,8 @@ int main()
             
             // Check collision between ray and box
             collision = CheckCollisionRayBox(ray,
-                (Vector3){ cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2 },
-                (Vector3){ cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 });
+                        (BoundingBox){(Vector3){ cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2 },
+                                      (Vector3){ cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 }});
         }
         //----------------------------------------------------------------------------------
 

+ 2 - 1
examples/core_world_screen.c

@@ -21,7 +21,7 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free");
 
     // Define the camera to look into our 3d world
-    Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }};
+    Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
 
     Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
     
@@ -30,6 +30,7 @@ int main()
     SetCameraMode(CAMERA_FREE);         // Set a free camera mode
     SetCameraPosition(camera.position); // Set internal camera position to match our camera position
     SetCameraTarget(camera.target);     // Set internal camera target to match our camera target
+    SetCameraFovy(camera.fovy);         // Set internal camera field-of-view Y
 
     SetTargetFPS(60);                   // Set our game to run at 60 frames-per-second
     //--------------------------------------------------------------------------------------

+ 2 - 1
examples/models_billboard.c

@@ -21,7 +21,7 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [models] example - drawing billboards");
 
     // Define the camera to look into our 3d world
-    Camera camera = {{ 5.0f, 4.0f, 5.0f }, { 0.0f, 2.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }};
+    Camera camera = {{ 5.0f, 4.0f, 5.0f }, { 0.0f, 2.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
 
     Texture2D bill = LoadTexture("resources/billboard.png");     // Our texture billboard
     Vector3 billPosition = { 0.0f, 2.0f, 0.0f };                 // Position where draw billboard
@@ -29,6 +29,7 @@ int main()
     SetCameraMode(CAMERA_ORBITAL);      // Set an orbital camera mode
     SetCameraPosition(camera.position); // Set internal camera position to match our camera position
     SetCameraTarget(camera.target);     // Set internal camera target to match our camera target
+    SetCameraFovy(camera.fovy);         // Set internal camera field-of-view Y
 
     SetTargetFPS(60);                   // Set our game to run at 60 frames-per-second
     //--------------------------------------------------------------------------------------

+ 22 - 20
examples/models_box_collisions.c

@@ -21,7 +21,7 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [models] example - box collisions");
 
     // Define the camera to look into our 3d world
-    Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }};
+    Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
     
     Vector3 playerPosition = { 0.0f, 1.0f, 2.0f };
     Vector3 playerSize = { 1.0f, 2.0f, 1.0f };
@@ -53,27 +53,29 @@ int main()
         collision = false;
         
         // Check collisions player vs enemy-box
-        if (CheckCollisionBoxes((Vector3){ playerPosition.x - playerSize.x/2, 
-                                           playerPosition.y - playerSize.y/2, 
-                                           playerPosition.z - playerSize.z/2 }, 
-                                (Vector3){ playerPosition.x + playerSize.x/2,
-                                           playerPosition.y + playerSize.y/2, 
-                                           playerPosition.z + playerSize.z/2 },
-                                (Vector3){ enemyBoxPos.x - enemyBoxSize.x/2, 
-                                           enemyBoxPos.y - enemyBoxSize.y/2, 
-                                           enemyBoxPos.z - enemyBoxSize.z/2 }, 
-                                (Vector3){ enemyBoxPos.x + enemyBoxSize.x/2,
-                                           enemyBoxPos.y + enemyBoxSize.y/2, 
-                                           enemyBoxPos.z + enemyBoxSize.z/2 })) collision = true;
+        if (CheckCollisionBoxes(
+            (BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2, 
+                                     playerPosition.y - playerSize.y/2, 
+                                     playerPosition.z - playerSize.z/2 }, 
+                          (Vector3){ playerPosition.x + playerSize.x/2,
+                                     playerPosition.y + playerSize.y/2, 
+                                     playerPosition.z + playerSize.z/2 }},
+            (BoundingBox){(Vector3){ enemyBoxPos.x - enemyBoxSize.x/2, 
+                                     enemyBoxPos.y - enemyBoxSize.y/2, 
+                                     enemyBoxPos.z - enemyBoxSize.z/2 }, 
+                          (Vector3){ enemyBoxPos.x + enemyBoxSize.x/2,
+                                     enemyBoxPos.y + enemyBoxSize.y/2, 
+                                     enemyBoxPos.z + enemyBoxSize.z/2 }})) collision = true;
         
         // Check collisions player vs enemy-sphere
-        if (CheckCollisionBoxSphere((Vector3){ playerPosition.x - playerSize.x/2, 
-                                               playerPosition.y - playerSize.y/2, 
-                                               playerPosition.z - playerSize.z/2 }, 
-                                    (Vector3){ playerPosition.x + playerSize.x/2,
-                                               playerPosition.y + playerSize.y/2, 
-                                               playerPosition.z + playerSize.z/2 }, 
-                                               enemySpherePos, enemySphereSize)) collision = true;
+        if (CheckCollisionBoxSphere(
+            (BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2, 
+                                     playerPosition.y - playerSize.y/2, 
+                                     playerPosition.z - playerSize.z/2 }, 
+                          (Vector3){ playerPosition.x + playerSize.x/2,
+                                     playerPosition.y + playerSize.y/2, 
+                                     playerPosition.z + playerSize.z/2 }}, 
+            enemySpherePos, enemySphereSize)) collision = true;
         
         if (collision) playerColor = RED;
         else playerColor = GREEN;

+ 2 - 1
examples/models_cubicmap.c

@@ -21,7 +21,7 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [models] example - cubesmap loading and drawing");
 
     // Define the camera to look into our 3d world
-    Camera camera = {{ 16.0f, 14.0f, 16.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }};
+    Camera camera = {{ 16.0f, 14.0f, 16.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
 
     Image image = LoadImage("resources/cubicmap.png");      // Load cubicmap image (RAM)
     Texture2D cubicmap = LoadTextureFromImage(image);       // Convert image to texture to display (VRAM)
@@ -37,6 +37,7 @@ int main()
     
     SetCameraMode(CAMERA_ORBITAL);      // Set an orbital camera mode
     SetCameraPosition(camera.position); // Set internal camera position to match our custom camera position
+    SetCameraFovy(camera.fovy);         // Set internal camera field-of-view Y
 
     SetTargetFPS(60);                   // Set our game to run at 60 frames-per-second
     //--------------------------------------------------------------------------------------

+ 1 - 1
examples/models_geometric_shapes.c

@@ -21,7 +21,7 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes");
 
     // Define the camera to look into our 3d world
-    Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }};
+    Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
 
     SetTargetFPS(60);   // Set our game to run at 60 frames-per-second
     //--------------------------------------------------------------------------------------

+ 1 - 1
examples/models_heightmap.c

@@ -21,7 +21,7 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [models] example - heightmap loading and drawing");
 
     // Define our custom camera to look into our 3d world
-    Camera camera = {{ 18.0f, 16.0f, 18.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }};
+    Camera camera = {{ 18.0f, 16.0f, 18.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
 
     Image image = LoadImage("resources/heightmap.png");         // Load heightmap image (RAM)
     Texture2D texture = LoadTextureFromImage(image);            // Convert image to texture (VRAM)

+ 1 - 1
examples/models_obj_loading.c

@@ -21,7 +21,7 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [models] example - obj model loading");
 
     // Define the camera to look into our 3d world
-    Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }};
+    Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
 
     Model dwarf = LoadModel("resources/model/dwarf.obj");                   // Load OBJ model
     Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png");   // Load model texture

+ 1 - 1
examples/shaders_basic_lighting.c

@@ -36,7 +36,7 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic lighting");
     
     // Camera initialization
-    Camera camera = {{ 8.0f, 8.0f, 8.0f }, { 0.0f, 3.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }};
+    Camera camera = {{ 8.0f, 8.0f, 8.0f }, { 0.0f, 3.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
     
     // Model initialization
     Vector3 position = { 0.0f, 0.0f, 0.0f };

+ 1 - 1
examples/shaders_custom_uniform.c

@@ -30,7 +30,7 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [shaders] example - custom uniform variable");
 
     // Define the camera to look into our 3d world
-    Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }};
+    Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
 
     Model dwarf = LoadModel("resources/model/dwarf.obj");                   // Load OBJ model
     Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png");   // Load model texture

+ 1 - 1
examples/shaders_model_shader.c

@@ -30,7 +30,7 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [shaders] example - model shader");
 
     // Define the camera to look into our 3d world
-    Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }};
+    Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
 
     Model dwarf = LoadModel("resources/model/dwarf.obj");                   // Load OBJ model
     Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png");   // Load model texture

+ 1 - 1
examples/shaders_postprocessing.c

@@ -30,7 +30,7 @@ int main()
     InitWindow(screenWidth, screenHeight, "raylib [shaders] example - postprocessing shader");
 
     // Define the camera to look into our 3d world
-    Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }};
+    Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
     
     Model dwarf = LoadModel("resources/model/dwarf.obj");                   // Load OBJ model
     Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png");   // Load model texture

+ 233 - 233
games/tetris.c

@@ -179,22 +179,22 @@ void InitGame(void)
 
     // Initialize grid matrices
     for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++)
-	{
-		for (int j = 0; j < GRID_VERTICAL_SIZE; j++)
-		{
+    {
+        for (int j = 0; j < GRID_VERTICAL_SIZE; j++)
+        {
             if ((j == GRID_VERTICAL_SIZE - 1) || (i == 0) || (i == GRID_HORIZONTAL_SIZE - 1)) grid[i][j] = BLOCK;
             else grid[i][j] = EMPTY;
-		}
-	}
+        }
+    }
 
     // Initialize incoming piece matrices
     for (int i = 0; i < 4; i++)
-	{
-		for (int j = 0; j< 4; j++)
-		{
-			incomingPiece[i][j] = EMPTY;
-		}
-	}
+    {
+        for (int j = 0; j< 4; j++)
+        {
+            incomingPiece[i][j] = EMPTY;
+        }
+    }
 }
 
 // Update game (one frame)
@@ -423,34 +423,34 @@ static bool Createpiece()
     piecePositionY = 0;
 
     // If the game is starting and you are going to create the first piece, we create an extra one
-	if (beginPlay)
-	{
+    if (beginPlay)
+    {
         GetRandompiece();
         beginPlay = false;
-	}
-	
+    }
+    
     // We assign the incoming piece to the actual piece
     for (int i = 0; i < 4; i++)
-	{
-		for (int j = 0; j< 4; j++)
-		{
-			piece[i][j] = incomingPiece[i][j];
-		}
-	}
-	
+    {
+        for (int j = 0; j< 4; j++)
+        {
+            piece[i][j] = incomingPiece[i][j];
+        }
+    }
+    
     // We assign a random piece to the incoming one
-	GetRandompiece();
+    GetRandompiece();
 
     // Assign the piece to the grid
     for (int i = piecePositionX; i < piecePositionX + 4; i++)
-	{
-		for (int j = 0; j < 4; j++)
-		{
-			if (piece[i - (int)piecePositionX][j] == MOVING) grid[i][j] = MOVING;
-		}
-	}
-
-	return true;
+    {
+        for (int j = 0; j < 4; j++)
+        {
+            if (piece[i - (int)piecePositionX][j] == MOVING) grid[i][j] = MOVING;
+        }
+    }
+
+    return true;
 }
 
 static void GetRandompiece()
@@ -459,22 +459,22 @@ static void GetRandompiece()
     int random = rand() % 7;
 
     for (int i = 0; i < 4; i++)
-	{
-		for (int j = 0; j < 4; j++)
-		{
-			incomingPiece[i][j] = EMPTY;
-		}
-	}
+    {
+        for (int j = 0; j < 4; j++)
+        {
+            incomingPiece[i][j] = EMPTY;
+        }
+    }
 
     switch(random)
-	{
-        case 0:	{	incomingPiece[1][1] = MOVING;   incomingPiece[2][1] = MOVING;	incomingPiece[1][2] = MOVING;	incomingPiece[2][2] = MOVING;	}	break;	//Cube
-        case 1:	{	incomingPiece[1][0] = MOVING;	incomingPiece[1][1] = MOVING;	incomingPiece[1][2] = MOVING;	incomingPiece[2][2] = MOVING;	}	break;	//L
-        case 2:	{	incomingPiece[1][2] = MOVING;	incomingPiece[2][0] = MOVING;	incomingPiece[2][1] = MOVING;	incomingPiece[2][2] = MOVING;	}	break;	//L inversa
-        case 3:	{	incomingPiece[0][1] = MOVING;	incomingPiece[1][1] = MOVING;	incomingPiece[2][1] = MOVING;	incomingPiece[3][1] = MOVING;	}	break;	//Recta
-        case 4:	{	incomingPiece[1][0] = MOVING;	incomingPiece[1][1] = MOVING;	incomingPiece[1][2] = MOVING;	incomingPiece[2][1] = MOVING;	}	break;	//Creu tallada
-        case 5: {	incomingPiece[1][1] = MOVING;	incomingPiece[2][1] = MOVING; 	incomingPiece[2][2] = MOVING;	incomingPiece[3][2] = MOVING;	}	break;	//S
-        case 6: {	incomingPiece[1][2] = MOVING;	incomingPiece[2][2] = MOVING; 	incomingPiece[2][1] = MOVING;	incomingPiece[3][1] = MOVING;	}	break;	//S inversa
+    {
+        case 0:    {    incomingPiece[1][1] = MOVING;   incomingPiece[2][1] = MOVING;    incomingPiece[1][2] = MOVING;    incomingPiece[2][2] = MOVING;    }    break;    //Cube
+        case 1:    {    incomingPiece[1][0] = MOVING;    incomingPiece[1][1] = MOVING;    incomingPiece[1][2] = MOVING;    incomingPiece[2][2] = MOVING;    }    break;    //L
+        case 2:    {    incomingPiece[1][2] = MOVING;    incomingPiece[2][0] = MOVING;    incomingPiece[2][1] = MOVING;    incomingPiece[2][2] = MOVING;    }    break;    //L inversa
+        case 3:    {    incomingPiece[0][1] = MOVING;    incomingPiece[1][1] = MOVING;    incomingPiece[2][1] = MOVING;    incomingPiece[3][1] = MOVING;    }    break;    //Recta
+        case 4:    {    incomingPiece[1][0] = MOVING;    incomingPiece[1][1] = MOVING;    incomingPiece[1][2] = MOVING;    incomingPiece[2][1] = MOVING;    }    break;    //Creu tallada
+        case 5: {    incomingPiece[1][1] = MOVING;    incomingPiece[2][1] = MOVING;     incomingPiece[2][2] = MOVING;    incomingPiece[3][2] = MOVING;    }    break;    //S
+        case 6: {    incomingPiece[1][2] = MOVING;    incomingPiece[2][2] = MOVING;     incomingPiece[2][1] = MOVING;    incomingPiece[3][1] = MOVING;    }    break;    //S inversa
     }
 }
 
@@ -482,34 +482,34 @@ static void ResolveFallingMovement(bool *detection, bool *pieceActive)
 {
     // If we finished moving this piece, we stop it
     if (*detection)
-	{
+    {
         for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
-		{
-			for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
-			{
-				if (grid[i][j] == MOVING)
-				{
-					grid[i][j] = FULL;
-					*detection = false;
-					*pieceActive = false;
-				}
-			}
-		}
-	}
+        {
+            for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+            {
+                if (grid[i][j] == MOVING)
+                {
+                    grid[i][j] = FULL;
+                    *detection = false;
+                    *pieceActive = false;
+                }
+            }
+        }
+    }
     // We move down the piece
-	else
-	{
+    else
+    {
         for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
-		{
-			for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
-			{
-				if (grid[i][j] == MOVING)
-				{
-					grid[i][j+1] = MOVING;
-					grid[i][j] = EMPTY;
-				}
-			}
-		}
+        {
+            for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+            {
+                if (grid[i][j] == MOVING)
+                {
+                    grid[i][j+1] = MOVING;
+                    grid[i][j] = EMPTY;
+                }
+            }
+        }
         piecePositionY++;
     }
 }
@@ -519,78 +519,78 @@ static bool ResolveLateralMovement()
     bool collision = false;
 
     // Move left
-	if (IsKeyDown(KEY_LEFT))
-	{
+    if (IsKeyDown(KEY_LEFT))
+    {
         // Check if is possible to move to left
-		for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
-		{
-			for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
-			{
-				if (grid[i][j] == MOVING)
-				{
+        for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+        {
+            for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+            {
+                if (grid[i][j] == MOVING)
+                {
                     // Check if we are touching the left wall or we have a full square at the left
-					if ((i-1 == 0) || (grid[i-1][j] == FULL)) collision = true;
-				}
-			}
-		}
+                    if ((i-1 == 0) || (grid[i-1][j] == FULL)) collision = true;
+                }
+            }
+        }
         // If able, move left
-		if (!collision)
-		{
-			for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
-			{
-				for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)             // We check the matrix from left to right
-				{
+        if (!collision)
+        {
+            for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+            {
+                for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)             // We check the matrix from left to right
+                {
                     // Move everything to the left
-					if (grid[i][j] == MOVING)
-					{
-						grid[i-1][j] = MOVING;
-						grid[i][j] = EMPTY;
-					}
-				}
-			}
+                    if (grid[i][j] == MOVING)
+                    {
+                        grid[i-1][j] = MOVING;
+                        grid[i][j] = EMPTY;
+                    }
+                }
+            }
 
             piecePositionX--;
-		}
-	}
+        }
+    }
 
     // Move right
-	else if (IsKeyDown(KEY_RIGHT))
-	{
+    else if (IsKeyDown(KEY_RIGHT))
+    {
         // Check if is possible to move to right
-		for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
-		{
-			for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
-			{
-				if (grid[i][j] == MOVING)
-				{
+        for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+        {
+            for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+            {
+                if (grid[i][j] == MOVING)
+                {
                     // Check if we are touching the right wall or we have a full square at the right
-					if ((i+1 == GRID_HORIZONTAL_SIZE - 1) || (grid[i+1][j] == FULL))
+                    if ((i+1 == GRID_HORIZONTAL_SIZE - 1) || (grid[i+1][j] == FULL))
                     {
                         collision = true;
 
                     }
-				}
-			}
-		}
+                }
+            }
+        }
         // If able move right
-		if (!collision)
-		{
-			for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
-			{
-				for (int i = GRID_HORIZONTAL_SIZE - 1; i >= 1; i--)             // We check the matrix from right to left
-				{
+        if (!collision)
+        {
+            for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+            {
+                for (int i = GRID_HORIZONTAL_SIZE - 1; i >= 1; i--)             // We check the matrix from right to left
+                {
                     // Move everything to the right
-					if (grid[i][j] == MOVING)
-					{
-						grid[i+1][j] = MOVING;
-						grid[i][j] = EMPTY;
-					}
-				}
-			}
+                    if (grid[i][j] == MOVING)
+                    {
+                        grid[i+1][j] = MOVING;
+                        grid[i][j] = EMPTY;
+                    }
+                }
+            }
 
             piecePositionX++;
-		}
-	}
+        }
+    }
 
     return collision;
 }
@@ -599,164 +599,164 @@ static bool ResolveTurnMovement()
 {
     // Input for turning the piece
     if (IsKeyDown(KEY_UP))
-	{
-		int aux;
-		bool checker = false;
+    {
+        int aux;
+        bool checker = false;
 
         // Check all turning possibilities
-		if ((grid[piecePositionX + 3][piecePositionY] == MOVING) &&
+        if ((grid[piecePositionX + 3][piecePositionY] == MOVING) &&
             (grid[piecePositionX][piecePositionY] != EMPTY) &&
             (grid[piecePositionX][piecePositionY] != MOVING))
-        {	
+        {    
             checker = true;
         }
-		if ((grid[piecePositionX + 3][piecePositionY + 3] == MOVING) &&
+        if ((grid[piecePositionX + 3][piecePositionY + 3] == MOVING) &&
             (grid[piecePositionX + 3][piecePositionY] != EMPTY) &&
             (grid[piecePositionX + 3][piecePositionY] != MOVING))
-        {	
+        {    
             checker = true;
         }
-		if ((grid[piecePositionX][piecePositionY + 3] == MOVING) &&
+        if ((grid[piecePositionX][piecePositionY + 3] == MOVING) &&
             (grid[piecePositionX + 3][piecePositionY + 3] != EMPTY) &&
             (grid[piecePositionX + 3][piecePositionY + 3] != MOVING))
-        {	
+        {    
             checker = true;
         }
-		if ((grid[piecePositionX][piecePositionY] == MOVING) &&
+        if ((grid[piecePositionX][piecePositionY] == MOVING) &&
             (grid[piecePositionX][piecePositionY + 3] != EMPTY) &&
             (grid[piecePositionX][piecePositionY + 3] != MOVING))
-        {	
+        {    
             checker = true;
         }
 
 
-		if ((grid[piecePositionX + 1][piecePositionY] == MOVING) &&
+        if ((grid[piecePositionX + 1][piecePositionY] == MOVING) &&
             (grid[piecePositionX][piecePositionY + 2] != EMPTY) &&
             (grid[piecePositionX][piecePositionY + 2] != MOVING))
-        {	
+        {    
             checker = true;
         }
-		if ((grid[piecePositionX + 3][piecePositionY + 1] == MOVING) &&
+        if ((grid[piecePositionX + 3][piecePositionY + 1] == MOVING) &&
             (grid[piecePositionX + 1][piecePositionY] != EMPTY) &&
             (grid[piecePositionX + 1][piecePositionY] != MOVING))
-        {	
+        {    
             checker = true;
         }
-		if ((grid[piecePositionX + 2][piecePositionY + 3] == MOVING) &&
+        if ((grid[piecePositionX + 2][piecePositionY + 3] == MOVING) &&
             (grid[piecePositionX + 3][piecePositionY + 1] != EMPTY) &&
             (grid[piecePositionX + 3][piecePositionY + 1] != MOVING))
-        {	
+        {    
             checker = true;
         }
-		if ((grid[piecePositionX][piecePositionY + 2] == MOVING) &&
+        if ((grid[piecePositionX][piecePositionY + 2] == MOVING) &&
             (grid[piecePositionX + 2][piecePositionY + 3] != EMPTY) &&
             (grid[piecePositionX + 2][piecePositionY + 3] != MOVING))
-        {	
+        {    
             checker = true;
         }
 
 
-		if ((grid[piecePositionX + 2][piecePositionY] == MOVING) &&
+        if ((grid[piecePositionX + 2][piecePositionY] == MOVING) &&
             (grid[piecePositionX][piecePositionY + 1] != EMPTY) &&
             (grid[piecePositionX][piecePositionY + 1] != MOVING))
-        {	
+        {    
             checker = true;
         }
-		if ((grid[piecePositionX + 3][piecePositionY + 2] == MOVING) &&
+        if ((grid[piecePositionX + 3][piecePositionY + 2] == MOVING) &&
             (grid[piecePositionX + 2][piecePositionY] != EMPTY) &&
             (grid[piecePositionX + 2][piecePositionY] != MOVING))
-        {	
+        {    
             checker = true;
         }
-		if ((grid[piecePositionX + 1][piecePositionY + 3] == MOVING) &&
+        if ((grid[piecePositionX + 1][piecePositionY + 3] == MOVING) &&
             (grid[piecePositionX + 3][piecePositionY + 2] != EMPTY) &&
             (grid[piecePositionX + 3][piecePositionY + 2] != MOVING))
-        {	
+        {    
             checker = true;
         }
-		if ((grid[piecePositionX][piecePositionY + 1] == MOVING) &&
+        if ((grid[piecePositionX][piecePositionY + 1] == MOVING) &&
             (grid[piecePositionX + 1][piecePositionY + 3] != EMPTY) &&
             (grid[piecePositionX + 1][piecePositionY + 3] != MOVING))
-        {	
+        {    
             checker = true;
         }
 
-		if ((grid[piecePositionX + 1][piecePositionY + 1] == MOVING) &&
+        if ((grid[piecePositionX + 1][piecePositionY + 1] == MOVING) &&
             (grid[piecePositionX + 1][piecePositionY + 2] != EMPTY) &&
             (grid[piecePositionX + 1][piecePositionY + 2] != MOVING))
-        {	
+        {    
             checker = true;
         }
         
-		if ((grid[piecePositionX + 2][piecePositionY + 1] == MOVING) &&
+        if ((grid[piecePositionX + 2][piecePositionY + 1] == MOVING) &&
             (grid[piecePositionX + 1][piecePositionY + 1] != EMPTY) &&
             (grid[piecePositionX + 1][piecePositionY + 1] != MOVING))
-        {	
+        {    
             checker = true;
         }
-		if ((grid[piecePositionX + 2][piecePositionY + 2] == MOVING) &&
+        if ((grid[piecePositionX + 2][piecePositionY + 2] == MOVING) &&
             (grid[piecePositionX + 2][piecePositionY + 1] != EMPTY) &&
             (grid[piecePositionX + 2][piecePositionY + 1] != MOVING))
-        {	
+        {    
             checker = true;
         }
-		if ((grid[piecePositionX + 1][piecePositionY + 2] == MOVING) &&
+        if ((grid[piecePositionX + 1][piecePositionY + 2] == MOVING) &&
             (grid[piecePositionX + 2][piecePositionY + 2] != EMPTY) &&
             (grid[piecePositionX + 2][piecePositionY + 2] != MOVING))
-        {	
+        {    
             checker = true;
         }
 
-		if (!checker)
-		{
-			aux = piece[0][0];
-			piece[0][0] = piece[3][0];
-			piece[3][0] = piece[3][3];
-			piece[3][3] = piece[0][3];
-			piece[0][3] = aux;
-
-			aux = piece[1][0];
-			piece[1][0] = piece[3][1];
-			piece[3][1] = piece[2][3];
-			piece[2][3] = piece[0][2];
-			piece[0][2] = aux;
-
-			aux = piece[2][0];
-			piece[2][0] = piece[3][2];
-			piece[3][2] = piece[1][3];
-			piece[1][3] = piece[0][1];
-			piece[0][1] = aux;
-
-			aux = piece[1][1];
-			piece[1][1] = piece[2][1];
-			piece[2][1] = piece[2][2];
-			piece[2][2] = piece[1][2];
-			piece[1][2] = aux;
-		}
-
-		for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
-		{
-			for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
-			{
-				if (grid[i][j] == MOVING)
-				{
-					grid[i][j] = EMPTY;
-				}
-			}
-		}
-
-		for (int i = piecePositionX; i < piecePositionX + 4; i++)
-		{
-			for (int j = piecePositionY; j < piecePositionY + 4; j++)
-			{
-				if (piece[i - piecePositionX][j - piecePositionY] == MOVING)
-				{
-					grid[i][j] = MOVING;
-				}
-			}
-		}
+        if (!checker)
+        {
+            aux = piece[0][0];
+            piece[0][0] = piece[3][0];
+            piece[3][0] = piece[3][3];
+            piece[3][3] = piece[0][3];
+            piece[0][3] = aux;
+
+            aux = piece[1][0];
+            piece[1][0] = piece[3][1];
+            piece[3][1] = piece[2][3];
+            piece[2][3] = piece[0][2];
+            piece[0][2] = aux;
+
+            aux = piece[2][0];
+            piece[2][0] = piece[3][2];
+            piece[3][2] = piece[1][3];
+            piece[1][3] = piece[0][1];
+            piece[0][1] = aux;
+
+            aux = piece[1][1];
+            piece[1][1] = piece[2][1];
+            piece[2][1] = piece[2][2];
+            piece[2][2] = piece[1][2];
+            piece[1][2] = aux;
+        }
+
+        for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+        {
+            for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+            {
+                if (grid[i][j] == MOVING)
+                {
+                    grid[i][j] = EMPTY;
+                }
+            }
+        }
+
+        for (int i = piecePositionX; i < piecePositionX + 4; i++)
+        {
+            for (int j = piecePositionY; j < piecePositionY + 4; j++)
+            {
+                if (piece[i - piecePositionX][j - piecePositionY] == MOVING)
+                {
+                    grid[i][j] = MOVING;
+                }
+            }
+        }
         return true;
-	}
+    }
 
     return false;
 }
@@ -764,44 +764,44 @@ static bool ResolveTurnMovement()
 static void CheckDetection(bool *detection)
 {
     for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
-	{
-		for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
-		{
-			if ((grid[i][j] == MOVING) && ((grid[i][j+1] == FULL) || (grid[i][j+1] == BLOCK))) *detection = true;
-		}
-	}
+    {
+        for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+        {
+            if ((grid[i][j] == MOVING) && ((grid[i][j+1] == FULL) || (grid[i][j+1] == BLOCK))) *detection = true;
+        }
+    }
 }
 
 static void CheckCompletition(bool *lineToDelete)
 {
     int calculator;
 
-	for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
-	{
-		calculator = 0;
-		for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
-		{
+    for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
+    {
+        calculator = 0;
+        for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
+        {
             // Count each square of the line
-			if (grid[i][j] == FULL)
-			{
-				calculator++;
-			}
+            if (grid[i][j] == FULL)
+            {
+                calculator++;
+            }
 
             // Check if we completed the whole line
-			if (calculator == GRID_HORIZONTAL_SIZE - 2)
-			{
+            if (calculator == GRID_HORIZONTAL_SIZE - 2)
+            {
                 *lineToDelete = true;
                 calculator = 0;
-				// points++;
+                // points++;
 
                 // Mark the completed line
-				for (int z = 1; z < GRID_HORIZONTAL_SIZE - 1; z++)
-				{
-					grid[z][j] = FADING;
-				}
-			}
-		}
-	}
+                for (int z = 1; z < GRID_HORIZONTAL_SIZE - 1; z++)
+                {
+                    grid[z][j] = FADING;
+                }
+            }
+        }
+    }
 }
 
 static void DeleteCompleteLines()

+ 0 - 0
src/makefile → src/Makefile


+ 7 - 1
src/camera.c

@@ -84,7 +84,7 @@ typedef enum { MOVE_FRONT = 0, MOVE_LEFT, MOVE_BACK, MOVE_RIGHT, MOVE_UP, MOVE_D
 //----------------------------------------------------------------------------------
 // Global Variables Definition
 //----------------------------------------------------------------------------------
-static Camera internalCamera = {{ 2.0f, 0.0f, 2.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }};
+static Camera internalCamera = {{ 2.0f, 0.0f, 2.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
 static Vector2 cameraAngle = { 0.0f, 0.0f };
 static float cameraTargetDistance = 5.0f;
 static Vector2 cameraMousePosition = { 0.0f, 0.0f };
@@ -212,6 +212,12 @@ void SetCameraTarget(Vector3 target)
     cameraTargetDistance = sqrt(dx*dx + dy*dy + dz*dz);
 }
 
+// Set internal camera fovy
+void SetCameraFovy(float fovy)
+{
+    internalCamera.fovy = fovy;
+}
+
 // Set camera pan key to combine with mouse movement (free camera)
 void SetCameraPanControl(int panKey)
 {

+ 1 - 0
src/camera.h

@@ -81,6 +81,7 @@ void UpdateCameraPlayer(Camera *camera, Vector3 *position); // Update camera and
 
 void SetCameraPosition(Vector3 position);                   // Set internal camera position
 void SetCameraTarget(Vector3 target);                       // Set internal camera target
+void SetCameraFovy(float fovy);                             // Set internal camera field-of-view-y
 
 void SetCameraPanControl(int panKey);                       // Set camera pan key to combine with mouse movement (free camera)
 void SetCameraAltControl(int altKey);                       // Set camera alt key to combine with mouse movement (free camera)

+ 47 - 29
src/core.c

@@ -560,8 +560,25 @@ void BeginDrawing(void)
                                         // NOTE: Not required with OpenGL 3.3+
 }
 
-// Setup drawing canvas with extended parameters
-void BeginDrawingEx(int blendMode, Shader shader, Matrix transform)
+// Setup drawing canvas with 2d camera
+void BeginDrawingEx(Camera2D camera)
+{
+    BeginDrawing();
+    
+    // TODO: Consider origin offset on position, rotation, scaling
+    
+    Matrix matRotation = MatrixRotate((Vector3){ 0.0f, 0.0f, 1.0f }, camera.rotation*DEG2RAD);
+    Matrix matScale = MatrixScale(camera.zoom, camera.zoom, 1.0f);
+    Matrix matTranslation = MatrixTranslate(camera.position.x, camera.position.y, 0.0f);
+    Matrix matOrigin = MatrixTranslate(-camera.origin.x, -camera.origin.y, 0.0f);
+
+    Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation);
+    
+    rlMultMatrixf(MatrixToFloat(matTransform));
+}
+
+// Setup drawing canvas with pro parameters
+void BeginDrawingPro(int blendMode, Shader shader, Matrix transform)
 {
     BeginDrawing();
     
@@ -609,14 +626,14 @@ void Begin3dMode(Camera camera)
 
     rlPushMatrix();                     // Save previous matrix, which contains the settings for the 2d ortho projection
     rlLoadIdentity();                   // Reset current matrix (PROJECTION)
-
+    
     // Setup perspective projection
     float aspect = (float)screenWidth/(float)screenHeight;
-    double top = 0.1*tan(45.0*PI/360.0);
+    double top = 0.01*tan(camera.fovy*PI/360.0);
     double right = top*aspect;
 
     // NOTE: zNear and zFar values are important when computing depth buffer values
-    rlFrustum(-right, right, -top, top, 0.1f, 1000.0f);
+    rlFrustum(-right, right, -top, top, 0.01, 1000.0);
 
     rlMatrixMode(RL_MODELVIEW);         // Switch back to modelview matrix
     rlLoadIdentity();                   // Reset current matrix (MODELVIEW)
@@ -867,16 +884,8 @@ int StorageLoadValue(int position)
 }
 
 // Returns a ray trace from mouse position
-//http://www.songho.ca/opengl/gl_transform.html
-//http://www.songho.ca/opengl/gl_matrix.html
-//http://www.sjbaker.org/steve/omniv/matrices_can_be_your_friends.html
-//https://www.opengl.org/archives/resources/faq/technical/transformations.htm
 Ray GetMouseRay(Vector2 mousePosition, Camera camera)
-{
-    // Tutorial used: https://mkonrad.net/2014/08/07/simple-opengl-object-picking-in-3d.html
-    // Similar to http://antongerdelan.net, the problem is maybe in MatrixPerspective vs MatrixFrustum
-    // or matrix order (transpose it or not... that's the question)
-    
+{   
     Ray ray;
     
     // Calculate normalized device coordinates
@@ -886,40 +895,48 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
     float z = 1.0f;
     
     // Store values in a vector
-    Vector3 deviceCoords = {x, y, z};
+    Vector3 deviceCoords = { x, y, z };
     
-    // Device debug message
-    TraceLog(INFO, "device(%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.z);
+    TraceLog(DEBUG, "Device coordinates: (%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.z);
     
-    // Calculate projection matrix (from perspective instead of frustum
-    Matrix matProj = MatrixPerspective(45.0f, (float)((float)GetScreenWidth() / (float)GetScreenHeight()), 0.01f, 1000.0f);
+    // Calculate projection matrix (from perspective instead of frustum)
+    Matrix matProj = MatrixPerspective(camera.fovy, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0);
     
     // Calculate view matrix from camera look at
     Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
     
     // Do I need to transpose it? It seems that yes...
-    // NOTE: matrix order is maybe incorrect... In OpenGL to get world position from
+    // NOTE: matrix order may be incorrect... In OpenGL to get world position from
     // camera view it just needs to get inverted, but here we need to transpose it too.
     // For example, if you get view matrix, transpose and inverted and you transform it
     // to a vector, you will get its 3d world position coordinates (camera.position).
     // If you don't transpose, final position will be wrong.
     MatrixTranspose(&matView);
     
+//#define USE_RLGL_UNPROJECT
+#if defined(USE_RLGL_UNPROJECT)     // OPTION 1: Use rlglUnproject()
+    
+    Vector3 nearPoint = rlglUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 0.0f }, matProj, matView);
+    Vector3 farPoint = rlglUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView);
+
+#else   // OPTION 2: Compute unprojection directly here
+    
     // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it
     Matrix matProjView = MatrixMultiply(matProj, matView);
     MatrixInvert(&matProjView);
     
     // Calculate far and near points
-    Quaternion near = { deviceCoords.x, deviceCoords.y, 0.0f, 1.0f};
-    Quaternion far = { deviceCoords.x, deviceCoords.y, 1.0f, 1.0f};
+    Quaternion near = { deviceCoords.x, deviceCoords.y, 0.0f, 1.0f };
+    Quaternion far = { deviceCoords.x, deviceCoords.y, 1.0f, 1.0f };
     
     // Multiply points by unproject matrix
     QuaternionTransform(&near, matProjView);
     QuaternionTransform(&far, matProjView);
     
     // Calculate normalized world points in vectors
-    Vector3 nearPoint = {near.x / near.w, near.y / near.w, near.z / near.w};
-    Vector3 farPoint = {far.x / far.w, far.y / far.w, far.z / far.w};
+    Vector3 nearPoint = { near.x/near.w, near.y/near.w, near.z/near.w};
+    Vector3 farPoint = { far.x/far.w, far.y/far.w, far.z/far.w};
+#endif
     
     // Calculate normalized direction vector
     Vector3 direction = VectorSubtract(farPoint, nearPoint);
@@ -936,7 +953,7 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
 Vector2 WorldToScreen(Vector3 position, Camera camera)
 {    
     // Calculate projection matrix (from perspective instead of frustum
-    Matrix matProj = MatrixPerspective(45.0f, (float)((float)GetScreenWidth() / (float)GetScreenHeight()), 0.01f, 1000.0f);
+    Matrix matProj = MatrixPerspective(camera.fovy, (double)GetScreenWidth()/(double)GetScreenHeight(), 0.01, 1000.0);
     
     // Calculate view matrix from camera look at (and transpose it)
     Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
@@ -1718,10 +1735,11 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
         TakeScreenshot();
     }
 #endif
-    else currentKeyState[key] = action;
-
-    // TODO: Review (and remove) this HACK for GuiTextBox, to deteck back key
-    if ((key == 259) && (action == GLFW_PRESS)) lastKeyPressed = 3;
+    else 
+    {
+        currentKeyState[key] = action;
+        if (action == GLFW_PRESS) lastKeyPressed = key;
+    }
 }
 
 // GLFW3 Mouse Button Callback, runs on mouse button pressed

+ 5 - 5
src/gestures.c

@@ -72,7 +72,7 @@ static Vector2 moveDownPosition2 = { 0.0f, 0.0f };
 static int numTap = 0;
 
 static int pointCount = 0;
-static int touchId = -1;
+static int firstTouchId = -1;
 
 static double eventTime = 0.0;
 static double swipeTime = 0.0;
@@ -120,9 +120,7 @@ void ProcessGestureEvent(GestureEvent event)
     pointCount = event.pointCount;      // Required on UpdateGestures()
     
     if (pointCount < 2)
-    {      
-        touchId = event.pointerId[0];
-        
+    {
         if (event.touchAction == TOUCH_DOWN)
         {
             numTap++;    // Tap counter
@@ -145,6 +143,8 @@ void ProcessGestureEvent(GestureEvent event)
             touchUpPosition = touchDownPosition;
             eventTime = GetCurrentTime();
             
+            firstTouchId = event.pointerId[0];
+            
             dragVector = (Vector2){ 0.0f, 0.0f };
         }
         else if (event.touchAction == TOUCH_UP)
@@ -158,7 +158,7 @@ void ProcessGestureEvent(GestureEvent event)
             startMoving = false;
             
             // Detect GESTURE_SWIPE
-            if ((dragIntensity > FORCE_TO_SWIPE) && (touchId == 0))        // RAY: why check (touchId == 0)???
+            if ((dragIntensity > FORCE_TO_SWIPE) && firstTouchId == event.pointerId[0])
             {
                 // NOTE: Angle should be inverted in Y
                 dragAngle = 360.0f - Vector2Angle(touchDownPosition, touchUpPosition);

+ 104 - 194
src/models.c

@@ -56,6 +56,8 @@ extern unsigned int whiteTexture;
 // Module specific Functions Declaration
 //----------------------------------------------------------------------------------
 static Mesh LoadOBJ(const char *fileName);
+static Mesh GenMeshHeightmap(Image image, Vector3 size);
+static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize);
 
 //----------------------------------------------------------------------------------
 // Module Functions Definition
@@ -446,41 +448,24 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl
 // Draw a plane
 void DrawPlane(Vector3 centerPos, Vector2 size, Color color)
 {
-    // NOTE: QUADS usage require defining a texture on OpenGL 3.3+
-    if (rlGetVersion() != OPENGL_11) rlEnableTexture(whiteTexture);    // Default white texture
-
     // NOTE: Plane is always created on XZ ground
     rlPushMatrix();
         rlTranslatef(centerPos.x, centerPos.y, centerPos.z);
         rlScalef(size.x, 1.0f, size.y);
 
-        rlBegin(RL_QUADS);
+        rlBegin(RL_TRIANGLES);
             rlColor4ub(color.r, color.g, color.b, color.a);
             rlNormal3f(0.0f, 1.0f, 0.0f);
-            rlTexCoord2f(0.0f, 0.0f); rlVertex3f(-0.5f, 0.0f, -0.5f);
-            rlTexCoord2f(1.0f, 0.0f); rlVertex3f(-0.5f, 0.0f, 0.5f);
-            rlTexCoord2f(1.0f, 1.0f); rlVertex3f(0.5f, 0.0f, 0.5f);
-            rlTexCoord2f(0.0f, 1.0f); rlVertex3f(0.5f, 0.0f, -0.5f);
-        rlEnd();
-    rlPopMatrix();
 
-    if (rlGetVersion() != OPENGL_11) rlDisableTexture();
-}
+            rlVertex3f(0.5f, 0.0f, -0.5f);
+            rlVertex3f(-0.5f, 0.0f, -0.5f);
+            rlVertex3f(-0.5f, 0.0f, 0.5f);
 
-// Draw a quad
-void DrawQuad(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Color color)
-{
-    // TODO: Calculate normals from vertex position
-    
-    rlBegin(RL_QUADS);
-        rlColor4ub(color.r, color.g, color.b, color.a);
-        //rlNormal3f(0.0f, 0.0f, 0.0f);
-
-        rlVertex3f(v1.x, v1.y, v1.z);
-        rlVertex3f(v2.x, v2.y, v2.z);
-        rlVertex3f(v3.x, v3.y, v3.z);
-        rlVertex3f(v4.x, v4.y, v4.z);
-    rlEnd();
+            rlVertex3f(-0.5f, 0.0f, 0.5f);
+            rlVertex3f(0.5f, 0.0f, 0.5f);
+            rlVertex3f(0.5f, 0.0f, -0.5f);
+        rlEnd();
+    rlPopMatrix();
 }
 
 // Draw a ray line
@@ -566,28 +551,15 @@ Model LoadModel(const char *fileName)
 
     // NOTE: At this point we have all vertex, texcoord, normal data for the model in mesh struct
     
-    if (mesh.vertexCount == 0)
-    {
-        TraceLog(WARNING, "Model could not be loaded");
-    }
+    if (mesh.vertexCount == 0) TraceLog(WARNING, "Model could not be loaded");
     else
     {
         // NOTE: model properties (transform, texture, shader) are initialized inside rlglLoadModel()
         model = rlglLoadModel(mesh);     // Upload vertex data to GPU
 
-        // Now that vertex data is uploaded to GPU, we can free arrays
-        // NOTE 1: We don't need CPU vertex data on OpenGL 3.3 or ES2... for static meshes...
-        // NOTE 2: ...but we could keep CPU vertex data in case we need to update the mesh
-        
-        /*
-        if (rlGetVersion() != OPENGL_11)
-        {
-            free(mesh.vertices);
-            free(mesh.texcoords);
-            free(mesh.normals);
-            free(mesh.colors);
-        }
-        */
+        // NOTE: Now that vertex data is uploaded to GPU VRAM, we can free arrays from CPU RAM
+        // We don't need CPU vertex data on OpenGL 3.3 or ES2... for static meshes...
+        // ...but we could keep CPU vertex data in case we need to update the mesh
     }
 
     return model;
@@ -609,6 +581,54 @@ Model LoadModelEx(Mesh data)
 // Load a heightmap image as a 3d model
 // NOTE: model map size is defined in generic units
 Model LoadHeightmap(Image heightmap, Vector3 size)
+{
+    Mesh mesh = GenMeshHeightmap(heightmap, size);
+    Model model = rlglLoadModel(mesh);
+
+    return model;
+}
+
+// Load a map image as a 3d model (cubes based)
+Model LoadCubicmap(Image cubicmap)
+{
+    Mesh mesh = GenMeshCubicmap(cubicmap, (Vector3){ 1.0, 1.0, 1.5f });
+    Model model = rlglLoadModel(mesh);
+
+    return model;
+}
+
+// Unload 3d model from memory
+void UnloadModel(Model model)
+{
+    // Unload mesh data
+    free(model.mesh.vertices);
+    free(model.mesh.texcoords);
+    free(model.mesh.normals);
+    free(model.mesh.colors);
+    //if (model.mesh.texcoords2 != NULL) free(model.mesh.texcoords2); // Not used
+    //if (model.mesh.tangents != NULL) free(model.mesh.tangents); // Not used
+    
+    rlDeleteBuffers(model.mesh.vboId[0]);   // vertex
+    rlDeleteBuffers(model.mesh.vboId[1]);   // texcoords
+    rlDeleteBuffers(model.mesh.vboId[2]);   // normals
+    //rlDeleteBuffers(model.mesh.vboId[3]);   // texcoords2 (NOT USED)
+    //rlDeleteBuffers(model.mesh.vboId[4]);   // tangents (NOT USED)
+    //rlDeleteBuffers(model.mesh.vboId[5]);   // colors (NOT USED)
+
+    rlDeleteVertexArrays(model.mesh.vaoId);
+    
+    if (model.mesh.vaoId > 0) TraceLog(INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", model.mesh.vaoId);
+    else TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i] Unloaded model data from VRAM (GPU)", model.mesh.vboId[0], model.mesh.vboId[1], model.mesh.vboId[2]);
+}
+
+// Link a texture to a model
+void SetModelTexture(Model *model, Texture2D texture)
+{
+    if (texture.id <= 0) model->material.texDiffuse.id = whiteTexture;  // Use default white texture
+    else model->material.texDiffuse = texture;
+}
+
+static Mesh GenMeshHeightmap(Image heightmap, Vector3 size)
 {
     #define GRAY_VALUE(c) ((c.r+c.g+c.b)/3)
     
@@ -714,34 +734,17 @@ Model LoadHeightmap(Image heightmap, Vector3 size)
     // NOTE: Not used any more... just one plain color defined at DrawModel()
     for (int i = 0; i < (4*mesh.vertexCount); i++) mesh.colors[i] = 255;
 
-    // NOTE: At this point we have all vertex, texcoord, normal data for the model in mesh struct
-
-    Model model = rlglLoadModel(mesh);
-
-    // Now that vertex data is uploaded to GPU, we can free arrays
-    // NOTE: We don't need CPU vertex data on OpenGL 3.3 or ES2
-    if (rlGetVersion() != OPENGL_11)
-    {
-        free(mesh.vertices);
-        free(mesh.texcoords);
-        free(mesh.normals);
-        free(mesh.colors);
-    }
-
-    return model;
+    return mesh;
 }
 
-// Load a map image as a 3d model (cubes based)
-Model LoadCubicmap(Image cubicmap)
+static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)
 {
     Mesh mesh;
 
     Color *cubicmapPixels = GetImageData(cubicmap);
     
-    // Map cube size will be 1.0
-    float mapCubeSide = 1.0f;
-    int mapWidth = cubicmap.width*(int)mapCubeSide;
-    int mapHeight = cubicmap.height*(int)mapCubeSide;
+    int mapWidth = cubicmap.width*(int)cubeSize.x;
+    int mapHeight = cubicmap.height*(int)cubeSize.z;
 
     // NOTE: Max possible number of triangles numCubes * (12 triangles by cube)
     int maxTriangles = cubicmap.width*cubicmap.height*12;
@@ -750,9 +753,9 @@ Model LoadCubicmap(Image cubicmap)
     int tcCounter = 0;      // Used to count texcoords
     int nCounter = 0;       // Used to count normals
 
-    float w = mapCubeSide;
-    float h = mapCubeSide;
-    float h2 = mapCubeSide*1.5f;   // TODO: Review walls height...
+    float w = cubeSize.x;
+    float h = cubeSize.z;
+    float h2 = cubeSize.y;
 
     Vector3 *mapVertices = (Vector3 *)malloc(maxTriangles*3*sizeof(Vector3));
     Vector2 *mapTexcoords = (Vector2 *)malloc(maxTriangles*3*sizeof(Vector2));
@@ -781,9 +784,9 @@ Model LoadCubicmap(Image cubicmap)
     RectangleF topTexUV = { 0.0f, 0.5f, 0.5f, 0.5f };
     RectangleF bottomTexUV = { 0.5f, 0.5f, 0.5f, 0.5f };
 
-    for (int z = 0; z < mapHeight; z += mapCubeSide)
+    for (int z = 0; z < mapHeight; z += cubeSize.z)
     {
-        for (int x = 0; x < mapWidth; x += mapCubeSide)
+        for (int x = 0; x < mapWidth; x += cubeSize.x)
         {
             // Define the 8 vertex of the cube, we will combine them accordingly later...
             Vector3 v1 = { x - w/2, h2, z - h/2 };
@@ -1087,59 +1090,9 @@ Model LoadCubicmap(Image cubicmap)
     free(mapNormals);
     free(mapTexcoords);
     
-    free(cubicmapPixels);
-
-    // NOTE: At this point we have all vertex, texcoord, normal data for the model in mesh struct
-
-    Model model = rlglLoadModel(mesh);
-
-    // Now that vertex data is uploaded to GPU, we can free arrays
-    // NOTE: We don't need CPU vertex data on OpenGL 3.3 or ES2
-    if (rlGetVersion() != OPENGL_11)
-    {
-        free(mesh.vertices);
-        free(mesh.texcoords);
-        free(mesh.normals);
-        free(mesh.colors);
-    }
-
-    return model;
-}
-
-// Unload 3d model from memory
-void UnloadModel(Model model)
-{
-    if (rlGetVersion() == OPENGL_11)
-    {
-        free(model.mesh.vertices);
-        free(model.mesh.texcoords);
-        free(model.mesh.normals);
-    }
-
-    rlDeleteBuffers(model.mesh.vboId[0]);
-    rlDeleteBuffers(model.mesh.vboId[1]);
-    rlDeleteBuffers(model.mesh.vboId[2]);
-
-    rlDeleteVertexArrays(model.mesh.vaoId);
+    free(cubicmapPixels);   // Free image pixel data
     
-    if (model.mesh.vaoId > 0) TraceLog(INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", model.mesh.vaoId);
-    else TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i] Unloaded model data from VRAM (GPU)", model.mesh.vboId[0], model.mesh.vboId[1], model.mesh.vboId[2]);
-}
-
-// Link a texture to a model
-void SetModelTexture(Model *model, Texture2D texture)
-{
-    if (texture.id <= 0)
-    {
-        // Use default white texture (use mesh color)
-        model->texture.id = whiteTexture;               // OpenGL 1.1
-        model->shader.texDiffuseId = whiteTexture;      // OpenGL 3.3 / ES 2.0
-    }
-    else
-    {
-        model->texture = texture;
-        model->shader.texDiffuseId = texture.id;
-    }
+    return mesh;
 }
 
 // Draw a model (with texture if set)
@@ -1177,60 +1130,25 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float
 // Draw a billboard
 void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint)
 {
-    // NOTE: Billboard size will maintain texture aspect ratio, size will be billboard width
-    Vector2 sizeRatio = { size, size * (float)texture.height/texture.width };
-
-    Matrix viewMatrix = MatrixLookAt(camera.position, camera.target, camera.up);
-    MatrixTranspose(&viewMatrix);
-
-    Vector3 right = { viewMatrix.m0, viewMatrix.m4, viewMatrix.m8 };
-    //Vector3 up = { viewMatrix.m1, viewMatrix.m5, viewMatrix.m9 };
+    Rectangle sourceRec = { 0, 0, texture.width, texture.height };
     
-    // NOTE: Billboard locked to axis-Y
-    Vector3 up = { 0.0f, 1.0f, 0.0f };
-/*
-    a-------b
-    |       |
-    |   *   |
-    |       |
-    d-------c
-*/
-    VectorScale(&right, sizeRatio.x/2);
-    VectorScale(&up, sizeRatio.y/2);
-
-    Vector3 p1 = VectorAdd(right, up);
-    Vector3 p2 = VectorSubtract(right, up);
-
-    Vector3 a = VectorSubtract(center, p2);
-    Vector3 b = VectorAdd(center, p1);
-    Vector3 c = VectorAdd(center, p2);
-    Vector3 d = VectorSubtract(center, p1);
-
-    rlEnableTexture(texture.id);
-
-    rlBegin(RL_QUADS);
-        rlColor4ub(tint.r, tint.g, tint.b, tint.a);
-
-        rlTexCoord2f(0.0f, 0.0f); rlVertex3f(a.x, a.y, a.z);
-        rlTexCoord2f(0.0f, 1.0f); rlVertex3f(d.x, d.y, d.z);
-        rlTexCoord2f(1.0f, 1.0f); rlVertex3f(c.x, c.y, c.z);
-        rlTexCoord2f(1.0f, 0.0f); rlVertex3f(b.x, b.y, b.z);
-    rlEnd();
-
-    rlDisableTexture();
+    DrawBillboardRec(camera, texture, sourceRec, center, size, tint);
 }
 
 // Draw a billboard (part of a texture defined by a rectangle)
 void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint)
 {
     // NOTE: Billboard size will maintain sourceRec aspect ratio, size will represent billboard width
-    Vector2 sizeRatio = { size, size * (float)sourceRec.height/sourceRec.width };
+    Vector2 sizeRatio = { size, size*(float)sourceRec.height/sourceRec.width };
 
     Matrix viewMatrix = MatrixLookAt(camera.position, camera.target, camera.up);
     MatrixTranspose(&viewMatrix);
 
     Vector3 right = { viewMatrix.m0, viewMatrix.m4, viewMatrix.m8 };
-    Vector3 up = { viewMatrix.m1, viewMatrix.m5, viewMatrix.m9 };
+    //Vector3 up = { viewMatrix.m1, viewMatrix.m5, viewMatrix.m9 };
+    
+    // NOTE: Billboard locked on axis-Y
+    Vector3 up = { 0.0f, 1.0f, 0.0f };
 /*
     a-------b
     |       |
@@ -1275,7 +1193,7 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec
 }
 
 // Draw a bounding box with wires
-void DrawBoundingBox(BoundingBox box)
+void DrawBoundingBox(BoundingBox box, Color color)
 {
     Vector3 size;
     
@@ -1285,7 +1203,7 @@ void DrawBoundingBox(BoundingBox box)
     
     Vector3 center = { box.min.x + size.x/2.0f, box.min.y + size.y/2.0f, box.min.z + size.z/2.0f };
     
-    DrawCubeWires(center, size.x, size.y, size.z, GREEN);
+    DrawCubeWires(center, size.x, size.y, size.z, color);
 }
 
 // Detect collision between two spheres
@@ -1306,14 +1224,14 @@ bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, floa
 
 // Detect collision between two boxes
 // NOTE: Boxes are defined by two points minimum and maximum
-bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2)
+bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2)
 {
     bool collision = true;
 
-    if ((maxBBox1.x >= minBBox2.x) && (minBBox1.x <= maxBBox2.x))
+    if ((box1.max.x >= box2.min.x) && (box1.min.x <= box2.max.x))
     {
-        if ((maxBBox1.y < minBBox2.y) || (minBBox1.y > maxBBox2.y)) collision = false;
-        if ((maxBBox1.z < minBBox2.z) || (minBBox1.z > maxBBox2.z)) collision = false;
+        if ((box1.max.y < box2.min.y) || (box1.min.y > box2.max.y)) collision = false;
+        if ((box1.max.z < box2.min.z) || (box1.min.z > box2.max.z)) collision = false;
     }
     else collision = false;
 
@@ -1321,30 +1239,22 @@ bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, V
 }
 
 // Detect collision between box and sphere
-bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, float radiusSphere)
+bool CheckCollisionBoxSphere(BoundingBox box, Vector3 centerSphere, float radiusSphere)
 {
     bool collision = false;
 
-    if ((centerSphere.x - minBBox.x > radiusSphere) && (centerSphere.y - minBBox.y > radiusSphere) && (centerSphere.z - minBBox.z > radiusSphere) &&
-            (maxBBox.x - centerSphere.x > radiusSphere) && (maxBBox.y - centerSphere.y > radiusSphere) && (maxBBox.z - centerSphere.z > radiusSphere))
-    {
-        collision = true;
-    }
-    else
-    {
-        float dmin = 0;
+    float dmin = 0;
 
-        if (centerSphere.x - minBBox.x <= radiusSphere) dmin += (centerSphere.x - minBBox.x)*(centerSphere.x - minBBox.x);
-        else if (maxBBox.x - centerSphere.x <= radiusSphere) dmin += (centerSphere.x - maxBBox.x)*(centerSphere.x - maxBBox.x);
+    if (centerSphere.x < box.min.x) dmin += pow(centerSphere.x - box.min.x, 2);
+    else if (centerSphere.x > box.max.x) dmin += pow(centerSphere.x - box.max.x, 2);
 
-        if (centerSphere.y - minBBox.y <= radiusSphere) dmin += (centerSphere.y - minBBox.y)*(centerSphere.y - minBBox.y);
-        else if (maxBBox.y - centerSphere.y <= radiusSphere) dmin += (centerSphere.y - maxBBox.y)*(centerSphere.y - maxBBox.y);
+    if (centerSphere.y < box.min.y) dmin += pow(centerSphere.y - box.min.y, 2);
+    else if (centerSphere.y > box.max.y) dmin += pow(centerSphere.y - box.max.y, 2);
 
-        if (centerSphere.z - minBBox.z <= radiusSphere) dmin += (centerSphere.z - minBBox.z)*(centerSphere.z - minBBox.z);
-        else if (maxBBox.z - centerSphere.z <= radiusSphere) dmin += (centerSphere.z - maxBBox.z)*(centerSphere.z - maxBBox.z);
+    if (centerSphere.z < box.min.z) dmin += pow(centerSphere.z - box.min.z, 2);
+    else if (centerSphere.z > box.max.z) dmin += pow(centerSphere.z - box.max.z, 2);
 
-        if (dmin <= radiusSphere*radiusSphere) collision = true;
-    }
+    if (dmin <= (radiusSphere*radiusSphere)) collision = true;
 
     return collision;
 }
@@ -1395,17 +1305,17 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi
 }
 
 // Detect collision between ray and bounding box
-bool CheckCollisionRayBox(Ray ray, Vector3 minBBox, Vector3 maxBBox)
+bool CheckCollisionRayBox(Ray ray, BoundingBox box)
 {
     bool collision = false;
     
     float t[8];
-    t[0] = (minBBox.x - ray.position.x)/ray.direction.x;
-    t[1] = (maxBBox.x - ray.position.x)/ray.direction.x;
-    t[2] = (minBBox.y - ray.position.y)/ray.direction.y;
-    t[3] = (maxBBox.y - ray.position.y)/ray.direction.y;
-    t[4] = (minBBox.z - ray.position.z)/ray.direction.z;
-    t[5] = (maxBBox.z - ray.position.z)/ray.direction.z;
+    t[0] = (box.min.x - ray.position.x)/ray.direction.x;
+    t[1] = (box.max.x - ray.position.x)/ray.direction.x;
+    t[2] = (box.min.y - ray.position.y)/ray.direction.y;
+    t[3] = (box.max.y - ray.position.y)/ray.direction.y;
+    t[4] = (box.min.z - ray.position.z)/ray.direction.z;
+    t[5] = (box.max.z - ray.position.z)/ray.direction.z;
     t[6] = fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5]));
     t[7] = fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5]));
     
@@ -1712,7 +1622,7 @@ static Mesh LoadOBJ(const char *fileName)
 
     // First reading pass: Get numVertex, numNormals, numTexCoords, numTriangles
     // NOTE: vertex, texcoords and normals could be optimized (to be used indexed on faces definition)
-    // NOTE: faces MUST be defined as TRIANGLES, not QUADS
+    // NOTE: faces MUST be defined as TRIANGLES (3 vertex per face)
     while(!feof(objFile))
     {
         fscanf(objFile, "%c", &dataType);

+ 31 - 15
src/raygui.c

@@ -59,16 +59,16 @@ static int style[NUM_PROPERTIES] = {
     1,                  // GLOBAL_BORDER_WIDTH
     0xf5f5f5ff,         // BACKGROUND_COLOR
     1,                  // LABEL_BORDER_WIDTH
-    0x000000ff,         // LABEL_TEXT_COLOR
+    0x4d4d4dff,         // LABEL_TEXT_COLOR
     20,                 // LABEL_TEXT_PADDING
     2,                  // BUTTON_BORDER_WIDTH
     20,                 // BUTTON_TEXT_PADDING
     0x828282ff,         // BUTTON_DEFAULT_BORDER_COLOR
     0xc8c8c8ff,         // BUTTON_DEFAULT_INSIDE_COLOR
-    0x000000ff,         // BUTTON_DEFAULT_TEXT_COLOR
+    0x4d4d4dff,         // BUTTON_DEFAULT_TEXT_COLOR
     0xc8c8c8ff,         // BUTTON_HOVER_BORDER_COLOR
     0xffffffff,         // BUTTON_HOVER_INSIDE_COLOR
-    0x000000ff,         // BUTTON_HOVER_TEXT_COLOR
+    0x353535ff,         // BUTTON_HOVER_TEXT_COLOR
     0x7bb0d6ff,         // BUTTON_PRESSED_BORDER_COLOR
     0xbcecffff,         // BUTTON_PRESSED_INSIDE_COLOR
     0x5f9aa7ff,         // BUTTON_PRESSED_TEXT_COLOR
@@ -120,7 +120,7 @@ static int style[NUM_PROPERTIES] = {
     0x000000ff,         // SPINNER_PRESSED_TEXT_COLOR
     1,                  // COMBOBOX_PADDING
     30,                 // COMBOBOX_BUTTON_WIDTH
-    30,                 // COMBOBOX_BUTTON_HEIGHT
+    20,                 // COMBOBOX_BUTTON_HEIGHT
     1,                  // COMBOBOX_BORDER_WIDTH
     0x828282ff,         // COMBOBOX_DEFAULT_BORDER_COLOR
     0xc8c8c8ff,         // COMBOBOX_DEFAULT_INSIDE_COLOR
@@ -258,15 +258,28 @@ bool GuiToggleButton(Rectangle bounds, const char *text, bool toggle)
     //--------------------------------------------------------------------   
     if (toggleButton.width < textWidth) toggleButton.width = textWidth + style[TOGGLE_TEXT_PADDING];
     if (toggleButton.height < textHeight) toggleButton.height = textHeight + style[TOGGLE_TEXT_PADDING]/2;
+    
+    if (toggle) toggleState = TOGGLE_ACTIVE;
+    else toggleState = TOGGLE_UNACTIVE;
+    
     if (CheckCollisionPointRec(mousePoint, toggleButton))
     {
         if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) toggleState = TOGGLE_PRESSED;
-        else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) toggleState = TOGGLE_ACTIVE;
+        else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
+        {
+            if (toggle)
+            {
+                toggle = false;
+                toggleState = TOGGLE_UNACTIVE;
+            }
+            else
+            {
+                toggle = true;
+                toggleState = TOGGLE_ACTIVE;
+            }
+        }
         else toggleState = TOGGLE_HOVER;
     }
-     
-    if (toggleState == TOGGLE_ACTIVE && !toggle) toggle = true;
-    if (toggle) toggleState = TOGGLE_ACTIVE;
     //--------------------------------------------------------------------   
     
     // Draw control
@@ -789,11 +802,11 @@ int GuiSpinner(Rectangle bounds, int value, int minValue, int maxValue)
 // NOTE: Requires static variables: framesCounter - ERROR!
 char *GuiTextBox(Rectangle bounds, char *text)
 {
-    #define MAX_CHARS_LENGTH  	20
-    #define KEY_BACKSPACE_TEXT   3
+    #define MAX_CHARS_LENGTH  	 20
+    #define KEY_BACKSPACE_TEXT  259     // GLFW BACKSPACE: 3 + 256
     
     int initPos = bounds.x + 4;
-    char letter = -1;
+    int letter = -1;
     static int framesCounter = 0;
     Vector2 mousePoint = GetMousePosition();
     
@@ -822,12 +835,15 @@ char *GuiTextBox(Rectangle bounds, char *text)
             }
             else
             {
-                for (int i = 0; i < MAX_CHARS_LENGTH; i++)
+                if ((letter >= 32) && (letter < 127))
                 {
-                    if (text[i] == '\0')
+                    for (int i = 0; i < MAX_CHARS_LENGTH; i++)
                     {
-                        text[i] = letter;
-                        break;
+                        if (text[i] == '\0')
+                        {
+                            text[i] = (char)letter;
+                            break;
+                        }
                     }
                 }
             }

+ 41 - 36
src/raylib.h

@@ -309,11 +309,20 @@ typedef struct SpriteFont {
 
 // Camera type, defines a camera position/orientation in 3d space
 typedef struct Camera {
-    Vector3 position;
-    Vector3 target;
-    Vector3 up;
+    Vector3 position;       // Camera position
+    Vector3 target;         // Camera target it looks-at
+    Vector3 up;             // Camera up vector (rotation over its axis)
+    float fovy;             // Field-Of-View apperture in Y (degrees)
 } Camera;
 
+// Camera2D type, defines a 2d camera
+typedef struct Camera2D {
+    Vector2 position;       // Camera position
+    Vector2 origin;         // Camera origin (for rotation and zoom)
+    float rotation;         // Camera rotation in degrees
+    float zoom;             // Camera zoom (scaling), should be 1.0f by default
+} Camera2D;
+
 // Bounding box type
 typedef struct BoundingBox {
     Vector3 min;
@@ -338,12 +347,7 @@ typedef struct Mesh {
 
 // Shader type (generic shader)
 typedef struct Shader {
-    unsigned int id;                // Shader program id
-
-    // TODO: This should be Texture2D objects
-    unsigned int texDiffuseId;      // Diffuse texture id
-    unsigned int texNormalId;       // Normal texture id
-    unsigned int texSpecularId;     // Specular texture id
+    unsigned int id;            // Shader program id
     
     // Variable attributes
     int vertexLoc;        // Vertex attribute location point (vertex shader)
@@ -361,20 +365,19 @@ typedef struct Shader {
 } Shader;
 
 // Material type
-// TODO: Redesign material-shaders-textures system
 typedef struct Material {
-    //Shader shader;
+    Shader shader;              // Standard shader (supports 3 map types: diffuse, normal, specular)
 
-    //Texture2D texDiffuse;      // Diffuse texture
-    //Texture2D texNormal;       // Normal texture
-    //Texture2D texSpecular;     // Specular texture
+    Texture2D texDiffuse;       // Diffuse texture
+    Texture2D texNormal;        // Normal texture
+    Texture2D texSpecular;      // Specular texture
     
-    Color colDiffuse;
-    Color colAmbient;
-    Color colSpecular;
+    Color colDiffuse;           // Diffuse color
+    Color colAmbient;           // Ambient color
+    Color colSpecular;          // Specular color
     
-    float glossiness;
-    float normalDepth;
+    float glossiness;           // Glossiness level
+    float normalDepth;          // Normal map depth
 } Material;
 
 // 3d Model type
@@ -382,9 +385,7 @@ typedef struct Material {
 typedef struct Model {
     Mesh mesh;
     Matrix transform;
-    Texture2D texture;    // Only for OpenGL 1.1, on newer versions this should be in the shader
-    Shader shader;
-	//Material material;
+    Material material;
 } Model;
 
 // Ray type (useful for raycast)
@@ -530,7 +531,8 @@ int GetScreenHeight(void);                                  // Get current scree
 
 void ClearBackground(Color color);                          // Sets Background Color
 void BeginDrawing(void);                                    // Setup drawing canvas to start drawing
-void BeginDrawingEx(int blendMode, Shader shader, Matrix transform);   // Setup drawing canvas with extended parameters
+void BeginDrawingEx(Camera2D camera);                       // Setup drawing canvas with 2d camera
+void BeginDrawingPro(int blendMode, Shader shader, Matrix transform);   // Setup drawing canvas with pro parameters
 void EndDrawing(void);                                      // End canvas drawing and Swap Buffers (Double Buffering)
 
 void Begin3dMode(Camera camera);                            // Initializes 3D mode for drawing (Camera setup)
@@ -632,6 +634,7 @@ void UpdateCameraPlayer(Camera *camera, Vector3 *position); // Update camera and
 
 void SetCameraPosition(Vector3 position);                   // Set internal camera position
 void SetCameraTarget(Vector3 target);                       // Set internal camera target
+void SetCameraFovy(float fovy);                             // Set internal camera field-of-view-y
 
 void SetCameraPanControl(int panKey);                       // Set camera pan key to combine with mouse movement (free camera)
 void SetCameraAltControl(int altKey);                       // Set camera alt key to combine with mouse movement (free camera)
@@ -693,9 +696,12 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp);
 Image ImageCopy(Image image);                                                                      // Create an image duplicate (useful for transformations)
 void ImageCrop(Image *image, Rectangle crop);                                                      // Crop an image to a defined rectangle
 void ImageResize(Image *image, int newWidth, int newHeight);                                       // Resize and image (bilinear filtering)
-void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec);                         // Draw a source image within a destination image
+void ImageResizeNN(Image *image,int newWidth,int newHeight);                                       // Resize and image (Nearest-Neighbor scaling algorithm)
 Image ImageText(const char *text, int fontSize, Color color);                                      // Create an image from text (default font)
 Image ImageTextEx(SpriteFont font, const char *text, int fontSize, int spacing, Color tint);       // Create an image from text (custom sprite font)
+void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec);                         // Draw a source image within a destination image
+void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, Color color);     // Draw text (default font) within an image (destination)
+void ImageDrawTextEx(Image *dst, Vector2 position, SpriteFont font, const char *text, int fontSize, int spacing, Color color); // Draw text (custom sprite font) within an image (destination)
 void ImageFlipVertical(Image *image);                                                              // Flip image vertically
 void ImageFlipHorizontal(Image *image);                                                            // Flip image horizontally
 void ImageColorTint(Image *image, Color color);                                                    // Modify image color: tint
@@ -743,7 +749,6 @@ void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Col
 void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone
 void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires
 void DrawPlane(Vector3 centerPos, Vector2 size, Color color);                                      // Draw a plane XZ
-void DrawQuad(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Color color);                        // Draw a quad
 void DrawRay(Ray ray, Color color);                                                                // Draw a ray line
 void DrawGrid(int slices, float spacing);                                                          // Draw a grid (centered at (0, 0, 0))
 void DrawGizmo(Vector3 position);                                                                  // Draw simple gizmo
@@ -753,7 +758,7 @@ void DrawGizmo(Vector3 position);
 // Model 3d Loading and Drawing Functions (Module: models)
 //------------------------------------------------------------------------------------
 Model LoadModel(const char *fileName);                                                             // Load a 3d model (.OBJ)
-Model LoadModelEx(Mesh data);                                                                      // Load a 3d model (from vertex data)
+Model LoadModelEx(Mesh data);                                                                      // Load a 3d model (from mesh data)
 //Model LoadModelFromRES(const char *rresName, int resId);                                         // TODO: Load a 3d model from rRES file (raylib Resource)
 Model LoadHeightmap(Image heightmap, Vector3 size);                                                // Load a heightmap image as a 3d model
 Model LoadCubicmap(Image cubicmap);                                                                // Load a map image as a 3d model (cubes based)
@@ -763,19 +768,19 @@ void SetModelTexture(Model *model, Texture2D texture);
 void DrawModel(Model model, Vector3 position, float scale, Color tint);                            // Draw a model (with texture if set)
 void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint);      // Draw a model with extended parameters
 void DrawModelWires(Model model, Vector3 position, float scale, Color color);                      // Draw a model wires (with texture if set)
-void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint);      // Draw a model wires (with texture if set) with extended parameters
-void DrawBoundingBox(BoundingBox box);                                                             // Draw bounding box (wires)
+void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
+void DrawBoundingBox(BoundingBox box, Color color);                                                // Draw bounding box (wires)
 
 void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint);                         // Draw a billboard texture
 void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec
 
-BoundingBox CalculateBoundingBox(Mesh mesh);                                                       // Calculate mesh bounding box limits
+BoundingBox CalculateBoundingBox(Mesh mesh);                                                                    // Calculate mesh bounding box limits
 bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB);                     // Detect collision between two spheres
-bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2);               // Detect collision between two boxes
-bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, float radiusSphere);       // Detect collision between box and sphere
+bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2);                                                   // Detect collision between two bounding boxes
+bool CheckCollisionBoxSphere(BoundingBox box, Vector3 centerSphere, float radiusSphere);                        // Detect collision between box and sphere
 bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius);                              // Detect collision between ray and sphere
 bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadius, Vector3 *collisionPoint);   // Detect collision between ray and sphere with extended parameters and collision point detection
-bool CheckCollisionRayBox(Ray ray, Vector3 minBBox, Vector3 maxBBox);                                           // Detect collision between ray and box
+bool CheckCollisionRayBox(Ray ray, BoundingBox box);                                                            // Detect collision between ray and box
 Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius);   // Detect collision of player radius with cubicmap
                                                                                                                 // NOTE: Return the normal vector of the impacted surface
 //------------------------------------------------------------------------------------
@@ -795,10 +800,10 @@ int GetShaderLocation(Shader shader, const char *uniformName);
 void SetShaderValue(Shader shader, int uniformLoc, float *value, int size);             // Set shader uniform value (float)
 void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size);              // Set shader uniform value (int)
 void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat);                   // Set shader uniform value (matrix 4x4)
-void SetShaderMapDiffuse(Shader *shader, Texture2D texture);                            // Default diffuse shader map texture assignment
-void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture);    // Normal map texture shader assignment
-void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture);  // Specular map texture shader assignment
-void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit); // TODO: Generic shader map assignment
+//void SetShaderMapDiffuse(Shader *shader, Texture2D texture);                            // Default diffuse shader map texture assignment
+//void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture);    // Normal map texture shader assignment
+//void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture);  // Specular map texture shader assignment
+//void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit); // TODO: Generic shader map assignment
 
 void SetBlendMode(int mode);                                        // Set blending mode (alpha, additive, multiplied)
 

+ 1 - 1
src/raymath.h

@@ -803,7 +803,7 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top,
 // Returns perspective projection matrix
 RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far)
 {
-    double top = near*tanf(fovy*PI/360.0f);
+    double top = near*tan(fovy*PI/360.0);
     double right = top*aspect;
 
     return MatrixFrustum(-right, right, -top, top, near, far);

+ 71 - 232
src/rlgl.c

@@ -1421,7 +1421,7 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro
 
 #if defined(GRAPHICS_API_OPENGL_11)
     glEnable(GL_TEXTURE_2D);
-    glBindTexture(GL_TEXTURE_2D, model.texture.id);
+    glBindTexture(GL_TEXTURE_2D, model.material.texDiffuse.id);
 
     // NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model
     glEnableClientState(GL_VERTEX_ARRAY);                     // Enable vertex array
@@ -1452,7 +1452,7 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro
 #endif
 
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    glUseProgram(model.shader.id);
+    glUseProgram(model.material.shader.id);
     
     // At this point the modelview matrix just contains the view matrix (camera)
     // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix()
@@ -1476,28 +1476,30 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro
     Matrix matMVP = MatrixMultiply(matModelView, matProjection);        // Transform to screen-space coordinates
 
     // Send combined model-view-projection matrix to shader
-    glUniformMatrix4fv(model.shader.mvpLoc, 1, false, MatrixToFloat(matMVP));
+    glUniformMatrix4fv(model.material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP));
 
     // Apply color tinting to model
     // NOTE: Just update one uniform on fragment shader
     float vColor[4] = { (float)color.r/255, (float)color.g/255, (float)color.b/255, (float)color.a/255 };
-    glUniform4fv(model.shader.tintColorLoc, 1, vColor);
+    glUniform4fv(model.material.shader.tintColorLoc, 1, vColor);
 
     // Set shader textures (diffuse, normal, specular)
     glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, model.shader.texDiffuseId);
-    glUniform1i(model.shader.mapDiffuseLoc, 0);
-
-    if (model.shader.texNormalId != 0)
+    glBindTexture(GL_TEXTURE_2D, model.material.texDiffuse.id);
+    glUniform1i(model.material.shader.mapDiffuseLoc, 0);        // Texture fits in active texture unit 0
+    
+    if (model.material.texNormal.id != 0)
     {
         glActiveTexture(GL_TEXTURE1);
-        glBindTexture(GL_TEXTURE_2D, model.shader.texNormalId);
+        glBindTexture(GL_TEXTURE_2D, model.material.texNormal.id);
+        glUniform1i(model.material.shader.mapNormalLoc, 1);     // Texture fits in active texture unit 1
     }
     
-    if (model.shader.texSpecularId != 0)
+    if (model.material.texSpecular.id != 0)
     {
         glActiveTexture(GL_TEXTURE2);
-        glBindTexture(GL_TEXTURE_2D, model.shader.texSpecularId);
+        glBindTexture(GL_TEXTURE_2D, model.material.texSpecular.id);
+        glUniform1i(model.material.shader.mapSpecularLoc, 2);   // Texture fits in active texture unit 2
     }
 
     if (vaoSupported)
@@ -1508,19 +1510,19 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro
     {
         // Bind model VBOs data
         glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[0]);
-        glVertexAttribPointer(model.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-        glEnableVertexAttribArray(model.shader.vertexLoc);
+        glVertexAttribPointer(model.material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
+        glEnableVertexAttribArray(model.material.shader.vertexLoc);
 
         glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[1]);
-        glVertexAttribPointer(model.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
-        glEnableVertexAttribArray(model.shader.texcoordLoc);
+        glVertexAttribPointer(model.material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
+        glEnableVertexAttribArray(model.material.shader.texcoordLoc);
 
         // Add normals support
-        if (model.shader.normalLoc != -1)
+        if (model.material.shader.normalLoc != -1)
         {
             glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[2]);
-            glVertexAttribPointer(model.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
-            glEnableVertexAttribArray(model.shader.normalLoc);
+            glVertexAttribPointer(model.material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
+            glEnableVertexAttribArray(model.material.shader.normalLoc);
         }
     }
 
@@ -1531,13 +1533,13 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro
     //glDisableVertexAttribArray(model.shader.texcoordLoc);
     //if (model.shader.normalLoc != -1) glDisableVertexAttribArray(model.shader.normalLoc);
     
-    if (model.shader.texNormalId != 0)
+    if (model.material.texNormal.id != 0)
     {
         glActiveTexture(GL_TEXTURE1);
         glBindTexture(GL_TEXTURE_2D, 0);
     }
     
-    if (model.shader.texSpecularId != 0)
+    if (model.material.texSpecular.id != 0)
     {
         glActiveTexture(GL_TEXTURE2);
         glBindTexture(GL_TEXTURE_2D, 0);
@@ -1611,54 +1613,24 @@ void rlglInitGraphics(int offsetX, int offsetY, int width, int height)
 }
 
 // Get world coordinates from screen coordinates
-// NOTE: Using global variables: screenWidth, screenHeight
 Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view)
 {
-    Vector3 result = { 0.0f, 0.0f, 0.0f };   // Object coordinates
+    Vector3 result = { 0.0f, 0.0f, 0.0f };
     
-    //GLint viewport[4];
-    //glGetIntegerv(GL_VIEWPORT, viewport); // Not available on OpenGL ES 2.0
-
-    // Viewport data
-    int x = 0;                  // viewport[0]
-    int y = 0;                  // viewport[1]
-    int width = screenWidth;    // viewport[2]
-    int height = screenHeight;  // viewport[3]
+    // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it
+    Matrix matProjView = MatrixMultiply(proj, view);
+    MatrixInvert(&matProjView);
     
-    Matrix modelviewprojection = MatrixMultiply(view, proj);
-    MatrixInvert(&modelviewprojection);
-/*
-    // NOTE: Compute unproject using Vector3
-
-    // Transformation of normalized coordinates between -1 and 1
-    result.x = ((source.x - (float)x)/(float)width)*2.0f - 1.0f;
-    result.y = ((source.y - (float)y)/(float)height)*2.0f - 1.0f;
-    result.z = source.z*2.0f - 1.0f;
-
-    // Object coordinates (multiply vector by matrix)
-    VectorTransform(&result, modelviewprojection);
-*/
- 
-    // NOTE: Compute unproject using Quaternion (Vector4)
-    Quaternion quat;
+    // Create quaternion from source point
+    Quaternion quat = { source.x, source.y, source.z, 1.0f };
     
-    quat.x = ((source.x - (float)x)/(float)width)*2.0f - 1.0f;
-    quat.y = ((source.y - (float)y)/(float)height)*2.0f - 1.0f;
-    quat.z = source.z*2.0f - 1.0f;
-    quat.w = 1.0f;
+    // Multiply quat point by unproject matrix
+    QuaternionTransform(&quat, matProjView);
     
-    QuaternionTransform(&quat, modelviewprojection);
-
-    if (quat.w != 0.0f)
-    {
-        quat.x /= quat.w;
-        quat.y /= quat.w;
-        quat.z /= quat.w;
-    }
-
-    result.x = quat.x;
-    result.y = quat.y;
-    result.z = quat.z;
+    // Normalized world points in vectors
+    result.x = quat.x/quat.w;
+    result.y = quat.y/quat.w;
+    result.z = quat.z/quat.w;
 
     return result;
 }
@@ -1892,9 +1864,9 @@ void rlglGenerateMipmaps(Texture2D texture)
         void *data = rlglReadTexturePixels(texture);
         
         // NOTE: data size is reallocated to fit mipmaps data
+        // NOTE: CPU mipmap generation only supports RGBA 32bit data
         int mipmapCount = GenerateMipmaps(data, texture.width, texture.height);
 
-        // TODO: Adjust mipmap size depending on texture format!
         int size = texture.width*texture.height*4;  // RGBA 32bit only
         int offset = size;
 
@@ -1915,6 +1887,9 @@ void rlglGenerateMipmaps(Texture2D texture)
         
         TraceLog(WARNING, "[TEX ID %i] Mipmaps generated manually on CPU side", texture.id);
         
+        // NOTE: Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data
+        free(data):
+        
 #elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
         glGenerateMipmap(GL_TEXTURE_2D);    // Generate mipmaps automatically
         TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically", texture.id);
@@ -1924,7 +1899,7 @@ void rlglGenerateMipmaps(Texture2D texture)
 #endif
     }
     else TraceLog(WARNING, "[TEX ID %i] Mipmaps can not be generated", texture.id);
-        
+
     glBindTexture(GL_TEXTURE_2D, 0);
 }
 
@@ -1934,22 +1909,29 @@ Model rlglLoadModel(Mesh mesh)
     Model model;
 
     model.mesh = mesh;
-    model.transform = MatrixIdentity();
     model.mesh.vaoId = 0;       // Vertex Array Object
-    model.mesh.vboId[0] = 0;    // Vertex position VBO
-    model.mesh.vboId[1] = 0;    // Texcoords VBO
-    model.mesh.vboId[2] = 0;    // Normals VBO
+    model.mesh.vboId[0] = 0;    // Vertex positions VBO
+    model.mesh.vboId[1] = 0;    // Vertex texcoords VBO
+    model.mesh.vboId[2] = 0;    // Vertex normals VBO
+    
+    model.transform = MatrixIdentity();
 
 #if defined(GRAPHICS_API_OPENGL_11)
-    model.texture.id = 0;       // No texture required
-    model.shader.id = 0;        // No shader used
+    model.material.texDiffuse.id = 0;    // No texture required
+    model.material.shader.id = 0;        // No shader used
 
 #elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    model.texture.id = whiteTexture;    // Default whiteTexture
-    model.texture.width = 1;            // Default whiteTexture width
-    model.texture.height = 1;           // Default whiteTexture height
-    model.texture.format = UNCOMPRESSED_R8G8B8A8; // Default whiteTexture format
-    model.shader = simpleShader;        // Default model shader
+    model.material.shader = simpleShader;           // Default model shader
+    
+    model.material.texDiffuse.id = whiteTexture;    // Default whiteTexture
+    model.material.texDiffuse.width = 1;            // Default whiteTexture width
+    model.material.texDiffuse.height = 1;           // Default whiteTexture height
+    model.material.texDiffuse.format = UNCOMPRESSED_R8G8B8A8; // Default whiteTexture format
+    
+    model.material.texNormal.id = 0;        // By default, no normal texture
+    model.material.texSpecular.id = 0;      // By default, no specular texture
+    
+    // TODO: Fill default material properties (color, glossiness...)
     
     GLuint vaoModel = 0;         // Vertex Array Objects (VAO)
     GLuint vertexBuffer[3];      // Vertex Buffer Objects (VBO)
@@ -1967,20 +1949,20 @@ Model rlglLoadModel(Mesh mesh)
     // Enable vertex attributes: position
     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]);
     glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.vertices, GL_STATIC_DRAW);
-    glVertexAttribPointer(model.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-    glEnableVertexAttribArray(model.shader.vertexLoc);
+    glVertexAttribPointer(model.material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
+    glEnableVertexAttribArray(model.material.shader.vertexLoc);
 
     // Enable vertex attributes: texcoords
     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[1]);
     glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh.vertexCount, mesh.texcoords, GL_STATIC_DRAW);
-    glVertexAttribPointer(model.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
-    glEnableVertexAttribArray(model.shader.texcoordLoc);
+    glVertexAttribPointer(model.material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
+    glEnableVertexAttribArray(model.material.shader.texcoordLoc);
 
     // Enable vertex attributes: normals
     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]);
     glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.normals, GL_STATIC_DRAW);
-    glVertexAttribPointer(model.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
-    glEnableVertexAttribArray(model.shader.normalLoc);
+    glVertexAttribPointer(model.material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
+    glEnableVertexAttribArray(model.material.shader.normalLoc);
 
     model.mesh.vboId[0] = vertexBuffer[0];     // Vertex position VBO
     model.mesh.vboId[1] = vertexBuffer[1];     // Texcoords VBO
@@ -2180,11 +2162,6 @@ Shader LoadShader(char *vsFileName, char *fsFileName)
         if (shader.id != 0)
         {
             TraceLog(INFO, "[SHDR ID %i] Custom shader loaded successfully", shader.id);
-        
-            // Set shader textures ids (all 0 by default)
-            shader.texDiffuseId = 0;
-            shader.texNormalId = 0;
-            shader.texSpecularId = 0;
 
             // Get handles to GLSL input attibute locations
             //-------------------------------------------------------------------
@@ -2341,28 +2318,7 @@ void SetCustomShader(Shader shader)
     if (currentShader.id != shader.id)
     {
         rlglDraw();
-
         currentShader = shader;
-/*
-        if (vaoSupported) glBindVertexArray(vaoQuads);
-        
-        // Enable vertex attributes: position
-        glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]);
-        glEnableVertexAttribArray(currentShader.vertexLoc);
-        glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-
-        // Enable vertex attributes: texcoords
-        glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]);
-        glEnableVertexAttribArray(currentShader.texcoordLoc);
-        glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
-
-        // Enable vertex attributes: colors
-        glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]);
-        glEnableVertexAttribArray(currentShader.colorLoc);
-        glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
-
-        if (vaoSupported) glBindVertexArray(0);     // Unbind VAO
-*/
     }
 #endif
 }
@@ -2385,7 +2341,7 @@ void SetPostproShader(Shader shader)
     texture.width = screenWidth;
     texture.height = screenHeight;
 
-    SetShaderMapDiffuse(&postproQuad.shader, texture);
+    postproQuad.material.texDiffuse = texture;
     
     //TraceLog(DEBUG, "Postproquad texture id: %i", postproQuad.texture.id);
     //TraceLog(DEBUG, "Postproquad shader diffuse map id: %i", postproQuad.shader.texDiffuseId);
@@ -2413,7 +2369,7 @@ void SetDefaultShader(void)
 void SetModelShader(Model *model, Shader shader)
 {
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    model->shader = shader;
+    model->material.shader = shader;
 
     if (vaoSupported) glBindVertexArray(model->mesh.vaoId);
 
@@ -2433,9 +2389,7 @@ void SetModelShader(Model *model, Shader shader)
     glVertexAttribPointer(shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
 
     if (vaoSupported) glBindVertexArray(0);     // Unbind VAO
-    
-    // NOTE: If SetModelTexture() is called previously, texture is not assigned to new shader
-    if (model->texture.id > 0) model->shader.texDiffuseId = model->texture.id;
+
 #elif (GRAPHICS_API_OPENGL_11)
     TraceLog(WARNING, "Shaders not supported on OpenGL 1.1");
 #endif
@@ -2507,104 +2461,6 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat)
 #endif
 }
 
-// Default diffuse shader map texture assignment
-void SetShaderMapDiffuse(Shader *shader, Texture2D texture)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    shader->texDiffuseId = texture.id;
-    
-    glUseProgram(shader->id);
-    
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, shader->texDiffuseId);
-    
-    glUniform1i(shader->mapDiffuseLoc, 0);    // Texture fits in active texture unit 0
-    
-    glBindTexture(GL_TEXTURE_2D, 0);
-    glActiveTexture(GL_TEXTURE0);
-    glUseProgram(0);
-#endif
-}
-
-// Normal map texture shader assignment
-void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    shader->mapNormalLoc = glGetUniformLocation(shader->id, uniformName);
-
-    if (shader->mapNormalLoc == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader->id, uniformName);
-    else
-    {
-        shader->texNormalId = texture.id;
-        
-        glUseProgram(shader->id);
-        
-        glActiveTexture(GL_TEXTURE1);
-        glBindTexture(GL_TEXTURE_2D, shader->texNormalId);
-        
-        glUniform1i(shader->mapNormalLoc, 1);    // Texture fits in active texture unit 1
-        
-        glBindTexture(GL_TEXTURE_2D, 0);
-        glActiveTexture(GL_TEXTURE0);
-        glUseProgram(0);
-    }
-#endif
-}
-
-// Specular map texture shader assignment
-void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    shader->mapSpecularLoc = glGetUniformLocation(shader->id, uniformName);
-
-    if (shader->mapSpecularLoc == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader->id, uniformName);
-    else
-    {
-        shader->texSpecularId = texture.id;
-        
-        glUseProgram(shader->id);
-        
-        glActiveTexture(GL_TEXTURE2);
-        glBindTexture(GL_TEXTURE_2D, shader->texSpecularId);
-        
-        glUniform1i(shader->mapSpecularLoc, 2);    // Texture fits in active texture unit 2
-        
-        glBindTexture(GL_TEXTURE_2D, 0);
-        glActiveTexture(GL_TEXTURE0);
-        glUseProgram(0);
-    }
-#endif
-}
-
-// Generic shader maps assignment
-// TODO: Trying to find a generic shader to allow any kind of map
-// NOTE: mapLocation should be retrieved by user with GetShaderLocation()
-// ISSUE: mapTextureId: Shader should contain a reference to map texture and corresponding textureUnit,
-//        so it can be automatically checked and used in rlglDrawModel()
-void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit)
-{
-/*
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    if (mapLocation == -1) TraceLog(WARNING, "[SHDR ID %i] Map location could not be found", shader->id);
-    else
-    {
-        shader->mapTextureId = texture.id;
-        
-        glUseProgram(shader->id);
-        
-        glActiveTexture(GL_TEXTURE0 + textureUnit);
-        glBindTexture(GL_TEXTURE_2D, shader->mapTextureId);
-        
-        glUniform1i(mapLocation, textureUnit);    // Texture fits in active textureUnit
-        
-        glBindTexture(GL_TEXTURE_2D, 0);
-        glActiveTexture(GL_TEXTURE0);
-        glUseProgram(0);
-    }
-#endif
-*/
-}
-
 // Set blending mode (alpha, additive, multiplied)
 // NOTE: Only 3 blending modes predefined
 void SetBlendMode(int mode)
@@ -2679,15 +2535,11 @@ static void LoadCompressedTexture(unsigned char *data, int width, int height, in
 }
 
 // Load Shader (Vertex and Fragment)
-// NOTE: This shader program is used only for batch buffers (lines, triangles, quads)
+// NOTE: This shader program is used for batch buffers (lines, triangles, quads)
 static Shader LoadDefaultShader(void)
 {
     Shader shader;
 
-    // NOTE: Shaders are written using GLSL 110 (desktop), that is equivalent to GLSL 100 on ES2
-    // NOTE: Detected an error on ATI cards if defined #version 110 while OpenGL 3.3+
-    // Just defined #version 330 despite shader is #version 110
-
     // Vertex shader directly defined, no external file required
 #if defined(GRAPHICS_API_OPENGL_33)
     char vShaderStr[] = "#version 330       \n"
@@ -2695,7 +2547,7 @@ static Shader LoadDefaultShader(void)
         "in vec2 vertexTexCoord;            \n"
         "in vec4 vertexColor;               \n"
         "out vec2 fragTexCoord;             \n"
-        "out vec4 fragTintColor;                \n"
+        "out vec4 fragTintColor;            \n"
 #elif defined(GRAPHICS_API_OPENGL_ES2)
     char vShaderStr[] = "#version 100       \n"
         "attribute vec3 vertexPosition;     \n"
@@ -2704,7 +2556,7 @@ static Shader LoadDefaultShader(void)
         "varying vec2 fragTexCoord;         \n"
         "varying vec4 fragTintColor;        \n"
 #endif
-        "uniform mat4 mvpMatrix;     \n"
+        "uniform mat4 mvpMatrix;            \n"
         "void main()                        \n"
         "{                                  \n"
         "    fragTexCoord = vertexTexCoord; \n"
@@ -2716,7 +2568,7 @@ static Shader LoadDefaultShader(void)
 #if defined(GRAPHICS_API_OPENGL_33)
     char fShaderStr[] = "#version 330       \n"
         "in vec2 fragTexCoord;              \n"
-        "in vec4 fragTintColor;                 \n"
+        "in vec4 fragTintColor;             \n"
 #elif defined(GRAPHICS_API_OPENGL_ES2)
     char fShaderStr[] = "#version 100       \n"
         "precision mediump float;           \n"     // precision required for OpenGL ES2 (WebGL)
@@ -2751,10 +2603,6 @@ static Shader LoadDefaultShader(void)
     shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0");
     shader.mapNormalLoc = -1;       // It can be set later
     shader.mapSpecularLoc = -1;     // It can be set later
-    
-    shader.texDiffuseId = whiteTexture; // Default white texture
-    shader.texNormalId = 0;
-    shader.texSpecularId = 0;
     //--------------------------------------------------------------------
 
     return shader;
@@ -2766,10 +2614,6 @@ static Shader LoadSimpleShader(void)
 {
     Shader shader;
 
-    // NOTE: Shaders are written using GLSL 110 (desktop), that is equivalent to GLSL 100 on ES2
-    // NOTE: Detected an error on ATI cards if defined #version 110 while OpenGL 3.3+
-    // Just defined #version 330 despite shader is #version 110
-
     // Vertex shader directly defined, no external file required
 #if defined(GRAPHICS_API_OPENGL_33)
     char vShaderStr[] = "#version 330       \n"
@@ -2829,10 +2673,6 @@ static Shader LoadSimpleShader(void)
     shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0");
     shader.mapNormalLoc = -1;       // It can be set later
     shader.mapSpecularLoc = -1;     // It can be set later
-    
-    shader.texDiffuseId = whiteTexture; // Default white texture
-    shader.texNormalId = 0;
-    shader.texSpecularId = 0;
     //--------------------------------------------------------------------
 
     return shader;
@@ -2905,7 +2745,6 @@ static void InitializeBuffers(void)
     quads.indices = (unsigned short *)malloc(sizeof(short)*6*MAX_QUADS_BATCH);  // 6 int by quad (indices)
 #endif
 
-
     for (int i = 0; i < (3*4*MAX_QUADS_BATCH); i++) quads.vertices[i] = 0.0f;
     for (int i = 0; i < (2*4*MAX_QUADS_BATCH); i++) quads.texcoords[i] = 0.0f;
     for (int i = 0; i < (4*4*MAX_QUADS_BATCH); i++) quads.colors[i] = 0;
@@ -3106,7 +2945,7 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight)
     int mipmapCount = 1;                // Required mipmap levels count (including base level)
     int width = baseWidth;
     int height = baseHeight;
-    int size = baseWidth*baseHeight*4;  // Size in bytes (will include mipmaps...)
+    int size = baseWidth*baseHeight*4;  // Size in bytes (will include mipmaps...), RGBA only
 
     // Count mipmap levels required
     while ((width != 1) && (height != 1))

+ 17 - 7
src/rlgl.h

@@ -154,11 +154,6 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
     typedef struct Shader {
         unsigned int id;                // Shader program id
 
-        // TODO: This should be Texture2D objects
-        unsigned int texDiffuseId;      // Diffuse texture id
-        unsigned int texNormalId;       // Normal texture id
-        unsigned int texSpecularId;     // Specular texture id
-        
         // Variable attributes
         int vertexLoc;        // Vertex attribute location point (vertex shader)
         int texcoordLoc;      // Texcoord attribute location point (vertex shader)
@@ -184,12 +179,27 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
         int format;             // Data format (TextureFormat)
     } Texture2D;
     
+    // Material type
+    typedef struct Material {
+        Shader shader;
+
+        Texture2D texDiffuse;      // Diffuse texture
+        Texture2D texNormal;       // Normal texture
+        Texture2D texSpecular;     // Specular texture
+        
+        Color colDiffuse;
+        Color colAmbient;
+        Color colSpecular;
+        
+        float glossiness;
+        float normalDepth;
+    } Material;
+
     // 3d Model type
     typedef struct Model {
         Mesh mesh;
         Matrix transform;
-        Texture2D texture;
-        Shader shader;
+        Material material;
     } Model;
 	
     // Color blending modes (pre-defined)

+ 9 - 36
src/shapes.c

@@ -180,44 +180,17 @@ void DrawRectangleGradient(int posX, int posY, int width, int height, Color colo
 // Draw a color-filled rectangle (Vector version)
 void DrawRectangleV(Vector2 position, Vector2 size, Color color)
 {
-    if (rlGetVersion() == OPENGL_11)
-    {
-        rlBegin(RL_TRIANGLES);
-            rlColor4ub(color.r, color.g, color.b, color.a);
-
-            rlVertex2i(position.x, position.y);
-            rlVertex2i(position.x, position.y + size.y);
-            rlVertex2i(position.x + size.x, position.y + size.y);
-
-            rlVertex2i(position.x, position.y);
-            rlVertex2i(position.x + size.x, position.y + size.y);
-            rlVertex2i(position.x + size.x, position.y);
-        rlEnd();
-    }
-    else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
-    {
-        // NOTE: This shape uses QUADS to avoid drawing order issues (view rlglDraw)
-        rlEnableTexture(whiteTexture); // Default white texture
-
-        rlBegin(RL_QUADS);
-            rlColor4ub(color.r, color.g, color.b, color.a);
-            rlNormal3f(0.0f, 0.0f, 1.0f);
-
-            rlTexCoord2f(0.0f, 0.0f);
-            rlVertex2f(position.x, position.y);
-
-            rlTexCoord2f(0.0f, 1.0f);
-            rlVertex2f(position.x, position.y + size.y);
-
-            rlTexCoord2f(1.0f, 1.0f);
-            rlVertex2f(position.x + size.x, position.y + size.y);
+    rlBegin(RL_TRIANGLES);
+        rlColor4ub(color.r, color.g, color.b, color.a);
 
-            rlTexCoord2f(1.0f, 0.0f);
-            rlVertex2f(position.x + size.x, position.y);
-        rlEnd();
+        rlVertex2i(position.x, position.y);
+        rlVertex2i(position.x, position.y + size.y);
+        rlVertex2i(position.x + size.x, position.y + size.y);
 
-        rlDisableTexture();
-    }
+        rlVertex2i(position.x, position.y);
+        rlVertex2i(position.x + size.x, position.y + size.y);
+        rlVertex2i(position.x + size.x, position.y);
+    rlEnd();
 }
 
 // Draw rectangle outline

+ 17 - 5
src/text.c

@@ -819,11 +819,17 @@ static SpriteFont LoadBMFont(const char *fileName)
     
     int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
     
+    bool unorderedChars = false;
+    int firstChar = 0;
+    
     for (int i = 0; i < numChars; i++)
     {
         fgets(buffer, MAX_BUFFER_SIZE, fntFile);
         sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i", 
                        &charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX);
+                       
+        if (i == 0) firstChar = charId;
+        else if (i != (charId - firstChar)) unorderedChars = true;
         
         // Save data properly in sprite font
         font.charValues[i] = charId;
@@ -832,14 +838,20 @@ static SpriteFont LoadBMFont(const char *fileName)
         font.charAdvanceX[i] = charAdvanceX;
     }
     
-    // TODO: Font data could be not ordered by charId: 32,33,34,35... review charValues and charRecs order
-    
     fclose(fntFile);
-
-    TraceLog(INFO, "[%s] SpriteFont loaded successfully", fileName);
+    
+    if (firstChar != FONT_FIRST_CHAR) TraceLog(WARNING, "BMFont not supported: expected SPACE(32) as first character, falling back to default font");
+    else if (unorderedChars) TraceLog(WARNING, "BMFont not supported: unordered chars data, falling back to default font");
+    
+    // NOTE: Font data could be not ordered by charId: 32,33,34,35... raylib does not support unordered BMFonts
+    if ((firstChar != FONT_FIRST_CHAR) || (unorderedChars))
+    {
+        UnloadSpriteFont(font);
+        font = GetDefaultFont();
+    }
+    else TraceLog(INFO, "[%s] SpriteFont loaded successfully", fileName);
 
     return font;
-    
 }
 
 // Generate a sprite font from TTF file data (font size required)

+ 55 - 2
src/textures.c

@@ -919,6 +919,39 @@ void ImageResize(Image *image, int newWidth, int newHeight)
     free(pixels);
 }
 
+// Resize and image to new size using Nearest-Neighbor scaling algorithm
+void ImageResizeNN(Image *image,int newWidth,int newHeight) 
+{
+    Color *pixels = GetImageData(*image);
+    Color *output = (Color *)malloc(newWidth*newHeight*sizeof(Color));
+    
+    // EDIT: added +1 to account for an early rounding problem
+    int x_ratio = (int)((image->width<<16)/newWidth) + 1;
+    int y_ratio = (int)((image->height<<16)/newHeight) + 1;
+    
+    int x2, y2;
+    for (int i = 0; i < newHeight; i++) 
+    {
+        for (int j = 0; j < newWidth; j++) 
+        {
+            x2 = ((j*x_ratio) >> 16);
+            y2 = ((i*y_ratio) >> 16);
+            
+            output[(i*newWidth) + j] = pixels[(y2*image->width) + x2] ;
+        }                
+    }                
+
+    int format = image->format;
+
+    UnloadImage(*image);
+
+    *image = LoadImageEx(output, newWidth, newHeight);
+    ImageFormat(image, format);  // Reformat 32bit RGBA image to original format 
+    
+    free(output);
+    free(pixels);
+}
+
 // Draw an image (source) within an image (destination)
 void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) 
 {
@@ -1046,8 +1079,9 @@ Image ImageTextEx(SpriteFont font, const char *text, int fontSize, int spacing,
         float scaleFactor = (float)fontSize/imSize.y;
         TraceLog(INFO, "Scalefactor: %f", scaleFactor);
         
-        // TODO: Allow nearest-neighbor scaling algorithm
-        ImageResize(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor)); 
+        // Using nearest-neighbor scaling algorithm for default font
+        if (font.texture.id == GetDefaultFont().texture.id) ImageResizeNN(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor));
+        else ImageResize(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor));
     }
     
     free(pixels);
@@ -1056,6 +1090,25 @@ Image ImageTextEx(SpriteFont font, const char *text, int fontSize, int spacing,
     return imText;
 }
 
+// Draw text (default font) within an image (destination)
+void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, Color color)
+{
+    ImageDrawTextEx(dst, position, GetDefaultFont(), text, fontSize, 0, color);
+}
+
+// Draw text (custom sprite font) within an image (destination)
+void ImageDrawTextEx(Image *dst, Vector2 position, SpriteFont font, const char *text, int fontSize, int spacing, Color color)
+{
+    Image imText = ImageTextEx(font, text, fontSize, spacing, color);
+    
+    Rectangle srcRec = { 0, 0, imText.width, imText.height };
+    Rectangle dstRec = { (int)position.x, (int)position.y, imText.width, imText.height };
+    
+    ImageDraw(dst, imText, srcRec, dstRec);
+    
+    UnloadImage(imText);
+}
+
 // Flip image vertically
 void ImageFlipVertical(Image *image)
 {

+ 56 - 23
templates/advance_game/makefile → templates/advance_game/Makefile

@@ -83,30 +83,64 @@ endif
 # define any directories containing required header files
 ifeq ($(PLATFORM),PLATFORM_RPI)
     INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
-else
-    INCLUDES = -I. -I../../src -IC:/raylib/raylib/src
-# external libraries headers
-# GLFW3
-    INCLUDES += -I../../external/glfw3/include
-# GLEW - Not required any more, replaced by GLAD
-    #INCLUDES += -I../external/glew/include
-# OpenAL Soft
-    INCLUDES += -I../../external/openal_soft/include
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        INCLUDES = -I. -I../src -I/usr/local/include/raylib/
+    else
+        INCLUDES = -I. -I../../src -IC:/raylib/raylib/src
+        # external libraries headers
+        # GLFW3
+            INCLUDES += -I../../external/glfw3/include
+        # GLEW - Not required any more, replaced by GLAD
+            #INCLUDES += -I../external/glew/include
+        # OpenAL Soft
+            INCLUDES += -I../../external/openal_soft/include
+    endif
 endif
 
 # define library paths containing required libs
 ifeq ($(PLATFORM),PLATFORM_RPI)
     LFLAGS = -L. -L../../src -L/opt/vc/lib
-else
-    LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
-    # external libraries to link with
-    # GLFW3
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        LFLAGS = -L. -L../../src
+    else
+        LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+        # external libraries to link with
+        # GLFW3
+            LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+        ifneq ($(PLATFORM_OS),OSX)
+        # OpenAL Soft
+            LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+        # GLEW: Not used, replaced by GLAD
+            #LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+        endif
+    endif
+endif
+
+# define library paths containing required libs
+ifeq ($(PLATFORM),PLATFORM_RPI)
+    LFLAGS = -L. -L../../src -L/opt/vc/lib
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        LFLAGS = -L. -L../../src
+    else
+        LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+        # external libraries to link with
+        # GLFW3
         LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
-    ifneq ($(PLATFORM_OS),OSX)
-    # OpenAL Soft
-        LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
-    # GLEW: Not used, replaced by GLAD
-        #LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+        ifneq ($(PLATFORM_OS),OSX)
+        # OpenAL Soft
+            LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+        # GLEW
+            LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+        endif
     endif
 endif
 
@@ -117,9 +151,8 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
         # libraries for Debian GNU/Linux desktop compiling
         # requires the following packages:
         # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
-        LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lm -pthread
-        # on XWindow could require also below libraries, just uncomment
-        #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+        LIBS = -lraylib -lglfw3 -lGL -lopenal -lm -pthread -ldl -lX11 \
+               -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
     else
     ifeq ($(PLATFORM_OS),OSX)
         # libraries for OS X 10.9 desktop compiling
@@ -162,9 +195,9 @@ SCREENS = \
 	screens/screen_gameplay.o \
 	screens/screen_ending.o \
 
-# typing 'make' will invoke the first target entry in the file,
+# typing 'make' will invoke the default target entry called 'all',
 # in this case, the 'default' target entry is advance_game
-default: advance_game
+all: advance_game
 
 # compile template - advance_game
 advance_game: advance_game.c $(SCREENS)

+ 57 - 24
templates/basic_game/makefile → templates/basic_game/Makefile

@@ -83,30 +83,64 @@ endif
 # define any directories containing required header files
 ifeq ($(PLATFORM),PLATFORM_RPI)
     INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
-else
-    INCLUDES = -I. -I../../src -IC:/raylib/raylib/src
-# external libraries headers
-# GLFW3
-    INCLUDES += -I../../external/glfw3/include
-# GLEW
-    INCLUDES += -I../../external/glew/include
-# OpenAL Soft
-    INCLUDES += -I../../external/openal_soft/include
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        INCLUDES = -I. -I../src -I/usr/local/include/raylib/
+    else
+        INCLUDES = -I. -I../../src -IC:/raylib/raylib/src
+        # external libraries headers
+        # GLFW3
+            INCLUDES += -I../../external/glfw3/include
+        # GLEW - Not required any more, replaced by GLAD
+            #INCLUDES += -I../external/glew/include
+        # OpenAL Soft
+            INCLUDES += -I../../external/openal_soft/include
+    endif
 endif
 
 # define library paths containing required libs
 ifeq ($(PLATFORM),PLATFORM_RPI)
     LFLAGS = -L. -L../../src -L/opt/vc/lib
-else
-    LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
-    # external libraries to link with
-    # GLFW3
-    LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
-    ifneq ($(PLATFORM_OS),OSX)
-    # OpenAL Soft
-        LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
-    # GLEW: Not used, replaced by GLAD
-        #LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        LFLAGS = -L. -L../../src
+    else
+        LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+        # external libraries to link with
+        # GLFW3
+            LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+        ifneq ($(PLATFORM_OS),OSX)
+        # OpenAL Soft
+            LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+        # GLEW: Not used, replaced by GLAD
+            #LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+        endif
+    endif
+endif
+
+# define library paths containing required libs
+ifeq ($(PLATFORM),PLATFORM_RPI)
+    LFLAGS = -L. -L../../src -L/opt/vc/lib
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        LFLAGS = -L. -L../../src
+    else
+        LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+        # external libraries to link with
+        # GLFW3
+        LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+        ifneq ($(PLATFORM_OS),OSX)
+        # OpenAL Soft
+            LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+        # GLEW
+            LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+        endif
     endif
 endif
 
@@ -117,9 +151,8 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
         # libraries for Debian GNU/Linux desktop compiling
         # requires the following packages:
         # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
-        LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lm -pthread
-        # on XWindow could require also below libraries, just uncomment
-        #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+        LIBS = -lraylib -lglfw3 -lGL -lopenal -lm -pthread -ldl -lX11 \
+               -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
     else
     ifeq ($(PLATFORM_OS),OSX)
         # libraries for OS X 10.9 desktop compiling
@@ -154,9 +187,9 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
     EXT = .html
 endif
 
-# typing 'make' will invoke the first target entry in the file,
+# typing 'make' will invoke the default target entry called 'all',
 # in this case, the 'default' target entry is basic_game
-default: basic_game
+all: basic_game
 
 # compile template - basic_game
 basic_game: basic_game.c

+ 57 - 24
templates/basic_test/makefile → templates/basic_test/Makefile

@@ -82,30 +82,64 @@ endif
 # define any directories containing required header files
 ifeq ($(PLATFORM),PLATFORM_RPI)
     INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
-else
-    INCLUDES = -I. -I../../src -IC:/raylib/raylib/src
-# external libraries headers
-# GLFW3
-    INCLUDES += -I../../external/glfw3/include
-# GLEW
-    INCLUDES += -I../../external/glew/include
-# OpenAL Soft
-    INCLUDES += -I../../external/openal_soft/include
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        INCLUDES = -I. -I../src -I/usr/local/include/raylib/
+    else
+        INCLUDES = -I. -I../../src -IC:/raylib/raylib/src
+        # external libraries headers
+        # GLFW3
+            INCLUDES += -I../../external/glfw3/include
+        # GLEW - Not required any more, replaced by GLAD
+            #INCLUDES += -I../external/glew/include
+        # OpenAL Soft
+            INCLUDES += -I../../external/openal_soft/include
+    endif
 endif
 
 # define library paths containing required libs
 ifeq ($(PLATFORM),PLATFORM_RPI)
     LFLAGS = -L. -L../../src -L/opt/vc/lib
-else
-    LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
-    # external libraries to link with
-    # GLFW3
-    LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
-    ifneq ($(PLATFORM_OS),OSX)
-    # OpenAL Soft
-        LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
-    # GLEW
-        LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        LFLAGS = -L. -L../../src
+    else
+        LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+        # external libraries to link with
+        # GLFW3
+            LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+        ifneq ($(PLATFORM_OS),OSX)
+        # OpenAL Soft
+            LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+        # GLEW: Not used, replaced by GLAD
+            #LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+        endif
+    endif
+endif
+
+# define library paths containing required libs
+ifeq ($(PLATFORM),PLATFORM_RPI)
+    LFLAGS = -L. -L../../src -L/opt/vc/lib
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        LFLAGS = -L. -L../../src
+    else
+        LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+        # external libraries to link with
+        # GLFW3
+        LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+        ifneq ($(PLATFORM_OS),OSX)
+        # OpenAL Soft
+            LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+        # GLEW
+            LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+        endif
     endif
 endif
 
@@ -116,9 +150,8 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
         # libraries for Debian GNU/Linux desktop compiling
         # requires the following packages:
         # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
-        LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lm -pthread
-        # on XWindow could require also below libraries, just uncomment
-        #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+        LIBS = -lraylib -lglfw3 -lGL -lopenal -lm -pthread -ldl -lX11 \
+               -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
     else
     ifeq ($(PLATFORM_OS),OSX)
         # libraries for OS X 10.9 desktop compiling
@@ -153,9 +186,9 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
     EXT = .html
 endif
 
-# typing 'make' will invoke the first target entry in the file,
+# typing 'make' will invoke the default target entry called 'all',
 # in this case, the 'default' target entry is basic_test
-default: basic_test
+all: basic_test
 
 # compile template - basic_test
 basic_test: basic_test.c

+ 57 - 24
templates/simple_game/makefile → templates/simple_game/Makefile

@@ -83,30 +83,64 @@ endif
 # define any directories containing required header files
 ifeq ($(PLATFORM),PLATFORM_RPI)
     INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
-else
-    INCLUDES = -I. -I../../src -IC:/raylib/raylib/src
-# external libraries headers
-# GLFW3
-    INCLUDES += -I../../external/glfw3/include
-# GLEW
-    INCLUDES += -I../../external/glew/include
-# OpenAL Soft
-    INCLUDES += -I../../external/openal_soft/include
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        INCLUDES = -I. -I../src -I/usr/local/include/raylib/
+    else
+        INCLUDES = -I. -I../../src -IC:/raylib/raylib/src
+        # external libraries headers
+        # GLFW3
+            INCLUDES += -I../../external/glfw3/include
+        # GLEW - Not required any more, replaced by GLAD
+            #INCLUDES += -I../external/glew/include
+        # OpenAL Soft
+            INCLUDES += -I../../external/openal_soft/include
+    endif
 endif
 
 # define library paths containing required libs
 ifeq ($(PLATFORM),PLATFORM_RPI)
     LFLAGS = -L. -L../../src -L/opt/vc/lib
-else
-    LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
-    # external libraries to link with
-    # GLFW3
-    LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
-    ifneq ($(PLATFORM_OS),OSX)
-    # OpenAL Soft
-        LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
-    # GLEW: Not used, replaced by GLAD
-        #LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        LFLAGS = -L. -L../../src
+    else
+        LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+        # external libraries to link with
+        # GLFW3
+            LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+        ifneq ($(PLATFORM_OS),OSX)
+        # OpenAL Soft
+            LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+        # GLEW: Not used, replaced by GLAD
+            #LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+        endif
+    endif
+endif
+
+# define library paths containing required libs
+ifeq ($(PLATFORM),PLATFORM_RPI)
+    LFLAGS = -L. -L../../src -L/opt/vc/lib
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        LFLAGS = -L. -L../../src
+    else
+        LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+        # external libraries to link with
+        # GLFW3
+        LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+        ifneq ($(PLATFORM_OS),OSX)
+        # OpenAL Soft
+            LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+        # GLEW
+            LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+        endif
     endif
 endif
 
@@ -117,9 +151,8 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
         # libraries for Debian GNU/Linux desktop compiling
         # requires the following packages:
         # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
-        LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lm -pthread
-        # on XWindow could require also below libraries, just uncomment
-        #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+        LIBS = -lraylib -lglfw3 -lGL -lopenal -lm -pthread -ldl -lX11 \
+               -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
     else
     ifeq ($(PLATFORM_OS),OSX)
         # libraries for OS X 10.9 desktop compiling
@@ -154,9 +187,9 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
     EXT = .html
 endif
 
-# typing 'make' will invoke the first target entry in the file,
+# typing 'make' will invoke the default target entry called 'all',
 # in this case, the 'default' target entry is simple_game
-default: simple_game
+all: simple_game
 
 # compile template - simple_game
 simple_game: simple_game.c screens.o

+ 57 - 24
templates/standard_game/makefile → templates/standard_game/Makefile

@@ -83,30 +83,64 @@ endif
 # define any directories containing required header files
 ifeq ($(PLATFORM),PLATFORM_RPI)
     INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads
-else
-    INCLUDES = -I. -I../../src -IC:/raylib/raylib/src
-# external libraries headers
-# GLFW3
-    INCLUDES += -I../../external/glfw3/include
-# GLEW
-    INCLUDES += -I../../external/glew/include
-# OpenAL Soft
-    INCLUDES += -I../../external/openal_soft/include
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        INCLUDES = -I. -I../src -I/usr/local/include/raylib/
+    else
+        INCLUDES = -I. -I../../src -IC:/raylib/raylib/src
+        # external libraries headers
+        # GLFW3
+            INCLUDES += -I../../external/glfw3/include
+        # GLEW - Not required any more, replaced by GLAD
+            #INCLUDES += -I../external/glew/include
+        # OpenAL Soft
+            INCLUDES += -I../../external/openal_soft/include
+    endif
 endif
 
 # define library paths containing required libs
 ifeq ($(PLATFORM),PLATFORM_RPI)
     LFLAGS = -L. -L../../src -L/opt/vc/lib
-else
-    LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
-    # external libraries to link with
-    # GLFW3
-    LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
-    ifneq ($(PLATFORM_OS),OSX)
-    # OpenAL Soft
-        LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
-    # GLEW: Not used, replaced by GLAD
-        #LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        LFLAGS = -L. -L../../src
+    else
+        LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+        # external libraries to link with
+        # GLFW3
+            LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+        ifneq ($(PLATFORM_OS),OSX)
+        # OpenAL Soft
+            LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+        # GLEW: Not used, replaced by GLAD
+            #LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+        endif
+    endif
+endif
+
+# define library paths containing required libs
+ifeq ($(PLATFORM),PLATFORM_RPI)
+    LFLAGS = -L. -L../../src -L/opt/vc/lib
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+    # add standard directories for GNU/Linux
+    ifeq ($(PLATFORM_OS),LINUX)
+        LFLAGS = -L. -L../../src
+    else
+        LFLAGS = -L. -L../../src -LC:/raylib/raylib/src
+        # external libraries to link with
+        # GLFW3
+        LFLAGS += -L../../external/glfw3/lib/$(LIBPATH)
+        ifneq ($(PLATFORM_OS),OSX)
+        # OpenAL Soft
+            LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH)
+        # GLEW
+            LFLAGS += -L../../external/glew/lib/$(LIBPATH)
+        endif
     endif
 endif
 
@@ -117,9 +151,8 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
         # libraries for Debian GNU/Linux desktop compiling
         # requires the following packages:
         # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev
-        LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lm -pthread
-        # on XWindow could require also below libraries, just uncomment
-        #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+        LIBS = -lraylib -lglfw3 -lGL -lopenal -lm -pthread -ldl -lX11 \
+               -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
     else
     ifeq ($(PLATFORM_OS),OSX)
         # libraries for OS X 10.9 desktop compiling
@@ -162,9 +195,9 @@ SCREENS = \
 	screens/screen_gameplay.o \
 	screens/screen_ending.o \
 
-# typing 'make' will invoke the first target entry in the file,
+# typing 'make' will invoke the default target entry called 'all',
 # in this case, the 'default' target entry is standard_game
-default: standard_game
+all: standard_game
 
 # compile template - standard_game
 standard_game: standard_game.c $(SCREENS)