mirror of
https://github.com/raysan5/raylib.git
synced 2026-07-22 13:31:56 -04:00
Compare commits
26 Commits
caadb48e25
...
patch-1
| Author | SHA1 | Date | |
|---|---|---|---|
| 46b9579f0c | |||
| 8eb613e50a | |||
| 89b4fbd298 | |||
| 93e64f2210 | |||
| a9a0c046f1 | |||
| d224912bd5 | |||
| 39706cccbe | |||
| 4640c84920 | |||
| af98e3126e | |||
| e063385c47 | |||
| 7a247ff40f | |||
| 5de8c3521f | |||
| b631fb3d05 | |||
| fb4649a3fe | |||
| f00317bead | |||
| 8805ab3ee2 | |||
| ebec978443 | |||
| cfe56d97ea | |||
| 97d2b0146c | |||
| c31666fe2a | |||
| ab35e0f712 | |||
| c85cd07db0 | |||
| f458296a07 | |||
| 8df2f13962 | |||
| cba8f4286d | |||
| 86c7edfd74 |
@ -99,7 +99,7 @@ vec3 ComputePBR()
|
||||
vec3 N = normalize(fragNormal);
|
||||
if (useTexNormal == 1)
|
||||
{
|
||||
N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||
N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||
N = normalize(N*2.0 - 1.0);
|
||||
N = normalize(N*TBN);
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ vec3 ComputePBR()
|
||||
vec3 N = normalize(fragNormal);
|
||||
if (useTexNormal == 1)
|
||||
{
|
||||
N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||
N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||
N = normalize(N*2.0 - 1.0);
|
||||
N = normalize(N*TBN);
|
||||
}
|
||||
|
||||
@ -100,7 +100,7 @@ vec3 ComputePBR()
|
||||
vec3 N = normalize(fragNormal);
|
||||
if (useTexNormal == 1)
|
||||
{
|
||||
N = texture(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||
N = texture(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||
N = normalize(N*2.0 - 1.0);
|
||||
N = normalize(N*TBN);
|
||||
}
|
||||
|
||||
@ -9,10 +9,10 @@ IDE | Platform(s) | Source | Example(s)
|
||||
[CMake](https://cmake.org/) | Windows, Linux, macOS, Web | ✔️ | ✔️
|
||||
[CodeBlocks](http://www.codeblocks.org/) | Windows, Linux, macOS | ❌ | ✔️
|
||||
[Geany](https://www.geany.org/) | Windows, Linux | ✔️ | ✔️
|
||||
[Notepad++](https://notepad-plus-plus.org/) | Windows | ✔️ | ✔️
|
||||
[Notepad++](https://notepad-plus-plus.org/) | Windows Web | ✔️ | ✔️
|
||||
[SublimeText](https://www.sublimetext.com/) | Windows, Linux, macOS | ✔️ | ✔️
|
||||
[VS2019](https://www.visualstudio.com) | Windows | ✔️ | ✔️
|
||||
[VSCode](https://code.visualstudio.com/) | Windows, macOS | ❌ | ✔️
|
||||
[VS2022](https://www.visualstudio.com) | Windows | ✔️ | ✔️
|
||||
[VSCode](https://code.visualstudio.com/) | Windows, Linux, macOS | ❌ | ✔️
|
||||
[Zig](https://ziglang.org) | Windows, Linux, macOS, Web | ✔️ | ✔️
|
||||
scripts | Windows, Linux, macOS | ✔️ | ✔️
|
||||
|
||||
|
||||
8
src/external/rlsw.h
vendored
8
src/external/rlsw.h
vendored
@ -3909,7 +3909,6 @@ static void sw_immediate_set_color(const float color[4])
|
||||
RLSW.primitive.color[2] = color[2];
|
||||
RLSW.primitive.color[3] = color[3];
|
||||
|
||||
RLSW.primitive.hasColorAlpha |= (color[3] < 1.0f);
|
||||
}
|
||||
|
||||
static void sw_immediate_set_texcoord(const float texcoord[2])
|
||||
@ -3948,6 +3947,9 @@ static void sw_immediate_push_vertex(const float position[4])
|
||||
for (int i = 0; i < 4; i++) vertex->color[i] = RLSW.primitive.color[i];
|
||||
for (int i = 0; i < 2; i++) vertex->texcoord[i] = RLSW.primitive.texcoord[i];
|
||||
|
||||
// Track whether any vertex in this primitive has alpha < 1.0
|
||||
RLSW.primitive.hasColorAlpha |= (vertex->color[3] < 1.0f);
|
||||
|
||||
// Immediate rendering of the primitive if the required number is reached
|
||||
if (RLSW.primitive.vertexCount == SW_PRIMITIVE_VERTEX_COUNT[RLSW.drawMode])
|
||||
{
|
||||
@ -4307,8 +4309,8 @@ void swScissor(int x, int y, int width, int height)
|
||||
|
||||
RLSW.scClipMin[0] = (2.0f*(float)RLSW.scMin[0]/(float)RLSW.vpSize[0]) - 1.0f;
|
||||
RLSW.scClipMax[0] = (2.0f*(float)RLSW.scMax[0]/(float)RLSW.vpSize[0]) - 1.0f;
|
||||
RLSW.scClipMax[1] = 1.0f - (2.0f*(float)RLSW.scMin[1]/(float)RLSW.vpSize[1]);
|
||||
RLSW.scClipMin[1] = 1.0f - (2.0f*(float)RLSW.scMax[1]/(float)RLSW.vpSize[1]);
|
||||
RLSW.scClipMin[1] = (2.0f*(float)RLSW.scMin[1]/(float)RLSW.vpSize[1]) - 1.0f;
|
||||
RLSW.scClipMax[1] = (2.0f*(float)RLSW.scMax[1]/(float)RLSW.vpSize[1]) - 1.0f;
|
||||
}
|
||||
|
||||
void swClearColor(float r, float g, float b, float a)
|
||||
|
||||
21
src/external/tinyobj_loader_c.h
vendored
21
src/external/tinyobj_loader_c.h
vendored
@ -1020,7 +1020,12 @@ static int parseLine(Command *command, const char *p, unsigned int p_len,
|
||||
int triangulate) {
|
||||
char linebuf[4096];
|
||||
const char *token;
|
||||
assert(p_len < 4095);
|
||||
|
||||
// @raysan5:
|
||||
// WARNING: If -DNDEBUG is set when compiling, assertions will not
|
||||
// be present in the compiled binary, replacing by a runtime check
|
||||
//assert(p_len < 4095);
|
||||
if (p_len > 4095) return 0;
|
||||
|
||||
memcpy(linebuf, p, p_len);
|
||||
linebuf[p_len] = '\0';
|
||||
@ -1102,7 +1107,11 @@ static int parseLine(Command *command, const char *p, unsigned int p_len,
|
||||
tinyobj_vertex_index_t i1;
|
||||
tinyobj_vertex_index_t i2 = f[1];
|
||||
|
||||
assert(3 * num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
|
||||
// @raysan5:
|
||||
// WARNING: If -DNDEBUG is set when compiling, assertions will not
|
||||
// be present in the compiled binary, replacing by a runtime check
|
||||
//assert(3 * num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
|
||||
if (3*num_f > TINYOBJ_MAX_FACES_PER_F_LINE) return 0;
|
||||
|
||||
for (k = 2; k < num_f; k++) {
|
||||
i1 = i2;
|
||||
@ -1119,7 +1128,13 @@ static int parseLine(Command *command, const char *p, unsigned int p_len,
|
||||
|
||||
} else {
|
||||
unsigned int k = 0;
|
||||
assert(num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
|
||||
|
||||
// @raysan5:
|
||||
// WARNING: If -DNDEBUG is set when compiling, assertions will not
|
||||
// be present in the compiled binary, replacing by a runtime check
|
||||
//assert(num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
|
||||
if (num_f > TINYOBJ_MAX_FACES_PER_F_LINE) return 0;
|
||||
|
||||
for (k = 0; k < num_f; k++) {
|
||||
command->f[k] = f[k];
|
||||
}
|
||||
|
||||
@ -726,7 +726,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
|
||||
void SetMousePosition(int x, int y)
|
||||
{
|
||||
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
|
||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||
}
|
||||
|
||||
// Set mouse cursor
|
||||
|
||||
@ -1237,7 +1237,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
|
||||
void SetMousePosition(int x, int y)
|
||||
{
|
||||
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
|
||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||
|
||||
// NOTE: emscripten not implemented
|
||||
glfwSetCursorPos(platform.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y);
|
||||
@ -1326,7 +1325,7 @@ void PollInputEvents(void)
|
||||
// Register previous gamepad states
|
||||
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
|
||||
|
||||
// Get current gamepad state
|
||||
// Get current gamepad state using internal GLFW mapping, instead of the immediate joystick API
|
||||
// NOTE: There is no callback available, getting it manually
|
||||
GLFWgamepadstate state = { 0 };
|
||||
int result = glfwGetGamepadState(i, &state); // This remaps all gamepads so they have their buttons mapped like an xbox controller
|
||||
@ -1341,7 +1340,7 @@ void PollInputEvents(void)
|
||||
|
||||
for (int k = 0; (buttons != NULL) && (k < MAX_GAMEPAD_BUTTONS); k++)
|
||||
{
|
||||
int button = -1; // GamepadButton enum values assigned
|
||||
int button = -1; // GamepadButton enum values assigned
|
||||
|
||||
switch (k)
|
||||
{
|
||||
@ -1367,7 +1366,7 @@ void PollInputEvents(void)
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (button != -1) // Check for valid button
|
||||
if (button != -1) // Check for valid button
|
||||
{
|
||||
if (buttons[k] == GLFW_PRESS)
|
||||
{
|
||||
@ -1409,10 +1408,10 @@ void PollInputEvents(void)
|
||||
if ((CORE.Window.eventWaiting) ||
|
||||
(FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED) && !FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_ALWAYS_RUN)))
|
||||
{
|
||||
glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
|
||||
glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
|
||||
CORE.Time.previous = GetTime();
|
||||
}
|
||||
else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks) -> Update keys state
|
||||
else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks) -> Update keys state
|
||||
|
||||
CORE.Window.shouldClose = glfwWindowShouldClose(platform.handle);
|
||||
|
||||
@ -1693,6 +1692,14 @@ int InitPlatform(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
// AppKit can constrain the requested window size to the visible work area during creation
|
||||
int windowWidth = 0;
|
||||
int windowHeight = 0;
|
||||
glfwGetWindowSize(platform.handle, &windowWidth, &windowHeight);
|
||||
if ((windowWidth > 0) && (windowHeight > 0)) CORE.Window.screen = (Size){ windowWidth, windowHeight };
|
||||
#endif
|
||||
|
||||
// NOTE: Not considering scale factor now, considered below
|
||||
CORE.Window.render.width = CORE.Window.screen.width;
|
||||
CORE.Window.render.height = CORE.Window.screen.height;
|
||||
|
||||
@ -1526,7 +1526,6 @@ void SetMousePosition(int x, int y)
|
||||
{
|
||||
RGFW_window_moveMouse(platform.window, x, y);
|
||||
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
|
||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||
}
|
||||
|
||||
// Set mouse cursor
|
||||
|
||||
@ -1255,12 +1255,14 @@ Image GetClipboardImage(void)
|
||||
|
||||
for (int i = 0; i < SDL_arraysize(imageFormats); i++)
|
||||
{
|
||||
// NOTE: This pointer should be free with SDL_free() at some point
|
||||
fileData = SDL_GetClipboardData(imageFormats[i], &dataSize);
|
||||
|
||||
if (fileData)
|
||||
{
|
||||
image = LoadImageFromMemory(imageExtensions[i], fileData, (int)dataSize);
|
||||
|
||||
SDL_free(fileData);
|
||||
|
||||
if (IsImageValid(image))
|
||||
{
|
||||
TRACELOG(LOG_INFO, "Clipboard: Got image from clipboard successfully: %s", imageExtensions[i]);
|
||||
@ -1409,7 +1411,6 @@ void SetMousePosition(int x, int y)
|
||||
SDL_WarpMouseInWindow(platform.window, x, y);
|
||||
|
||||
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
|
||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||
}
|
||||
|
||||
// Set mouse cursor
|
||||
|
||||
@ -1299,8 +1299,8 @@ void SetMousePosition(int x, int y)
|
||||
if (!CORE.Input.Mouse.cursorLocked)
|
||||
{
|
||||
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
|
||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||
TRACELOG(LOG_WARNING, "SetMousePosition not implemented");
|
||||
|
||||
TRACELOG(LOG_WARNING, "SetMousePosition not implemented at platform level");
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "INPUT: MOUSE: Cursor not enabled");
|
||||
}
|
||||
|
||||
@ -1042,7 +1042,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
|
||||
void SetMousePosition(int x, int y)
|
||||
{
|
||||
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
|
||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||
}
|
||||
|
||||
// Set mouse cursor
|
||||
|
||||
@ -420,7 +420,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
|
||||
void SetMousePosition(int x, int y)
|
||||
{
|
||||
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
|
||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||
}
|
||||
|
||||
// Set mouse cursor
|
||||
|
||||
@ -395,7 +395,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
|
||||
void SetMousePosition(int x, int y)
|
||||
{
|
||||
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
|
||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||
}
|
||||
|
||||
// Set mouse cursor
|
||||
|
||||
@ -1047,7 +1047,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
|
||||
void SetMousePosition(int x, int y)
|
||||
{
|
||||
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
|
||||
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
|
||||
|
||||
if (CORE.Input.Mouse.cursorLocked) CORE.Input.Mouse.lockedPosition = CORE.Input.Mouse.currentPosition;
|
||||
|
||||
|
||||
@ -1507,8 +1507,16 @@ static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent
|
||||
{
|
||||
switch (eventType)
|
||||
{
|
||||
case EMSCRIPTEN_EVENT_MOUSEENTER: CORE.Input.Mouse.cursorOnScreen = true; break;
|
||||
case EMSCRIPTEN_EVENT_MOUSELEAVE: CORE.Input.Mouse.cursorOnScreen = false; break;
|
||||
case EMSCRIPTEN_EVENT_MOUSEENTER: {
|
||||
// NOTE: Mouse position updated by EmscriptenMouseMoveCallback(),
|
||||
// EmscriptenPointerlockCallback(), and EmscriptenTouchCallback()
|
||||
CORE.Input.Mouse.cursorOnScreen = true;
|
||||
} break;
|
||||
case EMSCRIPTEN_EVENT_MOUSELEAVE:
|
||||
{
|
||||
CORE.Input.Mouse.cursorOnScreen = false;
|
||||
CORE.Input.Mouse.currentPosition = (Vector2){ 0 };
|
||||
} break;
|
||||
case EMSCRIPTEN_EVENT_MOUSEDOWN:
|
||||
{
|
||||
// NOTE: Emscripten and raylib buttons indices are not aligned
|
||||
|
||||
@ -822,7 +822,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||
wave.sampleRate = wav.sampleRate;
|
||||
wave.sampleSize = 16;
|
||||
wave.channels = wav.channels;
|
||||
wave.data = (short *)RL_MALLOC((size_t)wave.frameCount*wave.channels*sizeof(short));
|
||||
wave.data = (short *)RL_CALLOC((size_t)wave.frameCount*wave.channels, sizeof(short));
|
||||
|
||||
// NOTE: Forcing conversion to 16bit sample size on reading
|
||||
drwav_read_pcm_frames_s16(&wav, wave.frameCount, (drwav_int16 *)wave.data);
|
||||
@ -845,7 +845,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
|
||||
wave.sampleSize = 16; // By default, ogg data is 16 bit per sample (short)
|
||||
wave.channels = info.channels;
|
||||
wave.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples(oggData); // NOTE: It returns frames!
|
||||
wave.data = (short *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(short));
|
||||
wave.data = (short *)RL_CALLOC(wave.frameCount*wave.channels, sizeof(short));
|
||||
|
||||
// NOTE: Get the number of samples to process (be careful! asking for number of shorts, not bytes!)
|
||||
stb_vorbis_get_samples_short_interleaved(oggData, info.channels, (short *)wave.data, wave.frameCount*wave.channels);
|
||||
@ -1258,7 +1258,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels)
|
||||
return;
|
||||
}
|
||||
|
||||
void *data = RL_MALLOC(frameCount*channels*(sampleSize/8));
|
||||
void *data = RL_CALLOC(frameCount*channels*(sampleSize/8), 1);
|
||||
|
||||
frameCount = (ma_uint32)ma_convert_frames(data, frameCount, formatOut, channels, sampleRate, wave->data, frameCountIn, formatIn, wave->channels, wave->sampleRate);
|
||||
if (frameCount == 0)
|
||||
@ -1772,7 +1772,7 @@ void UnloadMusicStream(Music music)
|
||||
{
|
||||
if (false) { }
|
||||
#if SUPPORT_FILEFORMAT_WAV
|
||||
else if (music.ctxType == MUSIC_AUDIO_WAV) drwav_uninit((drwav *)music.ctxData);
|
||||
else if (music.ctxType == MUSIC_AUDIO_WAV) { drwav_uninit((drwav *)music.ctxData); RL_FREE(music.ctxData); }
|
||||
#endif
|
||||
#if SUPPORT_FILEFORMAT_OGG
|
||||
else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData);
|
||||
|
||||
14
src/rcore.c
14
src/rcore.c
@ -3273,7 +3273,7 @@ unsigned int *ComputeMD5(const unsigned char *data, int dataSize)
|
||||
memcpy(msg + newDataSize, &bitsLen, 4); // Append the len in bits at the end of the buffer
|
||||
|
||||
// Process the message in successive 512-bit chunks for each 512-bit chunk of message
|
||||
for (int offset = 0; offset < newDataSize; offset += (512/8))
|
||||
for (int offset = 0; offset < newDataSize; offset += 64) // 512/8
|
||||
{
|
||||
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
|
||||
unsigned int *w = (unsigned int *)(msg + offset);
|
||||
@ -3370,7 +3370,7 @@ unsigned int *ComputeSHA1(const unsigned char *data, int dataSize)
|
||||
msg[newDataSize - 8] = (unsigned char)(bitsLen >> 56);
|
||||
|
||||
// Process the message in successive 512-bit chunks
|
||||
for (int offset = 0; offset < newDataSize; offset += (512/8))
|
||||
for (int offset = 0; offset < newDataSize; offset += 64) // 512/8
|
||||
{
|
||||
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
|
||||
unsigned int w[80] = { 0 };
|
||||
@ -3601,10 +3601,14 @@ AutomationEventList LoadAutomationEventList(const char *fileName)
|
||||
case 'c': sscanf(buffer, "c %i", &list.count); break;
|
||||
case 'e':
|
||||
{
|
||||
sscanf(buffer, "e %d %d %d %d %d %d %[^\n]s", &list.events[counter].frame, &list.events[counter].type,
|
||||
&list.events[counter].params[0], &list.events[counter].params[1], &list.events[counter].params[2], &list.events[counter].params[3], eventDesc);
|
||||
if (counter < list.capacity)
|
||||
{
|
||||
sscanf(buffer, "e %d %d %d %d %d %d %63[^\n]s", &list.events[counter].frame, &list.events[counter].type,
|
||||
&list.events[counter].params[0], &list.events[counter].params[1], &list.events[counter].params[2], &list.events[counter].params[3], eventDesc);
|
||||
|
||||
counter++;
|
||||
counter++;
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "AUTOMATION: Event goes beyond automated list capacity (MAX: %i): %s", buffer, list.capacity);
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
33
src/rlgl.h
33
src/rlgl.h
@ -847,11 +847,11 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
||||
#define SW_CALLOC(n,sz) RL_CALLOC(n, sz)
|
||||
#define SW_REALLOC(ptr, newSz) RL_REALLOC(ptr, newSz)
|
||||
#define SW_FREE(ptr) RL_FREE(ptr)
|
||||
#include "external/rlsw.h" // OpenGL 1.1 software implementation
|
||||
#include "external/rlsw.h" // OpenGL 1.1 software implementation
|
||||
#else
|
||||
#if defined(__APPLE__)
|
||||
#include <OpenGL/gl.h> // OpenGL 1.1 library for OSX
|
||||
#include <OpenGL/glext.h> // OpenGL extensions library
|
||||
#include <OpenGL/gl.h> // OpenGL 1.1 library for OSX
|
||||
#include <OpenGL/glext.h> // OpenGL extensions library
|
||||
#else
|
||||
// APIENTRY for OpenGL function pointer declarations is required
|
||||
#if !defined(APIENTRY)
|
||||
@ -866,7 +866,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
||||
#define WINGDIAPI __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#include <GL/gl.h> // OpenGL 1.1 library
|
||||
#include <GL/gl.h> // OpenGL 1.1 library
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@ -907,9 +907,10 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> // Required for: calloc(), free()
|
||||
#include <string.h> // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading]
|
||||
#include <math.h> // Required for: sqrtf(), sinf(), cosf(), floor(), log()
|
||||
#include <stdlib.h> // Required for: calloc(), free()
|
||||
#include <string.h> // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading]
|
||||
#include <math.h> // Required for: sqrtf(), sinf(), cosf(), floor(), log()
|
||||
#include <limits.h> // Required for: INT_MAX
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Defines and Macros
|
||||
@ -5236,7 +5237,9 @@ static int rlGetPixelDataSize(int width, int height, int format)
|
||||
{
|
||||
int blockWidth = (width + 3)/4;
|
||||
int blockHeight = (height + 3)/4;
|
||||
dataSize = blockWidth*blockHeight*8;
|
||||
unsigned long long dataSizeBytes = (unsigned long long)blockWidth*blockHeight*8;
|
||||
if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
|
||||
|
||||
} break;
|
||||
case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA:
|
||||
case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA:
|
||||
@ -5245,13 +5248,17 @@ static int rlGetPixelDataSize(int width, int height, int format)
|
||||
{
|
||||
int blockWidth = (width + 3)/4;
|
||||
int blockHeight = (height + 3)/4;
|
||||
dataSize = blockWidth*blockHeight*16;
|
||||
unsigned long long dataSizeBytes = (unsigned long long)blockWidth*blockHeight*16;
|
||||
if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
|
||||
|
||||
} break;
|
||||
case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 4 bytes per each 4x4 block
|
||||
{
|
||||
int blockWidth = (width + 3)/4;
|
||||
int blockHeight = (height + 3)/4;
|
||||
dataSize = blockWidth*blockHeight*4;
|
||||
unsigned long long dataSizeBytes = (unsigned long long)blockWidth*blockHeight*4;
|
||||
if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
|
||||
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
@ -5260,10 +5267,12 @@ static int rlGetPixelDataSize(int width, int height, int format)
|
||||
if ((format >= RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) &&
|
||||
(format <= RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16))
|
||||
{
|
||||
double bytesPerPixel = (double)bpp/8.0;
|
||||
dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes
|
||||
unsigned long long dataSizeBytes = ((unsigned long long)width*height*bpp) >> 3; // Get size in bytes (dividing by 8)
|
||||
if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
|
||||
}
|
||||
|
||||
if (dataSize == 0) TRACELOG(LOG_WARNING, "Requested image size is larger than 2GB, it can not be allocated");
|
||||
|
||||
return dataSize;
|
||||
}
|
||||
|
||||
|
||||
@ -2320,7 +2320,7 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, float frame)
|
||||
Matrix currentPoseMatrix = { 0 };
|
||||
|
||||
// Update all bones and bone matrices of model
|
||||
for (int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
|
||||
for (unsigned int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
|
||||
{
|
||||
// Compute interpolated pose between current and next frame
|
||||
// NOTE: Storing animation frame data in model.currentPose
|
||||
@ -2390,7 +2390,7 @@ void UpdateModelAnimationEx(Model model, ModelAnimation animA, float frameA, Mod
|
||||
Matrix bindPoseMatrix = { 0 };
|
||||
Matrix currentPoseMatrix = { 0 };
|
||||
|
||||
for (int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
|
||||
for (unsigned int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
|
||||
{
|
||||
// Get frame-interpolation for first animation
|
||||
Vector3 frameATranslation = Vector3Lerp(
|
||||
@ -5013,7 +5013,7 @@ static Model LoadIQM(const char *fileName)
|
||||
// Initialize runtime animation data: current pose and bone matrices
|
||||
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
||||
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
|
||||
for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||
for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||
|
||||
UnloadFileData(fileData);
|
||||
|
||||
@ -5241,7 +5241,7 @@ static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCou
|
||||
// Build frameposes
|
||||
for (unsigned int frame = 0; frame < anim[a].num_frames; frame++)
|
||||
{
|
||||
for (int i = 0; i < animations[a].boneCount; i++)
|
||||
for (unsigned int i = 0; i < animations[a].boneCount; i++)
|
||||
{
|
||||
if (bones[i].parent >= 0)
|
||||
{
|
||||
@ -5316,8 +5316,8 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
|
||||
{
|
||||
int base64Size = (int)strlen(cgltfImage->uri + i + 1);
|
||||
while (cgltfImage->uri[i + base64Size] == '=') base64Size--; // Ignore optional paddings
|
||||
int numberOfEncodedBits = base64Size*6 - (base64Size*6) % 8 ; // Encoded bits minus extra bits, so it becomes a multiple of 8 bits
|
||||
int outSize = numberOfEncodedBits/8 ; // Actual encoded bytes
|
||||
int numberOfEncodedBits = base64Size*6 - (base64Size*6)%8; // Encoded bits minus extra bits, so it becomes a multiple of 8 bits
|
||||
int outSize = numberOfEncodedBits >> 3; // Actual encoded bytes
|
||||
void *data = NULL;
|
||||
|
||||
cgltf_options options = { 0 };
|
||||
@ -5371,7 +5371,7 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
|
||||
// Load bone info from GLTF skin data
|
||||
static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, unsigned int *boneCount)
|
||||
{
|
||||
*boneCount = skin.joints_count;
|
||||
*boneCount = (unsigned int)skin.joints_count;
|
||||
BoneInfo *bones = (BoneInfo *)RL_CALLOC(skin.joints_count, sizeof(BoneInfo));
|
||||
|
||||
for (unsigned int i = 0; i < skin.joints_count; i++)
|
||||
@ -6144,7 +6144,7 @@ static Model LoadGLTF(const char *fileName)
|
||||
model.skeleton.bones = LoadBoneInfoGLTF(skin, &model.skeleton.boneCount);
|
||||
model.skeleton.bindPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
||||
|
||||
for (int i = 0; i < model.skeleton.boneCount; i++)
|
||||
for (unsigned int i = 0; i < model.skeleton.boneCount; i++)
|
||||
{
|
||||
Matrix bindMatrix = { 0 };
|
||||
cgltf_float inverseBindTransform[16] = { 0 };
|
||||
@ -6309,7 +6309,7 @@ static Model LoadGLTF(const char *fileName)
|
||||
if ((data->skins_count > 0) && !hasJoints && (node->parent != NULL) && (node->parent->mesh == NULL))
|
||||
{
|
||||
int parentBoneId = -1;
|
||||
for (int joint = 0; joint < model.skeleton.boneCount; joint++)
|
||||
for (unsigned int joint = 0; joint < model.skeleton.boneCount; joint++)
|
||||
{
|
||||
if (data->skins[0].joints[joint] == node->parent)
|
||||
{
|
||||
@ -6347,7 +6347,7 @@ static Model LoadGLTF(const char *fileName)
|
||||
// Initialize runtime animation data: current pose and bone matrices
|
||||
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
||||
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
|
||||
for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||
for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
// Free unused allocated memory in case of no bones defined
|
||||
@ -6670,7 +6670,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
|
||||
animations[a].keyframePoses[j] = (Transform *)RL_CALLOC(animations[a].boneCount, sizeof(Transform));
|
||||
float time = (float)j / GLTF_FRAMERATE;
|
||||
|
||||
for (int k = 0; k < animations[a].boneCount; k++)
|
||||
for (unsigned int k = 0; k < animations[a].boneCount; k++)
|
||||
{
|
||||
Vector3 translation = {skin.joints[k]->translation[0], skin.joints[k]->translation[1], skin.joints[k]->translation[2]};
|
||||
Quaternion rotation = {skin.joints[k]->rotation[0], skin.joints[k]->rotation[1], skin.joints[k]->rotation[2], skin.joints[k]->rotation[3]};
|
||||
@ -7204,7 +7204,7 @@ static Model LoadM3D(const char *fileName)
|
||||
// Initialize runtime animation data: current pose and bone matrices
|
||||
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
||||
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
|
||||
for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||
for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||
}
|
||||
|
||||
m3d_free(m3d);
|
||||
|
||||
300
src/rshapes.c
300
src/rshapes.c
@ -888,14 +888,13 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
|
||||
// Draw rectangle with rounded edges
|
||||
void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color)
|
||||
{
|
||||
// NOTE: For line thicknes <=1.0f using RL_LINES, otherwise using RL_QUADS/RL_TRIANGLES
|
||||
DrawRectangleRoundedLinesEx(rec, roundness, segments, 1.0f, color);
|
||||
}
|
||||
|
||||
// Draw rectangle with rounded edges outline with line thickness
|
||||
void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float thick, Color color)
|
||||
{
|
||||
if (thick < 0) thick = 0;
|
||||
if (thick <= 0) return;
|
||||
|
||||
// Not a rounded rectangle
|
||||
if (roundness <= 0.0f)
|
||||
@ -966,176 +965,145 @@ void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, f
|
||||
|
||||
const float angles[4] = { 180.0f, 270.0f, 0.0f, 90.0f };
|
||||
|
||||
if (thick > 1)
|
||||
{
|
||||
#if SUPPORT_QUADS_DRAW_MODE
|
||||
rlSetTexture(GetShapesTexture().id);
|
||||
Rectangle shapeRect = GetShapesTextureRectangle();
|
||||
rlSetTexture(GetShapesTexture().id);
|
||||
Rectangle shapeRect = GetShapesTextureRectangle();
|
||||
|
||||
rlBegin(RL_QUADS);
|
||||
rlBegin(RL_QUADS);
|
||||
|
||||
// Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
|
||||
for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
|
||||
{
|
||||
float angle = angles[k];
|
||||
const Vector2 center = centers[k];
|
||||
for (int i = 0; i < segments; i++)
|
||||
{
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||
|
||||
angle += stepLength;
|
||||
}
|
||||
}
|
||||
|
||||
// Upper rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[0].x, point[0].y);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[8].x, point[8].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[9].x, point[9].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[1].x, point[1].y);
|
||||
|
||||
// Right rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[2].x, point[2].y);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[10].x, point[10].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[11].x, point[11].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[3].x, point[3].y);
|
||||
|
||||
// Lower rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[13].x, point[13].y);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[5].x, point[5].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[4].x, point[4].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[12].x, point[12].y);
|
||||
|
||||
// Left rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[15].x, point[15].y);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[7].x, point[7].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[6].x, point[6].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[14].x, point[14].y);
|
||||
|
||||
rlEnd();
|
||||
rlSetTexture(0);
|
||||
#else
|
||||
rlBegin(RL_TRIANGLES);
|
||||
|
||||
// Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
|
||||
for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
|
||||
{
|
||||
float angle = angles[k];
|
||||
const Vector2 center = centers[k];
|
||||
|
||||
for (int i = 0; i < segments; i++)
|
||||
{
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||
|
||||
angle += stepLength;
|
||||
}
|
||||
}
|
||||
|
||||
// Upper rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(point[0].x, point[0].y);
|
||||
rlVertex2f(point[8].x, point[8].y);
|
||||
rlVertex2f(point[9].x, point[9].y);
|
||||
rlVertex2f(point[1].x, point[1].y);
|
||||
rlVertex2f(point[0].x, point[0].y);
|
||||
rlVertex2f(point[9].x, point[9].y);
|
||||
|
||||
// Right rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(point[10].x, point[10].y);
|
||||
rlVertex2f(point[11].x, point[11].y);
|
||||
rlVertex2f(point[3].x, point[3].y);
|
||||
rlVertex2f(point[2].x, point[2].y);
|
||||
rlVertex2f(point[10].x, point[10].y);
|
||||
rlVertex2f(point[3].x, point[3].y);
|
||||
|
||||
// Lower rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(point[13].x, point[13].y);
|
||||
rlVertex2f(point[5].x, point[5].y);
|
||||
rlVertex2f(point[4].x, point[4].y);
|
||||
rlVertex2f(point[12].x, point[12].y);
|
||||
rlVertex2f(point[13].x, point[13].y);
|
||||
rlVertex2f(point[4].x, point[4].y);
|
||||
|
||||
// Left rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(point[7].x, point[7].y);
|
||||
rlVertex2f(point[6].x, point[6].y);
|
||||
rlVertex2f(point[14].x, point[14].y);
|
||||
rlVertex2f(point[15].x, point[15].y);
|
||||
rlVertex2f(point[7].x, point[7].y);
|
||||
rlVertex2f(point[14].x, point[14].y);
|
||||
rlEnd();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use LINES to draw the outline
|
||||
rlBegin(RL_LINES);
|
||||
// Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
|
||||
for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
|
||||
{
|
||||
float angle = angles[k];
|
||||
const Vector2 center = centers[k];
|
||||
|
||||
for (int i = 0; i < segments; i++)
|
||||
{
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||
angle += stepLength;
|
||||
}
|
||||
}
|
||||
|
||||
// And now the remaining 4 lines
|
||||
for (int i = 0; i < 8; i += 2)
|
||||
// Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
|
||||
for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
|
||||
{
|
||||
float angle = angles[k];
|
||||
const Vector2 center = centers[k];
|
||||
for (int i = 0; i < segments; i++)
|
||||
{
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(point[i].x, point[i].y);
|
||||
rlVertex2f(point[i + 1].x, point[i + 1].y);
|
||||
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||
|
||||
angle += stepLength;
|
||||
}
|
||||
rlEnd();
|
||||
}
|
||||
}
|
||||
|
||||
// Upper rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[0].x, point[0].y);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[8].x, point[8].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[9].x, point[9].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[1].x, point[1].y);
|
||||
|
||||
// Right rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[2].x, point[2].y);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[10].x, point[10].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[11].x, point[11].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[3].x, point[3].y);
|
||||
|
||||
// Lower rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[13].x, point[13].y);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[5].x, point[5].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[4].x, point[4].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[12].x, point[12].y);
|
||||
|
||||
// Left rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[15].x, point[15].y);
|
||||
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[7].x, point[7].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
|
||||
rlVertex2f(point[6].x, point[6].y);
|
||||
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
|
||||
rlVertex2f(point[14].x, point[14].y);
|
||||
|
||||
rlEnd();
|
||||
rlSetTexture(0);
|
||||
#else
|
||||
rlBegin(RL_TRIANGLES);
|
||||
|
||||
// Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
|
||||
for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
|
||||
{
|
||||
float angle = angles[k];
|
||||
const Vector2 center = centers[k];
|
||||
|
||||
for (int i = 0; i < segments; i++)
|
||||
{
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||
|
||||
angle += stepLength;
|
||||
}
|
||||
}
|
||||
|
||||
// Upper rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(point[0].x, point[0].y);
|
||||
rlVertex2f(point[8].x, point[8].y);
|
||||
rlVertex2f(point[9].x, point[9].y);
|
||||
rlVertex2f(point[1].x, point[1].y);
|
||||
rlVertex2f(point[0].x, point[0].y);
|
||||
rlVertex2f(point[9].x, point[9].y);
|
||||
|
||||
// Right rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(point[10].x, point[10].y);
|
||||
rlVertex2f(point[11].x, point[11].y);
|
||||
rlVertex2f(point[3].x, point[3].y);
|
||||
rlVertex2f(point[2].x, point[2].y);
|
||||
rlVertex2f(point[10].x, point[10].y);
|
||||
rlVertex2f(point[3].x, point[3].y);
|
||||
|
||||
// Lower rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(point[13].x, point[13].y);
|
||||
rlVertex2f(point[5].x, point[5].y);
|
||||
rlVertex2f(point[4].x, point[4].y);
|
||||
rlVertex2f(point[12].x, point[12].y);
|
||||
rlVertex2f(point[13].x, point[13].y);
|
||||
rlVertex2f(point[4].x, point[4].y);
|
||||
|
||||
// Left rectangle
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
rlVertex2f(point[7].x, point[7].y);
|
||||
rlVertex2f(point[6].x, point[6].y);
|
||||
rlVertex2f(point[14].x, point[14].y);
|
||||
rlVertex2f(point[15].x, point[15].y);
|
||||
rlVertex2f(point[7].x, point[7].y);
|
||||
rlVertex2f(point[14].x, point[14].y);
|
||||
rlEnd();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Draw a polygon of n sides
|
||||
|
||||
20
src/rtext.c
20
src/rtext.c
@ -1699,7 +1699,7 @@ const char *TextSubtext(const char *text, int position, int length)
|
||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
||||
if (text != NULL)
|
||||
if ((text != NULL) && (position >= 0) && (length > 0))
|
||||
{
|
||||
int textLength = TextLength(text);
|
||||
|
||||
@ -1975,10 +1975,11 @@ char *TextInsert(const char *text, const char *insert, int position)
|
||||
{
|
||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
int textLen = TextLength(text);
|
||||
|
||||
if ((text != NULL) && (insert != NULL))
|
||||
if ((text != NULL) && (insert != NULL) && (position >= 0))
|
||||
{
|
||||
int textLen = TextLength(text);
|
||||
if (position > textLen) position = textLen; // End of text string
|
||||
int insertLen = TextLength(insert);
|
||||
|
||||
if ((textLen + insertLen) < (MAX_TEXT_BUFFER_LENGTH - 1))
|
||||
@ -1987,7 +1988,7 @@ char *TextInsert(const char *text, const char *insert, int position)
|
||||
|
||||
for (int i = 0; i < position; i++) buffer[i] = text[i];
|
||||
for (int i = position; i < insertLen + position; i++) buffer[i] = insert[i - position];
|
||||
for (int i = (insertLen + position); i < (textLen + insertLen); i++) buffer[i] = text[i];
|
||||
for (int i = (insertLen + position); i < (textLen + insertLen); i++) buffer[i] = text[i - insertLen];
|
||||
|
||||
buffer[textLen + insertLen] = '\0'; // Add EOL
|
||||
}
|
||||
@ -2002,17 +2003,18 @@ char *TextInsert(const char *text, const char *insert, int position)
|
||||
char *TextInsertAlloc(const char *text, const char *insert, int position)
|
||||
{
|
||||
char *result = NULL;
|
||||
int textLen = TextLength(text);
|
||||
|
||||
if ((text != NULL) && (insert != NULL))
|
||||
if ((text != NULL) && (insert != NULL) && (position >= 0))
|
||||
{
|
||||
int textLen = TextLength(text);
|
||||
if (position > textLen) position = textLen; // End of text string
|
||||
int insertLen = TextLength(insert);
|
||||
|
||||
result = (char *)RL_MALLOC(textLen + insertLen + 1);
|
||||
|
||||
for (int i = 0; i < position; i++) result[i] = text[i];
|
||||
for (int i = position; i < insertLen + position; i++) result[i] = insert[i - position];
|
||||
for (int i = (insertLen + position); i < (textLen + insertLen); i++) result[i] = text[i];
|
||||
for (int i = position; i < (insertLen + position); i++) result[i] = insert[i - position];
|
||||
for (int i = (insertLen + position); i < (textLen + insertLen); i++) result[i] = text[i - insertLen];
|
||||
|
||||
result[textLen + insertLen] = '\0'; // Add EOL
|
||||
}
|
||||
@ -2036,7 +2038,7 @@ char *TextJoin(char **textList, int count, const char *delimiter)
|
||||
int textLength = TextLength(textList[i]);
|
||||
|
||||
// Make sure joined text could fit inside MAX_TEXT_BUFFER_LENGTH
|
||||
if ((totalLength + textLength) < MAX_TEXT_BUFFER_LENGTH)
|
||||
if ((totalLength + textLength + delimiterLen) < MAX_TEXT_BUFFER_LENGTH)
|
||||
{
|
||||
memcpy(textPtr, textList[i], textLength);
|
||||
totalLength += textLength;
|
||||
|
||||
110
src/rtextures.c
110
src/rtextures.c
@ -70,6 +70,7 @@
|
||||
#include <string.h> // Required for: strlen() [Used in ImageTextEx()], strcmp() [Used in LoadImageFromMemory()/LoadImageAnimFromMemory()/ExportImageToMemory()]
|
||||
#include <math.h> // Required for: fabsf() [Used in DrawTextureRec()]
|
||||
#include <stdio.h> // Required for: sprintf() [Used in ExportImageAsCode()]
|
||||
#include <limits.h> // Required for: INT_MAX
|
||||
|
||||
// Support only desired texture formats on stb_image
|
||||
#if !SUPPORT_FILEFORMAT_BMP
|
||||
@ -843,9 +844,10 @@ bool ExportImageAsCode(Image image, const char *fileName)
|
||||
// Generate image: plain color
|
||||
Image GenImageColor(int width, int height, Color color)
|
||||
{
|
||||
Color *pixels = (Color *)RL_CALLOC(width*height, sizeof(Color));
|
||||
int dataSize = GetPixelDataSize(width, height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8);
|
||||
Color *pixels = (Color *)RL_CALLOC(dataSize, 1);
|
||||
|
||||
for (int i = 0; i < width*height; i++) pixels[i] = color;
|
||||
for (int i = 0; (pixels != NULL) && (i < width*height); i++) pixels[i] = color;
|
||||
|
||||
Image image = {
|
||||
.data = pixels,
|
||||
@ -1228,18 +1230,25 @@ Image ImageFromImage(Image image, Rectangle rec)
|
||||
{
|
||||
Image result = { 0 };
|
||||
|
||||
int bytesPerPixel = GetPixelDataSize(1, 1, image.format);
|
||||
|
||||
result.width = (int)rec.width;
|
||||
result.height = (int)rec.height;
|
||||
result.data = RL_CALLOC((int)rec.width*(int)rec.height*bytesPerPixel, 1);
|
||||
result.format = image.format;
|
||||
result.mipmaps = 1;
|
||||
|
||||
for (int y = 0; y < (int)rec.height; y++)
|
||||
// Basic rectangle validation: size smaller than image size
|
||||
if ((rec.x >= 0) && (rec.y >= 0) && (rec.width > 0) && (rec.height > 0) &&
|
||||
(((int)rec.x + (int)rec.width) <= image.width) &&
|
||||
(((int)rec.y + (int)rec.height) <= image.height))
|
||||
{
|
||||
memcpy(((unsigned char *)result.data) + y*(int)rec.width*bytesPerPixel, ((unsigned char *)image.data) + ((y + (int)rec.y)*image.width + (int)rec.x)*bytesPerPixel, (int)rec.width*bytesPerPixel);
|
||||
int bytesPerPixel = GetPixelDataSize(1, 1, image.format);
|
||||
|
||||
result.width = (int)rec.width;
|
||||
result.height = (int)rec.height;
|
||||
result.data = RL_CALLOC((int)rec.width*(int)rec.height*bytesPerPixel, 1);
|
||||
result.format = image.format;
|
||||
result.mipmaps = 1;
|
||||
|
||||
for (int y = 0; y < (int)rec.height; y++)
|
||||
{
|
||||
memcpy(((unsigned char *)result.data) + y*(int)rec.width*bytesPerPixel, ((unsigned char *)image.data) + ((y + (int)rec.y)*image.width + (int)rec.x)*bytesPerPixel, (int)rec.width*bytesPerPixel);
|
||||
}
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "IMAGE: Rectangle provided for ImageToImage not valid");
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -2684,45 +2693,49 @@ void ImageRotate(Image *image, int degrees)
|
||||
int width = (int)(fabsf(image->width*cosRadius) + fabsf(image->height*sinRadius));
|
||||
int height = (int)(fabsf(image->height*cosRadius) + fabsf(image->width*sinRadius));
|
||||
|
||||
int dataSize = GetPixelDataSize(width, height, image->format);
|
||||
int bytesPerPixel = GetPixelDataSize(1, 1, image->format);
|
||||
unsigned char *rotatedData = (unsigned char *)RL_CALLOC(width*height, bytesPerPixel);
|
||||
unsigned char *rotatedData = (unsigned char *)RL_CALLOC(dataSize, 1);
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
if (rotatedData != NULL)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
float oldX = ((x - width/2.0f)*cosRadius + (y - height/2.0f)*sinRadius) + image->width/2.0f;
|
||||
float oldY = ((y - height/2.0f)*cosRadius - (x - width/2.0f)*sinRadius) + image->height/2.0f;
|
||||
|
||||
if ((oldX >= 0) && (oldX < image->width) && (oldY >= 0) && (oldY < image->height))
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
int x1 = (int)floorf(oldX);
|
||||
int y1 = (int)floorf(oldY);
|
||||
int x2 = MIN(x1 + 1, image->width - 1);
|
||||
int y2 = MIN(y1 + 1, image->height - 1);
|
||||
float oldX = ((x - width/2.0f)*cosRadius + (y - height/2.0f)*sinRadius) + image->width/2.0f;
|
||||
float oldY = ((y - height/2.0f)*cosRadius - (x - width/2.0f)*sinRadius) + image->height/2.0f;
|
||||
|
||||
float px = oldX - x1;
|
||||
float py = oldY - y1;
|
||||
|
||||
for (int i = 0; i < bytesPerPixel; i++)
|
||||
if ((oldX >= 0) && (oldX < image->width) && (oldY >= 0) && (oldY < image->height))
|
||||
{
|
||||
float f1 = ((unsigned char *)image->data)[(y1*image->width + x1)*bytesPerPixel + i];
|
||||
float f2 = ((unsigned char *)image->data)[(y1*image->width + x2)*bytesPerPixel + i];
|
||||
float f3 = ((unsigned char *)image->data)[(y2*image->width + x1)*bytesPerPixel + i];
|
||||
float f4 = ((unsigned char *)image->data)[(y2*image->width + x2)*bytesPerPixel + i];
|
||||
int x1 = (int)floorf(oldX);
|
||||
int y1 = (int)floorf(oldY);
|
||||
int x2 = MIN(x1 + 1, image->width - 1);
|
||||
int y2 = MIN(y1 + 1, image->height - 1);
|
||||
|
||||
float val = f1*(1 - px)*(1 - py) + f2*px*(1 - py) + f3*(1 - px)*py + f4*px*py;
|
||||
float px = oldX - x1;
|
||||
float py = oldY - y1;
|
||||
|
||||
rotatedData[(y*width + x)*bytesPerPixel + i] = (unsigned char)val;
|
||||
for (int i = 0; i < bytesPerPixel; i++)
|
||||
{
|
||||
float f1 = ((unsigned char *)image->data)[(y1*image->width + x1)*bytesPerPixel + i];
|
||||
float f2 = ((unsigned char *)image->data)[(y1*image->width + x2)*bytesPerPixel + i];
|
||||
float f3 = ((unsigned char *)image->data)[(y2*image->width + x1)*bytesPerPixel + i];
|
||||
float f4 = ((unsigned char *)image->data)[(y2*image->width + x2)*bytesPerPixel + i];
|
||||
|
||||
float val = f1*(1 - px)*(1 - py) + f2*px*(1 - py) + f3*(1 - px)*py + f4*px*py;
|
||||
|
||||
rotatedData[(y*width + x)*bytesPerPixel + i] = (unsigned char)val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RL_FREE(image->data);
|
||||
image->data = rotatedData;
|
||||
image->width = width;
|
||||
image->height = height;
|
||||
RL_FREE(image->data);
|
||||
image->data = rotatedData;
|
||||
image->width = width;
|
||||
image->height = height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5502,17 +5515,24 @@ int GetPixelDataSize(int width, int height, int format)
|
||||
default: break;
|
||||
}
|
||||
|
||||
double bytesPerPixel = (double)bpp/8.0;
|
||||
dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes
|
||||
unsigned long long dataSizeBytes = ((unsigned long long)width*height*bpp) >> 3; // Get size in bytes (dividing by 8)
|
||||
|
||||
// Most compressed formats works on 4x4 blocks,
|
||||
// if texture is smaller, minimum dataSize is 8 or 16
|
||||
if ((width < 4) && (height < 4))
|
||||
if (dataSizeBytes < INT_MAX)
|
||||
{
|
||||
if ((format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8;
|
||||
else if ((format >= PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16;
|
||||
dataSize = (int)dataSizeBytes;
|
||||
|
||||
// Most compressed formats works on 4x4 blocks,
|
||||
// if texture is smaller, minimum dataSize is 8 or 16
|
||||
if ((width < 4) && (height < 4))
|
||||
{
|
||||
if ((format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8;
|
||||
else if ((format >= PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: In case required image data larger than 2GB, no memory allocated at all (NULL)
|
||||
if (dataSize == 0) TRACELOG(LOG_WARNING, "Requested image size is larger than 2GB, it can not be allocated");
|
||||
|
||||
return dataSize;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user