This commit is contained in:
Hristo Stamenov 2021-06-24 00:12:38 +03:00
commit 9a1816bc5b
33 changed files with 643 additions and 414 deletions

14
.gitignore vendored
View File

@ -53,17 +53,6 @@ packages/
*.bc
*.so
# Ignore all examples files
examples/*
# Unignore all examples files with extension
!examples/*.c
!examples/*.png
# Unignore examples Makefile
!examples/Makefile
!examples/Makefile.Android
!examples/raylib_compile_execute.bat
!examples/raylib_makefile_example.bat
# Ignore files build by xcode
*.mode*v*
*.pbxuser
@ -93,9 +82,6 @@ compile_commands.json
CTestTestfile.cmake
build
# Unignore These makefiles...
!examples/CMakeLists.txt
# Ignore GNU global tags
GPATH
GRTAGS

View File

@ -64,6 +64,7 @@ Here it is a list with the ones I'm aware of:
| raylib-factor | 3.5 | [Factor](https://factorcode.org/) | https://github.com/ArnautDaniel/raylib-factor |
| gforth-raylib | 3.5 | [Gforth](https://gforth.org/) | https://github.com/ArnautDaniel/gforth-raylib |
| raylib-haxe | 2.4 | [Haxe](https://haxe.org/) | https://github.com/ibilon/raylib-haxe |
| hxRaylib | 3.7 | [Haxe](https://haxe.org/) | https://github.com/ForeignSasquatch/hxRaylib |
| ringraylib | 2.6 | [Ring](http://ring-lang.sourceforge.net/) | https://github.com/ringpackages/ringraylib |
| cl-raylib | 3.0 | [Common Lisp](https://common-lisp.net/) | https://github.com/longlene/cl-raylib |
| raylib-scm | 2.5 | [Chicken Scheme](https://www.call-cc.org/) | https://github.com/yashrk/raylib-scm |

View File

@ -5,15 +5,16 @@
* This example has been created using raylib 3.7 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Example contributed by Giancamillo Alessandroni ([discord]NotManyIdeas#9972 - [github]NotManyIdeasDev) and
* Example contributed by Giancamillo Alessandroni (@NotManyIdeasDev) and
* reviewed by Ramon Santamaria (@raysan5)
*
* Copyright (c) 2021 Giancamillo Alessandroni (NotManyIdeas#9972) and Ramon Santamaria (@raysan5)
* Copyright (c) 2021 Giancamillo Alessandroni (@NotManyIdeasDev) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include <math.h>
#include <math.h> // Required for: sinf(), cosf()
int main(void)
{
@ -22,33 +23,32 @@ int main(void)
const int screenWidth = 800;
const int screenHeight = 450;
const int virualScreenWidth = 160;
const int virtualScreenWidth = 160;
const int virtualScreenHeight = 90;
const float virtualRatio = (float)screenWidth/(float)virualScreenWidth;
const float virtualRatio = (float)screenWidth/(float)virtualScreenWidth;
InitWindow(screenWidth, screenHeight, "raylib [core] example - smooth pixel-perfect camera");
Camera2D worldSpaceCamera = { 0 }; // Game world camera
Camera2D worldSpaceCamera = { 0 }; // Game world camera
worldSpaceCamera.zoom = 1.0f;
Camera2D screenSpaceCamera = { 0 }; //Smoothing camera
Camera2D screenSpaceCamera = { 0 }; // Smoothing camera
screenSpaceCamera.zoom = 1.0f;
RenderTexture2D renderTexture = LoadRenderTexture(virualScreenWidth, virtualScreenHeight); //This is where we'll draw all our objects.
RenderTexture2D target = LoadRenderTexture(virtualScreenWidth, virtualScreenHeight); // This is where we'll draw all our objects.
Rectangle firstRectangle = { 70.0f, 35.0f, 20.0f, 20.0f };
Rectangle secondRectangle = { 90.0f, 55.0f, 30.0f, 10.0f };
Rectangle thirdRectangle = { 80.0f, 65.0f, 15.0f, 25.0f };
Rectangle rec01 = { 70.0f, 35.0f, 20.0f, 20.0f };
Rectangle rec02 = { 90.0f, 55.0f, 30.0f, 10.0f };
Rectangle rec03 = { 80.0f, 65.0f, 15.0f, 25.0f };
//The renderTexture's height is flipped (in the source Rectangle), due to OpenGL reasons.
Rectangle renderTextureSource = { 0.0f, 0.0f, (float)renderTexture.texture.width, (float)-renderTexture.texture.height };
Rectangle renderTextureDest = { -virtualRatio, -virtualRatio, screenWidth + (virtualRatio*2), screenHeight + (virtualRatio*2) };
// The target's height is flipped (in the source Rectangle), due to OpenGL reasons
Rectangle sourceRec = { 0.0f, 0.0f, (float)target.texture.width, -(float)target.texture.height };
Rectangle destRec = { -virtualRatio, -virtualRatio, screenWidth + (virtualRatio*2), screenHeight + (virtualRatio*2) };
Vector2 origin = { 0.0f, 0.0f };
float rotation = 0.0f;
float degreesPerSecond = 60.0f;
float cameraX = 0.0f;
float cameraY = 0.0f;
@ -61,16 +61,16 @@ int main(void)
{
// Update
//----------------------------------------------------------------------------------
rotation += degreesPerSecond*GetFrameTime(); // Rotate the rectangles.
rotation += 60.0f*GetFrameTime(); // Rotate the rectangles, 60 degrees per second
// Make the camera move to demonstrate the effect.
// Make the camera move to demonstrate the effect
cameraX = (sinf(GetTime())*50.0f) - 10.0f;
cameraY = cosf(GetTime())*30.0f;
// Set the camera's target to the values computed above.
// Set the camera's target to the values computed above
screenSpaceCamera.target = (Vector2){ cameraX, cameraY };
//Round worldSpace coordinates, keep decimals into screenSpace coordinates.
// Round worldSpace coordinates, keep decimals into screenSpace coordinates
worldSpaceCamera.target.x = (int)screenSpaceCamera.target.x;
screenSpaceCamera.target.x -= worldSpaceCamera.target.x;
screenSpaceCamera.target.x *= virtualRatio;
@ -83,47 +83,35 @@ int main(void)
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RED); // This is for debug purposes. If you see red, then you've probably done something wrong.
BeginTextureMode(renderTexture);
BeginMode2D(worldSpaceCamera);
ClearBackground(RAYWHITE); // This is the color you should see as background color.
// Draw the rectangles
DrawRectanglePro(firstRectangle, origin, rotation, BLACK);
DrawRectanglePro(secondRectangle, origin, -rotation, RED);
DrawRectanglePro(thirdRectangle, origin, rotation + 45.0f, BLUE);
EndMode2D();
BeginTextureMode(target);
ClearBackground(RAYWHITE);
BeginMode2D(worldSpaceCamera);
DrawRectanglePro(rec01, origin, rotation, BLACK);
DrawRectanglePro(rec02, origin, -rotation, RED);
DrawRectanglePro(rec03, origin, rotation + 45.0f, BLUE);
EndMode2D();
EndTextureMode();
BeginDrawing();
ClearBackground(RED);
BeginMode2D(screenSpaceCamera);
BeginMode2D(screenSpaceCamera);
DrawTexturePro(target.texture, sourceRec, destRec, origin, 0.0f, WHITE);
EndMode2D();
// Draw the render texture with an offset of 1 worldSpace unit/pixel, so that the content behind the renderTexture is not shown.
DrawTexturePro(
renderTexture.texture,
renderTextureSource,
renderTextureDest,
origin,
0.0f,
WHITE
);
EndMode2D();
//Debug info
DrawText("Screen resolution: 800x450", 5, 0, 20, DARKBLUE);
DrawText("World resolution: 160x90", 5, 20, 20, DARKGREEN);
DrawFPS(screenWidth - 75, 0);
DrawText(TextFormat("Screen resolution: %ix%i", screenWidth, screenHeight), 10, 10, 20, DARKBLUE);
DrawText(TextFormat("World resolution: %ix%i", virtualScreenWidth, virtualScreenHeight), 10, 40, 20, DARKGREEN);
DrawFPS(GetScreenWidth() - 95, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadRenderTexture(renderTexture); // RenderTexture unloading
CloseWindow(); // Close window and OpenGL context
UnloadRenderTexture(target); // Unload render texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,125 @@
/*******************************************************************************************
*
* raylib [core] example - custom frame control
*
* WARNING: This is an example for advance users willing to have full control over
* the frame processes. By default, EndDrawing() calls the following processes:
* 1. Draw remaining batch data: rlDrawRenderBatchActive()
* 2. SwapScreenBuffer()
* 3. Frame time control: WaitTime()
* 4. PollInputEvents()
*
* To avoid steps 2, 3 and 4, flag SUPPORT_CUSTOM_FRAME_CONTROL can be enabled in
* config.h (it requires recompiling raylib). This way those steps are up to the user.
*
* Note that enabling this flag invalidates some functions:
* - GetFrameTime()
* - SetTargetFPS()
* - GetFPS()
*
* This example has been created using raylib 3.8 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2021 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - custom frame control");
// Custom timming variables
double previousTime = GetTime(); // Previous time measure
double currentTime = 0.0; // Current time measure
double updateDrawTime = 0.0; // Update + Draw time
double waitTime = 0.0; // Wait time (if target fps required)
float deltaTime = 0.0f; // Frame time (Update + Draw + Wait time)
float timeCounter = 0.0f; // Accumulative time counter (seconds)
float position = 0.0f; // Circle position
bool pause = false; // Pause control flag
int targetFPS = 60; // Our initial target fps
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
PollInputEvents(); // Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL)
if (IsKeyPressed(KEY_SPACE)) pause = !pause;
if (IsKeyPressed(KEY_UP)) targetFPS += 20;
else if (IsKeyPressed(KEY_DOWN)) targetFPS -= 20;
if (targetFPS < 0) targetFPS = 0;
if (!pause)
{
position += 200*deltaTime; // We move at 200 pixels per second
if (position >= GetScreenWidth()) position = 0;
timeCounter += deltaTime; // We count time (seconds)
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
for (int i = 0; i < GetScreenWidth()/200; i++) DrawRectangle(200*i, 0, 1, GetScreenHeight(), SKYBLUE);
DrawCircle((int)position, GetScreenHeight()/2 - 25, 50, RED);
DrawText(FormatText("%03.0f ms", timeCounter*1000.0f), position - 40, GetScreenHeight()/2 - 100, 20, MAROON);
DrawText(FormatText("PosX: %03.0f", position), position - 50, GetScreenHeight()/2 + 40, 20, BLACK);
DrawText("Circle is moving at a constant 200 pixels/sec,\nindependently of the frame rate.", 10, 10, 20, DARKGRAY);
DrawText("PRESS SPACE to PAUSE MOVEMENT", 10, GetScreenHeight() - 60, 20, GRAY);
DrawText("PRESS UP | DOWN to CHANGE TARGET FPS", 10, GetScreenHeight() - 30, 20, GRAY);
DrawText(FormatText("TARGET FPS: %i", targetFPS), GetScreenWidth() - 220, 10, 20, LIME);
DrawText(FormatText("CURRENT FPS: %i", (int)(1.0f/deltaTime)), GetScreenWidth() - 220, 40, 20, GREEN);
EndDrawing();
// NOTE: In case raylib is configured to SUPPORT_CUSTOM_FRAME_CONTROL,
// Events polling, screen buffer swap and frame time control must be managed by the user
SwapScreenBuffer(); // Flip the back buffer to screen (front buffer)
currentTime = GetTime();
updateDrawTime = currentTime - previousTime;
if (targetFPS > 0) // We want a fixed frame rate
{
waitTime = (1.0f/(float)targetFPS) - updateDrawTime;
if (waitTime > 0.0)
{
WaitTime((float)waitTime*1000.0f);
currentTime = GetTime();
deltaTime = (float)(currentTime - previousTime);
}
}
else deltaTime = updateDrawTime; // Framerate could be variable
previousTime = currentTime;
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,83 @@
#include "raylib.h"
#include "rlgl.h" // just to change line width
#include "raymath.h"
#define windowWidth 1280
#define windowHeight 720
Vector3 Vector3MultiplyQuaternion(Vector3 v, Quaternion q)
{
Vector3 r, qv, uv, uuv;
qv.x = q.x;
qv.y = q.y;
qv.z = q.z;
uv = Vector3CrossProduct(qv, v);
uuv = Vector3CrossProduct(qv, uv);
uv = Vector3Scale(uv, 2.f*q.w);
uuv = Vector3Scale(uuv, 2.0f);
r = Vector3Add(v, uv);
r = Vector3Add(r, uuv);
return r;
}
int main(void)
{
SetTraceLogLevel( LOG_ALL );
SetConfigFlags( FLAG_VSYNC_HINT | FLAG_MSAA_4X_HINT );
InitWindow( windowWidth, windowHeight, "Raylib - template" );
Camera camera = { 0 };
camera.position = (Vector3){ 0.0f, 1.0f, 4.0f };
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
camera.fovy = 45.0f;
camera.projection = CAMERA_PERSPECTIVE;
Vector3 ang = { 0 };
Vector3 qv = { 0 };
Vector3 mv = { 0 };
Vector3 bv = { 0 };
Quaternion q;
float dT = 0;
rlSetLineWidth(4);
while ( !WindowShouldClose() )
{
dT = GetFrameTime();
ang.x += .7f * dT;
ang.y += .55 * dT;
ang.z -= 2.75 * dT;
q = QuaternionFromEuler(ang.x, ang.y, ang.z);
qv = Vector3MultiplyQuaternion((Vector3){0,0,1}, q);
Matrix m = QuaternionToMatrix(q);
mv = Vector3Transform((Vector3){0,0,1},m);
bv = Vector3RotateByQuaternion((Vector3){0,0,1}, q);
BeginDrawing();
ClearBackground( (Color){64,128,255,255} );
BeginMode3D( camera );
DrawLine3D((Vector3){0,0,0}, qv, GREEN);
DrawLine3D((Vector3){-.1,0,0}, mv, YELLOW);
DrawLine3D((Vector3){.1,0,0}, bv, RED);
DrawGrid( 10, 1.0f );
EndMode3D();
EndDrawing();
}
CloseWindow();
return 0;
}

View File

@ -89,7 +89,7 @@ int main(void)
// this moves thigns at 10 world units per second, regardless of the actual FPS
float offsetThisFrame = 10.0f*GetFrameTime();
// Move player 1 forward and backwards (no turning)
// Move Player1 forward and backwards (no turning)
if (IsKeyDown(KEY_W))
{
cameraPlayer1.position.z += offsetThisFrame;
@ -101,7 +101,7 @@ int main(void)
cameraPlayer1.target.z -= offsetThisFrame;
}
// Move player 2 forward and backwards (no turning)
// Move Player2 forward and backwards (no turning)
if (IsKeyDown(KEY_UP))
{
cameraPlayer2.position.x += offsetThisFrame;
@ -116,7 +116,7 @@ int main(void)
// Draw
//----------------------------------------------------------------------------------
// Draw player 1's view to the render texture
// Draw Player1 view to the render texture
BeginTextureMode(screenPlayer1);
ClearBackground(SKYBLUE);
BeginMode3D(cameraPlayer1);
@ -125,7 +125,7 @@ int main(void)
DrawText("PLAYER1 W/S to move", 0, 0, 20, RED);
EndTextureMode();
// Draw player 2's view to the render texture
// Draw Player2 view to the render texture
BeginTextureMode(screenPlayer2);
ClearBackground(SKYBLUE);
BeginMode3D(cameraPlayer2);
@ -134,21 +134,21 @@ int main(void)
DrawText("PLAYER2 UP/DOWN to move", 0, 0, 20, BLUE);
EndTextureMode();
// Draw both view render textures to the screen side by side
// Draw both views render textures to the screen side by side
BeginDrawing();
ClearBackground(BLACK);
DrawTextureRec(screenPlayer1.texture, splitScreenRect, (Vector2) { 0, 0 }, WHITE);
DrawTextureRec(screenPlayer2.texture, splitScreenRect, (Vector2) { screenWidth/2.0f, 0 }, WHITE);
DrawTextureRec(screenPlayer1.texture, splitScreenRect, (Vector2){ 0, 0 }, WHITE);
DrawTextureRec(screenPlayer2.texture, splitScreenRect, (Vector2){ screenWidth/2.0f, 0 }, WHITE);
EndDrawing();
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadRenderTexture(screenPlayer1);
UnloadRenderTexture(screenPlayer2);
UnloadTexture(textureGrid);
UnloadRenderTexture(screenPlayer1); // Unload render texture
UnloadRenderTexture(screenPlayer2); // Unload render texture
UnloadTexture(textureGrid); // Unload texture
CloseWindow(); // Close window and OpenGL context
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;

View File

@ -105,30 +105,26 @@ int main(void)
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
BeginTextureMode(target);
ClearBackground(RAYWHITE);
BeginVrStereoMode(config);
BeginMode3D(camera);
BeginTextureMode(target);
ClearBackground(RAYWHITE);
BeginVrStereoMode(config);
BeginMode3D(camera);
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
DrawGrid(40, 1.0f);
EndMode3D();
EndVrStereoMode();
EndTextureMode();
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
DrawGrid(40, 1.0f);
EndMode3D();
EndVrStereoMode();
EndTextureMode();
BeginDrawing();
ClearBackground(RAYWHITE);
BeginShaderMode(distortion);
DrawTextureRec(target.texture, (Rectangle){ 0, 0, (float)target.texture.width,
(float)-target.texture.height }, (Vector2){ 0.0f, 0.0f }, WHITE);
EndShaderMode();
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}

View File

@ -48,11 +48,11 @@ int main(void)
Color colors[10] = { 0 };
for (int i = 0; i < 10; i++) colors[i] = (Color){ GetRandomValue(100, 250), GetRandomValue(50, 150), GetRandomValue(10, 100), 255 };
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
@ -79,37 +79,33 @@ int main(void)
// Draw
//----------------------------------------------------------------------------------
// Draw everything in the render texture, note this will not be rendered on screen, yet
BeginTextureMode(target);
ClearBackground(RAYWHITE); // Clear render texture background color
for (int i = 0; i < 10; i++) DrawRectangle(0, (gameScreenHeight/10)*i, gameScreenWidth, gameScreenHeight/10, colors[i]);
DrawText("If executed inside a window,\nyou can resize the window,\nand see the screen scaling!", 10, 25, 20, WHITE);
DrawText(TextFormat("Default Mouse: [%i , %i]", (int)mouse.x, (int)mouse.y), 350, 25, 20, GREEN);
DrawText(TextFormat("Virtual Mouse: [%i , %i]", (int)virtualMouse.x, (int)virtualMouse.y), 350, 55, 20, YELLOW);
EndTextureMode();
BeginDrawing();
ClearBackground(BLACK);
ClearBackground(BLACK); // Clear screen background
// Draw everything in the render texture, note this will not be rendered on screen, yet
BeginTextureMode(target);
ClearBackground(RAYWHITE); // Clear render texture background color
for (int i = 0; i < 10; i++) DrawRectangle(0, (gameScreenHeight/10)*i, gameScreenWidth, gameScreenHeight/10, colors[i]);
DrawText("If executed inside a window,\nyou can resize the window,\nand see the screen scaling!", 10, 25, 20, WHITE);
DrawText(TextFormat("Default Mouse: [%i , %i]", (int)mouse.x, (int)mouse.y), 350, 25, 20, GREEN);
DrawText(TextFormat("Virtual Mouse: [%i , %i]", (int)virtualMouse.x, (int)virtualMouse.y), 350, 55, 20, YELLOW);
EndTextureMode();
// Draw RenderTexture2D to window, properly scaled
// Draw render texture to screen, properly scaled
DrawTexturePro(target.texture, (Rectangle){ 0.0f, 0.0f, (float)target.texture.width, (float)-target.texture.height },
(Rectangle){ (GetScreenWidth() - ((float)gameScreenWidth*scale))*0.5f, (GetScreenHeight() - ((float)gameScreenHeight*scale))*0.5f,
(float)gameScreenWidth*scale, (float)gameScreenHeight*scale }, (Vector2){ 0, 0 }, 0.0f, WHITE);
EndDrawing();
//--------------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadRenderTexture(target); // Unload render texture
UnloadRenderTexture(target); // Unload render texture
CloseWindow(); // Close window and OpenGL context
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;

View File

@ -41,16 +41,18 @@
*
* raylib [core] example - Basic window
*
* This example has been created using raylib 2.5 (www.raylib.com)
* This example has been created using raylib 3.8 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2019 Ramon Santamaria (@raysan5)
* Example contributed by <user_name> (@<user_github>) and reviewed by Ramon Santamaria (@raysan5)
*
* Copyright (c) 2021 <user_name> (@<user_github>)
*
********************************************************************************************/
#include "raylib.h"
int main()
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------

