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/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/core.c b/src/core.c index 1dad59d99..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 @@ -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 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]; diff --git a/src/models.c b/src/models.c index e30eb5472..5dce17678 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,11 @@ 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, + // 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); RL_FREE(model.materials); @@ -2492,11 +2496,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 +3350,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 +3439,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..576190deb 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 @@ -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 @@ -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. @@ -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; @@ -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; @@ -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; @@ -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; @@ -1661,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 1bf0afd5f..6cf6fd23b 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) @@ -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) @@ -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 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) { 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; } 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; } 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)