From 2d5cc5ddbf3c0d157b67e7896f6b6efe58c65ef4 Mon Sep 17 00:00:00 2001 From: chriscamacho Date: Thu, 8 Aug 2019 08:57:21 +0100 Subject: [PATCH 01/11] fixed xmloader bug, user must free model shaders and textures as they might be shared (#933) --- src/models.c | 21 +++++++++++++-------- src/raudio.c | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/models.c b/src/models.c index e30eb5472..df123fa7b 100644 --- a/src/models.c +++ b/src/models.c @@ -71,7 +71,7 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define MAX_MESH_VBO 7 // Maximum number of vbo per mesh +#define MAX_MESH_VBO 7 // Maximum number of vbo per mesh //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -703,7 +703,12 @@ Model LoadModelFromMesh(Mesh mesh) void UnloadModel(Model model) { for (int i = 0; i < model.meshCount; i++) UnloadMesh(model.meshes[i]); - for (int i = 0; i < model.materialCount; i++) UnloadMaterial(model.materials[i]); + + // as the user could be sharing shaders and textures between + // models, don't unload the material but free it's maps instead + // the user is responsible for freeing models shaders and textures + //for (int i = 0; i < model.materialCount; i++) UnloadMaterial(model.materials[i]); + for (int i = 0; i < model.materialCount; i++) RL_FREE(model.materials[i].maps); RL_FREE(model.meshes); RL_FREE(model.materials); @@ -2492,11 +2497,11 @@ bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, floa // Simple way to check for collision, just checking distance between two points // Unfortunately, sqrtf() is a costly operation, so we avoid it with following solution /* - float dx = centerA.x - centerB.x; // X distance between centers - float dy = centerA.y - centerB.y; // Y distance between centers - float dz = centerA.z - centerB.z; // Z distance between centers + float dx = centerA.x - centerB.x; // X distance between centers + float dy = centerA.y - centerB.y; // Y distance between centers + float dz = centerA.z - centerB.z; // Z distance between centers - float distance = sqrtf(dx*dx + dy*dy + dz*dz); // Distance between centers + float distance = sqrtf(dx*dx + dy*dy + dz*dz); // Distance between centers if (distance <= (radiusA + radiusB)) collision = true; */ @@ -3346,7 +3351,7 @@ static Model LoadGLTF(const char *fileName) - Triangle-only meshes - Not supported node hierarchies or transforms - Only loads the diffuse texture... but not too hard to support other maps (normal, roughness/metalness...) - - Only supports unsigned short indices (no byte/unsigned int) + - Only supports unsigned short indices (no byte/unsigned int) - Only supports float for texture coordinates (no byte/unsigned short) *************************************************************************************/ @@ -3435,7 +3440,7 @@ static Model LoadGLTF(const char *fileName) if (img->uri) { - if ((strlen(img->uri) > 5) && + if ((strlen(img->uri) > 5) && (img->uri[0] == 'd') && (img->uri[1] == 'a') && (img->uri[2] == 't') && diff --git a/src/raudio.c b/src/raudio.c index bfd7ef220..40c136674 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -1250,7 +1250,7 @@ Music LoadMusicStream(const char *fileName) int result = jar_xm_create_context_from_file(&ctxXm, 48000, fileName); - if (result > 0) // XM context created successfully + if (result == 0) // XM context created successfully { music.ctxType = MUSIC_MODULE_XM; jar_xm_set_max_loop_count(ctxXm, 0); // Set infinite number of loops From 084fb31186d740c5aa7c72225e3c1ab0965b36f2 Mon Sep 17 00:00:00 2001 From: Kevin Yonan Date: Thu, 8 Aug 2019 01:00:23 -0700 Subject: [PATCH 02/11] Removing '__RemoveNode' (#935) Replaced '__RemoveNode' as it was causing invalid memory accesses with regular doubly linked list deletion algorithm. Replaced double pointer iterator in 'MemPoolAlloc' with single pointer iterator. Fixed undefined variables errors in 'MemPoolFree' for the freelist bucket. --- src/rmem.h | 56 ++++++++++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/src/rmem.h b/src/rmem.h index 87ceacc23..11e69588a 100644 --- a/src/rmem.h +++ b/src/rmem.h @@ -5,7 +5,7 @@ * A quick, efficient, and minimal free list and stack-based allocator * * PURPOSE: -* - Aquicker, efficient memory allocator alternative to 'malloc' and friends. +* - A quicker, efficient memory allocator alternative to 'malloc' and friends. * - Reduce the possibilities of memory leaks for beginner developers using Raylib. * - Being able to flexibly range check memory if necessary. * @@ -168,21 +168,6 @@ static inline size_t __AlignSize(const size_t size, const size_t align) return (size + (align - 1)) & -align; } -static void __RemoveNode(MemPool *const mempool, MemNode **const node) -{ - if ((*node)->next != NULL) (*node)->next->prev = (*node)->prev; - else { - mempool->freeList.tail = (*node)->prev; - if (mempool->freeList.tail != NULL) mempool->freeList.tail->next = NULL; - } - - if ((*node)->prev != NULL) (*node)->prev->next = (*node)->next; - else { - mempool->freeList.head = (*node)->next; - if (mempool->freeList.head != NULL) mempool->freeList.head->prev = NULL; - } -} - //---------------------------------------------------------------------------------- // Module Functions Definition - Memory Pool //---------------------------------------------------------------------------------- @@ -244,6 +229,7 @@ void *MemPoolAlloc(MemPool *const mempool, const size_t size) const size_t ALLOC_SIZE = __AlignSize(size + sizeof *new_mem, sizeof(intptr_t)); const size_t BUCKET_INDEX = (ALLOC_SIZE >> MEMPOOL_BUCKET_BITS) - 1; + // If the size is small enough, let's check if our buckets has a fitting memory block. if (BUCKET_INDEX < MEMPOOL_BUCKET_SIZE && mempool->buckets[BUCKET_INDEX] != NULL && mempool->buckets[BUCKET_INDEX]->size >= ALLOC_SIZE) { new_mem = mempool->buckets[BUCKET_INDEX]; @@ -256,22 +242,28 @@ void *MemPoolAlloc(MemPool *const mempool, const size_t size) const size_t MEM_SPLIT_THRESHOLD = 16; // If the freelist is valid, let's allocate FROM the freelist then! - for (MemNode **inode = &mempool->freeList.head; *inode != NULL; inode = &(*inode)->next) + for (MemNode *inode = mempool->freeList.head; inode != NULL; inode = inode->next) { - if ((*inode)->size < ALLOC_SIZE) continue; - else if ((*inode)->size <= (ALLOC_SIZE + MEM_SPLIT_THRESHOLD)) + if (inode->size < ALLOC_SIZE) continue; + else if (inode->size <= (ALLOC_SIZE + MEM_SPLIT_THRESHOLD)) { // Close in size - reduce fragmentation by not splitting. - new_mem = *inode; - __RemoveNode(mempool, inode); + new_mem = inode; + (inode->prev != NULL)? (inode->prev->next = inode->next) : (mempool->freeList.head = inode->next); + (inode->next != NULL)? (inode->next->prev = inode->prev) : (mempool->freeList.tail = inode->prev); + + if (mempool->freeList.head != NULL) mempool->freeList.head->prev = NULL; + else mempool->freeList.tail = NULL; + + if (mempool->freeList.tail != NULL) mempool->freeList.tail->next = NULL; mempool->freeList.len--; break; } else { // Split the memory chunk. - new_mem = (MemNode *)((uint8_t *)*inode + ((*inode)->size - ALLOC_SIZE)); - (*inode)->size -= ALLOC_SIZE; + new_mem = (MemNode *)((uint8_t *)inode + (inode->size - ALLOC_SIZE)); + inode->size -= ALLOC_SIZE; new_mem->size = ALLOC_SIZE; break; } @@ -356,13 +348,13 @@ void MemPoolFree(MemPool *const restrict mempool, void *ptr) // attempted stack merge failed, try to place it into the memnode buckets else if (BUCKET_INDEX < MEMPOOL_BUCKET_SIZE) { - if (mempool->buckets[index] == NULL) mempool->buckets[index] = node; + if (mempool->buckets[BUCKET_INDEX] == NULL) mempool->buckets[BUCKET_INDEX] = mem_node; else { - for (MemNode *n = mempool->buckets[index]; n != NULL; n = n->next) if( n==node ) return; - mempool->buckets[index]->prev = node; - node->next = mempool->buckets[index]; - mempool->buckets[index] = node; + for (MemNode *n = mempool->buckets[BUCKET_INDEX]; n != NULL; n = n->next) if( n==mem_node ) return; + mempool->buckets[BUCKET_INDEX]->prev = mem_node; + mem_node->next = mempool->buckets[BUCKET_INDEX]; + mempool->buckets[BUCKET_INDEX] = mem_node; } } // Otherwise, we add it to the free list. @@ -459,7 +451,13 @@ bool MemPoolDefrag(MemPool *const mempool) // If node is right at the stack, merge it back into the stack. mempool->stack.base += (*node)->size; (*node)->size = 0UL; - __RemoveNode(mempool, node); + ((*node)->prev != NULL)? ((*node)->prev->next = (*node)->next) : (mempool->freeList.head = (*node)->next); + ((*node)->next != NULL)? ((*node)->next->prev = (*node)->prev) : (mempool->freeList.tail = (*node)->prev); + + if (mempool->freeList.head != NULL) mempool->freeList.head->prev = NULL; + else mempool->freeList.tail = NULL; + + if (mempool->freeList.tail != NULL) mempool->freeList.tail->next = NULL; mempool->freeList.len--; node = &mempool->freeList.head; } From 3ebc55fdfe856e5d1086fa35333bff296cc169bb Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 8 Aug 2019 10:18:12 +0200 Subject: [PATCH 03/11] Reviewed comment --- src/models.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/models.c b/src/models.c index df123fa7b..5dce17678 100644 --- a/src/models.c +++ b/src/models.c @@ -704,10 +704,9 @@ void UnloadModel(Model model) { for (int i = 0; i < model.meshCount; i++) UnloadMesh(model.meshes[i]); - // as the user could be sharing shaders and textures between - // models, don't unload the material but free it's maps instead - // the user is responsible for freeing models shaders and textures - //for (int i = 0; i < model.materialCount; i++) UnloadMaterial(model.materials[i]); + // As the user could be sharing shaders and textures between models, + // we don't unload the material but just free it's maps, the user + // is responsible for freeing models shaders and textures for (int i = 0; i < model.materialCount; i++) RL_FREE(model.materials[i].maps); RL_FREE(model.meshes); From 108f7f6fee475642e0d76807fc2fd21db1d56744 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 8 Aug 2019 10:32:42 +0200 Subject: [PATCH 04/11] Corrected small issue on miniaudio ONly Neon processors --- src/external/miniaudio.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/external/miniaudio.h b/src/external/miniaudio.h index e6752fbf5..528ff5746 100644 --- a/src/external/miniaudio.h +++ b/src/external/miniaudio.h @@ -29498,8 +29498,8 @@ static MA_INLINE float32x4_t ma_src_sinc__interpolation_factor__neon(const ma_sr { float32x4_t xabs; int32x4_t ixabs; - float32x4_t a - float32x4_t r + float32x4_t a; + float32x4_t r; int* ixabsv; float lo[4]; float hi[4]; From e6e48675cc8c8a2a9abe7bae257054f529da419a Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 8 Aug 2019 23:08:54 +0200 Subject: [PATCH 05/11] Formating tweaks --- src/raudio.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/raudio.c b/src/raudio.c index 40c136674..b6f9191e1 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -204,9 +204,9 @@ struct rAudioBuffer { bool paused; // Audio buffer state: AUDIO_PAUSED bool looping; // Audio buffer looping, always true for AudioStreams int usage; // Audio buffer usage mode: STATIC or STREAM - + bool isSubBufferProcessed[2]; - unsigned int frameCursorPos; + unsigned int frameCursorPos; // Samples processed? unsigned int bufferSizeInFrames; rAudioBuffer *next; @@ -402,7 +402,7 @@ static ma_uint32 OnAudioBufferDSPRead(ma_pcm_converter *pDSP, void *pFramesOut, } else { - ma_uint32 firstFrameIndexOfThisSubBuffer = subBufferSizeInFrames * currentSubBufferIndex; + ma_uint32 firstFrameIndexOfThisSubBuffer = subBufferSizeInFrames*currentSubBufferIndex; framesRemainingInOutputBuffer = subBufferSizeInFrames - (audioBuffer->frameCursorPos - firstFrameIndexOfThisSubBuffer); } @@ -410,7 +410,7 @@ static ma_uint32 OnAudioBufferDSPRead(ma_pcm_converter *pDSP, void *pFramesOut, if (framesToRead > framesRemainingInOutputBuffer) framesToRead = framesRemainingInOutputBuffer; memcpy((unsigned char *)pFramesOut + (framesRead*frameSizeInBytes), audioBuffer->buffer + (audioBuffer->frameCursorPos*frameSizeInBytes), framesToRead*frameSizeInBytes); - audioBuffer->frameCursorPos = (audioBuffer->frameCursorPos + framesToRead) % audioBuffer->bufferSizeInFrames; + audioBuffer->frameCursorPos = (audioBuffer->frameCursorPos + framesToRead)%audioBuffer->bufferSizeInFrames; framesRead += framesToRead; // If we've read to the end of the buffer, mark it as processed @@ -877,7 +877,7 @@ void UpdateSound(Sound sound, const void *data, int samplesCount) StopAudioBuffer(audioBuffer); - // TODO: May want to lock/unlock this since this data buffer is read at mixing time. + // TODO: May want to lock/unlock this since this data buffer is read at mixing time memcpy(audioBuffer->buffer, data, samplesCount*audioBuffer->dsp.formatConverterIn.config.channels*ma_get_bytes_per_sample(audioBuffer->dsp.formatConverterIn.config.formatIn)); } @@ -1188,10 +1188,10 @@ Music LoadMusicStream(const char *fileName) music.loopCount = 0; // Infinite loop by default musicLoaded = true; - TraceLog(LOG_DEBUG, "[%s] OGG total samples: %i", fileName, music.sampleCount); - TraceLog(LOG_DEBUG, "[%s] OGG sample rate: %i", fileName, info.sample_rate); - TraceLog(LOG_DEBUG, "[%s] OGG channels: %i", fileName, info.channels); - TraceLog(LOG_DEBUG, "[%s] OGG memory required: %i", fileName, info.temp_memory_required); + TraceLog(LOG_INFO, "[%s] OGG total samples: %i", fileName, music.sampleCount); + TraceLog(LOG_INFO, "[%s] OGG sample rate: %i", fileName, info.sample_rate); + TraceLog(LOG_INFO, "[%s] OGG channels: %i", fileName, info.channels); + TraceLog(LOG_INFO, "[%s] OGG memory required: %i", fileName, info.temp_memory_required); } } #endif @@ -1289,7 +1289,7 @@ Music LoadMusicStream(const char *fileName) music.loopCount = 0; // Infinite loop by default musicLoaded = true; - TraceLog(LOG_INFO, "[%s] MOD number of samples: %i", fileName, music.sampleLeft); + TraceLog(LOG_INFO, "[%s] MOD number of samples: %i", fileName, music.sampleCount); TraceLog(LOG_INFO, "[%s] MOD track length: %11.6f sec", fileName, (float)music.sampleCount/48000.0f); } } @@ -1354,10 +1354,10 @@ void PlayMusicStream(Music music) return; } - // For music streams, we need to make sure we maintain the frame cursor position. This is hack for this section of code in UpdateMusicStream() - // // NOTE: In case window is minimized, music stream is stopped, - // // just make sure to play again on window restore - // if (IsMusicPlaying(music)) PlayMusicStream(music); + // For music streams, we need to make sure we maintain the frame cursor position + // This is a hack for this section of code in UpdateMusicStream() + // NOTE: In case window is minimized, music stream is stopped, just make sure to + // play again on window restore: if (IsMusicPlaying(music)) PlayMusicStream(music); ma_uint32 frameCursorPos = audioBuffer->frameCursorPos; PlayAudioStream(music.stream); // <-- This resets the cursor position. @@ -1528,7 +1528,7 @@ void SetMusicPitch(Music music, float pitch) } // Set music loop count (loop repeats) -// NOTE: If set to -1, means infinite loop +// NOTE: If set to 0, means infinite loop void SetMusicLoopCount(Music music, int count) { music.loopCount = count; @@ -1622,7 +1622,8 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount) if (audioBuffer->isSubBufferProcessed[0] && audioBuffer->isSubBufferProcessed[1]) { - // Both buffers are available for updating. Update the first one and make sure the cursor is moved back to the front. + // Both buffers are available for updating. + // Update the first one and make sure the cursor is moved back to the front. subBufferToUpdate = 0; audioBuffer->frameCursorPos = 0; } @@ -1635,7 +1636,8 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount) ma_uint32 subBufferSizeInFrames = audioBuffer->bufferSizeInFrames/2; unsigned char *subBuffer = audioBuffer->buffer + ((subBufferSizeInFrames*stream.channels*(stream.sampleSize/8))*subBufferToUpdate); - // Does this API expect a whole buffer to be updated in one go? Assuming so, but if not will need to change this logic. + // Does this API expect a whole buffer to be updated in one go? + // Assuming so, but if not will need to change this logic. if (subBufferSizeInFrames >= (ma_uint32)samplesCount/stream.channels) { ma_uint32 framesToWrite = subBufferSizeInFrames; From 6f2f09947f5456cefb3d91d3f667f4d72fa55be6 Mon Sep 17 00:00:00 2001 From: chriscamacho Date: Fri, 9 Aug 2019 16:04:52 +0100 Subject: [PATCH 06/11] addition to raylib to create matrix from 3 euler angles (#938) --- examples/models/models_yaw_pitch_roll.c | 6 ++++- src/raymath.h | 31 +++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/examples/models/models_yaw_pitch_roll.c b/examples/models/models_yaw_pitch_roll.c index 0931c00e9..72529d892 100644 --- a/examples/models/models_yaw_pitch_roll.c +++ b/examples/models/models_yaw_pitch_roll.c @@ -92,6 +92,7 @@ int main(void) while (pitchOffset < -180) pitchOffset += 360; pitchOffset *= 10; + /* matrix transform done with multiplication to combine rotations Matrix transform = MatrixIdentity(); transform = MatrixMultiply(transform, MatrixRotateZ(DEG2RAD*roll)); @@ -99,8 +100,11 @@ int main(void) transform = MatrixMultiply(transform, MatrixRotateY(DEG2RAD*yaw)); model.transform = transform; - //---------------------------------------------------------------------------------- + */ + // matrix created from multiple axes at once + model.transform = MatrixRotateXYZ((Vector3){DEG2RAD*pitch,DEG2RAD*yaw,DEG2RAD*roll}); + //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); diff --git a/src/raymath.h b/src/raymath.h index d866ad826..12ea76b4e 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -56,7 +56,7 @@ #if defined(RAYMATH_IMPLEMENTATION) #if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED) #define RMDEF __declspec(dllexport) extern inline // We are building raylib as a Win32 shared library (.dll). - #elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED) + #elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED) #define RMDEF __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll) #else #define RMDEF extern inline // Provide external definition @@ -113,7 +113,7 @@ float y; float z; } Vector3; - + // Quaternion type typedef struct Quaternion { float x; @@ -794,6 +794,33 @@ RMDEF Matrix MatrixRotate(Vector3 axis, float angle) return result; } +// Returns xyz-rotation matrix (angles in radians) +RMDEF Matrix MatrixRotateXYZ(Vector3 ang) +{ + Matrix result = MatrixIdentity(); + + float cosz = cosf(-ang.z); + float sinz = sinf(-ang.z); + float cosy = cosf(-ang.y); + float siny = sinf(-ang.y); + float cosx = cosf(-ang.x); + float sinx = sinf(-ang.x); + + result.m0 = cosz * cosy; + result.m4 = (cosz * siny * sinx) - (sinz * cosx); + result.m8 = (cosz * siny * cosx) + (sinz * sinx); + + result.m1 = sinz * cosy; + result.m5 = (sinz * siny * sinx) + (cosz * cosx); + result.m9 = (sinz * siny * cosx) - (cosz * sinx); + + result.m2 = -siny; + result.m6 = cosy * sinx; + result.m10= cosy * cosx; + + return result; +} + // Returns x-rotation matrix (angle in radians) RMDEF Matrix MatrixRotateX(float angle) { From 2c2ccadd32df75af312a32f2d07ca1d29e83f42b Mon Sep 17 00:00:00 2001 From: Wayde Reitsma Date: Sun, 11 Aug 2019 19:17:20 +1000 Subject: [PATCH 07/11] Small fix in GetMouseY (#940) --- src/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core.c b/src/core.c index 1dad59d99..930bd2597 100644 --- a/src/core.c +++ b/src/core.c @@ -2324,7 +2324,7 @@ int GetMouseX(void) int GetMouseY(void) { #if defined(PLATFORM_ANDROID) - return (int)touchPosition[0].x; + return (int)touchPosition[0].y; #else return (int)((mousePosition.y + mouseOffset.y)*mouseScale.y); #endif From 740834bb83734d436ba4c5324a4ccb026ebf5c6c Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 11 Aug 2019 12:04:54 +0200 Subject: [PATCH 08/11] REVIEW: GetDirectoryPath() and GetPrevDirectoryPath() --- src/core.c | 42 +++++++++++++++++++++--------------------- src/raylib.h | 4 ++-- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/core.c b/src/core.c index 930bd2597..ac0ddd294 100644 --- a/src/core.c +++ b/src/core.c @@ -1814,43 +1814,43 @@ const char *GetFileNameWithoutExt(const char *filePath) return fileName; } -// Get directory for a given fileName (with path) -const char *GetDirectoryPath(const char *fileName) +// Get directory for a given filePath +const char *GetDirectoryPath(const char *filePath) { const char *lastSlash = NULL; - static char filePath[MAX_FILEPATH_LENGTH]; - memset(filePath, 0, MAX_FILEPATH_LENGTH); + static char dirPath[MAX_FILEPATH_LENGTH]; + memset(dirPath, 0, MAX_FILEPATH_LENGTH); - lastSlash = strprbrk(fileName, "\\/"); + lastSlash = strprbrk(filePath, "\\/"); if (!lastSlash) return NULL; // NOTE: Be careful, strncpy() is not safe, it does not care about '\0' - strncpy(filePath, fileName, strlen(fileName) - (strlen(lastSlash) - 1)); - filePath[strlen(fileName) - strlen(lastSlash)] = '\0'; // Add '\0' manually + strncpy(dirPath, filePath, strlen(filePath) - (strlen(lastSlash) - 1)); + dirPath[strlen(filePath) - strlen(lastSlash)] = '\0'; // Add '\0' manually - return filePath; + return dirPath; } // Get previous directory path for a given path -const char *GetPrevDirectoryPath(const char *path) +const char *GetPrevDirectoryPath(const char *dirPath) { - static char prevDir[MAX_FILEPATH_LENGTH]; - memset(prevDir, 0, MAX_FILEPATH_LENGTH); - int pathLen = strlen(path); - - for (int i = (pathLen - 1); i >= 0; i--) + static char prevDirPath[MAX_FILEPATH_LENGTH]; + memset(prevDirPath, 0, MAX_FILEPATH_LENGTH); + int pathLen = strlen(dirPath); + + if (pathLen <= 3) strcpy(prevDirPath, dirPath); + + for (int i = (pathLen - 1); (i > 0) && (pathLen > 3); i--) { - if ((path[i] == '\\') || (path[i] == '/')) + if ((dirPath[i] == '\\') || (dirPath[i] == '/')) { - if ((i != (pathLen - 1)) && (path[pathLen - 2] != ':')) - { - strncpy(prevDir, path, i); - break; - } + if (i == 2) i++; // Check for root: "C:\" + strncpy(prevDirPath, dirPath, i); + break; } } - return prevDir; + return prevDirPath; } // Get current working directory diff --git a/src/raylib.h b/src/raylib.h index 1bf0afd5f..3cb8d327b 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -940,8 +940,8 @@ RLAPI bool DirectoryExists(const char *dirPath); // Check if a RLAPI const char *GetExtension(const char *fileName); // Get pointer to extension for a filename string RLAPI const char *GetFileName(const char *filePath); // Get pointer to filename for a path string RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (memory should be freed) -RLAPI const char *GetDirectoryPath(const char *fileName); // Get full path for a given fileName (uses static string) -RLAPI const char *GetPrevDirectoryPath(const char *path); // Get previous directory path for a given path (uses static string) +RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string) +RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string) RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string) RLAPI char **GetDirectoryFiles(const char *dirPath, int *count); // Get filenames in a directory path (memory should be freed) RLAPI void ClearDirectoryFiles(void); // Clear directory files paths buffers (free memory) From cef1e6e2e2a015d56b3018465f9094887ff94bdd Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 11 Aug 2019 21:26:12 +0200 Subject: [PATCH 09/11] Added notes about vertex order --- src/raylib.h | 6 +++--- src/shapes.c | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index 3cb8d327b..37557c613 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1054,9 +1054,9 @@ RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color c RLAPI void DrawRectangleLinesEx(Rectangle rec, int lineThick, Color color); // Draw rectangle outline with extended parameters RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, int lineThick, Color color); // Draw rectangle with rounded edges outline -RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle -RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline -RLAPI void DrawTriangleFan(Vector2 *points, int numPoints, Color color); // Draw a triangle fan defined by points +RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!) +RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!) +RLAPI void DrawTriangleFan(Vector2 *points, int numPoints, Color color); // Draw a triangle fan defined by points (first vertex is the center) RLAPI void DrawTriangleStrip(Vector2 *points, int pointsCount, Color color); // Draw a triangle strip defined by points RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version) diff --git a/src/shapes.c b/src/shapes.c index d1956b26a..6217d2ada 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -1179,6 +1179,7 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, int } // Draw a triangle +// NOTE: Vertex must be provided in counter-clockwise order void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color) { if (rlCheckBufferLimit(4)) rlglDraw(); @@ -1214,6 +1215,7 @@ void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color) } // Draw a triangle using lines +// NOTE: Vertex must be provided in counter-clockwise order void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color) { if (rlCheckBufferLimit(6)) rlglDraw(); @@ -1232,7 +1234,7 @@ void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color) } // Draw a triangle fan defined by points -// NOTE: First point provided is shared by all triangles +// NOTE: First vertex provided is the center, shared by all triangles void DrawTriangleFan(Vector2 *points, int pointsCount, Color color) { if (pointsCount >= 3) @@ -1263,7 +1265,7 @@ void DrawTriangleFan(Vector2 *points, int pointsCount, Color color) } // Draw a triangle strip defined by points -// NOTE: Every new point connects with previous two +// NOTE: Every new vertex connects with previous two void DrawTriangleStrip(Vector2 *points, int pointsCount, Color color) { if (pointsCount >= 3) From c629b16ebce5c8e7b2d8e2a3e842b069965bd6be Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 12 Aug 2019 12:35:23 +0200 Subject: [PATCH 10/11] Corrected issue on compressed textures data size --- src/rlgl.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/rlgl.h b/src/rlgl.h index aa0c5e144..5e7312bde 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -4623,6 +4623,14 @@ int GetPixelDataSize(int width, int height, int format) } dataSize = width*height*bpp/8; // Total data size in bytes + + // Most compressed formats works on 4x4 blocks, + // if texture is smaller, minimum dataSize is 8 or 16 + if ((width < 4) && (height < 4)) + { + if ((format >= COMPRESSED_DXT1_RGB) && (format < COMPRESSED_DXT3_RGBA)) dataSize = 8; + else if ((format >= COMPRESSED_DXT3_RGBA) && (format < COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16; + } return dataSize; } From c387bc586d9c8b9fe9bb840926d12526aaad9116 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 13 Aug 2019 17:41:31 +0200 Subject: [PATCH 11/11] RENAMED: IsAudioBufferProcessed() -> IsAudioStreamProcessed() Renamed for consistency with similar functions --- examples/audio/audio_raw_stream.c | 2 +- src/raudio.c | 8 ++++---- src/raylib.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/audio/audio_raw_stream.c b/examples/audio/audio_raw_stream.c index 136e02f30..85a77bc0a 100644 --- a/examples/audio/audio_raw_stream.c +++ b/examples/audio/audio_raw_stream.c @@ -99,7 +99,7 @@ int main(void) } // Refill audio stream if required - if (IsAudioBufferProcessed(stream)) + if (IsAudioStreamProcessed(stream)) { // Synthesize a buffer that is exactly the requested size int writeCursor = 0; diff --git a/src/raudio.c b/src/raudio.c index b6f9191e1..576190deb 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -1418,7 +1418,7 @@ void UpdateMusicStream(Music music) int samplesCount = 0; // Total size of data steamed in L+R samples for xm floats, individual L or R for ogg shorts - while (IsAudioBufferProcessed(music.stream)) + while (IsAudioStreamProcessed(music.stream)) { if ((music.sampleLeft/music.stream.channels) >= subBufferSizeInFrames) samplesCount = subBufferSizeInFrames*music.stream.channels; else samplesCount = music.sampleLeft; @@ -1605,7 +1605,7 @@ void CloseAudioStream(AudioStream stream) // Update audio stream buffers with data // NOTE 1: Only updates one buffer of the stream source: unqueue -> update -> queue -// NOTE 2: To unqueue a buffer it needs to be processed: IsAudioBufferProcessed() +// NOTE 2: To unqueue a buffer it needs to be processed: IsAudioStreamProcessed() void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount) { AudioBuffer *audioBuffer = stream.buffer; @@ -1663,11 +1663,11 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount) } // Check if any audio stream buffers requires refill -bool IsAudioBufferProcessed(AudioStream stream) +bool IsAudioStreamProcessed(AudioStream stream) { if (stream.buffer == NULL) { - TraceLog(LOG_ERROR, "IsAudioBufferProcessed() : No audio buffer"); + TraceLog(LOG_ERROR, "IsAudioStreamProcessed() : No audio buffer"); return false; } diff --git a/src/raylib.h b/src/raylib.h index 37557c613..6cf6fd23b 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1392,7 +1392,7 @@ RLAPI float GetMusicTimePlayed(Music music); // Get cur RLAPI AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Init audio stream (to stream raw audio pcm data) RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount); // Update audio stream buffers with data RLAPI void CloseAudioStream(AudioStream stream); // Close audio stream and free memory -RLAPI bool IsAudioBufferProcessed(AudioStream stream); // Check if any audio stream buffers requires refill +RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill RLAPI void PlayAudioStream(AudioStream stream); // Play audio stream RLAPI void PauseAudioStream(AudioStream stream); // Pause audio stream RLAPI void ResumeAudioStream(AudioStream stream); // Resume audio stream