View File

@ -99,7 +99,7 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
for(int i = 0; i < MAX_MODELS; i++) UnloadModel(model[i]); // Unload models
for (int i = 0; i < MAX_MODELS; i++) UnloadModel(model[i]); // Unload models
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -65,6 +65,14 @@
#define RAYWHITE (Color){ 245, 245, 245, 255 } // My own White (raylib logo)
#define DARKGRAY (Color){ 80, 80, 80, 255 } // Dark Gray
// Color, 4 components, R8G8B8A8 (32bit)
typedef struct Color {
unsigned char r; // Color red value
unsigned char g; // Color green value
unsigned char b; // Color blue value
unsigned char a; // Color alpha value
} Color;
// Camera type, defines a camera position/orientation in 3d space
typedef struct Camera {
Vector3 position; // Camera position
@ -271,7 +279,7 @@ static void DrawGrid(int slices, float spacing)
int halfSlices = slices / 2;
rlBegin(RL_LINES);
for(int i = -halfSlices; i <= halfSlices; i++)
for (int i = -halfSlices; i <= halfSlices; i++)
{
if (i == 0)
{

View File

@ -65,11 +65,11 @@ int main(void)
// Setup orbital camera
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
@ -81,55 +81,46 @@ int main(void)
// Send new value to the shader to be used on drawing
SetShaderValue(shader, swirlCenterLoc, swirlCenter, SHADER_UNIFORM_VEC2);
UpdateCamera(&camera); // Update camera
UpdateCamera(&camera); // Update camera
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginTextureMode(target); // Enable drawing to texture
ClearBackground(RAYWHITE); // Clear texture background
BeginMode3D(camera); // Begin 3d mode drawing
DrawModel(model, position, 0.5f, WHITE); // Draw 3d model with texture
DrawGrid(10, 1.0f); // Draw a grid
EndMode3D(); // End 3d mode drawing, returns to orthographic 2d mode
DrawText("TEXT DRAWN IN RENDER TEXTURE", 200, 10, 30, RED);
EndTextureMode(); // End drawing to texture (now we have a texture available for next passes)
BeginDrawing();
ClearBackground(RAYWHITE); // Clear screen background
ClearBackground(RAYWHITE);
BeginTextureMode(target); // Enable drawing to texture
ClearBackground(RAYWHITE); // Clear texture background
BeginMode3D(camera); // Begin 3d mode drawing
DrawModel(model, position, 0.5f, WHITE); // Draw 3d model with texture
DrawGrid(10, 1.0f); // Draw a grid
EndMode3D(); // End 3d mode drawing, returns to orthographic 2d mode
DrawText("TEXT DRAWN IN RENDER TEXTURE", 200, 10, 30, RED);
EndTextureMode(); // End drawing to texture (now we have a texture available for next passes)
// Enable shader using the custom uniform
BeginShaderMode(shader);
// NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
DrawTextureRec(target.texture, (Rectangle){ 0, 0, (float)target.texture.width, (float)-target.texture.height }, (Vector2){ 0, 0 }, WHITE);
EndShaderMode();
// Draw some 2d text over drawn texture
DrawText("(c) Barracks 3D model by Alberto Cano", screenWidth - 220, screenHeight - 20, 10, GRAY);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadShader(shader); // Unload shader
UnloadTexture(texture); // Unload texture
UnloadModel(model); // Unload model
UnloadRenderTexture(target); // Unload render texture
UnloadShader(shader); // Unload shader
UnloadTexture(texture); // Unload texture
UnloadModel(model); // Unload model
UnloadRenderTexture(target); // Unload render texture
CloseWindow(); // Close window and OpenGL context
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;

View File

@ -46,11 +46,11 @@ int main(void)
// NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader
Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/eratosthenes.fs", GLSL_VERSION));
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
@ -59,35 +59,33 @@ int main(void)
// Draw
//----------------------------------------------------------------------------------
BeginTextureMode(target); // Enable drawing to texture
ClearBackground(BLACK); // Clear the render texture
// Draw a rectangle in shader mode to be used as shader canvas
// NOTE: Rectangle uses font white character texture coordinates,
// so shader can not be applied here directly because input vertexTexCoord
// do not represent full screen coordinates (space where want to apply shader)
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), BLACK);
EndTextureMode(); // End drawing to texture (now we have a blank texture available for the shader)
BeginDrawing();
ClearBackground(RAYWHITE);
BeginTextureMode(target); // Enable drawing to texture
ClearBackground(BLACK); // Clear the render texture
// Draw a rectangle in shader mode to be used as shader canvas
// NOTE: Rectangle uses font white character texture coordinates,
// so shader can not be applied here directly because input vertexTexCoord
// do not represent full screen coordinates (space where want to apply shader)
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), BLACK);
EndTextureMode(); // End drawing to texture (now we have a blank texture available for the shader)
ClearBackground(RAYWHITE); // Clear screen background
BeginShaderMode(shader);
// NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
DrawTextureRec(target.texture, (Rectangle){ 0, 0, (float)target.texture.width, (float)-target.texture.height }, (Vector2){ 0.0f, 0.0f }, WHITE);
EndShaderMode();
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadShader(shader); // Unload shader
UnloadRenderTexture(target); // Unload texture
UnloadShader(shader); // Unload shader
UnloadRenderTexture(target); // Unload render texture
CloseWindow(); // Close window and OpenGL context
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;

