summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--examples/core_2d_camera.c71
-rw-r--r--examples/core_3d_camera_first_person.c3
-rw-r--r--examples/core_3d_camera_free.c2
-rw-r--r--examples/core_3d_mode.c1
-rw-r--r--examples/core_3d_picking.c6
-rw-r--r--examples/core_world_screen.c3
-rw-r--r--examples/models_billboard.c3
-rw-r--r--examples/models_box_collisions.c42
-rw-r--r--examples/models_cubicmap.c3
-rw-r--r--examples/models_geometric_shapes.c2
-rw-r--r--examples/models_heightmap.c2
-rw-r--r--examples/models_obj_loading.c2
-rw-r--r--examples/shaders_basic_lighting.c2
-rw-r--r--examples/shaders_custom_uniform.c2
-rw-r--r--examples/shaders_model_shader.c2
-rw-r--r--examples/shaders_postprocessing.c2
-rw-r--r--games/tetris.c466
-rw-r--r--src/camera.c8
-rw-r--r--src/camera.h1
-rw-r--r--src/core.c67
-rw-r--r--src/models.c302
-rw-r--r--src/raylib.h35
-rw-r--r--src/raymath.h2
-rw-r--r--src/rlgl.c63
-rw-r--r--src/shapes.c45
-rw-r--r--src/text.c22
-rw-r--r--src/textures.c38
27 files changed, 614 insertions, 583 deletions
diff --git a/examples/core_2d_camera.c b/examples/core_2d_camera.c
new file mode 100644
index 00000000..71c474f0
--- /dev/null
+++ b/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;
+} \ No newline at end of file
diff --git a/examples/core_3d_camera_first_person.c b/examples/core_3d_camera_first_person.c
index 2b8dc7fc..16d388df 100644
--- a/examples/core_3d_camera_first_person.c
+++ b/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
//--------------------------------------------------------------------------------------
diff --git a/examples/core_3d_camera_free.c b/examples/core_3d_camera_free.c
index 4b45373d..234c46b3 100644
--- a/examples/core_3d_camera_free.c
+++ b/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
//--------------------------------------------------------------------------------------
diff --git a/examples/core_3d_mode.c b/examples/core_3d_mode.c
index 7be5dd45..5f761655 100644
--- a/examples/core_3d_mode.c
+++ b/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 };
diff --git a/examples/core_3d_picking.c b/examples/core_3d_picking.c
index fdf77030..33eaed8a 100644
--- a/examples/core_3d_picking.c
+++ b/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 }});
}
//----------------------------------------------------------------------------------
diff --git a/examples/core_world_screen.c b/examples/core_world_screen.c
index b70b40dd..d89a296b 100644
--- a/examples/core_world_screen.c
+++ b/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
//--------------------------------------------------------------------------------------
diff --git a/examples/models_billboard.c b/examples/models_billboard.c
index bac42d35..654b3618 100644
--- a/examples/models_billboard.c
+++ b/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
//--------------------------------------------------------------------------------------
diff --git a/examples/models_box_collisions.c b/examples/models_box_collisions.c
index 3751041f..69cec418 100644
--- a/examples/models_box_collisions.c
+++ b/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;
diff --git a/examples/models_cubicmap.c b/examples/models_cubicmap.c
index e2a902ef..1ca27dfd 100644
--- a/examples/models_cubicmap.c
+++ b/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
//--------------------------------------------------------------------------------------
diff --git a/examples/models_geometric_shapes.c b/examples/models_geometric_shapes.c
index 9ea5b423..a13a1f3b 100644
--- a/examples/models_geometric_shapes.c
+++ b/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
//--------------------------------------------------------------------------------------
diff --git a/examples/models_heightmap.c b/examples/models_heightmap.c
index f1da3301..c8e5ff35 100644
--- a/examples/models_heightmap.c
+++ b/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)
diff --git a/examples/models_obj_loading.c b/examples/models_obj_loading.c
index 41f4569a..e8dd0adc 100644
--- a/examples/models_obj_loading.c
+++ b/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
diff --git a/examples/shaders_basic_lighting.c b/examples/shaders_basic_lighting.c
index 84bd1af4..18aea8e1 100644
--- a/examples/shaders_basic_lighting.c
+++ b/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 };
diff --git a/examples/shaders_custom_uniform.c b/examples/shaders_custom_uniform.c
index 0377cfff..ecfbaa71 100644
--- a/examples/shaders_custom_uniform.c
+++ b/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
diff --git a/examples/shaders_model_shader.c b/examples/shaders_model_shader.c
index 5d8c3711..a10ec235 100644
--- a/examples/shaders_model_shader.c
+++ b/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
diff --git a/examples/shaders_postprocessing.c b/examples/shaders_postprocessing.c
index 0f851658..44829648 100644
--- a/examples/shaders_postprocessing.c
+++ b/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
diff --git a/games/tetris.c b/games/tetris.c
index 62400201..84ba9196 100644
--- a/games/tetris.c
+++ b/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()
diff --git a/src/camera.c b/src/camera.c
index 517e4a2b..8e5c527e 100644
--- a/src/camera.c
+++ b/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)
{
diff --git a/src/camera.h b/src/camera.h
index 9ad09c6f..8d8029af 100644
--- a/src/camera.h
+++ b/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)
diff --git a/src/core.c b/src/core.c
index dbcfa6bc..870ca3b4 100644
--- a/src/core.c
+++ b/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);
diff --git a/src/models.c b/src/models.c
index 8a36c279..ee5e57c7 100644
--- a/src/models.c
+++ b/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
@@ -575,19 +560,9 @@ Model LoadModel(const char *fileName)
// 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;
@@ -610,6 +585,63 @@ Model LoadModelEx(Mesh data)
// 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)
+ {
+ // 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;
+ }
+}
+
+static Mesh GenMeshHeightmap(Image heightmap, Vector3 size)
+{
#define GRAY_VALUE(c) ((c.r+c.g+c.b)/3)
Mesh mesh;
@@ -714,34 +746,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 +765,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 +796,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 +1102,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 +1142,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 +1205,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 +1215,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 +1236,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 +1251,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 +1317,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 +1634,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);
diff --git a/src/raylib.h b/src/raylib.h
index b9cf05a4..83e41ac7 100644
--- a/src/raylib.h
+++ b/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;
@@ -384,7 +393,7 @@ typedef struct Model {
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 +539,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 +642,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,6 +704,7 @@ 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 ImageResizeNN(Image *image,int newWidth,int newHeight); // Resize and image (Nearest-Neighbor scaling algorithm)
void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec); // Draw a source image within a destination image
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)
@@ -743,7 +755,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 +764,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)
@@ -764,18 +775,18 @@ void DrawModel(Model model, Vector3 position, float scale, Color tint);
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 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
//------------------------------------------------------------------------------------
diff --git a/src/raymath.h b/src/raymath.h
index 35cee39f..52e92b50 100644
--- a/src/raymath.h
+++ b/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);
diff --git a/src/rlgl.c b/src/rlgl.c
index 8ea7d0f2..e1949274 100644
--- a/src/rlgl.c
+++ b/src/rlgl.c
@@ -1611,54 +1611,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 +1862,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 +1885,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 +1897,7 @@ void rlglGenerateMipmaps(Texture2D texture)
#endif
}
else TraceLog(WARNING, "[TEX ID %i] Mipmaps can not be generated", texture.id);
-
+
glBindTexture(GL_TEXTURE_2D, 0);
}
@@ -3106,7 +3079,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))
diff --git a/src/shapes.c b/src/shapes.c
index 65e3621b..51730a05 100644
--- a/src/shapes.c
+++ b/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
diff --git a/src/text.c b/src/text.c
index e4c7bbf3..f89d5e4e 100644
--- a/src/text.c
+++ b/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)
diff --git a/src/textures.c b/src/textures.c
index 36819daf..cb3113dc 100644
--- a/src/textures.c
+++ b/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);