Merge pull request #1 from raysan5/master

Merge with Master
This commit is contained in:
Tyler Jessilynn Bezera 2019-08-15 10:11:40 -07:00 committed by GitHub
commit 55fd48b883
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 140 additions and 95 deletions

View File

@ -99,7 +99,7 @@ int main(void)
} }
// Refill audio stream if required // Refill audio stream if required
if (IsAudioBufferProcessed(stream)) if (IsAudioStreamProcessed(stream))
{ {
// Synthesize a buffer that is exactly the requested size // Synthesize a buffer that is exactly the requested size
int writeCursor = 0; int writeCursor = 0;

View File

@ -92,6 +92,7 @@ int main(void)
while (pitchOffset < -180) pitchOffset += 360; while (pitchOffset < -180) pitchOffset += 360;
pitchOffset *= 10; pitchOffset *= 10;
/* matrix transform done with multiplication to combine rotations
Matrix transform = MatrixIdentity(); Matrix transform = MatrixIdentity();
transform = MatrixMultiply(transform, MatrixRotateZ(DEG2RAD*roll)); transform = MatrixMultiply(transform, MatrixRotateZ(DEG2RAD*roll));
@ -99,8 +100,11 @@ int main(void)
transform = MatrixMultiply(transform, MatrixRotateY(DEG2RAD*yaw)); transform = MatrixMultiply(transform, MatrixRotateY(DEG2RAD*yaw));
model.transform = transform; model.transform = transform;
//---------------------------------------------------------------------------------- */
// matrix created from multiple axes at once
model.transform = MatrixRotateXYZ((Vector3){DEG2RAD*pitch,DEG2RAD*yaw,DEG2RAD*roll});
//----------------------------------------------------------------------------------
// Draw // Draw
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
BeginDrawing(); BeginDrawing();

View File

@ -1814,43 +1814,43 @@ const char *GetFileNameWithoutExt(const char *filePath)
return fileName; return fileName;
} }
// Get directory for a given fileName (with path) // Get directory for a given filePath
const char *GetDirectoryPath(const char *fileName) const char *GetDirectoryPath(const char *filePath)
{ {
const char *lastSlash = NULL; const char *lastSlash = NULL;
static char filePath[MAX_FILEPATH_LENGTH]; static char dirPath[MAX_FILEPATH_LENGTH];
memset(filePath, 0, MAX_FILEPATH_LENGTH); memset(dirPath, 0, MAX_FILEPATH_LENGTH);
lastSlash = strprbrk(fileName, "\\/"); lastSlash = strprbrk(filePath, "\\/");
if (!lastSlash) return NULL; if (!lastSlash) return NULL;
// NOTE: Be careful, strncpy() is not safe, it does not care about '\0' // NOTE: Be careful, strncpy() is not safe, it does not care about '\0'
strncpy(filePath, fileName, strlen(fileName) - (strlen(lastSlash) - 1)); strncpy(dirPath, filePath, strlen(filePath) - (strlen(lastSlash) - 1));
filePath[strlen(fileName) - strlen(lastSlash)] = '\0'; // Add '\0' manually dirPath[strlen(filePath) - strlen(lastSlash)] = '\0'; // Add '\0' manually
return filePath; return dirPath;
} }
// Get previous directory path for a given path // 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]; static char prevDirPath[MAX_FILEPATH_LENGTH];
memset(prevDir, 0, MAX_FILEPATH_LENGTH); memset(prevDirPath, 0, MAX_FILEPATH_LENGTH);
int pathLen = strlen(path); int pathLen = strlen(dirPath);
for (int i = (pathLen - 1); i >= 0; i--) 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] != ':')) if (i == 2) i++; // Check for root: "C:\"
{ strncpy(prevDirPath, dirPath, i);
strncpy(prevDir, path, i); break;
break;
}
} }
} }
return prevDir; return prevDirPath;
} }
// Get current working directory // Get current working directory
@ -2324,7 +2324,7 @@ int GetMouseX(void)
int GetMouseY(void) int GetMouseY(void)
{ {
#if defined(PLATFORM_ANDROID) #if defined(PLATFORM_ANDROID)
return (int)touchPosition[0].x; return (int)touchPosition[0].y;
#else #else
return (int)((mousePosition.y + mouseOffset.y)*mouseScale.y); return (int)((mousePosition.y + mouseOffset.y)*mouseScale.y);
#endif #endif

View File

@ -29498,8 +29498,8 @@ static MA_INLINE float32x4_t ma_src_sinc__interpolation_factor__neon(const ma_sr
{ {
float32x4_t xabs; float32x4_t xabs;
int32x4_t ixabs; int32x4_t ixabs;
float32x4_t a float32x4_t a;
float32x4_t r float32x4_t r;
int* ixabsv; int* ixabsv;
float lo[4]; float lo[4];
float hi[4]; float hi[4];

View File

@ -71,7 +71,7 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // 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 // Types and Structures Definition
@ -703,7 +703,11 @@ Model LoadModelFromMesh(Mesh mesh)
void UnloadModel(Model model) void UnloadModel(Model model)
{ {
for (int i = 0; i < model.meshCount; i++) UnloadMesh(model.meshes[i]); 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.meshes);
RL_FREE(model.materials); 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 // 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 // Unfortunately, sqrtf() is a costly operation, so we avoid it with following solution
/* /*
float dx = centerA.x - centerB.x; // X distance between centers float dx = centerA.x - centerB.x; // X distance between centers
float dy = centerA.y - centerB.y; // Y distance between centers float dy = centerA.y - centerB.y; // Y distance between centers
float dz = centerA.z - centerB.z; // Z 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; if (distance <= (radiusA + radiusB)) collision = true;
*/ */
@ -3346,7 +3350,7 @@ static Model LoadGLTF(const char *fileName)
- Triangle-only meshes - Triangle-only meshes
- Not supported node hierarchies or transforms - Not supported node hierarchies or transforms
- Only loads the diffuse texture... but not too hard to support other maps (normal, roughness/metalness...) - 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) - Only supports float for texture coordinates (no byte/unsigned short)
*************************************************************************************/ *************************************************************************************/
@ -3435,7 +3439,7 @@ static Model LoadGLTF(const char *fileName)
if (img->uri) if (img->uri)
{ {
if ((strlen(img->uri) > 5) && if ((strlen(img->uri) > 5) &&
(img->uri[0] == 'd') && (img->uri[0] == 'd') &&
(img->uri[1] == 'a') && (img->uri[1] == 'a') &&
(img->uri[2] == 't') && (img->uri[2] == 't') &&

View File

@ -204,9 +204,9 @@ struct rAudioBuffer {
bool paused; // Audio buffer state: AUDIO_PAUSED bool paused; // Audio buffer state: AUDIO_PAUSED
bool looping; // Audio buffer looping, always true for AudioStreams bool looping; // Audio buffer looping, always true for AudioStreams
int usage; // Audio buffer usage mode: STATIC or STREAM int usage; // Audio buffer usage mode: STATIC or STREAM
bool isSubBufferProcessed[2]; bool isSubBufferProcessed[2];
unsigned int frameCursorPos; unsigned int frameCursorPos; // Samples processed?
unsigned int bufferSizeInFrames; unsigned int bufferSizeInFrames;
rAudioBuffer *next; rAudioBuffer *next;
@ -402,7 +402,7 @@ static ma_uint32 OnAudioBufferDSPRead(ma_pcm_converter *pDSP, void *pFramesOut,
} }
else else
{ {
ma_uint32 firstFrameIndexOfThisSubBuffer = subBufferSizeInFrames * currentSubBufferIndex; ma_uint32 firstFrameIndexOfThisSubBuffer = subBufferSizeInFrames*currentSubBufferIndex;
framesRemainingInOutputBuffer = subBufferSizeInFrames - (audioBuffer->frameCursorPos - firstFrameIndexOfThisSubBuffer); framesRemainingInOutputBuffer = subBufferSizeInFrames - (audioBuffer->frameCursorPos - firstFrameIndexOfThisSubBuffer);
} }
@ -410,7 +410,7 @@ static ma_uint32 OnAudioBufferDSPRead(ma_pcm_converter *pDSP, void *pFramesOut,
if (framesToRead > framesRemainingInOutputBuffer) framesToRead = framesRemainingInOutputBuffer; if (framesToRead > framesRemainingInOutputBuffer) framesToRead = framesRemainingInOutputBuffer;
memcpy((unsigned char *)pFramesOut + (framesRead*frameSizeInBytes), audioBuffer->buffer + (audioBuffer->frameCursorPos*frameSizeInBytes), framesToRead*frameSizeInBytes); 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; framesRead += framesToRead;
// If we've read to the end of the buffer, mark it as processed // 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); 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)); 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 music.loopCount = 0; // Infinite loop by default
musicLoaded = true; musicLoaded = true;
TraceLog(LOG_DEBUG, "[%s] OGG total samples: %i", fileName, music.sampleCount); TraceLog(LOG_INFO, "[%s] OGG total samples: %i", fileName, music.sampleCount);
TraceLog(LOG_DEBUG, "[%s] OGG sample rate: %i", fileName, info.sample_rate); TraceLog(LOG_INFO, "[%s] OGG sample rate: %i", fileName, info.sample_rate);
TraceLog(LOG_DEBUG, "[%s] OGG channels: %i", fileName, info.channels); TraceLog(LOG_INFO, "[%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 memory required: %i", fileName, info.temp_memory_required);
} }
} }
#endif #endif
@ -1250,7 +1250,7 @@ Music LoadMusicStream(const char *fileName)
int result = jar_xm_create_context_from_file(&ctxXm, 48000, 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; music.ctxType = MUSIC_MODULE_XM;
jar_xm_set_max_loop_count(ctxXm, 0); // Set infinite number of loops 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 music.loopCount = 0; // Infinite loop by default
musicLoaded = true; 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); 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; 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() // For music streams, we need to make sure we maintain the frame cursor position
// // NOTE: In case window is minimized, music stream is stopped, // This is a hack for this section of code in UpdateMusicStream()
// // just make sure to play again on window restore // NOTE: In case window is minimized, music stream is stopped, just make sure to
// if (IsMusicPlaying(music)) PlayMusicStream(music); // play again on window restore: if (IsMusicPlaying(music)) PlayMusicStream(music);
ma_uint32 frameCursorPos = audioBuffer->frameCursorPos; ma_uint32 frameCursorPos = audioBuffer->frameCursorPos;
PlayAudioStream(music.stream); // <-- This resets the cursor position. 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 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; if ((music.sampleLeft/music.stream.channels) >= subBufferSizeInFrames) samplesCount = subBufferSizeInFrames*music.stream.channels;
else samplesCount = music.sampleLeft; else samplesCount = music.sampleLeft;
@ -1528,7 +1528,7 @@ void SetMusicPitch(Music music, float pitch)
} }
// Set music loop count (loop repeats) // 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) void SetMusicLoopCount(Music music, int count)
{ {
music.loopCount = count; music.loopCount = count;
@ -1605,7 +1605,7 @@ void CloseAudioStream(AudioStream stream)
// Update audio stream buffers with data // Update audio stream buffers with data
// NOTE 1: Only updates one buffer of the stream source: unqueue -> update -> queue // 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) void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
{ {
AudioBuffer *audioBuffer = stream.buffer; AudioBuffer *audioBuffer = stream.buffer;
@ -1622,7 +1622,8 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
if (audioBuffer->isSubBufferProcessed[0] && audioBuffer->isSubBufferProcessed[1]) 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; subBufferToUpdate = 0;
audioBuffer->frameCursorPos = 0; audioBuffer->frameCursorPos = 0;
} }
@ -1635,7 +1636,8 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
ma_uint32 subBufferSizeInFrames = audioBuffer->bufferSizeInFrames/2; ma_uint32 subBufferSizeInFrames = audioBuffer->bufferSizeInFrames/2;
unsigned char *subBuffer = audioBuffer->buffer + ((subBufferSizeInFrames*stream.channels*(stream.sampleSize/8))*subBufferToUpdate); 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) if (subBufferSizeInFrames >= (ma_uint32)samplesCount/stream.channels)
{ {
ma_uint32 framesToWrite = subBufferSizeInFrames; 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 // Check if any audio stream buffers requires refill
bool IsAudioBufferProcessed(AudioStream stream) bool IsAudioStreamProcessed(AudioStream stream)
{ {
if (stream.buffer == NULL) if (stream.buffer == NULL)
{ {
TraceLog(LOG_ERROR, "IsAudioBufferProcessed() : No audio buffer"); TraceLog(LOG_ERROR, "IsAudioStreamProcessed() : No audio buffer");
return false; return false;
} }

View File

@ -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 *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 *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 *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 *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string)
RLAPI const char *GetPrevDirectoryPath(const char *path); // Get previous directory path for a given 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 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 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) 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 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 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 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 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 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 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 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) 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 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 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 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 PlayAudioStream(AudioStream stream); // Play audio stream
RLAPI void PauseAudioStream(AudioStream stream); // Pause audio stream RLAPI void PauseAudioStream(AudioStream stream); // Pause audio stream
RLAPI void ResumeAudioStream(AudioStream stream); // Resume audio stream RLAPI void ResumeAudioStream(AudioStream stream); // Resume audio stream

View File

@ -56,7 +56,7 @@
#if defined(RAYMATH_IMPLEMENTATION) #if defined(RAYMATH_IMPLEMENTATION)
#if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED) #if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED)
#define RMDEF __declspec(dllexport) extern inline // We are building raylib as a Win32 shared library (.dll). #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) #define RMDEF __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll)
#else #else
#define RMDEF extern inline // Provide external definition #define RMDEF extern inline // Provide external definition
@ -113,7 +113,7 @@
float y; float y;
float z; float z;
} Vector3; } Vector3;
// Quaternion type // Quaternion type
typedef struct Quaternion { typedef struct Quaternion {
float x; float x;
@ -794,6 +794,33 @@ RMDEF Matrix MatrixRotate(Vector3 axis, float angle)
return result; 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) // Returns x-rotation matrix (angle in radians)
RMDEF Matrix MatrixRotateX(float angle) RMDEF Matrix MatrixRotateX(float angle)
{ {

View File

@ -4623,6 +4623,14 @@ int GetPixelDataSize(int width, int height, int format)
} }
dataSize = width*height*bpp/8; // Total data size in bytes 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; return dataSize;
} }

View File

@ -5,7 +5,7 @@
* A quick, efficient, and minimal free list and stack-based allocator * A quick, efficient, and minimal free list and stack-based allocator
* *
* PURPOSE: * 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. * - Reduce the possibilities of memory leaks for beginner developers using Raylib.
* - Being able to flexibly range check memory if necessary. * - 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; 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 // 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 ALLOC_SIZE = __AlignSize(size + sizeof *new_mem, sizeof(intptr_t));
const size_t BUCKET_INDEX = (ALLOC_SIZE >> MEMPOOL_BUCKET_BITS) - 1; 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) if (BUCKET_INDEX < MEMPOOL_BUCKET_SIZE && mempool->buckets[BUCKET_INDEX] != NULL && mempool->buckets[BUCKET_INDEX]->size >= ALLOC_SIZE)
{ {
new_mem = mempool->buckets[BUCKET_INDEX]; 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; const size_t MEM_SPLIT_THRESHOLD = 16;
// If the freelist is valid, let's allocate FROM the freelist then! // 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; if (inode->size < ALLOC_SIZE) continue;
else if ((*inode)->size <= (ALLOC_SIZE + MEM_SPLIT_THRESHOLD)) else if (inode->size <= (ALLOC_SIZE + MEM_SPLIT_THRESHOLD))
{ {
// Close in size - reduce fragmentation by not splitting. // Close in size - reduce fragmentation by not splitting.
new_mem = *inode; new_mem = inode;
__RemoveNode(mempool, 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--; mempool->freeList.len--;
break; break;
} }
else else
{ {
// Split the memory chunk. // Split the memory chunk.
new_mem = (MemNode *)((uint8_t *)*inode + ((*inode)->size - ALLOC_SIZE)); new_mem = (MemNode *)((uint8_t *)inode + (inode->size - ALLOC_SIZE));
(*inode)->size -= ALLOC_SIZE; inode->size -= ALLOC_SIZE;
new_mem->size = ALLOC_SIZE; new_mem->size = ALLOC_SIZE;
break; 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 // attempted stack merge failed, try to place it into the memnode buckets
else if (BUCKET_INDEX < MEMPOOL_BUCKET_SIZE) 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 else
{ {
for (MemNode *n = mempool->buckets[index]; n != NULL; n = n->next) if( n==node ) return; for (MemNode *n = mempool->buckets[BUCKET_INDEX]; n != NULL; n = n->next) if( n==mem_node ) return;
mempool->buckets[index]->prev = node; mempool->buckets[BUCKET_INDEX]->prev = mem_node;
node->next = mempool->buckets[index]; mem_node->next = mempool->buckets[BUCKET_INDEX];
mempool->buckets[index] = node; mempool->buckets[BUCKET_INDEX] = mem_node;
} }
} }
// Otherwise, we add it to the free list. // 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. // If node is right at the stack, merge it back into the stack.
mempool->stack.base += (*node)->size; mempool->stack.base += (*node)->size;
(*node)->size = 0UL; (*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--; mempool->freeList.len--;
node = &mempool->freeList.head; node = &mempool->freeList.head;
} }

View File

@ -1179,6 +1179,7 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, int
} }
// Draw a triangle // Draw a triangle
// NOTE: Vertex must be provided in counter-clockwise order
void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color) void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
{ {
if (rlCheckBufferLimit(4)) rlglDraw(); if (rlCheckBufferLimit(4)) rlglDraw();
@ -1214,6 +1215,7 @@ void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
} }
// Draw a triangle using lines // Draw a triangle using lines
// NOTE: Vertex must be provided in counter-clockwise order
void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color) void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
{ {
if (rlCheckBufferLimit(6)) rlglDraw(); 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 // 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) void DrawTriangleFan(Vector2 *points, int pointsCount, Color color)
{ {
if (pointsCount >= 3) if (pointsCount >= 3)
@ -1263,7 +1265,7 @@ void DrawTriangleFan(Vector2 *points, int pointsCount, Color color)
} }
// Draw a triangle strip defined by points // 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) void DrawTriangleStrip(Vector2 *points, int pointsCount, Color color)
{ {
if (pointsCount >= 3) if (pointsCount >= 3)