View File

@ -75,15 +75,15 @@ int main(void)
SetShaderValue(shader, zoomLoc, &zoom, SHADER_UNIFORM_FLOAT);
SetShaderValue(shader, offsetLoc, offset, SHADER_UNIFORM_VEC2);
int incrementSpeed = 0; // Multiplier of speed to change c value
bool showControls = true; // Show controls
bool pause = false; // Pause animation
int incrementSpeed = 0; // Multiplier of speed to change c value
bool showControls = true; // Show controls
bool pause = false; // Pause animation
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
@ -145,20 +145,19 @@ int main(void)
// Draw
//----------------------------------------------------------------------------------
// Using a render texture to draw Julia set
BeginTextureMode(target); // Enable drawing to texture
ClearBackground(BLACK); // Clear the render texture
// Draw a rectangle in shader mode to be used as shader canvas
// NOTE: Rectangle uses font white character texture coordinates,
// so shader can not be applied here directly because input vertexTexCoord
// do not represent full screen coordinates (space where want to apply shader)
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), BLACK);
EndTextureMode();
BeginDrawing();
ClearBackground(BLACK); // Clear the screen of the previous frame.
// Using a render texture to draw Julia set
BeginTextureMode(target); // Enable drawing to texture
ClearBackground(BLACK); // Clear the render texture
// Draw a rectangle in shader mode to be used as shader canvas
// NOTE: Rectangle uses font white character texture coordinates,
// so shader can not be applied here directly because input vertexTexCoord
// do not represent full screen coordinates (space where want to apply shader)
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), BLACK);
EndTextureMode();
ClearBackground(BLACK); // Clear screen background
// Draw the saved texture and rendered julia set with shader
// NOTE: We do not invert texture on Y, already considered inside shader
@ -176,17 +175,16 @@ int main(void)
DrawText("Press KEY_LEFT | KEY_RIGHT to change speed", 10, 60, 10, RAYWHITE);
DrawText("Press KEY_SPACE to pause movement animation", 10, 75, 10, RAYWHITE);
}
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadShader(shader); // Unload shader
UnloadRenderTexture(target); // Unload render texture
UnloadShader(shader); // Unload shader
UnloadRenderTexture(target); // Unload render texture
CloseWindow(); // Close window and OpenGL context
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;

View File

