commit
55fd48b883
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
40
src/core.c
40
src/core.c
|
|
@ -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
|
||||||
|
|
|
||||||
4
src/external/miniaudio.h
vendored
4
src/external/miniaudio.h
vendored
|
|
@ -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];
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
40
src/raudio.c
40
src/raudio.c
|
|
@ -206,7 +206,7 @@ struct rAudioBuffer {
|
||||||
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;
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
12
src/raylib.h
12
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 *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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4624,6 +4624,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;
|
||||||
}
|
}
|
||||||
#endif // RLGL_STANDALONE
|
#endif // RLGL_STANDALONE
|
||||||
|
|
|
||||||
54
src/rmem.h
54
src/rmem.h
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user