@ -124,50 +124,38 @@ int main(void)
// Draw
//----------------------------------------------------------------------------------
BeginTextureMode(target); // Enable drawing to texture
ClearBackground(RAYWHITE); // Clear texture background
BeginMode3D(camera); // Begin 3d mode drawing
DrawModel(model, position, 0.1f, WHITE); // Draw 3d model with texture
DrawGrid(10, 1.0f); // Draw a grid
EndMode3D(); // End 3d mode drawing, returns to orthographic 2d mode
EndTextureMode(); // End drawing to texture (now we have a texture available for next passes)
BeginDrawing();
ClearBackground(RAYWHITE); // Clear screen background
ClearBackground(RAYWHITE);
BeginTextureMode(target); // Enable drawing to texture
ClearBackground(RAYWHITE); // Clear texture background
BeginMode3D(camera); // Begin 3d mode drawing
DrawModel(model, position, 0.1f, WHITE); // Draw 3d model with texture
DrawGrid(10, 1.0f); // Draw a grid
EndMode3D(); // End 3d mode drawing, returns to orthographic 2d mode
EndTextureMode(); // End drawing to texture (now we have a texture available for next passes)
// Render previously generated texture using selected postpro shader
// Render generated texture using selected postprocessing shader
BeginShaderMode(shaders[currentShader]);
// NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
DrawTextureRec(target.texture, (Rectangle){ 0, 0, (float)target.texture.width, (float)-target.texture.height }, (Vector2){ 0, 0 }, WHITE);
EndShaderMode();
// Draw 2d shapes and text over drawn texture
DrawRectangle(0, 9, 580, 30, Fade(LIGHTGRAY, 0.7f));
DrawText("(c) Church 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY);
DrawText("CURRENT POSTPRO SHADER:", 10, 15, 20, BLACK);
DrawText(postproShaderText[currentShader], 330, 15, 20, RED);
DrawText("< >", 540, 10, 30, DARKBLUE);
DrawFPS(700, 15);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
// Unload all postpro shaders
for (int i = 0; i < MAX_POSTPRO_SHADERS; i++) UnloadShader(shaders[i]);

View File

@ -291,7 +291,7 @@ int main(void)
for (int i = 0; i < layers; ++i)
{
Color clr = light;
if(multicolor) clr = multi[i];
if (multicolor) clr = multi[i];
DrawTextWave3D(font, text, (Vector3){ -tbox.x/2.0f, layerDistance*i, -4.5f }, fontSize, fontSpacing, lineSpacing, true, &wcfg, time, clr);
}
@ -465,7 +465,7 @@ void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontS
float width = (float)(font.recs[index].width + 2.0f*font.charsPadding)/(float)font.baseSize*scale;
float height = (float)(font.recs[index].height + 2.0f*font.charsPadding)/(float)font.baseSize*scale;
if(font.texture.id > 0)
if (font.texture.id > 0)
{
const float x = 0.0f;
const float y = 0.0f;
@ -477,7 +477,7 @@ void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontS
const float tw = (srcRec.x+srcRec.width)/font.texture.width;
const float th = (srcRec.y+srcRec.height)/font.texture.height;
if(SHOW_LETTER_BOUNDRY)
if (SHOW_LETTER_BOUNDRY)
DrawCubeWiresV((Vector3){ position.x + width/2, position.y, position.z + height/2}, (Vector3){ width, LETTER_BOUNDRY_SIZE, height }, LETTER_BOUNDRY_COLOR);
#if defined(RAYLIB_NEW_RLGL)
@ -533,7 +533,7 @@ void DrawText3D(Font font, const char *text, Vector3 position, float fontSize, f
{
// Get next codepoint from byte string and glyph index in font
int codepointByteCount = 0;
int codepoint = GetNextCodepoint(&text[i], &codepointByteCount);
int codepoint = GetCodepoint(&text[i], &codepointByteCount);
int index = GetGlyphIndex(font, codepoint);
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
@ -582,7 +582,7 @@ Vector3 MeasureText3D(Font font, const char* text, float fontSize, float fontSpa
lenCounter++;
int next = 0;
letter = GetNextCodepoint(&text[i], &next);
letter = GetCodepoint(&text[i], &next);
index = GetGlyphIndex(font, letter);
// NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
@ -632,7 +632,7 @@ void DrawTextWave3D(Font font, const char *text, Vector3 position, float fontSiz
{
// Get next codepoint from byte string and glyph index in font
int codepointByteCount = 0;
int codepoint = GetNextCodepoint(&text[i], &codepointByteCount);
int codepoint = GetCodepoint(&text[i], &codepointByteCount);
int index = GetGlyphIndex(font, codepoint);
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
@ -649,7 +649,7 @@ void DrawTextWave3D(Font font, const char *text, Vector3 position, float fontSiz
}
else if (codepoint == '~')
{
if (GetNextCodepoint(&text[i+1], &codepointByteCount) == '~')
if (GetCodepoint(&text[i+1], &codepointByteCount) == '~')
{
codepointByteCount += 1;
wave = !wave;
@ -698,7 +698,7 @@ Vector3 MeasureTextWave3D(Font font, const char* text, float fontSize, float fon
lenCounter++;
int next = 0;
letter = GetNextCodepoint(&text[i], &next);
letter = GetCodepoint(&text[i], &next);
index = GetGlyphIndex(font, letter);
// NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
@ -708,7 +708,7 @@ Vector3 MeasureTextWave3D(Font font, const char* text, float fontSize, float fon
if (letter != '\n')
{
if(letter == '~' && GetNextCodepoint(&text[i+1], &next) == '~')
if (letter == '~' && GetCodepoint(&text[i+1], &next) == '~')
{
i++;
}

View File

@ -298,7 +298,7 @@ GenMeshTorus|Mesh|(float radius, float size, int radSeg, int sides);|
GenMeshKnot|Mesh|(float radius, float size, int radSeg, int sides);|
GenMeshHeightmap|Mesh|(Image heightmap, Vector3 size);|
GenMeshCubicmap|Mesh|(Image cubicmap, Vector3 cubeSize);|
MeshBoundingBox|BoundingBox|(Mesh mesh);|
GetMeshBoundingBox|BoundingBox|(Mesh mesh);|
MeshTangents|void|(Mesh *mesh);|
MeshBinormals|void|(Mesh *mesh);|
DrawModel|void|(Model model, Vector3 position, float scale, Color tint);|

View File

@ -1549,7 +1549,7 @@
</KeyWord>
<!-- Mesh manipulation functions -->
<KeyWord name="MeshBoundingBox" func="yes">
<KeyWord name="GetMeshBoundingBox" func="yes">
<Overload retVal="BoundingBox" descr="Compute mesh bounding box limits">
<Param name="Mesh mesh" />
</Overload>

View File

@ -2495,7 +2495,7 @@
</KeyWord>
<!-- Mesh manipulation functions -->
<KeyWord name="MeshBoundingBox" func="yes">
<KeyWord name="GetMeshBoundingBox" func="yes">
<Overload retVal="BoundingBox" descr="Compute mesh bounding box limits">
<Param name="Mesh mesh" />
</Overload>

View File

@ -515,7 +515,7 @@ RLAPI Mesh GenMeshHeightmap(Image heightmap, Vector3 size);
RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Generate cubes-based map mesh from image data
// Mesh manipulation functions
RLAPI BoundingBox MeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits
RLAPI BoundingBox GetMeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits
RLAPI void MeshTangents(Mesh *mesh); // Compute mesh tangents
RLAPI void MeshBinormals(Mesh *mesh); // Compute mesh binormals

View File

@ -37,7 +37,7 @@
// Reconfigure standard input to receive key inputs, works with SSH connection.
#define SUPPORT_SSH_KEYBOARD_RPI 1
// Draw a mouse pointer on screen
#define SUPPORT_MOUSE_CURSOR_NATIVE 1
//#define SUPPORT_MOUSE_CURSOR_POINT 1
// Setting a higher resolution can improve the accuracy of time-out intervals in wait functions.
// However, it can also reduce overall system performance, because the thread scheduler switches tasks more often.
#define SUPPORT_WINMM_HIGHRES_TIMER 1
@ -56,7 +56,11 @@
// Support saving binary data automatically to a generated storage.data file. This file is managed internally.
#define SUPPORT_DATA_STORAGE 1
// Support automatic generated events, loading and recording of those events when required
#define SUPPORT_EVENTS_AUTOMATION 1
//#define SUPPORT_EVENTS_AUTOMATION 1
// Support custom frame control, only for advance users
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timming + PollInputEvents()
// Enabling this flag allows manual control of the frame processes, use at your own risk
//#define SUPPORT_CUSTOM_FRAME_CONTROL 1
// core: Configuration values
//------------------------------------------------------------------------------------
@ -161,7 +165,6 @@
//------------------------------------------------------------------------------------
#define MAX_TEXT_BUFFER_LENGTH 1024 // Size of internal static buffers used on some functions:
// TextFormat(), TextSubtext(), TextToUpper(), TextToLower(), TextToPascal(), TextSplit()
#define MAX_TEXT_UNICODE_CHARS 512 // Maximum number of unicode codepoints: GetCodepoints()
#define MAX_TEXTSPLIT_COUNT 128 // Maximum number of substrings to split: TextSplit()

View File

@ -56,7 +56,7 @@
* WARNING: Reconfiguring standard input could lead to undesired effects, like breaking other running processes or
* blocking the device is not restored properly. Use with care.
*
* #define SUPPORT_MOUSE_CURSOR_NATIVE (Raspberry Pi and DRM only)
* #define SUPPORT_MOUSE_CURSOR_POINT
* Draw a mouse pointer on screen
*
* #define SUPPORT_BUSY_WAIT_LOOP
@ -387,7 +387,7 @@ typedef struct CoreData {
Point position; // Window position on screen (required on fullscreen toggle)
Size display; // Display width and height (monitor, device-screen, LCD, ...)
Size screen; // Screen width and height (used render area)
Size currentFbo; // Current render width and height, it could change on BeginTextureMode()
Size currentFbo; // Current render width and height (depends on active fbo)
Size render; // Framebuffer width and height (render area, including black bars if required)
Point renderOffset; // Offset from render area (must be divided by 2)
Matrix screenScale; // Matrix to scale screen (framebuffer rendering)
@ -599,15 +599,10 @@ extern void UnloadFontDefault(void); // [Module: text] Unloads default fo
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
static void InitTimer(void); // Initialize timer (hi-resolution if available)
static bool InitGraphicsDevice(int width, int height); // Initialize graphics device
static void SetupFramebuffer(int width, int height); // Setup main framebuffer
static void SetupViewport(int width, int height); // Set viewport for a provided width and height
static void SwapBuffers(void); // Copy back buffer to front buffer
static void InitTimer(void); // Initialize timer
static void Wait(float ms); // Wait for some milliseconds (stop program execution)
static void PollInputEvents(void); // Register user events
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
@ -636,6 +631,8 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
#if defined(PLATFORM_WEB)
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData);
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *e, void *userData);
#endif
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
@ -673,7 +670,7 @@ static void PlayAutomationEvent(unsigned int frame);
#if defined(_WIN32)
// NOTE: We include Sleep() function signature here to avoid windows.h inclusion (kernel32 lib)
void __stdcall Sleep(unsigned long msTimeout); // Required for Wait()
void __stdcall Sleep(unsigned long msTimeout); // Required for WaitTime()
#endif
//----------------------------------------------------------------------------------
@ -843,6 +840,9 @@ void InitWindow(int width, int height, const char *title)
// Init hi-res timer
InitTimer();
// Initialize random seed
srand((unsigned int)time(NULL));
#if defined(SUPPORT_DEFAULT_FONT)
// Load default font
@ -875,10 +875,14 @@ void InitWindow(int width, int height, const char *title)
#endif
#if defined(PLATFORM_WEB)
// Check fullscreen change events
//emscripten_set_fullscreenchange_callback("#canvas", NULL, 1, EmscriptenFullscreenChangeCallback);
//emscripten_set_resize_callback("#canvas", NULL, 1, EmscriptenResizeCallback);
// Check fullscreen change events(note this is done on the window since most
// browsers don't support this on #canvas)
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
// Check Resize event (note this is done on the window since most browsers
// don't support this on #canvas)
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 1, EmscriptenResizeCallback);
// Trigger this once to get initial window sizing
EmscriptenResizeCallback(EMSCRIPTEN_EVENT_RESIZE, NULL, NULL);
// Support keyboard events
//emscripten_set_keypress_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
//emscripten_set_keydown_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
@ -1556,7 +1560,7 @@ void SetWindowMinSize(int width, int height)
// TODO: Issues on HighDPI scaling
void SetWindowSize(int width, int height)
{
#if defined(PLATFORM_DESKTOP)
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
glfwSetWindowSize(CORE.Window.handle, width, height);
#endif
#if defined(PLATFORM_WEB)
@ -1938,7 +1942,10 @@ void ClearBackground(Color color)
// Setup canvas (framebuffer) to start drawing
void BeginDrawing(void)
{
CORE.Time.current = GetTime(); // Number of elapsed seconds since InitTimer()
// WARNING: Previously to BeginDrawing() other render textures drawing could happen,
// consequently the measure for update vs draw is not accurate (only the total frame time is accurate)
CORE.Time.current = GetTime(); // Number of elapsed seconds since InitTimer()
CORE.Time.update = CORE.Time.current - CORE.Time.previous;
CORE.Time.previous = CORE.Time.current;
@ -1952,22 +1959,22 @@ void BeginDrawing(void)
// End canvas drawing and swap buffers (double buffering)
void EndDrawing(void)
{
#if (defined(PLATFORM_RPI) || defined(PLATFORM_DRM)) && defined(SUPPORT_MOUSE_CURSOR_NATIVE)
// On native mode we have no system mouse cursor, so,
// we draw a small rectangle for user reference
rlDrawRenderBatchActive(); // Update and draw internal render batch
#if defined(SUPPORT_MOUSE_CURSOR_POINT)
// Draw a small rectangle on mouse position for user reference
if (!CORE.Input.Mouse.cursorHidden)
{
DrawRectangle(CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y, 3, 3, MAROON);
rlDrawRenderBatchActive(); // Update and draw internal render batch
}
#endif
rlDrawRenderBatchActive(); // Update and draw internal render batch
#if defined(SUPPORT_GIF_RECORDING)
#define GIF_RECORD_FRAMERATE 10
// Draw record indicator
if (gifRecording)
{
#define GIF_RECORD_FRAMERATE 10
gifFramesCounter++;
// NOTE: We record one gif frame every 10 game frames
@ -1992,6 +1999,7 @@ void EndDrawing(void)
#endif
#if defined(SUPPORT_EVENTS_AUTOMATION)
// Draw record/play indicator
if (eventsRecording)
{
gifFramesCounter++;
@ -2018,7 +2026,8 @@ void EndDrawing(void)
}
#endif
SwapBuffers(); // Copy back buffer to front buffer
#if !defined(SUPPORT_CUSTOM_FRAME_CONTROL)
SwapScreenBuffer(); // Copy back buffer to front buffer (screen)
// Frame time control system
CORE.Time.current = GetTime();
@ -2030,7 +2039,7 @@ void EndDrawing(void)
// Wait for some milliseconds...
if (CORE.Time.frame < CORE.Time.target)
{
Wait((float)(CORE.Time.target - CORE.Time.frame)*1000.0f);
WaitTime((float)(CORE.Time.target - CORE.Time.frame)*1000.0f);
CORE.Time.current = GetTime();
double waitTime = CORE.Time.current - CORE.Time.previous;
@ -2039,14 +2048,15 @@ void EndDrawing(void)
CORE.Time.frame += waitTime; // Total frame time: update + draw + wait
}
PollInputEvents(); // Poll user events
PollInputEvents(); // Poll user events (before next frame update)
#endif
#if defined(SUPPORT_EVENTS_AUTOMATION)
// Events recording and playing logic
if (eventsRecording) RecordAutomationEvent(CORE.Time.frameCounter);
// TODO: When should we play? After/before/replace PollInputEvents()?
if (eventsPlaying)
else if (eventsPlaying)
{
// TODO: When should we play? After/before/replace PollInputEvents()?
if (CORE.Time.frameCounter >= eventCount) eventsPlaying = false;
PlayAutomationEvent(CORE.Time.frameCounter);
}
@ -2638,6 +2648,9 @@ void SetTargetFPS(int fps)
// NOTE: We calculate an average framerate
int GetFPS(void)
{
int fps = 0;
#if !defined(SUPPORT_CUSTOM_FRAME_CONTROL)
#define FPS_CAPTURE_FRAMES_COUNT 30 // 30 captures
#define FPS_AVERAGE_TIME_SECONDS 0.5f // 500 millisecondes
#define FPS_STEP (FPS_AVERAGE_TIME_SECONDS/FPS_CAPTURE_FRAMES_COUNT)
@ -2658,7 +2671,10 @@ int GetFPS(void)
average += history[index];
}
return (int)roundf(1.0f/average);
fps = (int)roundf(1.0f/average);
#endif
return fps;
}
// Get time in seconds for last frame drawn (delta time)
@ -3540,6 +3556,17 @@ Vector2 GetMousePosition(void)
return position;
}
// Get mouse delta between frames
Vector2 GetMouseDelta(void)
{
Vector2 delta = {0};
delta.x = CORE.Input.Mouse.currentPosition.x - CORE.Input.Mouse.previousPosition.x;
delta.y = CORE.Input.Mouse.currentPosition.y - CORE.Input.Mouse.previousPosition.y;
return delta;
}
// Set mouse position XY
void SetMousePosition(int x, int y)
{
@ -4661,8 +4688,6 @@ static void SetupFramebuffer(int width, int height)
// Initialize hi-resolution timer
static void InitTimer(void)
{
srand((unsigned int)time(NULL)); // Initialize random seed
// Setting a higher resolution can improve the accuracy of time-out intervals in wait functions.
// However, it can also reduce overall system performance, because the thread scheduler switches tasks more often.
// High resolutions can also prevent the CPU power management system from entering power-saving modes.
@ -4689,7 +4714,7 @@ static void InitTimer(void)
// take longer than expected... for that reason we use the busy wait loop
// Ref: http://stackoverflow.com/questions/43057578/c-programming-win32-games-sleep-taking-longer-than-expected
// Ref: http://www.geisswerks.com/ryan/FAQS/timing.html --> All about timming on Win32!
static void Wait(float ms)
void WaitTime(float ms)
{
#if defined(PLATFORM_UWP)
UWPGetSleepFunc()(ms/1000);
@ -4737,8 +4762,70 @@ static void Wait(float ms)
#endif
}
// Poll (store) all input events
static void PollInputEvents(void)
// Swap back buffer with front buffer (screen drawing)
void SwapScreenBuffer(void)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
glfwSwapBuffers(CORE.Window.handle);
#endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM) || defined(PLATFORM_UWP)
eglSwapBuffers(CORE.Window.device, CORE.Window.surface);
#if defined(PLATFORM_DRM)
if (!CORE.Window.gbmSurface || (-1 == CORE.Window.fd) || !CORE.Window.connector || !CORE.Window.crtc)
{
TRACELOG(LOG_ERROR, "DISPLAY: DRM initialization failed to swap");
abort();
}
struct gbm_bo *bo = gbm_surface_lock_front_buffer(CORE.Window.gbmSurface);
if (!bo)
{
TRACELOG(LOG_ERROR, "DISPLAY: Failed GBM to lock front buffer");
abort();
}
uint32_t fb = 0;
int result = drmModeAddFB(CORE.Window.fd, CORE.Window.connector->modes[CORE.Window.modeIndex].hdisplay,
CORE.Window.connector->modes[CORE.Window.modeIndex].vdisplay, 24, 32, gbm_bo_get_stride(bo), gbm_bo_get_handle(bo).u32, &fb);
if (0 != result)
{
TRACELOG(LOG_ERROR, "DISPLAY: drmModeAddFB() failed with result: %d", result);
abort();
}
result = drmModeSetCrtc(CORE.Window.fd, CORE.Window.crtc->crtc_id, fb, 0, 0,
&CORE.Window.connector->connector_id, 1, &CORE.Window.connector->modes[CORE.Window.modeIndex]);
if (0 != result)
{
TRACELOG(LOG_ERROR, "DISPLAY: drmModeSetCrtc() failed with result: %d", result);
abort();
}
if (CORE.Window.prevFB)
{
result = drmModeRmFB(CORE.Window.fd, CORE.Window.prevFB);
if (0 != result)
{
TRACELOG(LOG_ERROR, "DISPLAY: drmModeRmFB() failed with result: %d", result);
abort();
}
}
CORE.Window.prevFB = fb;
if (CORE.Window.prevBO)
{
gbm_surface_release_buffer(CORE.Window.gbmSurface, CORE.Window.prevBO);
}
CORE.Window.prevBO = bo;
#endif // PLATFORM_DRM
#endif // PLATFORM_ANDROID || PLATFORM_RPI || PLATFORM_DRM || PLATFORM_UWP
}
// Register all input events
void PollInputEvents(void)
{
#if defined(SUPPORT_GESTURES_SYSTEM)
// NOTE: Gestures update must be called every frame to reset gestures correctly
@ -5014,68 +5101,6 @@ static void PollInputEvents(void)
#endif
}
// Copy back buffer to front buffers
static void SwapBuffers(void)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
glfwSwapBuffers(CORE.Window.handle);
#endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_DRM) || defined(PLATFORM_UWP)
eglSwapBuffers(CORE.Window.device, CORE.Window.surface);
#if defined(PLATFORM_DRM)
if (!CORE.Window.gbmSurface || (-1 == CORE.Window.fd) || !CORE.Window.connector || !CORE.Window.crtc)
{
TRACELOG(LOG_ERROR, "DISPLAY: DRM initialization failed to swap");
abort();
}
struct gbm_bo *bo = gbm_surface_lock_front_buffer(CORE.Window.gbmSurface);
if (!bo)
{
TRACELOG(LOG_ERROR, "DISPLAY: Failed GBM to lock front buffer");
abort();
}
uint32_t fb = 0;
int result = drmModeAddFB(CORE.Window.fd, CORE.Window.connector->modes[CORE.Window.modeIndex].hdisplay,
CORE.Window.connector->modes[CORE.Window.modeIndex].vdisplay, 24, 32, gbm_bo_get_stride(bo), gbm_bo_get_handle(bo).u32, &fb);
if (0 != result)
{
TRACELOG(LOG_ERROR, "DISPLAY: drmModeAddFB() failed with result: %d", result);
abort();
}
result = drmModeSetCrtc(CORE.Window.fd, CORE.Window.crtc->crtc_id, fb, 0, 0,
&CORE.Window.connector->connector_id, 1, &CORE.Window.connector->modes[CORE.Window.modeIndex]);
if (0 != result)
{
TRACELOG(LOG_ERROR, "DISPLAY: drmModeSetCrtc() failed with result: %d", result);
abort();
}
if (CORE.Window.prevFB)
{
result = drmModeRmFB(CORE.Window.fd, CORE.Window.prevFB);
if (0 != result)
{
TRACELOG(LOG_ERROR, "DISPLAY: drmModeRmFB() failed with result: %d", result);
abort();
}
}
CORE.Window.prevFB = fb;
if (CORE.Window.prevBO)
{
gbm_surface_release_buffer(CORE.Window.gbmSurface, CORE.Window.prevBO);
}
CORE.Window.prevBO = bo;
#endif // PLATFORM_DRM
#endif // PLATFORM_ANDROID || PLATFORM_RPI || PLATFORM_DRM || PLATFORM_UWP
}
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
// GLFW3 Error Callback, runs on GLFW3 error
static void ErrorCallback(int error, const char *description)
@ -5083,6 +5108,36 @@ static void ErrorCallback(int error, const char *description)
TRACELOG(LOG_WARNING, "GLFW: Error: %i Description: %s", error, description);
}
#if defined(PLATFORM_WEB)
EM_JS(int, GetCanvasWidth, (), { return canvas.clientWidth; });
EM_JS(int, GetCanvasHeight, (), { return canvas.clientHeight; });
static EM_BOOL EmscriptenResizeCallback(int eventType, const EmscriptenUiEvent *e, void *userData)
{
// Don't resize non-resizeable windows
if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) return true;
// This event is called whenever the window changes sizes,
// so the size of the canvas object is explicitly retrieved below
int width = GetCanvasWidth();
int height = GetCanvasHeight();
emscripten_set_canvas_element_size("#canvas",width,height);
SetupViewport(width, height); // Reset viewport and projection matrix for new size
CORE.Window.currentFbo.width = width;
CORE.Window.currentFbo.height = height;
CORE.Window.resizedLastFrame = true;
if (IsWindowFullscreen()) return true;
// Set current screen size
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
// NOTE: Postprocessing texture is not scaled to new size
}
#endif
// GLFW3 WindowSize Callback, runs when window is resizedLastFrame
// NOTE: Window resizing not allowed by default
@ -5374,6 +5429,9 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
// Init hi-res timer
InitTimer();
// Initialize random seed
srand((unsigned int)time(NULL));
#if defined(SUPPORT_DEFAULT_FONT)
// Load default font
@ -6327,7 +6385,8 @@ static void *EventThread(void *arg)
#endif
}
}
Wait(5); // Sleep for 5ms to avoid hogging CPU time
WaitTime(5); // Sleep for 5ms to avoid hogging CPU time
}
close(worker->fd);
@ -6415,7 +6474,7 @@ static void *GamepadThread(void *arg)
}
}
}
else Wait(1); // Sleep for 1 ms to avoid hogging CPU time
else WaitTime(1); // Sleep for 1 ms to avoid hogging CPU time
}
}
@ -6829,7 +6888,7 @@ static void LoadAutomationEvents(const char *fileName)
{
sscanf(buffer, "e %d %d %d %d %d", &events[count].frame, &events[count].type,
&events[count].params[0], &events[count].params[1], &events[count].params[2]);
count++;
}

View File

@ -948,6 +948,8 @@ static int tinyobj_parse_and_index_mtl_file(tinyobj_material_t **materials_out,
/* @todo { unknown parameter } */
}
fclose(fp);
if (material.name) {
/* Flush last material element */
materials = tinyobj_material_add(materials, num_materials, &material);

View File

@ -318,7 +318,7 @@ static unsigned int usedMemory = 0; // Total allocated d
//----------------------------------------------------------------------------------
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
// Timming measure functions
static void InitTimer(void); // Initializes hi-resolution MONOTONIC timer
static void InitTimerHiRes(void); // Initializes hi-resolution MONOTONIC timer
static unsigned long long int GetClockTicks(void); // Get hi-res MONOTONIC time measure in mseconds
static double GetCurrentTime(void); // Get current time measure in milliseconds
#endif
@ -370,7 +370,7 @@ PHYSACDEF void InitPhysics(void)
{
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
// Initialize high resolution timer
InitTimer();
InitTimerHiRes();
#endif
TRACELOG("[PHYSAC] Physics module initialized successfully\n");
@ -1848,7 +1848,7 @@ static Vector2 MathTriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3)
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
// Initializes hi-resolution MONOTONIC timer
static void InitTimer(void)
static void InitTimerHiRes(void)
{
#if defined(_WIN32)
QueryPerformanceFrequency((unsigned long long int *) &frequency);

View File

@ -1105,10 +1105,6 @@ void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int ins
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]);
rlEnableVertexBuffer(mesh.vboId[0]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]);
// Bind mesh VBO data: vertex texcoords (shader-location = 1)
rlEnableVertexBuffer(mesh.vboId[1]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0);
@ -2652,7 +2648,7 @@ BoundingBox GetMeshBoundingBox(Mesh mesh)
// Compute mesh tangents
// NOTE: To calculate mesh tangents and binormals we need mesh vertex positions and texture coordinates
// Implementation base don: https://answers.unity.com/questions/7789/calculating-tangents-vector4.html
void MeshTangents(Mesh *mesh)
void GenMeshTangents(Mesh *mesh)
{
if (mesh->tangents == NULL) mesh->tangents = (float *)RL_MALLOC(mesh->vertexCount*4*sizeof(float));
else TRACELOG(LOG_WARNING, "MESH: Tangents data already available, re-writting");
@ -2732,7 +2728,7 @@ void MeshTangents(Mesh *mesh)
}
// Compute mesh binormals (aka bitangent)
void MeshBinormals(Mesh *mesh)
void GenMeshBinormals(Mesh *mesh)
{
for (int i = 0; i < mesh->vertexCount; i++)
{
@ -4996,7 +4992,7 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
// output->framerate = // TODO: Use framerate instead of const timestep
// Name and parent bones
for (unsigned int j = 0; j < output->boneCount; j++)
for (int j = 0; j < output->boneCount; j++)
{
strcpy(output->bones[j].name, data->nodes[j].name == 0 ? "ANIMJOINT" : data->nodes[j].name);
output->bones[j].parent = (data->nodes[j].parent != NULL) ? (int)(data->nodes[j].parent - data->nodes) : -1;
@ -5007,7 +5003,7 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
for (int frame = 0; frame < output->frameCount; frame++)
{
output->framePoses[frame] = RL_MALLOC(output->boneCount*sizeof(Transform));
for (unsigned int i = 0; i < output->boneCount; i++)
{
if (data->nodes[i].has_translation) memcpy(&output->framePoses[frame][i].translation, data->nodes[i].translation, 3 * sizeof(float));

View File

@ -222,7 +222,7 @@ typedef struct Color {
// Rectangle, 4 components
typedef struct Rectangle {
float x; // Rectangle top-left corner position x
float x; // Rectangle top-left corner position x
float y; // Rectangle top-left corner position y
float width; // Rectangle width
float height; // Rectangle height
@ -960,6 +960,14 @@ RLAPI const char *GetMonitorName(int monitor); // Get the hum
RLAPI void SetClipboardText(const char *text); // Set clipboard text content
RLAPI const char *GetClipboardText(void); // Get clipboard text content
// Custom frame control functions
// NOTE: Those functions are intended for advance users that want full control over the frame processing
// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timming + PollInputEvents()
// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL
RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)
RLAPI void PollInputEvents(void); // Register all input events
RLAPI void WaitTime(float ms); // Wait for some milliseconds (halt program execution)
// Cursor-related functions
RLAPI void ShowCursor(void); // Shows cursor
RLAPI void HideCursor(void); // Hides cursor
@ -1104,6 +1112,7 @@ RLAPI bool IsMouseButtonUp(int button); // Check if a mous
RLAPI int GetMouseX(void); // Get mouse position X
RLAPI int GetMouseY(void); // Get mouse position Y
RLAPI Vector2 GetMousePosition(void); // Get mouse position XY
RLAPI Vector2 GetMouseDelta(void); // Get mouse delta between frames
RLAPI void SetMousePosition(int x, int y); // Set mouse position XY
RLAPI void SetMouseOffset(int offsetX, int offsetY); // Set mouse offset
RLAPI void SetMouseScale(float scaleX, float scaleY); // Set mouse scaling
@ -1360,9 +1369,10 @@ RLAPI int TextToInteger(const char *text); // Get int
RLAPI char *TextToUtf8(int *codepoints, int length); // Encode text codepoint into utf8 text (memory must be freed!)
// UTF8 text strings management functions
RLAPI int *GetCodepoints(const char *text, int *count); // Get all codepoints in a string, codepoints count returned by parameters
RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF8 text string, codepoints count returned by parameter
RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
RLAPI int GetCodepointsCount(const char *text); // Get total number of characters (codepoints) in a UTF8 encoded string
RLAPI int GetNextCodepoint(const char *text, int *bytesProcessed); // Get next codepoint in a UTF8 encoded string; 0x3f('?') is returned on failure
RLAPI int GetCodepoint(const char *text, int *bytesProcessed); // Get next codepoint in a UTF8 encoded string, 0x3f('?') is returned on failure
RLAPI const char *CodepointToUtf8(int codepoint, int *byteLength); // Encode codepoint into utf8 text (char array length returned as parameter)
//------------------------------------------------------------------------------------
@ -1435,8 +1445,8 @@ RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize);
// Mesh manipulation functions
RLAPI BoundingBox GetMeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits
RLAPI void MeshTangents(Mesh *mesh); // Compute mesh tangents
RLAPI void MeshBinormals(Mesh *mesh); // Compute mesh binormals
RLAPI void GenMeshTangents(Mesh *mesh); // Compute mesh tangents
RLAPI void GenMeshBinormals(Mesh *mesh); // Compute mesh binormals
// Model drawing functions
RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set)

View File

@ -138,7 +138,7 @@
typedef struct float3 { float v[3]; } float3;
typedef struct float16 { float v[16]; } float16;
#include <math.h> // Required for: sinf(), cosf(), sqrtf(), tan(), fabs()
#include <math.h> // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), fminf(), fmaxf(), fabs()
//----------------------------------------------------------------------------------
// Module Functions Definition - Utils math

View File

@ -297,14 +297,6 @@ typedef struct RenderBatch {
typedef enum { false, true } bool;
#endif
// Color, 4 components, R8G8B8A8 (32bit)
typedef struct Color {
unsigned char r; // Color red value
unsigned char g; // Color green value
unsigned char b; // Color blue value
unsigned char a; // Color alpha value
} Color;
// Texture type
// NOTE: Data stored in GPU memory
typedef struct Texture2D {
@ -880,8 +872,8 @@ static char *rlGetCompressedFormatName(int format); // Get compressed format off
#endif // SUPPORT_GL_DETAILS_INFO
#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
#if defined(GRAPHICS_API_OPENGL_11)
static int rlGenerateMipmapsData(unsigned char *data, int baseWidth, int baseHeight); // Generate mipmaps data on CPU side
static Color *rlGenNextMipmapData(Color *srcData, int srcWidth, int srcHeight); // Generate next mipmap level on CPU side
static int rlGenerateMipmapsData(unsigned char *data, int baseWidth, int baseHeight); // Generate mipmaps data on CPU side
static unsigned char *rlGenNextMipmapData(unsigned char *srcData, int srcWidth, int srcHeight); // Generate next mipmap level on CPU side
#endif
static int rlGetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes (image or texture)
@ -3957,22 +3949,20 @@ static int rlGenerateMipmapsData(unsigned char *data, int baseWidth, int baseHei
width = baseWidth;
height = baseHeight;
size = (width*height*4);
size = (width*height*4); // RGBA: 4 bytes
// Generate mipmaps
// NOTE: Every mipmap data is stored after data
Color *image = (Color *)RL_MALLOC(width*height*sizeof(Color));
Color *mipmap = NULL;
// NOTE: Every mipmap data is stored after data (RGBA - 4 bytes)
unsigned char *image = (unsigned char *)RL_MALLOC(width*height*4);
unsigned char *mipmap = NULL;
int offset = 0;
int j = 0;
for (int i = 0; i < size; i += 4)
{
image[j].r = data[i];
image[j].g = data[i + 1];
image[j].b = data[i + 2];
image[j].a = data[i + 3];
j++;
image[i] = data[i];
image[i + 1] = data[i + 1];
image[i + 2] = data[i + 2];
image[i + 3] = data[i + 3];
}
TRACELOGD("TEXTURE: Mipmap base size (%ix%i)", width, height);
@ -3982,7 +3972,6 @@ static int rlGenerateMipmapsData(unsigned char *data, int baseWidth, int baseHei
mipmap = rlGenNextMipmapData(image, width, height);
offset += (width*height*4); // Size of last mipmap
j = 0;
width /= 2;
height /= 2;
@ -3991,11 +3980,10 @@ static int rlGenerateMipmapsData(unsigned char *data, int baseWidth, int baseHei
// Add mipmap to data
for (int i = 0; i < size; i += 4)
{
data[offset + i] = mipmap[j].r;
data[offset + i + 1] = mipmap[j].g;
data[offset + i + 2] = mipmap[j].b;
data[offset + i + 3] = mipmap[j].a;
j++;
data[offset + i] = mipmap[i];
data[offset + i + 1] = mipmap[i + 1];
data[offset + i + 2] = mipmap[i + 2];
data[offset + i + 3] = mipmap[i + 3];
}
RL_FREE(image);
@ -4010,15 +3998,17 @@ static int rlGenerateMipmapsData(unsigned char *data, int baseWidth, int baseHei
}
// Manual mipmap generation (basic scaling algorithm)
static Color *rlGenNextMipmapData(Color *srcData, int srcWidth, int srcHeight)
static unsigned char *rlGenNextMipmapData(unsigned char *srcData, int srcWidth, int srcHeight)
{
int x2, y2;
Color prow, pcol;
int x2 = 0;
int y2 = 0;
unsigned char prow[4];
unsigned char pcol[4];
int width = srcWidth/2;
int height = srcHeight/2;
Color *mipmap = (Color *)RL_MALLOC(width*height*sizeof(Color));
unsigned char *mipmap = (unsigned char *)RL_MALLOC(width*height*4);
// Scaling algorithm works perfectly (box-filter)
for (int y = 0; y < height; y++)
@ -4029,20 +4019,20 @@ static Color *rlGenNextMipmapData(Color *srcData, int srcWidth, int srcHeight)
{
x2 = 2*x;
prow.r = (srcData[y2*srcWidth + x2].r + srcData[y2*srcWidth + x2 + 1].r)/2;
prow.g = (srcData[y2*srcWidth + x2].g + srcData[y2*srcWidth + x2 + 1].g)/2;
prow.b = (srcData[y2*srcWidth + x2].b + srcData[y2*srcWidth + x2 + 1].b)/2;
prow.a = (srcData[y2*srcWidth + x2].a + srcData[y2*srcWidth + x2 + 1].a)/2;
prow[0] = (srcData[(y2*srcWidth + x2)*4 + 0] + srcData[(y2*srcWidth + x2 + 1)*4 + 0])/2;
prow[1] = (srcData[(y2*srcWidth + x2)*4 + 1] + srcData[(y2*srcWidth + x2 + 1)*4 + 1])/2;
prow[2] = (srcData[(y2*srcWidth + x2)*4 + 2] + srcData[(y2*srcWidth + x2 + 1)*4 + 2])/2;
prow[3] = (srcData[(y2*srcWidth + x2)*4 + 3] + srcData[(y2*srcWidth + x2 + 1)*4 + 3])/2;
pcol.r = (srcData[(y2+1)*srcWidth + x2].r + srcData[(y2+1)*srcWidth + x2 + 1].r)/2;
pcol.g = (srcData[(y2+1)*srcWidth + x2].g + srcData[(y2+1)*srcWidth + x2 + 1].g)/2;
pcol.b = (srcData[(y2+1)*srcWidth + x2].b + srcData[(y2+1)*srcWidth + x2 + 1].b)/2;
pcol.a = (srcData[(y2+1)*srcWidth + x2].a + srcData[(y2+1)*srcWidth + x2 + 1].a)/2;
pcol[0] = (srcData[((y2 + 1)*srcWidth + x2)*4 + 0] + srcData[((y2 + 1)*srcWidth + x2 + 1)*4 + 0])/2;
pcol[1] = (srcData[((y2 + 1)*srcWidth + x2)*4 + 1] + srcData[((y2 + 1)*srcWidth + x2 + 1)*4 + 1])/2;
pcol[2] = (srcData[((y2 + 1)*srcWidth + x2)*4 + 2] + srcData[((y2 + 1)*srcWidth + x2 + 1)*4 + 2])/2;
pcol[3] = (srcData[((y2 + 1)*srcWidth + x2)*4 + 3] + srcData[((y2 + 1)*srcWidth + x2 + 1)*4 + 3])/2;
mipmap[y*width + x].r = (prow.r + pcol.r)/2;
mipmap[y*width + x].g = (prow.g + pcol.g)/2;
mipmap[y*width + x].b = (prow.b + pcol.b)/2;
mipmap[y*width + x].a = (prow.a + pcol.a)/2;
mipmap[(y*width + x)*4 + 0] = (prow[0] + pcol[0])/2;
mipmap[(y*width + x)*4 + 1] = (prow[1] + pcol[1])/2;
mipmap[(y*width + x)*4 + 2] = (prow[2] + pcol[2])/2;
mipmap[(y*width + x)*4 + 3] = (prow[3] + pcol[3])/2;
}
}

View File

@ -1645,7 +1645,7 @@ bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshol
if (fabsf(dxl) >= fabsf(dyl)) collision = (dxl > 0)? ((p1.x <= point.x) && (point.x <= p2.x)) : ((p2.x <= point.x) && (point.x <= p1.x));
else collision = (dyl > 0)? ((p1.y <= point.y) && (point.y <= p2.y)) : ((p2.y <= point.y) && (point.y <= p1.y));
}
return collision;
}

View File

@ -861,7 +861,7 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
{
// Get next codepoint from byte string and glyph index in font
int codepointByteCount = 0;
int codepoint = GetNextCodepoint(&text[i], &codepointByteCount);
int codepoint = GetCodepoint(&text[i], &codepointByteCount);
int index = GetGlyphIndex(font, codepoint);
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
@ -901,10 +901,10 @@ void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, f
{
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
int textOffsetY = 0; // Offset between lines (on line break '\n')
float textOffsetY = 0; // Offset between lines (on line break '\n')
float textOffsetX = 0.0f; // Offset X to next character to draw
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
float scaleFactor = fontSize/(float)font.baseSize; // Character quad scaling factor
// Word/character wrapping mechanism variables
enum { MEASURE_STATE = 0, DRAW_STATE = 1 };
@ -918,7 +918,7 @@ void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, f
{
// Get next codepoint from byte string and glyph index in font
int codepointByteCount = 0;
int codepoint = GetNextCodepoint(&text[i], &codepointByteCount);
int codepoint = GetCodepoint(&text[i], &codepointByteCount);
int index = GetGlyphIndex(font, codepoint);
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
@ -926,12 +926,12 @@ void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, f
if (codepoint == 0x3f) codepointByteCount = 1;
i += (codepointByteCount - 1);
int glyphWidth = 0;
float glyphWidth = 0;
if (codepoint != '\n')
{
glyphWidth = (font.chars[index].advanceX == 0)?
(int)(font.recs[index].width*scaleFactor + spacing):
(int)(font.chars[index].advanceX*scaleFactor + spacing);
glyphWidth = (font.chars[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.chars[index].advanceX*scaleFactor;
if (i + 1 < length) glyphWidth = glyphWidth + spacing;
}
// NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container
@ -945,7 +945,7 @@ void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, f
// Ref: http://jkorpela.fi/chars/spaces.html
if ((codepoint == ' ') || (codepoint == '\t') || (codepoint == '\n')) endLine = i;
if ((textOffsetX + glyphWidth + 1) >= rec.width)
if ((textOffsetX + glyphWidth) > rec.width)
{
endLine = (endLine < 1)? i : endLine;
if (i == endLine) endLine -= codepointByteCount;
@ -956,7 +956,6 @@ void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, f
else if ((i + 1) == length)
{
endLine = i;
state = !state;
}
else if (codepoint == '\n') state = !state;
@ -979,26 +978,26 @@ void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, f
{
if (!wordWrap)
{
textOffsetY += (int)((font.baseSize + font.baseSize/2)*scaleFactor);
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
textOffsetX = 0;
}
}
else
{
if (!wordWrap && ((textOffsetX + glyphWidth + 1) >= rec.width))
if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width))
{
textOffsetY += (int)((font.baseSize + font.baseSize/2)*scaleFactor);
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
textOffsetX = 0;
}
// When text overflows rectangle height limit, just stop drawing
if ((textOffsetY + (int)(font.baseSize*scaleFactor)) > rec.height) break;
if ((textOffsetY + font.baseSize*scaleFactor) > rec.height) break;
// Draw selection background
bool isGlyphSelected = false;
if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength)))
{
DrawRectangleRec((Rectangle){ rec.x + textOffsetX - 1, rec.y + textOffsetY, (float)glyphWidth, (float)font.baseSize*scaleFactor }, selectBackTint);
DrawRectangleRec((Rectangle){ rec.x + textOffsetX - 1, rec.y + textOffsetY, glyphWidth, (float)font.baseSize*scaleFactor }, selectBackTint);
isGlyphSelected = true;
}
@ -1011,7 +1010,7 @@ void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, f
if (wordWrap && (i == endLine))
{
textOffsetY += (int)((font.baseSize + font.baseSize/2)*scaleFactor);
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
textOffsetX = 0;
startLine = endLine;
endLine = -1;
@ -1090,7 +1089,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
lenCounter++;
int next = 0;
letter = GetNextCodepoint(&text[i], &next);
letter = GetCodepoint(&text[i], &next);
index = GetGlyphIndex(font, letter);
// NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
@ -1564,28 +1563,38 @@ RLAPI const char *CodepointToUtf8(int codepoint, int *byteLength)
return utf8;
}
// Get all codepoints in a string, codepoints count returned by parameters
// REQUIRES: memset()
int *GetCodepoints(const char *text, int *count)
// Load all codepoints from a UTF8 text string, codepoints count returned by parameter
int *LoadCodepoints(const char *text, int *count)
{
static int codepoints[MAX_TEXT_UNICODE_CHARS] = { 0 };
memset(codepoints, 0, MAX_TEXT_UNICODE_CHARS*sizeof(int));
int bytesProcessed = 0;
int textLength = TextLength(text);
int bytesProcessed = 0;
int codepointsCount = 0;
// Allocate a big enough buffer to store as many codepoints as text bytes
int *codepoints = RL_CALLOC(textLength, sizeof(int));
for (int i = 0; i < textLength; codepointsCount++)
{
codepoints[codepointsCount] = GetNextCodepoint(text + i, &bytesProcessed);
codepoints[codepointsCount] = GetCodepoint(text + i, &bytesProcessed);
i += bytesProcessed;
}
// Re-allocate buffer to the actual number of codepoints loaded
void *temp = RL_REALLOC(codepoints, codepointsCount*sizeof(int));
if (temp != NULL) codepoints = temp;
*count = codepointsCount;
return codepoints;
}
// Unload codepoints data from memory
void UnloadCodepoints(int *codepoints)
{
RL_FREE(codepoints);
}
// Get total number of characters(codepoints) in a UTF8 encoded text, until '\0' is found
// NOTE: If an invalid UTF8 sequence is encountered a '?'(0x3f) codepoint is counted instead
int GetCodepointsCount(const char *text)
@ -1596,7 +1605,7 @@ int GetCodepointsCount(const char *text)
while (*ptr != '\0')
{
int next = 0;
int letter = GetNextCodepoint(ptr, &next);
int letter = GetCodepoint(ptr, &next);
if (letter == 0x3f) ptr += 1;
else ptr += next;
@ -1614,7 +1623,7 @@ int GetCodepointsCount(const char *text)
// NOTE: the standard says U+FFFD should be returned in case of errors
// but that character is not supported by the default font in raylib
// TODO: Optimize this code for speed!!
int GetNextCodepoint(const char *text, int *bytesProcessed)
int GetCodepoint(const char *text, int *bytesProcessed)
{
/*
UTF8 specs from https://www.ietf.org/rfc/rfc3629.txt

View File

@ -1114,7 +1114,7 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co
{
// Get next codepoint from byte string and glyph index in font
int codepointByteCount = 0;
int codepoint = GetNextCodepoint(&text[i], &codepointByteCount);
int codepoint = GetCodepoint(&text[i], &codepointByteCount);
int index = GetGlyphIndex(font, codepoint);
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)